
简介面向Unity开发者的微信与支付宝SDK集成资料包覆盖微信登录、微信分享、微信支付及支付宝支付四大核心功能适用于需要为iOS/Android游戏快速接入第三方能力的中高级Unity开发者。资源包共包含7322个文件以C#脚本、二进制库和动态链接库为主体同时提供aar、jar、Java源码等Android工程依赖以及配置文件、图片、文档和少量示例场景压缩包大小约464.91MB目录结构完整便于按模块查阅。内容基于真实项目整理不仅列出了SDK导入、IL2CPP配置、登录与支付接口调用等操作流程还给出了回调解析、订单校验、平台差异处理等关键细节和排错思路配合3000余个脚本文件可直接对照工程实践。已有2245人学习下载对于希望少走弯路、快速完成微信/支付宝接入的开发者有切实帮助。1. 把 Unity 工程接入微信登录、微信分享、微信支付和支付宝SDK到底要做什么把 Unity 工程同时接入微信登录、微信分享、微信支付和支付宝SDK是国内双端发行绕不开的标配玩家用微信一键进游戏顺手分享给好友商城下单时又能用微信或支付宝完成支付。技术本身不复杂但这类 SDK 全部是原生侧Android 的 aar / iOS 的 frameworkUnity 侧要自己搭桥、配回调页面、管生命周期任何一环断了表现就是“微信没反应”“分享后没动静”“收银台不弹”或者“支付成功但游戏里没到账”。这篇文章面向双端打包、发行到中国大陆的 Unity 团队尤其是没有专职客户端平台组的项目把从账号申请、代码桥接、支付链路到上线验证的完整路径拆开每一步都给能直接抄的方案。2. 接入前先把地基打好AppID、包名、签名和 Unity 工程准备2.1 微信与支付宝开放平台AppID、AppSecret、商户号、RSA2 私钥谁用在哪微信开放平台创建“移动应用”并通过审核后会得到两个核心参数AppID 和 AppSecret。AppID 是客户端用来识别应用的标识可以出现在 Unity 工程和 APK 里AppSecret 必须只存在服务端绝对不能写进 Unity 代码或打包进安装包。否则别人反编译拿到 AppSecret就可以用你的身份去换 access_token后果基本等于把账号体系拱手送人。支付宝开放平台那边对应的是一组密钥应用公钥、应用私钥、支付宝公钥。应用私钥留在服务端给下单请求签名用应用公钥填回支付宝开放平台支付宝公钥用来验证支付宝异步通知。很多项目在支付宝文档里看到“应用私钥”就直接往客户端塞这是翻车的高发点——私钥一旦被客户端拿到任何人都能伪装你的应用向支付宝发起下单。这里还容易混的一个概念是微信支付商户号。微信支付的统一下单接口需要 mch_id商户号它和 AppID 是两个字段微信开放平台里还有一个开发者账号编号看起来像数字但不是 AppID 也不是商户号。建议在项目配置表里把 AppID、AppSecret、商户号、应用私钥、支付宝公钥分开存别放在同一行免得接支付时传错参数。要注意的是应用创建和审核在排期上得提前留时间。微信移动应用审核一般要 17 天且个人开发者拿不到微信支付权限。如果公司主体还没有企业资质先把这块启动否则后面只能拿测试号开发提审时会集中爆雷。2.2 把微信与支付宝 SDK 装进 Unity 工程Plugins 目录规划微信 SDK 分 Android 和 iOS 两份。Android 端一般是一个 aar新版本或者 jar so老版本iOS 是静态库加头文件。支付宝 Android 是一个 aariOS 是 framework 外加 AlipaySDK.bundle 资源包。我习惯按下面这个结构放简单直观Assets/Plugins/Android/ ├─ libs/ │ ├─ wechat-sdk-android-xx.aar │ └─ alipaysdk-android-xx.aar Assets/Plugins/iOS/ ├─ libWeChatSDK.a ├─ AlipaySDK.framework/ └─ AlipaySDK.bundle/Unity 打包时Assets/Plugins/Android 下的文件会进入 APKAssets/Plugins/iOS 下的会整体复制到导出的 Xcode 工程。注意 aar 本身可能自带 AndroidManifest它会在打包时参与 manifest merge如果工程里已经有重复的权限声明或 Activity 注册要留意打包日志中的 merge 报错。关于版本号不必过分纠结。去官网下载当前稳定版即可。微信 Android SDK 的核心包路径是 com.tencent.mm.opensdk支付宝是 com.alipay.sdk后面所有 C# 桥接代码都依赖这两个包名。需要注意的是支付宝 SDK 依赖 AndroidX 和相关网络库Unity 工程开 AndroidX 后不要重复引入旧版 support 库否则后面会遇到 duplicate class。2.3 AndroidManifest 和 wxapi 回调 Activity绕不开的固定动作微信要求接收登录、分享、支付结果的 Activity 必须放在“包名.wxapi”目录下也就是最终类名是com.你的包名.wxapi.WXEntryActivity和com.你的包名.wxapi.WXPayEntryActivity。Unity 默认不带这两个类必须在 Assets/Plugins/Android 下提供 Java 源码再由打包过程编译进去。下面是一个最简的 WXEntryActivity处理微信回传的 Intent 和回调结果package com.example.game.wxapi; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import com.tencent.mm.opensdk.modelbase.BaseReq; import com.tencent.mm.opensdk.modelbase.BaseResp; import com.tencent.mm.opensdk.modelmsg.SendAuth; 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 WXEntryActivity extends Activity implements IWXAPIEventHandler { private IWXAPI api; Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); api WXAPIFactory.createWXAPI(this, wxd1234567890abcdef, true); api.handleIntent(getIntent(), this); } Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); api.handleIntent(intent, this); } Override public void onResp(BaseResp resp) { if (resp instanceof SendAuth.Resp) { SendAuth.Resp authResp (SendAuth.Resp) resp; String code resp.errCode 0 ? authResp.code : ; UnityPlayer.UnitySendMessage(SDKManager, OnWxAuthResult, resp.errCode | code); } finish(); } Override public void onReq(BaseReq req) { } }这段代码有几个点必须说清楚onCreate 里用 WXAPIFactory.createWXAPI 创建实例然后立刻把 Intent 交给 handleIntent 分发。onNewIntent 对应微信用 singleTask 模式把回调页从后台拉到前台的场景如果不重新 setIntent 再分发第二次及之后的回调全会丢。onResp 是真正收结果的地方授权成功时 errCode 为 0SendAuth.Resp.code 是短期有效的授权码需要发给服务端换 access_tokenerrCode 为 -2 是用户取消。AndroidManifest 里要注册这两个 Activityapplication activity android:name${applicationId}.wxapi.WXEntryActivity android:exportedtrue android:launchModesingleTask / activity android:name${applicationId}.wxapi.WXPayEntryActivity android:exportedtrue android:launchModesingleTask / /application三个关键点exportedtrue 是让微信能拉起来这个 ActivitylaunchMode 必须是 singleTask否则每次回调都会新建页面微信回到游戏时栈关系混乱路径里的 ${applicationId} 是 Android 的 manifest 占位符打包时会自动替换成你在 Player Settings 里填的包名比手写死包名安全得多。2.4 applicationId、签名和打包出口三件事一起确认微信登录、分享、支付都会校验收到的包名和签名。支付宝也一样。所以打包前把下面三件事核对清楚基本能避免一半的回调问题Player Settings 里的 applicationId 必须和开放平台后台填写的包名完全一致。最终签名证书的 MD5 必须和开放平台后台上传的签名信息一致。Unity 导出的 APK 不要做二次签名后再提交测试如果渠道方一定要重新签名要同步更新开放平台的签名信息。一个常见的误操作是在 Unity 编辑器里直接 Run 到手机Unity 默认使用 debug keystore。调试包微信授权没问题但用发布证书重新打一遍微信提示“签名校验失败”于是开始怀疑自己代码写错。这通常不是代码问题是签名不一致。3. 微信登录与微信分享的 Unity 落地从发起授权到回调回游戏3.1 初始化注册在 Unity 主线程里把 AppID 交给微信 SDK微信 SDK 使用前必须调用 registerApp。这个调用会建立一个进程内的 IWXAPI 实例后面登录、分享、支付都复用它。我把初始化放在一个常驻 GameObject 的 Awake 里通过 C# 调用 Java 桥接类完成。Java 桥接类 WxApiBridge 负责注册和发起授权package com.example.game.bridge; import android.content.Context; import com.tencent.mm.opensdk.modelmsg.SendAuth; import com.tencent.mm.opensdk.openapi.IWXAPI; import com.tencent.mm.opensdk.openapi.WXAPIFactory; public class WxApiBridge { private static IWXAPI api; private static String appId; public static void register(Context context, String id) { appId id; api WXAPIFactory.createWXAPI(context, id, true); api.registerApp(id); } public static void sendAuth() { SendAuth.Req req new SendAuth.Req(); req.scope snsapi_userinfo; req.state unity_ System.currentTimeMillis(); api.sendReq(req); } }配合的 C# 侧调用public class SdkBridge : MonoBehaviour { void Awake() { #if UNITY_ANDROID !UNITY_EDITOR using (var unityPlayer new AndroidJavaClass(com.unity3d.player.UnityPlayer)) using (var activity unityPlayer.GetStaticAndroidJavaObject(currentActivity)) using (var bridge new AndroidJavaClass(com.example.game.bridge.WxApiBridge)) { bridge.CallStatic(register, activity, wxd1234567890abcdef); } #elif UNITY_IOS WxApiIOS.Register(wxd1234567890abcdef); #endif } }这里有一个容易踩的细节C# 里不能随便 new 一个 AndroidJavaObject 当 Context 传过去。微信 SDK 的 IWXAPI 是进程内单例如果拿到的是不同的 context 包装对象会出现在“注册成功但拉起微信没反应”这种玄学问题。正确做法是通过 UnityPlayer.currentActivity 拿真实的 Activity这也是所有原生桥接的统一姿势。3.2 发起登录与处理授权回调把 code 交给服务端换 token在登录界面调用 WxApiBridge.sendAuth()手机上装了微信客户端才能拉起授权页。如果玩家没装微信常见做法是提供手机号登录作为备选不建议把所有登录入口压到微信一个渠道上。微信授权返回后WXEntryActivity 已经把结果发给了 Unity 里名为 SDKManager 的 GameObject。Unity 侧接收并解析public class SDKManager : MonoBehaviour { public void OnWxAuthResult(string msg) { string[] parts msg.Split(|); int errCode int.Parse(parts[0]); if (errCode 0) { string code parts[1]; StartCoroutine(ServerLogin(code)); } else if (errCode -2) { // 用户主动取消重置登录 UI } else { // 其他错误提示用户稍后再试 } } }拿到 code 之后不要自己直接请求微信接口应该把它发给游戏服务端。服务端拿 code AppSecret 去微信的 sns/oauth2/access_token 接口换 access_token 和 openid然后再取用户信息。这样的原因是 AppSecret 不能暴露给客户端同时服务端可以做账号绑定、风控和登录日志如果客户端直接请求微信接口一旦 AppSecret 泄露账号安全风险会立刻放大。3.3 分享的三种内容网页、图片、文本和两个目标场景微信分享的核心是 SendMessageToWX.Req里面放一个 WXMediaMessage。根据分享载体不同消息类型字段也分三种WXWebpageObject 分享网页链接WXImageObject 分享图片WXTextObject 分享纯文本。public static void shareWeb(Context context, String appId, String url, String title, String desc, Bitmap thumb) { IWXAPI api WXAPIFactory.createWXAPI(context, appId, true); WXWebpageObject webPage new WXWebpageObject(); webPage.webpageUrl url; WXMediaMessage msg new WXMediaMessage(webPage); msg.title title; msg.description desc; msg.setThumbImage(thumb); SendMessageToWX.Req req new SendMessageToWX.Req(); req.transaction web_ System.currentTimeMillis(); req.message msg; req.scene SendMessageToWX.Req.WXSceneSession; api.sendReq(req); }这里三个参数要重点说url 不能为空且必须是 http/https 开头如果域名被微信标记恶意分享出去后打开是拦截页比分享失败还伤体验缩略图 thumb 压缩后必须小于 32KB超过这个值微信会直接返回错误码表现是转圈后没反应很多团队直接把原图塞进去scene 决定分享到哪WXSceneSession 是好友会话WXSceneTimeline 是朋友圈同一份内容想两个场景都发就得构造两次 Request。分享的结果也会回到 WXEntryActivity.onResp类型是 SendMessageToWX.Resp。这个回调一般只用来关闭分享面板和埋点不需要关心玩家分享后有没有人真正打开链接。3.4 iOS 端不能漏掉的转发口AppDelegate 的 openURLiOS 和 Android 最大的区别在于所有从微信返回 App 的 URL 必须显式转给微信 SDK。Unity 导出的 Xcode 工程里主 Controller 继承自 UnityAppController需要在 application:openURL 分支里调用 [WXApi handleOpenURL:url delegate:self];。没有这一步典型症状是 Android 一切正常iOS 上登录完一直停在微信界面回不来。常见做法是直接改导出工程里的 AppDelegate.mm或者用一个 Unity iOS 插件在导出时自动注入。我一般选择后者因为每次重新导出 Xcode 工程都会覆盖 AppDelegate手动改一次就忘一次。关键是 openURL 入口必须在每次回调时都执行不能只在冷启动处理。4. 微信支付与支付宝支付客户端只负责调起收银台服务端锁定金额和订单4.1 统一下单放在服务端Unity 客户端不碰金额客户端永远不能自己传金额给支付 SDK。微信支付的标准流程是游戏服务端调用统一下单接口把商品 ID、金额、玩家 ID 传给微信/支付宝拿到一个带签名的支付凭证微信的 prepayId、支付宝的 orderString再返给客户端。客户端拿这个凭证调起收银台微信和支付宝会按凭证里锁定的金额收款。为什么必须这样因为任何客户端本地参数都能被改。只要金额由客户端传给原生 SDK玩家用抓包工具把 100 元改成 0.01 元就能完成支付。服务端下单还有个好处游戏服务器能先做库存扣减、活动校验、订单号生成从流程上保证一个订单不会被客户端重复发起支付。在模块划分上Unity 侧不要出现任何价格计算逻辑只暴露“发起支付orderInfo”这个动作。4.2 微信支付落地把服务端字段组装成 PayReq 调起收银台服务端统一下单完成后返回给客户端一般包含 appId、partnerId、prepayId、nonceStr、timeStamp、sign。Unity 拿到后交给原生桥接public static void pay(Context context, String appId, String partnerId, String prepayId, String nonceStr, String timestamp, String sign) { IWXAPI api WXAPIFactory.createWXAPI(context, appId, true); PayReq req new PayReq(); req.appId appId; req.partnerId partnerId; req.prepayId prepayId; req.packageValue SignWXPay; req.nonceStr nonceStr; req.timeStamp timestamp; req.sign sign; api.sendReq(req); }PayReq 里所有字段都必须来自服务端Unity 侧不要自己拼任何参数。packageValue 固定是字符串 “SignWXPay”它只是协议规定的包体标识真正参与验签的不是它nonceStr 和 timeStamp 都是由服务端生成并参与签名客户端替换成本地时间戳会导致微信验签失败。还有一个容易忽略的细节req.appId 必须和服务端统一下单时用的 AppID 一致。如果开放平台下有多个应用服务端用 A 应用下单客户端注册 B 应用结果就是调不起微信支付或者回调永远进不来。4.3 支付回调与到账依据客户端刷新 UI服务端异步通知发货微信支付结果回到 WXPayEntryActivity它同样要放在包名.wxapi 路径下。支付类回调和登录类似public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler { Override public void onResp(BaseResp resp) { if (resp instanceof PayResp) { PayResp payResp (PayResp) resp; UnityPlayer.UnitySendMessage(SDKManager, OnWxPayResult, resp.errCode | payResp.prepayId); } finish(); } }注意最后那个 finish()不写会导致支付页在任务栈里残留下一次拉起支付时页面栈混乱。errCode 的语义是0 表示支付成功-1 表示支付失败-2 表示用户取消。但这里要反复强调客户端的“成功”只是拿到了微信返回的支付成功事件绝不代表游戏服务端已经确认到账。真正决定发货的是微信和支付宝的服务端异步通知。异步通知由微信服务器直接发到游戏服务器的回调地址携带金额、订单号、签名服务端要验签后按通知发货。客户端回调只用来刷新 UI比如提示“支付已成功到账请稍候”。如果客户端 errCode0 就直接发道具遇到异步通知延迟或丢失就会出现扣了款没发货玩家重试又导致发货两次的血泪经验。4.4 支付宝 App 支付orderString、PayTask 与 resultStatus 的正确用法支付宝 Android 侧不像微信那样走回调 Activity而是用 PayTask 类拉起收银台。Unity 接支付宝时C# 调用原生 Javapublic static void payWithAlipay(Activity activity, String orderString) { PayTask payTask new PayTask(activity); MapString, String result payTask.payV2(orderString, true); String resultStatus result.get(resultStatus); UnityPlayer.UnitySendMessage(SDKManager, OnAlipayResult, resultStatus); }PayTask 构造参数必须是 Activity不能传 Application context否则部分机型上拉起收银台会闪退。payV2 的第二个参数 true 表示拉起收银台时显示加载进度框一般保持 true。resultStatus 中 9000 代表支付成功8000 代表正在处理中。8000 这个状态经常出现在网络抖动或风控场景游戏端不能把 8000 当成失败让玩家重复支付正确做法是提示“等待确认”然后让服务端去支付宝查询订单状态。支付宝的 orderString 是服务端调用 alipay.trade.app.pay 接口后返回的签名串它是客户端调起收银台的全部依据。out_trade_no商户订单号由服务端生成建议包含业务标识和随机码比如 wxpay_20250101_xxxx这样客户端和服务端排查订单时能一眼看出来源。客户端回调里只拿 resultStatus 更新 UI授权服务器以支付宝异步通知为唯一发货依据。5. Unity 接入微信支付宝的高频坑回调进不来、签名不匹配、材质紫红色、依赖冲突5.1 微信没反应的经典原因WXEntryActivity 没注册或包名对不上现象调用 sendAuth 或 sendReq 后微信界面一闪而过甚至完全没有反应Logcat 里出现 ActivityNotFoundException或者提示找不到 com.xxx.wxapi.WXEntryActivity。原因AndroidManifest 里没有注册回调 Activity或者注册的类名路径和当前 applicationId 不一致。Unity 玩家在 Player Settings 里改包名后manifest 里还引用旧包名是最常见的翻车姿势。解决先确认最终 applicationId再验证 Assets/Plugins/Android 下的 AndroidManifest.xml。在 Player Settings 中勾选 Custom Main Manifest 后Unity 会生成一个可编辑的 manifest 文件把 Activity 的 android:name 改成${applicationId}.wxapi.WXEntryActivity这种占位符写法这样以后改包名也不用回头改这里。改完必须重新打包验证光改编辑器配置不生效。5.2 签名校验失败为什么编辑器里正常、真机上不行以及核对的姿势现象同一套代码Unity 直接 Run 到手机微信授权正常打包后再用 Android Studio 签名或渠道商签名微信弹出“签名校验失败请确认签名信息”。原因开放平台填的签名 MD5 与最终安装包的签名不一致。直接 Run 时 Unity 默认用 debug keystore开放平台校验的是 release 签名的 MD5渠道包经过二次签名后签名信息也会变化。解决始终拿“最终要给玩家用的那个包”去核对签名。用 keytool 命令把 APK 的签名信息打出来再和微信开放平台后台“应用签名”字段逐字对比。核对方法见下一章的命令这里只提醒排查顺序凡是“三台手机两台能调起、一台不能”的怪问题先查包名、签名、AppID 三件套不要只盯代码。5.3 支付成功但游戏不出货异步通知幂等和服务端发货原则现象玩家支付成功钱包扣款了游戏内道具没到账杀掉 App 重进又到账了或者同一个订单被发货两次。原因客户端 errCode0 时直接发货而服务端异步通知还没到或者服务端处理通知时没有做幂等控制同一条通知被多次消费。玩家在支付成功后立刻杀进程客户端的回调会直接消失只有服务端通知能兜底。解决服务端只认异步通知。收到通知后先按 out_trade_no 查本地订单状态如果已经发货直接响应成功并忽略如果未处理验签通过后核对金额、订单号都一致才进入发货逻辑。客户端回调只刷新 UI。这样就算客户端重复创建订单服务端也只会成功写一次。另外在支付订单表加一个唯一索引(order_no)防止并发通知下重复插入这是最实用的一层后悔药。5.4 材质紫红、类被裁剪、混淆改名IL2CPP 面数翻车现场现象编辑器里材质颜色正常Android/iOS 真机上出现大片紫红色同时可能伴随微信回调时灵时不灵。原因紫红色是 Unity 打包时把 shader 从资源里剥离了。常见于运行时加载的材质、AssetBundle 里的 shader、或者资源没有被 Always Included Shaders 收集。微信回调失效的另一个原因是 Android 混淆当 Unity 开启 Minify 后如果 Proguard 规则没有保留 SDK 类WXEntryActivity 的类名可能被改名微信按包名.wxapi 找不到入口。解决在 Edit Project Settings Graphics 的 Always Included Shaders 中把项目用到的 Shader 都加进去尤其是 AssetBundle 动态加载的材质。同时在混淆规则中保留微信、支付宝 SDK 和 wxapi 包名。常见做法是在 Assets/Plugins/Android/proguard-user.txt 里加-keep class com.tencent.mm.opensdk.** { *; } -keep class com.yourpackage.wxapi.** { *; } -keep class com.alipay.sdk.** { *; }还有一点要专门提醒你如果搜的是“unity 微信小游戏打包”那是另一条路线。微信小游戏用的是小游戏平台的登录和支付接口AppID、初始化方式、回调域名都和原生 App 不同不要拿这里的方法去套两个方向混用会卡审核。5.5 AndroidX 与依赖冲突微信支付宝一起进包时的版本债现象打包时 Java 编译报 “Duplicate class com.alipay.sdk...”或者 manifest merge 报冲突再或者编译通过但运行时 ClassNotFoundException。原因Unity 工程里不止一份支付宝/微信 SDK。比如旧版广告插件内置了一份老支付宝 SDK你又按文档放进了一个新版本或者支付宝 SDK 依赖 AndroidX而工程同时引入了一个旧版 support 库编译期就炸。解决优先清理 Assets/Plugins/Android 下的重复 aar/jar。把明显重复的旧版本删除保留一个即可。如果工程本身特别复杂用 Unity 的 External Dependency Manager 统一管理依赖版本让 Gradle 去解析传递依赖。注意一点不要同时“本地 aar Gradle 远程依赖”双轨制那是在制造新坑。6. 上线验证一条命令核对签名一个真机清单跑完整链路四件套接完后真正影响上线的是签名、回调、服务端通知这几条链路。我习惯在提审前做三层验证可以直接抄。第一层是静态检查。用 keytool 核对最终包的签名信息keytool -printcert -jarfile game-release.apk | grep -E MD5|SHA1把输出的 MD5 和微信开放平台后台的“应用签名”字段比对。再用 aapt 确认回调 Activity 被打进了包aapt dump xmltree game-release.apk AndroidManifest.xml | grep -i wxapi第二层是真机闭环。准备两台不同品牌的 Android 手机跑“微信登录、切后台再回来、微信分享、微信支付、支付宝支付”五个动作。重点关注微信支付后回到游戏的那一瞬间有没有卡死或白屏支付宝回跳到游戏时Unity 主线程是否报异常。这类问题多半是回调被放到了子线程处理需要放到主线程。第三层是流量侧验证。用抓包工具看客户端到游戏服务端的请求确认客户端只在支付时把 prepayId 或 orderString 发给游戏服请求里没有金额字段更没有 AppSecret 或应用私钥。服务端日志里对比下单时间和异步通知到达时间超过 5 分钟计入告警。上线之前我会把 Debug.Log 全部关掉日志里也不要带 prepayId 和大串签名值方便出问题时截图定位但又不至于被玩家拿去分析。我自己的习惯是接完这四个 SDK 后先把支付查询接口的管理后台入口做好因为“支付状态停在支付中”的咨询量比想象中大得多。提前把对账接口配好线上出问题时你能自己查不用等玩家反馈。希望这条验证路径能帮你少踩几次支付和登录的坑让玩家少等几秒到账。本文还有配套的精品资源点击获取