Unity集成微信支付全流程实战:从Android原生模块到C#桥接

📅 2026/7/13 6:30:11
Unity集成微信支付全流程实战:从Android原生模块到C#桥接
1. 项目概述如果你正在用Unity开发一款面向国内市场的Android应用并且需要接入支付功能那么微信支付几乎是绕不开的一环。我最近刚在一个商业项目中完整走通了Unity集成微信支付的流程从Android Studio的aar打包到Unity端的C#桥接再到微信开放平台的配置整个过程踩了不少坑也积累了一些实战经验。这篇文章就是一份详细的踩坑指南我会把每一步的操作、背后的原理以及那些官方文档里不会写的“坑点”都讲清楚。无论你是独立开发者还是团队中的技术负责人这篇指南都能帮你节省大量东拼西凑查资料的时间快速、稳定地实现Unity应用的微信支付功能。2. 核心原理与架构设计2.1 为什么Unity集成微信支付这么“麻烦”很多刚接触的开发者会疑惑为什么不能像用C#插件一样直接拖一个DLL到Unity里就完事了这得从微信支付SDK的调用机制和Android平台特性说起。微信支付本质上是一个跨应用通信的过程。你的Unity应用我们称之为“商户应用”需要调起微信客户端用户在微信内完成支付授权后微信客户端需要将支付结果回调给你的应用。在Android上这种跨应用回调通常通过特定的Activity来实现。微信SDK规定接收回调的Activity必须放在固定的包路径[你的应用包名].wxapi下并且命名为WXPayEntryActivity。这个Activity就像一个“接待处”专门处理从微信客户端跳转回来的信息。Unity打包的APK其入口Activity默认是com.unity3d.player.UnityPlayerActivity。我们的任务就是在这个标准的Unity应用框架里插入微信SDK要求的“接待处”并建立一条从C#脚本到Java层再到微信客户端最后再返回C#脚本的完整通信链路。这涉及到Android原生开发Java、Unity与Android的交互AndroidJavaClass/AndroidJavaObject、以及微信开放平台的配置三者缺一不可因此步骤显得繁琐。2.2 整体技术架构与数据流理解整个数据流对接下来的每一步操作至关重要。下图清晰地展示了从用户点击支付到收到回调的完整过程sequenceDiagram participant U as Unity C#脚本 participant A as Android Java层 (MainActivity) participant W as 微信客户端 participant S as 商户服务器 participant WX as 微信支付后台 U-A: 1. 调用支付方法传入订单参数 A-W: 2. 调起微信支付界面 W-用户: 3. 展示支付确认界面 用户-W: 4. 输入密码/确认支付 W-WX: 5. 提交支付请求 WX-S: 6. 异步通知支付结果 (可选) W--A: 7. 支付结果回调至 WXPayEntryActivity A-U: 8. 通过 UnitySendMessage 通知C# U-S: 9. 向自家服务器查询/验证最终订单状态流程关键点解析参数准备步骤1Unity C#脚本需要从你自己的业务服务器获取一组支付参数包括prepay_id,nonceStr,timeStamp,sign等。这些参数由你的服务器向微信支付后台发起统一下单API获得。C#脚本将这些参数传递给Android Java层。调起支付步骤2Java层的MainActivity使用微信SDK的IWXAPI.sendReq(PayReq)方法将支付参数封装成一个请求发送给微信客户端。如果微信已安装且参数正确系统会弹出微信支付界面。回调与通知步骤7, 8, 9这是最容易出错的部分。支付完成后微信客户端会跳转回你应用中指定的WXPayEntryActivity。该Activity的onResp方法会收到一个BaseResp对象其中errCode表示支付结果0成功-2用户取消。注意这个回调仅代表用户支付动作的完成不代表资金已结算。为了确保安全你必须在此处通过UnityPlayer.UnitySendMessage将结果告知Unity然后Unity再通知你的业务服务器。你的服务器应当以微信支付后台发来的异步通知步骤6作为最终入账依据或者主动调用微信的查询订单API进行二次确认。3. 环境准备与前置条件3.1 账号与密钥申请在写第一行代码之前你需要准备好以下“门票”微信开放平台账号与应用前往微信开放平台注册并完成开发者认证。创建一个移动应用获取应用的唯一标识AppID。这个AppID是后续所有调用的关键。微信支付商户号如果你还没有需要在开放平台内申请开通微信支付功能审核通过后你会获得一个MCHID商户号。API密钥在微信支付商户平台设置API密钥。这是一个32位的字符串用于生成支付签名务必妥善保管不要泄露到客户端。签名是在服务端生成的。重要提示确保开放平台应用填写的包名和应用签名与你最终发布的Unity应用完全一致。应用签名需要使用微信提供的“签名生成工具”获取而不是直接用Android Studio或Unity的调试密钥。包名不一致或签名不匹配会导致无法调起微信。3.2 本地开发环境配置Unity版本建议使用稳定的LTS版本如2020.3.x或2021.3.x。我使用的是2020.3.24f1c2。确保在Unity Hub中安装了对应的Android Build Support模块。Android Studio用于开发和编译包含微信SDK的Android Libraryaar包。版本无严格要求能正常构建即可。JDK确保已安装Java Development Kit (JDK 8或11)并配置好环境变量JAVA_HOME。Unity工程设置在Player Settings Android Other Settings中正确设置Package Name包名并与你在开放平台注册的包名一致。同时准备好你的发布密钥库Keystore因为调试版和发布版的签名不同测试时建议直接使用发布签名进行调试避免签名问题。4. Android原生模块开发详解这是整个集成过程中最核心、也最容易出错的一步。我们的目标是在Android Studio中创建一个Android Library模块它封装了微信SDK的调用逻辑并编译成.aar文件供Unity使用。4.1 创建Android Library工程打开Android Studio新建一个Empty Activity项目。在配置页面Package name必须填写与你的Unity工程完全一致的包名例如com.yourcompany.yourapp。项目创建后切换到Project视图左上角下拉菜单。右键点击项目根目录选择New Module。选择Android Library模块名称可以定为unitywechatpay包名会自动继承主项目确认与Unity包名一致例如com.yourcompany.yourapp.wx。这样创建出来的library其命名空间就与你的主应用一致了。4.2 引入依赖库微信SDK与Unity Classes.jarLibrary需要两个关键的依赖微信支付SDK和Unity的Java交互接口。1. 引入微信SDK微信官方推荐使用Maven Central仓库依赖。在你的library模块的build.gradle文件的dependencies块中添加dependencies { implementation com.tencent.mm.opensdk:wechat-sdk-android:6.8.0 // 使用当时最新稳定版 }但是这里有个大坑如果你直接这样依赖然后打包aar这个aar文件不会包含微信SDK的代码。它只会在gradle配置中声明依赖。当这个aar被放入Unity工程时Unity的构建系统无法解析这个Maven依赖导致最终APK中缺少微信SDK的类运行时就会报ClassNotFoundException。解决方案有两种方案A使用Unity的依赖解析插件推荐谷歌提供了External Dependency Manager for Unity原名Play Services Resolver。你可以在Unity Asset Store下载或通过Package Manager添加。这个插件可以识别aar中的Maven依赖并在Unity构建时自动下载并合并到APK中。这是最接近原生Android开发体验的方式。方案B手动下载并嵌入SDK本文采用更直观我们从Maven Central手动下载微信SDK的aar包。可以访问https://search.maven.org/搜索com.tencent.mm.opensdk:wechat-sdk-android选择版本下载.aar文件。然后用解压软件如7-Zip打开将其中的classes.jar提取出来重命名为wechat-sdk-android.jar放入library模块的libs目录下。最后在build.gradle中改为依赖本地jardependencies { implementation files(libs/wechat-sdk-android.jar) }2. 引入Unity Classes.jar为了让我们的Java代码能回调到Unity的C#脚本我们需要Unity提供的Java类。这个jar文件位于你的Unity安装目录下[Unity安装路径]\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono或il2cpp\Release或Development\Classes\classes.jar。 根据你的Unity脚本后端Mono或IL2CPP和构建类型Release或Development选择对应的jar。通常开发期选择mono/Development/classes.jar。同样将其复制到library模块的libs目录并在build.gradle中添加依赖dependencies { implementation files(libs/wechat-sdk-android.jar) compileOnly files(libs/classes.jar) // 注意是 compileOnly }这里使用compileOnly而不是implementation是因为这个jar只在编译时需要我们不希望将它打包进最终的aar。因为Unity在构建APK时会自己注入这个jar如果aar里也有一份就会导致类冲突引发Duplicate class错误。4.3 编写核心Java代码我们需要创建三个关键的Java类。1. WXPayEntryActivity.java - 支付回调接收器这个类必须放在[你的包名].wxapi包下。在Android Studio中在java目录下右键依次新建包com.yourcompany.yourapp.wxapi然后在该包下新建类WXPayEntryActivity。package com.yourcompany.yourapp.wxapi; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import com.tencent.mm.opensdk.constants.ConstantsAPI; import com.tencent.mm.opensdk.modelbase.BaseReq; import com.tencent.mm.opensdk.modelbase.BaseResp; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; import com.tencent.mm.opensdk.openapi.WXAPIFactory; import com.unity3d.player.UnityPlayer; public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler { private static final String TAG MicroMsg.WXPayEntry; private IWXAPI api; // 这两个静态变量用于接收Unity传过来的GameObject和Method名 public static String unityGameObjectName; public static String unityCallbackMethodName; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 这里不设置ContentView我们不需要界面 api WXAPIFactory.createWXAPI(this, null); // AppID可以从Manifest读取或由MainActivity设置 api.handleIntent(getIntent(), this); } Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); api.handleIntent(intent, this); } Override public void onReq(BaseReq baseReq) { // 微信发送请求到第三方应用时会回调此方法。支付场景一般不需要处理。 } Override public void onResp(BaseResp baseResp) { Log.d(TAG, onPayFinish, errCode baseResp.errCode); // 判断回调类型是否为支付 if (baseResp.getType() ConstantsAPI.COMMAND_PAY_BY_WX) { String resultMsg; switch (baseResp.errCode) { case BaseResp.ErrCode.ERR_OK: resultMsg PAY_SUCCESS; break; case BaseResp.ErrCode.ERR_USER_CANCEL: resultMsg PAY_CANCEL; break; default: resultMsg PAY_FAILED_ baseResp.errCode; break; } // 关键步骤将支付结果发送回Unity if (unityGameObjectName ! null unityCallbackMethodName ! null) { UnityPlayer.UnitySendMessage(unityGameObjectName, unityCallbackMethodName, resultMsg); } else { Log.e(TAG, Unity callback target not set!); } } finish(); // 关闭这个临时Activity } }2. MainActivity.java - 继承UnityPlayerActivity并封装支付调用我们需要替换Unity默认的Activity。在com.yourcompany.yourapp.wx包下创建MainActivity。package com.yourcompany.yourapp.wx; import android.os.Bundle; import com.tencent.mm.opensdk.modelpay.PayReq; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.WXAPIFactory; import com.unity3d.player.UnityPlayerActivity; public class MainActivity extends UnityPlayerActivity { private IWXAPI wxApi; public static final String WX_APP_ID 你的微信AppID; // 建议从C#传入或读取配置 Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initWXApi(); } private void initWXApi() { if (wxApi null) { wxApi WXAPIFactory.createWXAPI(this, WX_APP_ID, true); wxApi.registerApp(WX_APP_ID); } } /** 检查微信是否安装 */ public boolean isWeChatInstalled() { return wxApi ! null wxApi.isWXAppInstalled(); } /** 发起微信支付请求 */ public void requestWeChatPay(String appId, String partnerId, String prepayId, String packageValue, String nonceStr, String timeStamp, String sign, String callbackGameObject, String callbackMethod) { // 设置回调目标 WXPayEntryActivity.unityGameObjectName callbackGameObject; WXPayEntryActivity.unityCallbackMethodName callbackMethod; PayReq request new PayReq(); request.appId appId; request.partnerId partnerId; request.prepayId prepayId; request.packageValue packageValue; request.nonceStr nonceStr; request.timeStamp timeStamp; request.sign sign; if (wxApi ! null) { wxApi.sendReq(request); } } }3. 处理UnityPlayerActivity类缺失问题新版本的Unity大约2018以后classes.jar中可能不再包含UnityPlayerActivity的源码。如果你在编译时遇到这个类找不到的错误需要手动添加。从Unity安装目录Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player找到UnityPlayerActivity.java文件复制到你的Android Studio工程中放在与MainActivity相同的包 (com.yourcompany.yourapp.wx) 下。然后在MainActivity中继承它即可。4.4 生成AAR文件并解决依赖问题完成代码编写后点击Android Studio右侧Gradle面板找到你的library模块依次展开Tasks build双击assemble或assembleRelease。编译成功后aar文件会生成在模块目录/build/outputs/aar/下。关键检查点打开生成的aar文件用解压软件检查libs/目录下是否包含了wechat-sdk-android.jar但不应该包含classes.jar。如果包含了classes.jar说明之前的compileOnly依赖没有生效需要检查gradle配置或者手动从aar中删除这个jar否则Unity打包时会冲突。5. Unity工程配置与C#桥接5.1 导入AAR与配置AndroidManifest在Unity项目中创建文件夹Plugins/Android。将上一步生成的.aar文件以及可能用到的其他aar如微信SDK的aar如果你用方案B手动引入了复制到这个文件夹。Unity在构建Android APK时会自动处理该目录下的原生插件。配置自定义AndroidManifest.xmlUnity默认会生成一个AndroidManifest。为了注册我们的MainActivity和WXPayEntryActivity我们需要提供一个自定义的。在Plugins/Android下创建AndroidManifest.xml文件。?xml version1.0 encodingutf-8? manifest xmlns:androidhttp://schemas.android.com/apk/res/android packagecom.yourcompany.yourapp !-- 替换为你的包名 -- xmlns:toolshttp://schemas.android.com/tools !-- 对于 Android 11 (API 30) 及以上必须添加此 queries 声明才能正常检测和调起微信 -- queries package android:namecom.tencent.mm / /queries application !-- 替换Unity默认的Activity为我们自定义的MainActivity -- activity android:namecom.yourcompany.yourapp.wx.MainActivity android:exportedtrue android:themestyle/UnityThemeSelector android:launchModesingleTask tools:replaceandroid:theme intent-filter action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.LAUNCHER / /intent-filter meta-data android:nameunityplayer.UnityActivity android:valuetrue / /activity !-- 微信支付回调Activity必须放在.wxapi包下 -- activity android:namecom.yourcompany.yourapp.wxapi.WXPayEntryActivity android:exportedtrue android:launchModesingleTask / !-- 如果你还需要微信登录等功能也需要对应的WXEntryActivity -- !-- activity android:name.wxapi.WXEntryActivity ... / -- /application /manifest重要提示android:exportedtrue是必须的否则其他应用微信无法启动这个Activity。queries段落是针对Android 11以上包可见性限制的解决方案没有它isWXAppInstalled()会返回false且无法调起微信。在Unity Editor中打开Player Settings Android Publishing Settings勾选Custom Main Manifest和Custom Main Gradle Template如果需要修改Gradle配置。确保我们自定义的Manifest文件被使用。5.2 编写C#调用脚本在Unity中创建一个C#脚本例如WeChatPayManager.cs负责与Android Java层通信。using UnityEngine; using System; public class WeChatPayManager : MonoBehaviour { private static AndroidJavaObject _currentActivity; private static AndroidJavaObject CurrentActivity { get { if (_currentActivity null) { AndroidJavaClass unityPlayer new AndroidJavaClass(com.unity3d.player.UnityPlayer); _currentActivity unityPlayer.GetStaticAndroidJavaObject(currentActivity); } return _currentActivity; } } /// summary /// 检查设备是否安装微信 /// /summary public static bool IsWeChatInstalled() { try { return CurrentActivity.Callbool(isWeChatInstalled); } catch (Exception e) { Debug.LogError([WeChatPay] Check installation failed: e.Message); return false; } } /// summary /// 调用微信支付 /// /summary /// param namepayParams从服务器获取的支付参数对象/param /// param namecallbackGameObject接收回调的GameObject名称/param /// param namecallbackMethod接收回调的方法名称/param public static void RequestPayment(WeChatPayParams payParams, string callbackGameObject, string callbackMethod) { if (payParams null) { Debug.LogError([WeChatPay] Payment parameters are null.); return; } if (!IsWeChatInstalled()) { Debug.LogError([WeChatPay] WeChat is not installed.); // 可以在这里触发一个失败回调 GameObject.Find(callbackGameObject)?.SendMessage(callbackMethod, NOT_INSTALLED); return; } try { CurrentActivity.Call(requestWeChatPay, payParams.appId, payParams.partnerId, payParams.prepayId, payParams.package, payParams.nonceStr, payParams.timeStamp, payParams.sign, callbackGameObject, callbackMethod); Debug.Log($[WeChatPay] Payment request sent. PrepayId: {payParams.prepayId}); } catch (Exception e) { Debug.LogError($[WeChatPay] Failed to call native method: {e.Message}); GameObject.Find(callbackGameObject)?.SendMessage(callbackMethod, NATIVE_CALL_FAILED); } } /// summary /// 支付参数结构体应与服务端返回的JSON对应 /// /summary public struct WeChatPayParams { public string appId; // 微信开放平台AppID public string partnerId; // 商户号 MCHID public string prepayId; // 预支付交易会话ID由统一下单接口返回 public string package; // 固定值 SignWXPay public string nonceStr; // 随机字符串 public string timeStamp; // 时间戳秒 public string sign; // 签名 } } // 示例挂载在场景中的回调处理脚本 public class PaymentHandler : MonoBehaviour { void Start() { // 示例从服务器获取支付参数这里需要网络请求 // StartCoroutine(FetchPaymentParams(order_123)); } // 这个函数名需要和调用RequestPayment时传入的callbackMethod一致 public void OnWeChatPayCallback(string result) { Debug.Log($[PaymentHandler] WeChat Pay Callback: {result}); switch (result) { case PAY_SUCCESS: // 支付成功但此时仅代表用户支付动作完成。 // 必须通知服务器让服务器查询微信支付后台确认最终订单状态。 StartCoroutine(ConfirmOrderWithServer(order_123)); break; case PAY_CANCEL: // 用户取消支付 UIManager.Instance.ShowToast(支付已取消); break; default: // 支付失败result可能包含错误码如 PAY_FAILED_-1 UIManager.Instance.ShowToast(支付失败请重试); break; } } // 模拟调用支付 public void OnPayButtonClicked() { // 1. 先检查是否安装微信 if (!WeChatPayManager.IsWeChatInstalled()) { UIManager.Instance.ShowToast(请先安装微信客户端); return; } // 2. 模拟从服务器获取到的参数实际项目中需网络请求 WeChatPayManager.WeChatPayParams mockParams new WeChatPayManager.WeChatPayParams { appId wx1234567890abcdef, partnerId 1900000109, prepayId wx20250410123456abcdef, package SignWXPay, nonceStr 5K8264ILTKCH16CQ2502SI8ZNMTM67VS, timeStamp 1712731200, sign C380BEC2BFD727A4B6845133519F3AD6 // 示例签名切勿直接使用 }; // 3. 调用支付指定本GameObject和回调方法名 WeChatPayManager.RequestPayment(mockParams, this.gameObject.name, OnWeChatPayCallback); } private System.Collections.IEnumerator ConfirmOrderWithServer(string orderId) { // 向你的服务器发起请求验证订单最终状态 // yield return ... yield return null; } }6. 打包、签名与平台配置的终极陷阱代码写完了但距离成功调起支付还有最后也是最关键的几步。6.1 获取并配置应用签名这是导致“无法调起微信”最常见的原因。微信开放平台需要验证调用方的身份验证方式就是应用签名。不要使用调试签名Unity在Editor中运行或打Debug包时使用的调试密钥debug.keystore的签名与发布包使用你自己的.keystore文件的签名完全不同。获取发布版签名用你的发布密钥库.keystore文件打包一个正式的APK或Android App Bundle。将这个APK安装到你的测试手机上。在手机上安装微信官方提供的“签名生成工具”可在微信开放平台文档中找到下载链接。打开工具输入你的应用包名如com.yourcompany.yourapp点击“获取签名”。工具会计算并显示一个32位的MD5签名不带冒号。配置开放平台登录微信开放平台进入你的应用详情页找到“修改”应用签名的地方将上一步获取的签名字符串填写进去。注意这个修改可能需要一段时间通常是几个小时审核生效。在生效前你用该签名打包的APK依然无法调起微信。6.2 打包流程与关键设置Player Settings:Other Settings Package Name: 必须与开放平台注册的包名、AndroidManifest中的包名、Android Studio工程包名完全一致。Other Settings Minimum API Level: 建议设置为21Android 5.0或更高但需注意queries标签要求API Level 30如果设低了需要额外的兼容性处理。Publishing Settings Keystore: 选择你用于发布签名的.keystore文件并填写正确的alias和密码。构建在Build Settings中选择Android平台进行构建。建议先打一个Development Build并勾选Autoconnect Profiler方便在真机上通过Logcat查看日志。6.3 真机调试与日志查看连接Android手机开启USB调试。打包并安装APK。使用Android Studio的Logcat这是最强大的调试工具。在Android Studio中连接设备选择你的应用进程过滤Tag为MicroMsg.WXPayEntry或你自定义的TAG可以清晰地看到支付回调的日志。使用adb logcat命令如果你习惯命令行adb logcat -s MicroMsg.WXPayEntry可以起到同样的过滤效果。常见错误日志registerApp fail, appId is invalidAppID填写错误或该AppID与当前应用包名/签名不匹配。sendReq fail, not registered没有成功调用wxApi.registerApp。没有任何错误日志但微信没反应大概率是签名未配置或未生效或者queries标签在低版本Android上缺失导致无法找到微信包。7. 服务端交互与安全实践客户端集成只是半边天一个健壮的支付系统离不开服务端的配合。7.1 支付流程中的服务端职责你的服务器需要至少实现两个接口统一下单接口当客户端发起支付请求时客户端不应直接接触微信支付API密钥。应由你的服务器接收订单信息金额、商品描述、用户IP等然后使用商户密钥MCHKEY按照微信V3或V2 API的规则生成签名调用微信的统一下单API。微信服务器会返回一组支付参数prepay_id,nonce_str等你的服务器将这些参数返回给Unity客户端。签名过程必须在服务端完成支付结果通知/查询接口客户端收到支付成功回调errCode0后应立刻通知你的服务器“用户可能支付成功了”。你的服务器需要做两件事之一处理异步通知微信支付后台会在支付成功后主动向你服务器配置的notify_url发送一个POST请求携带加密的支付结果。这是最权威的支付成功凭证。你的服务器需要验证签名、解密数据、处理业务逻辑如给用户加钻石并返回成功响应给微信。主动查询订单如果担心异步通知丢失可以在收到客户端通知后由服务器主动调用微信的查询订单API根据返回的订单状态进行最终确认。7.2 客户端-服务端交互示例// 在PaymentHandler.cs中补充 private System.Collections.IEnumerator StartPaymentFlow(string productId) { // 1. 向自家服务器请求支付参数 string orderUrl $https://yourserver.com/api/createOrder?product{productId}userId{UserManager.Instance.UserId}; using (UnityWebRequest request UnityWebRequest.Get(orderUrl)) { yield return request.SendWebRequest(); if (request.result UnityWebRequest.Result.Success) { // 解析服务器返回的JSON得到 WeChatPayParams WeChatPayManager.WeChatPayParams payParams JsonUtility.FromJsonWeChatPayParams(request.downloadHandler.text); // 2. 调用原生支付 WeChatPayManager.RequestPayment(payParams, gameObject.name, OnWeChatPayCallback); } else { Debug.LogError(Failed to create order: request.error); } } } public void OnWeChatPayCallback(string result) { if (result PAY_SUCCESS) { // 3. 通知服务器支付成功让服务器去验证 StartCoroutine(NotifyServerPaymentResult(orderId_from_payParams)); } // ... 其他结果处理 } private System.Collections.IEnumerator NotifyServerPaymentResult(string orderId) { string notifyUrl $https://yourserver.com/api/confirmOrder?orderId{orderId}; using (UnityWebRequest request UnityWebRequest.Post(notifyUrl, )) { yield return request.SendWebRequest(); if (request.result UnityWebRequest.Result.Success) { // 服务器确认成功更新本地状态 Debug.Log(Order confirmed by server!); } } }8. 进阶问题与性能优化8.1 多场景与GameObject生命周期管理如果你的支付调用和回调处理分布在不同的场景或GameObject上需要谨慎管理。UnitySendMessage要求接收消息的GameObject在场景中处于活动状态。如果支付发起后用户切换了场景原来的GameObject被销毁回调就会丢失。解决方案使用单例或持久化GameObject创建一个名为PaymentCallbackManager的GameObject挂载一个DontDestroyOnLoad脚本专门用于处理支付回调。所有支付请求都指定这个GameObject为回调目标。使用事件/委托系统构建一个全局的事件管理器。支付回调脚本收到UnitySendMessage后不直接处理业务逻辑而是触发一个全局的支付结果事件。其他模块如UI、数据管理器订阅这个事件。这样解耦了回调接收者和业务处理者。8.2 支付参数缓存与重试机制网络不稳定时从服务器获取支付参数可能失败。可以考虑在本地缓存一份有效的支付参数注意预支付IDprepay_id有有效期通常2小时。当支付因网络问题失败时可以尝试使用缓存的参数直接发起支付避免再次请求服务器。8.3 减少包体积微信SDK的aar/jar文件有一定体积。如果对包体敏感可以考虑使用ProGuard或R8代码混淆在Android Studio的library模块中配置minifyEnabled true移除无用的代码。但务必做好测试确保混淆后与微信SDK的交互正常。8.4 兼容性处理Android 12 的PendingIntent可变性如果你的targetSdkVersion设置为31或更高在创建通知等相关功能时如果涉及微信支付结果的PendingIntent需要声明其可变性FLAG_IMMUTABLE或FLAG_MUTABLE。虽然支付回调本身不直接涉及但若你的应用有相关功能需注意。备用支付方式始终检查IsWeChatInstalled()。如果未安装应有友好的UI提示并引导用户使用其他支付方式如支付宝、银联或引导安装微信。9. 常见问题排查速查表下表汇总了集成过程中最常见的问题、可能原因和解决方案问题现象可能原因排查步骤与解决方案点击支付无任何反应微信未启动1. 应用签名未在开放平台配置或错误。2. 包名不一致。3. Android 11 缺少queries声明。4.MainActivity未成功替换Unity默认Activity。1. 用发布签名打包APK安装后使用微信签名工具获取签名与开放平台配置比对。2. 检查Unity、AndroidManifest、开放平台三处包名是否完全一致。3. 确认AndroidManifest.xml中已添加queries段落。4. 检查Logcat查看应用启动时运行的Activity是否是自定义的MainActivity。调起微信后显示“商家参数格式错误”支付参数appId,partnerId,prepayId,sign等有误或缺失。1. 检查所有支付参数是否从服务器正确获取并完整传递到Java层。2.重点检查签名(sign)确保是服务端用商户密钥对指定参数生成的正确签名。客户端不能参与签名生成。3. 检查timeStamp是否为字符串格式的秒数。支付完成后无法返回原应用或回调不执行1.WXPayEntryActivity的android:exported未设为true。2.WXPayEntryActivity未在AndroidManifest.xml中正确声明。3. 包名路径错误不是[包名].wxapi.WXPayEntryActivity。4. 回调的GameObject不存在或方法名错误。1. 确认Manifest中该Activity的exportedtrue。2. 确认Manifest中该Activity的声明路径完全正确。3. 在WXPayEntryActivity.onResp开始处加Log确认是否被调用。4. 检查C#调用RequestPayment时传入的callbackGameObject和callbackMethod名称是否准确且该GameObject在场景中激活。Logcat报错ClassNotFoundException或NoClassDefFoundError1. 微信SDK的jar/aar未正确打包进APK。2. Unity的classes.jar冲突。1. 如果用方案B手动jar检查aar的libs/目录下是否有微信SDK的jar。2. 如果用方案AEDM检查Unity Console看External Dependency Manager是否成功解析并添加了依赖。3. 检查aar中是否错误地包含了classes.jar如果有修改gradle为compileOnly并重新打包aar。在Editor中运行正常打包后失败1. 使用了调试签名与开放平台配置的发布签名不符。2. Development Build和Release Build的代码优化/混淆导致问题。3. 依赖的.so库未包含在发布包中。1.永远使用发布签名进行最终测试。2. 关闭代码优化Scripting Backend为Mono时或关闭混淆再试。3. 检查Player Settings Publishing Settings Split Application Binary是否被误勾选这可能导致原生库丢失。支付成功但服务器未收到异步通知1. 服务器notify_url未正确配置或不可访问。2. 服务器处理通知后未按规定返回成功的XML/JSON给微信。3. 网络延迟或微信通知重试机制尚未触发。1. 登录微信商户平台检查支付配置中的通知URL。2. 检查服务器端通知处理逻辑确保在验证签名和解密后返回xmlreturn_code![CDATA[SUCCESS]]/return_code/xmlV2或{“code”: “SUCCESS”, “message”: “成功”}V3。3. 商户平台有通知查询工具可以手动补发通知。整个集成过程就像搭积木每一步都要严丝合缝。最关键的三个匹配包名、签名、回调Activity路径只要有一个对不上支付流程就通不了。多利用Logcat和真机调试耐心比对每一步的输出问题总能定位。当你第一次成功看到微信支付界面弹出来的时候那种感觉之前的折腾都值了。