Unity接入微信与支付宝SDK:从原理到实战的完整指南
简介面向Unity开发者的微信与支付宝SDK接入资源包完整覆盖微信登录、微信分享、微信支付及支付宝支付四大场景适合需要在Android/iOS游戏中快速集成社交与支付能力的团队使用。资源包共7322个文件压缩后约464.91MB以C#脚本、DLL动态库、Bin数据文件为主体同时包含Java/AAR原生适配文件、编辑器配置与Meta标记能够支撑IL2CPP及多平台构建环境下的工程整合。已有2236人学习下载参考热度良好。从内容构成看内含大量可直接复用的SDK接入脚本、平台配置文件和回调处理示例可帮助开发者减少重复造轮子理解支付结果验证、分享场景调起、登录凭证交换等关键流程并规避常见平台兼容与签名校验问题从而更快完成联调上线。1. 为什么Unity接微信和支付宝SDK这么折腾做Unity游戏和应用的开发者迟早都要面对第三方SDK接入这关。微信登录、微信分享、微信支付、支付宝SDK这四个能力是国内安卓和iOS应用绕不开的基础设施尤其是做社交、工具、电商类产品缺一个都难受。我最早在项目里接这些的时候光是把微信SDK跑通就花了两三天不是因为文档多难读而是官方文档对Unity的适配说得含糊其辞很多坑都是自己踩出来的。这套东西本质上是原生SDK通过Unity的AndroidJavaObject / AndroidJavaClass 或者 iOS 的 Objective-C 桥接层去调用。也就是说Unity项目里不能直接引用微信的Android SDK类而是要通过反射机制或者封装好的C#插件去访问Java层。iOS端则是在Xcode工程里通过UnityFramework的桥接头文件暴露方法给C#调用。理解了这一点后面所有配置才有意义。这篇内容适合谁看凡是Unity项目需要在国内安卓和iOS渠道上线并且要接微信生态和支付宝能力的开发者都能直接用上。阅读过程中我会把每个环节的配置项、代码要点、常见坑都拆开讲尽量做到你照着操作就能跑通。2. 接入前的准备工作AppID、密钥与平台配置2.1 微信开放平台和支付宝开放平台的账号申请微信登录、分享、支付这三个能力都需要在微信开放平台不是微信公众平台创建移动应用审核通过后拿到AppID和AppSecret。iOS和安卓要分别填Bundle ID和包名注意签名一定要拿正式签名的MD5值去填测试签名和正式签名不一致的话登录和支付会直接回调失败这种问题排查起来特别折磨人。支付宝相对简单在支付宝开放平台创建应用签约支付产品拿到支付宝公钥、应用私钥、APPID这三件套。支付宝的密钥用RSA2算法生成工具在开放平台后台可以直接下载在线生成后要把公钥上传到平台私钥保存在本地用于请求签名。这里有个常见误区SDK验签用的支付宝公钥和后台上传的应用公钥不是同一个别搞混。2.2 Unity工程的安卓导出配置Unity接安卓SDK推荐的方式是直接导出Gradle工程而不是导出AAR。原因很简单微信和支付宝的SDK都依赖AndroidX库如果Unity版本较老默认的Android Support Library会和新SDK冲突。用Gradle工程你可以在build.gradle里手动调整依赖版本避免一堆莫名其妙的构建错误。Unity版本建议用2019.4 LTS以上安卓导出模块勾选SDK和NDK。微信SDK推荐用官方最新的版本Android Studio里新建的模块把wechat-sdk-android-xxx.aar复制到libs目录下。支付宝SDK同样也是一股脑丢进libs。然后在settings.gradle和build.gradle里配置好仓库地址allprojects { repositories { google() mavenCentral() flatDir { dirs libs } } }这一步的目的是让Gradle能把libs目录下的AAR包当依赖解析不配置的话就算你把文件放进去也一样报找不到包。2.3 iOS端的初始配置iOS端微信SDK是通过CocoaPods安装或者手动拖入。如果是手动拖入必须把SDK的静态库文件和Resource bundle都加进Unity导出的Xcode工程里然后在Build Settings中设置Other Linker Flags为-ObjC。这一步不设置的话调用微信方法时会直接崩溃报unrecognized selector错误。支付宝iOS SDK也是类似流程把AlipaySDK.framework拖进去然后在Build Phases里确保Embed Frameworks。iOS端的URL Scheme配置同样重要微信和支付宝的回调都靠它唤醒App。3. 微信登录接入实操C#层到底写了什么3.1 安卓端Java桥接类编写与AndroidManifest配置微信登录在安卓端需要注册一个WXEntryActivity作为回调入口。这个Activity必须放在应用包名下的wxapi目录里也就是说如果你的包名是com.example.game那么WXEntryActivity的路径必须是com.example.game.wxapi.WXEntryActivity。这个包名路径是硬性的改动任何一部分都收不到微信的回调。用Android Studio建一个Module作为Unity插件写一个Java类里面封装微信SDK的核心方法。比如初始化public class WeChatBridge { private static IWXAPI wxApi; public static void init(Context context, String appId) { wxApi WXAPIFactory.createWXAPI(context, appId, true); wxApi.registerApp(appId); } public static void login() { SendAuth.Req req new SendAuth.Req(); req.scope snsapi_userinfo; req.state unity_login; wxApi.sendReq(req); } }Unity C#端就通过AndroidJavaClass去调用这些静态方法using UnityEngine; public class WeChatBridge : MonoBehaviour { private static readonly AndroidJavaClass wechatBridgeClass new AndroidJavaClass(com.example.game.WeChatBridge); public static void Init(string appId) { AndroidJavaClass unityPlayer new AndroidJavaClass(com.unity3d.player.UnityPlayer); AndroidJavaObject activity unityPlayer.GetStaticAndroidJavaObject(currentActivity); wechatBridgeClass.CallStatic(init, activity, appId); } public static void Login() { wechatBridgeClass.CallStatic(login); } }这里要特别注意微信SDK的初始化必须在主线程中执行如果Unity的Start方法里调用没问题但如果在非主线程的异步回调里初始化会直接抛异常。3.2 iOS端桥接从GameObject到UnitySendMessageiOS端的微信登录需要把SDK的回调事件传递回Unity。在Unity的AppController或UnityAppController子类中注册微信SDK后当SDK回调登录结果时用UnitySendMessage方法传给场景里的某个GameObject- (void)onResp:(BaseResp *)resp { if ([resp isKindOfClass:[SendAuthResp class]]) { SendAuthResp *authResp (SendAuthResp *)resp; NSString *code authResp.code; NSString *message [NSString stringWithFormat:%|%d, code, authResp.errCode]; UnitySendMessage(WeChatManager, OnLoginCallback, [message UTF8String]); } }C#端只需要定义一个带字符串参数的公共方法即可public void OnLoginCallback(string result) { string[] parts result.Split(|); string code parts[0]; int errCode int.Parse(parts[1]); if (errCode 0) { // 拿code去后端换取access_token和用户信息 StartCoroutine(ExchangeAccessToken(code)); } }这里的关键点在于微信登录返回给客户端的是临时授权code真正获取用户信息openid、昵称、头像必须在服务端调用接口完成。客户端拿code去请求资源就等于把AppSecret暴露给了所有能抓包的人这是极其不安全的做法。我在前一个项目里见过把AppSecret写在客户端拿去换token的上线没几天账号就被别人盗刷了。3.3 登录状态回调与生命周期管理登录完成后微信SDK会通过WXEntryActivity的onResp方法回调。Unity端的GameObject必须在场景加载时保持常驻并且方法名要和原生层SendMessage的目标完全一致。C#方法签名需要注意大小写敏感Unreal里因为大小写匹配不上导致回调丢失的情况很常见Unity的坑其实是一样的。另一个细节是安卓的Activity在微信跳转回来时可能被系统杀掉重建。所以Unity场景中负责接受消息的GameObject建议用DontDestroyOnLoad挂载否则微信授权页面跳转回来后游戏场景重新加载GameObject被销毁回调就没人接了。4. 微信分享从分享文本到分享图片链接4.1 原生层分享接口封装微信分享在Unity端比登录好接得多因为不涉及Activity跳转的回调注册只是发送一个请求就够了。安卓端的Java类里封装一个分享方法public static void shareWebPage(String title, String description, String url, String thumbPath) { WXWebpageObject webpage new WXWebpageObject(); webpage.webpageUrl url; WXMediaMessage message new WXMediaMessage(); message.title title; message.description description; message.mediaObject webpage; message.thumbData getThumbData(thumbPath); // 压缩到32KB以内的缩略图 SendMessageToWX.Req req new SendMessageToWX.Req(); req.transaction webpage System.currentTimeMillis(); req.message message; req.scene SendMessageToWX.Req.WXSceneSession; // 好友会话 wxApi.sendReq(req); }缩略图这个点特别值得注意微信要求thumbData在32KB以内超过这个值就直接分享失败。很多人在Unity端传原图路径进去结果一分享就报错。解决办法是在Java层用BitmapFactory解码后压缩或者干脆在Unity端就先把图片缩成一个256x256的Texture2D再转成byte[]传过去。4.2 iOS分享与SceneTypeiOS端微信分享的逻辑相似但参数类型和设置方式有些不同。用WXMediaMessage创建消息对象webpageObject设置网页地址然后构建SendMessageToWXReq请求scene字段选择WXSceneSession、WXSceneTimeline或WXSceneFavorite。iOS分享还有一个坑如果要分享缩略图需要通过UIImage的SDK方法将图片缩略到合适尺寸再把图片转成NSData最后设置到message.thumbData。这里图片必须是JPEG或PNG格式否则微信识别不了。4.3 UI层与业务层解耦Unity端建议把分享逻辑封装到一个独立的类中UI按钮只负责调接口不关心具体平台。用#if UNITY_ANDROID和#if UNITY_IOS进行平台分支判断这样代码结构清晰后续想加分享到朋友圈、收藏等场景也只是在多传一个Int参数的问题。分享回调处理的方式和登录有差异登录和支付需要Activity接收回调分享如果只是发请求可以不关心结果。但如果你需要知道用户是否成功分享比如做邀请奖励活动那也必须注册回调Activity在onResp里返回errCode为0即成功-2表示用户取消。5. 微信支付接入服务端下单与客户端拉起收银台5.1 Unity端应该如何与后端配合微信支付的正确流程是客户端发起下单请求 - 服务端调用微信统一下单接口 - 拿到prepay_id - 服务端生成二次签名 - 返回给客户端 - 客户端调起微信收银台。客户端绝对不能自己拿着AppID和商户号去请求统一下单原因和登录一样密钥在客户端就是透明的。服务端返回给Unity的数据一般包括appId、partnerId、prepayId、nonceStr、timeStamp、sign这六个字段。Unity端把这六个字段传给原生SDK再由原生的pay方法调起收银台。5.2 安卓端支付代码public static void pay(String appId, String partnerId, String prepayId, String nonceStr, String timeStamp, String sign) { PayReq request new PayReq(); request.appId appId; request.partnerId partnerId; request.prepayId prepayId; request.packageValue SignWXPay; request.nonceStr nonceStr; request.timeStamp timeStamp; request.sign sign; wxApi.sendReq(request); }注意packageValue这个字段不能动必须是那个字符串。timeStamp在微信支付SDK中就是字符串类型不需要转成long再拼回String直接传就好。5.3 支付回调处理与状态校验支付结果通过WXEntryActivity的onResp回调到Unity层。errCode为0表示支付成功-2表示用户取消其他值为失败。但这里有一个重要的原则客户端收到成功回调后只能用来刷新UI真正的订单判定必须依赖服务端回调通知和查询接口。因为客户端回调是可以被篡改和模拟的。实现上推荐在支付成功后除了UI提示立即调服务端的订单查询接口以服务端返回的状态为准。如果服务端显示未支付客户端要给出对应提示而不是直接发奖。6. 支付宝SDK接入更简单的流程与更隐蔽的坑6.1 安卓端接入与Unity转调支付宝SDK比微信清爽不少客户端不需要注册回调Activity只要在点击支付时把服务端拼装好的orderString传给支付宝SDK即可。安卓端的桥接代码public class AlipayBridge { public static void pay(final Activity activity, final String orderInfo, final String callbackObjectName) { final Runnable payRunnable new Runnable() { Override public void run() { PayTask alipay new PayTask(activity); MapString, String result alipay.payV2(orderInfo, true); final String resultStatus result.get(resultStatus); activity.runOnUiThread(new Runnable() { Override public void run() { // 通过UnitySendMessage回调给C# } }); } }; Thread payThread new Thread(payRunnable); payThread.start(); } }支付宝的PayTask调用必须在子线程中执行这是很多Unity开发者第一次接的时候踩得最狠的坑——在主线程直接调界面会卡死严重时直接ANR。6.2 iOS端接入与URL SchemeiOS端支付宝SDK的接入主要是在AppDelegate的openURL回调里处理支付结果通过[AlipaySDK defaultService] processOrderWithPaymentResult:standbyCallback:方法解析结果。Unity层需要把回调结果传给C#侧。支付宝iOS的URL Scheme建议配置为alipay加上你的AppID前缀比如alipay2024000000000000确保唯一避免与其他App冲突。6.3 服务端签名与客户端验签的边界支付宝支付流程里orderString是服务端用支付宝私钥对业务参数签名后生成的字符串。客户端不参与签名但可以在收到支付宝回调结果后用支付宝公钥对结果做验签。这样做可以防止结果被第三方篡改。不过在Unity端验签逻辑一般不写在客户端因为公钥虽然在客户端不至于太敏感但防篡改的核心还是依赖服务端二次确认。7. 常见问题与排查技巧实录7.1 问题速查表现象可能原因解决方案微信登录无响应未在开放平台配置正确签名检查签名MD5是否与正式签名一致用微信官方签名获取工具验证登录回调收不到WXEntryActivity路径错误确保Activity位于包名.wxapi目录下且在AndroidManifest中声明微信分享图片失败缩略图超过32KB对缩略图做压缩处理控制在32KB以内支付返回-1签名错误或参数不完整核对服务端返回的签名字段与prepayId是否一致支付宝ANRPayTask在主线程执行放到子线程中调用payV2iOS编译报错找不到微信类缺少-ObjC标志Build Settings Other Linker Flags 添加-ObjCUnity场景切换后回调丢失接收消息的GameObject被销毁用DontDestroyOnLoad保留常驻节点7.2 调试经验分享调试微信SDK最痛苦的地方在于看不到底层日志。我的做法是写一个DebugLog工具类在Java层的onResp回调里把返回的errCode和errStr通过UnitySendMessage传给C#再在Unity的Console中打出来。这样一次联调就能看到完整链路省去反复查日志的烦恼。支付宝那边相对友好PayTask返回的resultStatus字段含义很清晰9000表示成功8000表示支付宝正在处理中6001表示用户取消4000表示订单支付失败。出现非9000的状态码时先别急着改代码去服务端查一下订单详情很多时候是签名参数被篡改或者订单已过期。7.3 一些比SDK接入本身更重要的事我在多个项目里做过一个相似的优化把第三方SDK的初始化全部延迟到首帧渲染之后再执行。原因很简单微信SDK初始化可能需要几毫秒到几十毫秒不等如果放在启动流程的前几步在低端安卓机上会明显拖慢首屏打开速度。而支付宝SDK初始化更重反而建议尽早初始化因为它的首次支付调用有个额外的网络握手流程。另外一个容易被忽视的点是在安卓上切换应用回来后Unity的OnApplicationPause会被调用。很多开发者在这个回调里只处理游戏暂停逻辑忘记把微信/支付宝的跳转返回状态同步给SDK。虽然现代SDK一般自带了Activity生命周期监听但如果你用的版本较老最好在OnApplicationPause参数为false时主动调用SDK的onResume接口避免支付完成后状态不同步。8. 我的最终实践体会走了这么一大圈我的感受是Unity接微信和支付宝SDK这件事本身难度不高高的是对原生生态的理解。如果你之前只写过纯C#逻辑第一次看到AndroidJavaObject和UnitySendMessage会非常不适应但这两个机制就是Unity和原生世界对话的全部桥梁。接入过程中最重要的习惯是把原生层的每个入口封装得足够小、足够单一。不要写一个巨大的Java类把所有API都塞进去也不要让Unity层直接依赖iOS的实现细节。把登录、分享、支付拆成三个独立的模块文件每个模块的C#接口保持一致这样将来无论是换SDK版本还是加新渠道都不至于动到游戏逻辑层的代码。还有一点SDK升级要极其谨慎。微信SDK和支付宝SDK的版本更新频率虽然不高但每次更新都可能改变回调的线程模型或回调参数的格式。升级前一定要看官方更新日志升级后在真机上完整跑一遍登录、分享、支付全流程不要只看编译能不能通过。我吃过一次亏微信SDK从5.x升到6.x后旧的WXEntryActivity回调线程变了原来的UI操作直接崩溃排查了很久才发现是SDK行为变化导致的。最后再分享一个实用技巧在Unity工程的Assets目录下建一个Editor文件夹写一个简单的菜单脚本一键打开微信和支付宝的开放平台配置页面、一键生成签名MD5等这些日常重复操作自动化之后效率能提升不少。看起来是小事但真正在联调阶段不断切换配置、重打签名、查看AppID的时候这种微小的效率提升会带来非常大的体验差异。本文还有配套的精品资源点击获取