Unity接入微信支付SDK 2022年版安卓篇
最近1年转了UE开发,博客更新的比较少,技术栈宽了不少,以后有空尽量多更新,也方便总结记忆
Unity接入微信支付整个过程坑比较多,网上之前的教程要么比较老,要么比较零碎,只能东拼西凑摸索,跑通后还是总结记录下吧
开发环境,Windows11,Unity2020.3.24f1c2,Android Studio2021.2.1 Patch2
1.注册微信开放平台,注册应用,申请微信支付,来获取调取SDK的必要参数,此处不展开了(https://open.weixin.qq.com/)
2.确保开发环境装好,jdk,sdk等,Unity的安卓环境可以用Unity Hub自带的装好,也可以用全局环境变量的
3.Android Studio端的开发,导出aar
新建工程
设置包名,注意要和unity工程的包名一致
切换到Project视图,新建module,要选择Android Library
保持包名一致
需要将微信的库和Unity(微信支付成功后需要安卓端主动通知Unity端)的库都加入到工程中的lib文件夹中
Unity的库在这个位置,classes.jar文件,根据自己的需求来选择il2cpp还是mono,release还是dev,一共四种
将Unity的库照图右键添加到gradle配置中
新版的classes.jar文件里不包含UnityPlayerActivity类,需要从你编辑器的这个路径里Editor\2020.3.24f1c2\Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player拷贝出UnityPlayerActivity.java文件
然后回到编辑器中,取消勾选图片中的选线,可以让包名文件夹分级
新建一级微信package
直接把UnityPlayerActivity.java文件拖到wx下面
然后我们开始引入微信的库,微信官方已经不直接提供jar或者aar的下载,已改用 gradle 形式,发布到 Maven Central
这样方便安卓工程集成,但是我们要打出aar包给unity使用,直接导出aar的话并不包含微信的库,有两种方法来解决
1)是谷歌出的一款插件,通过Unity插件Play Services Resolver for Unity在Unity端补全aar库的依赖关系,这个甚至可以补全ios平台的依赖,但我用的不多,引路官方仓库:https://github.com/googlesamples/unity-jar-resolver
2)通过Google Maven下载,搜索wechat,然后选择版本,选择aar包下载到本地
aar包中是包含jar的,我们需要用解压软件把jar包提取出来,然后改好名字
最后将微信的jar包放到lib下面并右键添加到工程中
这时我们rebuild工程,就可以看到打出的aar包了,在这个路径下
还有一点,这个aar包中包含unity的库,我们不需要,这会导致我们打包报错,修改build.gradle,将unity的库改为只引用,打包不包含
至此我们的lib依赖部分完成,下面开始添加Java的逻辑,首先是两个微信的Activity,用于安卓到Unity端的调用,一个登录,一个支付
代码在这里,记住,别忘了把APP_ID换成你们自己申请的
WXEntryActivity
package com.myvision.myapp.wxapi;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;
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.modelbiz.SubscribeMessage;
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram;
import com.tencent.mm.opensdk.modelbiz.WXOpenBusinessView;
import com.tencent.mm.opensdk.modelbiz.WXOpenBusinessWebview;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.modelmsg.ShowMessageFromWX;
import com.tencent.mm.opensdk.modelmsg.WXAppExtendObject;
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import java.lang.ref.WeakReference;
public class WXEntryActivity extends Activity implements IWXAPIEventHandler{
private static String TAG = "MicroMsg.WXEntryActivity";
private IWXAPI api;
private MyHandler handler;
public static String wxAPPID = "换成你们自己";
private static class MyHandler extends Handler {
private final WeakReference<WXEntryActivity> wxEntryActivityWeakReference;
public MyHandler(WXEntryActivity wxEntryActivity){
wxEntryActivityWeakReference = new WeakReference<WXEntryActivity>(wxEntryActivity);
}
@Override
public void handleMessage(Message msg) {
int tag = msg.what;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, wxAPPID, false);
handler = new MyHandler(this);
try {
Intent intent = getIntent();
api.handleIntent(intent, this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
switch (req.getType()) {
case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:
goToGetMsg();
break;
case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:
goToShowMsg((ShowMessageFromWX.Req) req);
break;
default:
break;
}
finish();
}
@Override
public void onResp(BaseResp resp) {
int result = 0;
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_OK:
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
break;
case BaseResp.ErrCode.ERR_UNSUPPORT:
break;
default:
break;
}
Toast.makeText(this, getString(result) + ", type=" + resp.getType(), Toast.LENGTH_SHORT).show();
if (resp.getType() == ConstantsAPI.COMMAND_SUBSCRIBE_MESSAGE) {
SubscribeMessage.Resp subscribeMsgResp = (SubscribeMessage.Resp) resp;
String text = String.format("openid=%s\ntemplate_id=%s\nscene=%d\naction=%s\nreserved=%s",
subscribeMsgResp.openId, subscribeMsgResp.templateID, subscribeMsgResp.scene, subscribeMsgResp.action, subscribeMsgResp.reserved);
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
if (resp.getType() == ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM) {
WXLaunchMiniProgram.Resp launchMiniProgramResp = (WXLaunchMiniProgram.Resp) resp;
String text = String.format("openid=%s\nextMsg=%s\nerrStr=%s",
launchMiniProgramResp.openId, launchMiniProgramResp.extMsg,launchMiniProgramResp.errStr);
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
if (resp.getType() == ConstantsAPI.COMMAND_OPEN_BUSINESS_VIEW) {
WXOpenBusinessView.Resp launchMiniProgramResp = (WXOpenBusinessView.Resp) resp;
String text = String.format("openid=%s\nextMsg=%s\nerrStr=%s\nbusinessType=%s",
launchMiniProgramResp.openId, launchMiniProgramResp.extMsg,launchMiniProgramResp.errStr,launchMiniProgramResp.businessType);
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
if (resp.getType() == ConstantsAPI.COMMAND_OPEN_BUSINESS_WEBVIEW) {
WXOpenBusinessWebview.Resp response = (WXOpenBusinessWebview.Resp) resp;
String text = String.format("businessType=%d\nresultInfo=%s\nret=%d",response.businessType,response.resultInfo,response.errCode);
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
if (resp.getType() == ConstantsAPI.COMMAND_SENDAUTH) {
SendAuth.Resp authResp = (SendAuth.Resp)resp;
final String code = authResp.code;
}
finish();
}
private void goToGetMsg() {
// Intent intent = new Intent(this, GetFromWXActivity.class);
// intent.putExtras(getIntent());
// startActivity(intent);
finish();
}
private void goToShowMsg(ShowMessageFromWX.Req showReq) {
WXMediaMessage wxMsg = showReq.message;
WXAppExtendObject obj = (WXAppExtendObject) wxMsg.mediaObject;
StringBuffer msg = new StringBuffer();
msg.append("description: ");
msg.append(wxMsg.description);
msg.append("\n");
msg.append("extInfo: ");
msg.append(obj.extInfo);
msg.append("\n");
msg.append("filePath: ");
msg.append(obj.filePath);
// Intent intent = new Intent(this, ShowFromWXActivity.class);
// intent.putExtra(Constants.ShowMsgActivity.STitle, wxMsg.title);
// intent.putExtra(Constants.ShowMsgActivity.SMessage, msg.toString());
// intent.putExtra(Constants.ShowMsgActivity.BAThumbData, wxMsg.thumbData);
// startActivity(intent);
finish();
}
}
WXPayEntryActivity
package com.myvision.myapp.wxapi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
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{
public static String GameObjectName;
public static String CallBackFuncName;
private static final String TAG = "WXPayEntryActivity";
private IWXAPI api;
public static String wxAPPID = "换成你们自己"; // 在调用微信支付处,设置该变量值
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.wx_pay_result);
//
api = WXAPIFactory.createWXAPI(this, wxAPPID);
api.handleIntent(getIntent(), this);
//UnityPlayer.UnitySendMessage(GameObjectName,CallBackFuncName,"微信API_ING");
}
@Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req)
{
}
/** 微信返回支付结果,会调用该函数*/
@Override
public void onResp(BaseResp resp)
{
showText("onPayFinish, errCode = " + resp.errCode);
if (resp.errCode != 0 && resp.errCode != -2)
{
showToast(this, "微信支付失败, errCode:" + resp.errCode);
}
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX)
{
// AlertDialog.Builder builder = new AlertDialog.Builder(this);
// builder.setTitle("提示");
// builder.setMessage("微信支付结果:" + resp.errCode);
// builder.show();
if(resp.errCode == 0)
{
// PaySuccess(this); // 可在此处,添加应用自己的支付结果统计相关逻辑
showToast(this, "微信支付成功");
}
else if(resp.errCode == -2) showToast(this, "用户取消支付");
else showToast(this, "支付失败,其他异常情形" );
}
showToast(this, GameObjectName+","+CallBackFuncName );
UnityPlayer.UnitySendMessage(GameObjectName,CallBackFuncName,"支付回调:"+resp.errCode);
this.finish();
}
/** 输出log信息 */
public static void showText(final String info)
{
Log.d(TAG, info);
}
/** 输出Toast消息 */
private void showToast(Context context, final String info)
{
Toast.makeText(context, info, Toast.LENGTH_SHORT).show();
Log.d(TAG, info);
}
}
然后我们需要新建一个继承自UnityPlayerActivity的MainActivity,里面目前只实现的创建wxapi和一个支付逻辑
package com.myvision.myapp.wx;
import android.os.Bundle;
import com.myvision.myapp.wxapi.WXPayEntryActivity;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
public class MainActivity extends UnityPlayerActivity {
public static String APP_ID;
private PayReq req = new PayReq();
private IWXAPI wxAPI = null;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
APP_ID = "换成你们自己";
WechatInit(APP_ID);
}
public void WechatInit(String appid){
APP_ID = appid;
if(wxAPI==null){
wxAPI = WXAPIFactory.createWXAPI(this,appid);
wxAPI.registerApp(appid);
}
}
public boolean IsWechatInstalled(){
return wxAPI.isWXAppInstalled();
}
public void WeChatPayReq(String APP_ID,String MCH_ID,String prepayid,String packageValue,String noncestr,String timestamp,String sign,String callBackObjectName,String CallBackFuncName) {
WXPayEntryActivity.GameObjectName = callBackObjectName;
WXPayEntryActivity.CallBackFuncName = CallBackFuncName;
req.appId = APP_ID;
req.partnerId = MCH_ID;
req.prepayId = prepayid;
req.packageValue =packageValue;
req.nonceStr = noncestr;
req.timeStamp = timestamp;
req.sign = sign;
wxAPI.sendReq(req);
}
}
坚持住伙计!Rebuild Project!我们的aar就新鲜出炉了!我为你感到自豪!
4.Unity端的开发
首先新建好unity工程,确保包名一致,把我们的aar丢到图中位置
切换到安卓平台,设置下你的keystore签名,没有这个的话不能正常唤起微信(关联Tip1),勾选Custon Main Manifest,我们需要创建一个自定义的AndroidManifest.xml文件
AndroidManifest这样写
<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myvision.myapp"
xmlns:tools="http://schemas.android.com/tools">
<queries>
<package android:name="com.tencent.mm" /> // 指定微信包名
</queries>
<application>
<activity android:name="com.myvision.myapp.wx.MainActivity"
android:exported="true"
android:theme="@style/UnityThemeSelector">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<activity
android:name="com.myvision.myapp.wxapi.WXEntryActivity"
android:exported="true"
android:launchMode="singleTask">
</activity>
<activity
android:name="com.myvision.myapp.wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTask">
</activity>
</application>
</manifest>
注意安卓11以上,一定要加这段,否则无法调起微信(落泪)
<queries>
<package android:name="com.tencent.mm" /> // 指定微信包名
</queries>
最后一的C#做一个简单的调用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
public Text ui;
public Text ui2;
private AndroidJavaObject jo= null;
// Start is called before the first frame update
public void Init() {
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
}
public void CheckWX() {
bool bo = true;
bo = jo.Call<bool>("IsWechatInstalled");
ui.text = bo.ToString();
}
public void WXPay() {
jo.Call("WeChatPayReq",
"你的APP_ID",
"",
"",
"com.myvision.myapp",
"",
"",
"",
"Test",
"WXCallback");
}
public void WXCallback(string str) {
print("WXCallback");
ui2.text = str;
}
}
Editor里面大概就是这个样子,自己给按钮绑定好对应事件
然后就可以打包了,签过名打出包来以后装在手机上,要再下载微信的签名获取工具:https://res.wx.qq.com/wxdoc/dist/assets/media/Gen_Signature_Android.e481f889.zip
在里面输入包名获取签名,把签名填在微信开平平台对应的app信息里面,否则无法正常调起
平台上更新好签名后(审核要半天左右),再重新运行app,就可以调用微信支付了,我目前还没接后端服务器部分,所以还没有真实的微信支付参数,但传入app_id后就可以正常调微信(但是没调起来,需要支付相关参数正确),以及接收到安卓传来的支付回调给Unity端,所以还不算完整流程,后面有机会再详细补充下
完毕,喜欢的同学请三连支持,谢谢~
感谢以下博主的分享:
https://www.bilibili.com/video/BV1Rq4y1S7qP?p=10&vd_source=4f7f14539886b3de3b8a98d2e2b3c90d
https://blog.csdn.net/linxinfa/article/details/117083637
https://blog.csdn.net/weixin_45724919/article/details/126139229
https://blog.csdn.net/Sun_XiaoChuan/article/details/110118309
https://blog.csdn.net/weixin_42414707/article/details/93844385
https://blog.csdn.net/songyu_95/article/details/88248350
Unity接入微信支付SDK 2022年版安卓篇的更多相关文章
- 【Unity】微信支付SDK官方安卓Demo的使用问题
Unity3d使用微信支付是属于APP内发起支付调用的情况,其本质上是在安卓项目上使用微信SDK,安卓项目开发完成后再导入到Unity中作为Unity插件使用,即Unity中C#调用安卓(Java)代 ...
- Unity接入微信登录 微信分享 微信支付 支付宝SDK
你将会学到的unity集成SDK游戏中接入微信支付与支付宝支付游戏中接入微信登录与微信分享 目录 mp4格式,大小2.2GB 扫码时备注或说明中留下邮箱 付款后如未回复请至https://shop13 ...
- Apicloud微信支付iOS可以,安卓返回-1的之避坑指南
相信各位小伙伴在接入微信支付的时候,一定遇到过返回-1的这个问题,说实话,这个问题真的很恶心,微信开放平台提供的文档在关于-1这个问题的描述(可能的原因:签名错误.未注册APPID.项目设置APPID ...
- 在Web应用中接入微信支付的流程之极简清晰版
在Web应用中接入微信支付的流程之极简清晰版 背景: 在Web应用中接入微信支付,我以为只是调用几个API稍作调试即可. 没想到微信的API和官方文档里隐坑无数,致我抱着怀疑人生的心情悲愤踩遍了丫们布 ...
- 在Web应用中接入微信支付的流程之极简清晰版 (转)
在Web应用中接入微信支付的流程之极简清晰版 背景: 在Web应用中接入微信支付,我以为只是调用几个API稍作调试即可. 没想到微信的API和官方文档里隐坑无数,致我抱着怀疑人生的心情悲愤踩遍了丫们布 ...
- 开源微信支付SDK
应该有一年多没在博客园上写文章了,毕竟是一个记录自己技术成长的平台,没能将写博客长期坚持下来,说起来也是挺惭愧的.对于自己的近况而言,确实平常加班也比较多,时间会比较压缩,所以到后来博客也基本停止了更 ...
- iOS 微信支付SDK与微信友盟分享两者同时集成时,出现的问题与解决之路。
这两天改版一个旧的APP,要旧貌换新颜,拿到app后进行编译,一直报下面的错误. 报不认识的符号名PayReq错误.奇怪,啥也没动就这样,真不知道给的包是不是本来就是个报错的工程. 不管怎样,要对它修 ...
- tp6中使用微信支付sdk
一.下载微信支付sdk 二.将lib文件夹下的文件复制到目录:extend->WxPay 将example文件夹下的WxPay.Config.php文件也复制到:extend->WxPay ...
- Unity接入谷歌支付
文章理由 前段时间负责Unity接入Google内购功能,一开始研究别人的技术博客时发现,他们的文章都有些年头了,有些细节的地方已经不像n年前那样了,技术永远是需要更新的,而这篇就作为2016年末的最 ...
随机推荐
- HiEngine:可媲美本地的云原生内存数据库引擎
摘要:HiEngine与华为GaussDB (for MySQL)集成,将内存数据库引擎的优势带到云端,并与基于磁盘的引擎共存.HiEngine的性能比传统的以存储为中心的解决方案高出7.5倍. 本文 ...
- 史上最全学习率调整策略lr_scheduler
学习率是深度学习训练中至关重要的参数,很多时候一个合适的学习率才能发挥出模型的较大潜力.所以学习率调整策略同样至关重要,这篇博客介绍一下Pytorch中常见的学习率调整方法. import torch ...
- IDEA的概述和IDEA的安装
开发工具概述 IDEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量. 它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公司中 ...
- 各种Git Bash乱码解决
乱码情景一: 当使用git log 出现乱码时,修改 %GIT_HOME%\etc\gitconfig 文件,加入如下内容: [gui] encoding = utf-8[i18n] commiten ...
- 【Unity基础知识】基础游戏单位GameObject中常用的属性和API
一.GameObject中的成员变量 主要思想:得到该脚本依附的GameObject的相关信息 现有: Lesson4的代码: using System.Collections; using Syst ...
- led闪烁(时序输入输出,自定义变量,时钟仿真,执行顺序)
1.设计定义 设计一个以200ms亮,200ms暗交替闪烁的led灯,并且有一个复位按钮可以停止工作. 2.设计输入 2.1端口 以固定周期交替闪烁说明由时钟控制,需要一个时钟控制端口clk,要求复位 ...
- 算法竞赛进阶指南 0x43 线段树
目录 线段树简介 线段树的简单代码实现 建树代码 修改操作 查询操作 线段树的查询操作的时间复杂度分析: AcWing245. 你能回答这些问题吗 思路 代码[时间复杂度:\(O( \space(N+ ...
- 【万字长文】使用 LSM-Tree 思想基于.Net 6.0 C# 实现 KV 数据库(案例版)
文章有点长,耐心看完应该可以懂实际原理到底是啥子. 这是一个KV数据库的C#实现,目前用.NET 6.0实现的,目前算是属于雏形,骨架都已经完备,毕竟刚完工不到一星期. 当然,这个其实也算是NoSQL ...
- 获取某个html元素相对于视窗的位置集合
getBoundingClientRect() getBoundingClientRect()获取元素位置,这个方法没有参数 getBoundingClientRect()用于获得页面中某个元素的左, ...
- nodejs学习总结01
主流渲染引擎介绍1.渲染引擎又叫 排版引擎 或 浏览器内核 .(双内核:执行html和css的)2,主流的渲染引擎有**Chrome浏览器**:Blink引壁(WebKit的一个分支)**Safari ...