简介面向 Unity 开发者的微信/支付宝 SDK 集成资源包主要解决 Unity 项目中接入微信登录、微信分享、微信支付和支付宝支付的需求适合需要快速落地第三方账号体系与支付能力的游戏和应用开发者。压缩包为 rar 格式约 464.91MB共包含 7322 个文件其中 3004 个 C# 脚本负责逻辑调用114 个 dll、13 个 aar、12 个 jar、23 个 java 等组成平台原生依赖另有大量 meta、asset、prefab、unity 文件用于工程配置并配备 553 个 info 说明文件整体是一个可导入的完整集成示例。资源给出了登录接口调用、分享场景构造、支付订单发起与结果回调处理的关键代码同时包含支付宝支付参数组织与订单返回解析逻辑能帮助开发者理解 Unity 接入微信与支付宝的步骤、平台差异和常见异常处理。已有 2245 人学习下载对于正在接入第三方登录和支付的 Unity 团队有直接参考价值。1. 先把三件套的坑说在前面一个Unity手游要上渠道提审绕不开微信登录、微信分享、微信支付、支付宝SDK这四件事。C#侧写调用并不难难的是这几个SDK都要求你在iOS和Android两侧把包名、签名、回调域名、URL Scheme对得严丝合缝任何一处对不上表现就是“点击没反应”或者“从微信返回后回调丢失”的玄学问题。这篇直接把接入链路拆开先讲接入前必须卡死的资质和签名再给一套统一桥接层的C#写法接着把支付流程和服务端验单讲透最后列几条最常见的翻车记录。适合正在给移动Unity项目接渠道SDK的开发者尤其是被两端文档绕晕、被回调折磨过的人。2. 接入前先卡三道门槛资质、签名、包名对齐2.1 微信与支付宝开放平台账户、应用、签约缺一不可很多人拿到Unity项目第一件事就是下载SDK、写代码结果卡在资质审核上。微信侧需要先在开放平台创建移动应用拿到AppID再准备应用签名Android和Bundle IDiOS。支付宝侧需要创建应用并签约“App支付”产品同时生成RSA2密钥对。这些步骤必须在写代码之前完成因为SDK初始化和调起都依赖这些参数。常见做法是先用测试参数把代码跑通再提交资质审核。但这里有个时间差问题——微信开放平台的移动应用审核通常需要几天而支付宝的签约也可能要求补充材料。我的习惯是开工第一天就把开放平台申请提交代码写到一半时资质正好下来两边不耽误。平台要准备的材料最容易错的地方微信开放平台AppID、应用签名Android、Bundle ID与Universal LinksiOS签名工具生成的MD5和平台填的不一致支付宝开放平台AppID、RSA2密钥对、App支付签约公钥粘贴时少了几行导致验签一直失败2.2 包名、签名、回调Scheme三处对不齐就是点击无反应微信SDK在Android端校验的是“包名 应用签名”这个组合。Unity默认包名是com.Company.ProductName如果你在开放平台填的包名和最终打包的包名不一致SDK会直接拒绝服务。我踩过的坑是开发时用debug签名跑通了登录上架前切到release签名微信登录立刻失效因为两个签名的MD5完全不同。iOS侧主要看三样Bundle ID、URL Scheme、Universal Links。微信SDK要求App注册一个URL Scheme通常是AppID本身用于从微信跳回App同时要求配置Universal Links用于iOS 9以后的回调。支付宝iOS也要求URL Scheme一般叫alipay开头或自定义的scheme。这三处配置需要记录在一张表里随时可以核对。配置项AndroidiOS包名 / Bundle ID开放平台、Gradle、AndroidManifest三处一致开放平台、Xcode、Unity PlayerSettings一致签名正式签名的MD5填入开放平台不需要单独填签名回调Scheme不需要用WXEntryActivityURL Types里加微信AppID回调查询AndroidManifest注册ActivityLSApplicationQueriesSchemes加weixin2.3 统一桥接层在C#侧留一个入口避免双端代码散落Unity工程里直接调微信SDK有两种路径Android用AndroidJavaObject反射调用Java层代码iOS用DllImport绑定原生C方法。如果每次调用都写一套平台判断代码会散得到处都是。我一般会在C#侧做一个静态类把所有涉及微信和支付宝的入口都收拢到这里。public static class SdkBridge { public static void InitWeChat(string appId, string universalLink) { #if UNITY_ANDROID !UNITY_EDITOR using (var player new AndroidJavaClass(com.unity3d.player.UnityPlayer)) { var activity player.GetStaticAndroidJavaObject(currentActivity); activity.Call(initWeChat, appId); } #elif UNITY_IOS !UNITY_EDITOR _InitWeChat(appId, universalLink); #endif } #if UNITY_IOS !UNITY_EDITOR [System.Runtime.InteropServices.DllImport(__Internal)] private static extern void _InitWeChat(string appId, string universalLink); #endif }这段代码的逻辑是在Android平台取UnityPlayer的currentActivity调用原生桥接类里的initWeChat方法在iOS平台走DllImport绑定Xcode工程里的Objective-C方法。两个平台共用同一个C#入口业务层只关心appId和universalLink这两个参数。universalLink只在iOS用Android传空字符串即可。参数说明appId来自微信开放平台universalLink是你在Apple Developer后台配置的域名格式类似https://example.com/app/。Android的initWeChat方法里不需要传universalLink但iOS必须传否则注册回调收不到。3. 微信登录与分享WXApi初始化、scope与回调桥接3.1 初始化WXApi时机、AppID与Universal Links初始化这一步决定了后面所有操作能不能回调。Android侧需要在主Activity的onCreate里调用IWXAPI.registerAppUnity里就通过AndroidJavaObject在生命周期合适的时机调用。iOS侧在didFinishLaunchingWithOptions里调用registerApp并传入Universal Links。一个容易忽略的点初始化要在主线程执行但不要放在Unity场景里某个脚本的Awake最前面因为SDK内部可能还没准备好。我一般放在启动场景的Start里延迟一帧再执行或者放在一个专门的启动管理脚本里统一控制。IEnumerator Start() { yield return null; // 等一帧确保SDK初始化环境就绪 SdkBridge.InitWeChat(wx1234567890abcdef, https://example.com/app/); }延迟一帧的目的是避开Unity引擎初始化高峰期。如果你在Awake里执行某些Android机型上会出现registerApp成功但后续调起微信时无法回调的情况。注意调用时机不是越早越好而是要保证SDK的依赖已经被正确加载。3.2 登录请求scope、state与code换token的边界微信登录的核心是发起一个AuthReq携带scope和state两个参数。scope决定你能拿到什么用户信息snsapi_userinfo可以拿用户头像昵称snsapi_base只能拿openid。state是防CSRF的随机字符串发起时生成并保存回调时校验。public static void LoginWeChat() { string state System.Guid.NewGuid().ToString(N); PlayerPrefs.SetString(wechat_auth_state, state); #if UNITY_ANDROID !UNITY_EDITOR using (var player new AndroidJavaClass(com.unity3d.player.UnityPlayer)) { var activity player.GetStaticAndroidJavaObject(currentActivity); activity.Call(sendAuthRequest, snsapi_userinfo, state); } #elif UNITY_IOS !UNITY_EDITOR _SendAuthRequest(snsapi_userinfo, state); #endif }state参数有两个作用防止第三方伪造回调以及回调回来后校验是不是自己发起的请求。我从登录发起时就把它存到PlayerPrefs回调里取出来比对不一致就丢弃。code是一次性的换取access_token必须在服务端完成客户端不持有多余凭证。这里有个边界要注意code有效期很短一般几分钟。如果你在客户端等太久才把code发给服务端换取就会失败。登录回调回来后应该立即把code通过自己的网络层传给服务端不要在客户端做缓存。3.3 分享消息构造网页分享和缩略图尺寸的硬限制微信分享的消息体是WXMediaMessage不同类型对应不同mediaObject。最常用的是网页分享需要传webpageUrl、title、description和缩略图。缩略图有硬性大小限制文档要求32KB以内我实际压到20KB以下更稳妥因为大图在部分机型上会直接分享失败。public static void ShareWebPage(string url, string title, string desc, byte[] thumbImage) { #if UNITY_ANDROID !UNITY_EDITOR using (var player new AndroidJavaClass(com.unity3d.player.UnityPlayer)) { var activity player.GetStaticAndroidJavaObject(currentActivity); activity.Call(shareWebPage, url, title, desc, thumbImage); } #elif UNITY_IOS !UNITY_EDITOR _ShareWebPage(url, title, desc, thumbImage); #endif }thumbImage是压缩后的缩略图字节数组不要在C#侧做Texture2D.EncodeToPNG直接塞给原生层因为PNG通常超过限制。建议先缩放到120像素左右再压缩成JPG体积小且清晰度足够。分享回调同样走onResp其中errCode为0表示用户完成分享-2表示用户取消-1表示失败。4. 微信支付与支付宝SDK客户端唤起与服务端验单的完整链路4.1 支付共性统一下单在服务端客户端只做唤起支付和登录分享最大的不同是客户端永远不要自己拼订单、自己签名。微信支付的标准流程是服务端调用统一下单API拿到prepayId再生成签名参数返回给客户端支付宝的标准流程是服务端用RSA2私钥生成orderString返回给客户端。客户端只负责拿这些参数唤起收银台。支付维度微信支付支付宝SDK下单方业务服务端调统一下单API业务服务端签orderString客户端任务用prepayId构造PayReq用orderString调起支付宝本地结果码WXApi回调的errCoderesultStatus业务确认服务端异步通知 订单查询服务端异步通知 订单查询这张表是整个支付接入的骨架。两条链路都遵守同一个原则客户端返回的只是“支付流程结束”的信号不是“钱到账”的凭证。4.2 微信支付PayReq参数从哪来C#怎么传服务端返回的支付参数一般有partnerId、prepayId、nonceStr、timeStamp和sign这五个字段。客户端拿到后构造PayReq并调用微信支付接口唤起微信客户端完成支付。public static void PayWeChat( string partnerId, string prepayId, string nonceStr, long timeStamp, string sign) { #if UNITY_ANDROID !UNITY_EDITOR using (var player new AndroidJavaClass(com.unity3d.player.UnityPlayer)) { var activity player.GetStaticAndroidJavaObject(currentActivity); activity.Call(payWeChat, partnerId, prepayId, nonceStr, timeStamp, sign); } #elif UNITY_IOS !UNITY_EDITOR _PayWeChat(partnerId, prepayId, nonceStr, timeStamp, sign); #endif }参数说明partnerId是商户号prepayId是统一下单返回的预支付会话标识nonceStr是随机字符串timeStamp是Unix时间戳秒级sign是服务端生成的签名。这些参数不能由客户端自己构造否则支付调起会报签名错误。如果服务端把参数生成逻辑放在客户端这本身就是安全隐患。常见现象是客户端调起微信后显示“支付验证失败”多半是sign不对或prepayId已经过期。prepayId有效期一般是两小时但实际建议拿到后立即唤起支付。另外timeStamp一定要用服务端返回的值不要用客户端当前时间两边时钟如果有偏移会导致验签失败。4.3 支付宝支付orderString与resultStatus支付宝的客户端接入比微信简单一些核心是把服务端签好的orderString传给支付宝SDK然后处理resultStatus结果码。public static void PayAlipay(string orderString) { #if UNITY_ANDROID !UNITY_EDITOR using (var player new AndroidJavaClass(com.unity3d.player.UnityPlayer)) { var activity player.GetStaticAndroidJavaObject(currentActivity); activity.Call(payAlipay, orderString); } #elif UNITY_IOS !UNITY_EDITOR _PayAlipay(orderString); #endif }orderString是服务端生成的包含订单信息和签名的完整字符串客户端原样传给SDK即可不要做任何拼接或修改。支付宝的resultStatus有意义的结果码有几个9000表示支付成功8000表示支付结果确认中6001表示用户中途取消6002表示网络连接失败6004表示支付结果未知。支付结果确认中和未知这两个状态最容易引起误判。8000和6004不代表失败可能支付已经成功但客户端没收到确认。遇到这两种情况正确做法是提示用户“支付处理中”然后去服务端查询订单状态而不是直接显示失败。4.4 回调显示与入账是两回事9000不等于钱到账这句值得反复强调无论微信还是支付宝客户端拿到的成功结果都只是SDK层面的回调不是资金到账凭证。真正能入账的依据是服务端收到的异步通知这个通知经过签名验证后才能更新订单状态。血泪经验是有一类订单客户端显示成功但服务端没有异步通知常见原因是服务端通知地址不可达、验签失败或通知重试机制没配好。客户端可以做的是显示支付结果时多加一句“支付结果以订单查询为准”并且在支付回调回来后主动向服务端查询一次订单状态。5. 常见问题与排查五条真实踩坑记录5.1 微信调不起初始化成功但后续请求都无响应现象registerApp没有报错但点击登录或支付时微信客户端没有弹出也没有任何回调。原因最常见的是开放平台填写的应用签名和实际打包签名不一致其次是Android包名和开放平台填写的包名不一致。iOS侧则是Universal Links没配对或没在微信开放平台配置。解决先在微信开放平台后台核对包名和应用签名。Android的签名MD5可以通过签名工具或命令行生成和后台填的一一对比。iOS确认Apple Developer后台的Associated Domains和微信开放平台填写的Universal Links是同一个域名。5.2 Android一调微信就崩NoClassDefFoundError现象点击微信登录或分享后进程直接崩溃日志里出现NoClassDefFoundError。原因微信SDK要求的Activity没有在AndroidManifest里注册或者混淆规则把SDK里的类给混淆掉了。Unity导出的工程默认有AndroidManifest但如果用自定义Manifest时漏掉了微信的Activity就会在调起时找不到类。解决在AndroidManifest里确认WXEntryActivity和WXPayEntryActivity的配置它们必须放在“你的包名.wxapi”这个包路径下。混淆规则里保留微信SDK的类常见做法是加一行keep住整个SDK的包。5.3 iOS从微信返回后回调丢失回到App但OnResp不触发现象微信页面正常弹出支付或登录完成后跳回App但C#侧的回调事件完全没有触发。原因iOS的URL Types里没有配置微信AppID作为Scheme或者LSApplicationQueriesSchemes里缺少weixin。SDK发起请求后没有合法的路径回到App回调和App断开了。解决在Info.plist里增加URL Types填上微信的AppID同时确认LSApplicationQueriesSchemes包含weixin。支付宝也有类似机制需要配置和App绑定的Scheme否则支付完成回不来。5.4 支付显示成功但服务端没收到钱现象客户端弹出支付成功但订单状态一直是未支付用户反馈钱扣了。原因客户端只能确认支付流程走完服务端异步通知可能因为回调地址不可达、签名验证失败或网络策略拦截而丢失。部分机型的支付宝resultStatus返回9000但服务端查询订单实际是未支付。解决客户端支付回调回来后再向服务端查询一次订单状态以查询结果展示给用户。服务端需要确保异步通知地址公网可达验签通过后返回成功应答并在没有收到通知时主动调用订单查询接口补单。5.5 回调重复触发事件重复订阅导致逻辑执行多次现象一次支付成功C#侧的事件处理函数执行了两三次导致弹窗重复、道具发放多次。原因原生层的onResp每次跳回都会调用UnitySendMessage发送到同一个GameObject上如果这个GameObject上的脚本在不同场景里被多次挂载或者事件总线里重复注册了监听就会执行多次。解决在C#侧的事件总线做成单例注册时先注销再注册原生层在回调里加一个防重标记同一个请求的回调只发送一次。道具发放逻辑必须加幂等判断服务端以订单号为准重复回调不重复发货。6. 接完以后我建议你这样验证和收尾接入完成不等于能用。我习惯按一套固定顺序验收真机双端跑通登录、分享、支付三条链路每一条都从冷启动开始杀进程后重新打开App再点一次支付链路还要测弱网环境断开WiFi切4G看结果码是否正常最后检查从微信或支付宝返回App时回调是否丢失。验证时不要只看“成功”路径。至少要测三次取消操作微信登录点返回、支付时取消、分享时关闭微信确认取消时回调能正确触发业务逻辑不卡死。沙箱环境可以帮你把流程跑通但要注意沙箱参数和正式参数的签名体系不同上线前必须在正式参数下完整回归一遍。一个建议把回调事件全部收到C#侧的统一事件总线里。这样不只是支付、登录、分享的代码好维护以后接数据统计、订单埋点、用户行为分析时直接从总线里取事件转发即可。另一个习惯维护一张环境配置表记录AppID、包名、应用签名、URL Scheme、Universal Links、服务端下单地址。每次换环境、换包名、换域名先改表再改代码。有一次因为改了回调域名忘了同步Universal Links上线当天登录全挂排查了一下午。这张表后来一直陪着我。希望帮到你。本文还有配套的精品资源点击获取