Unity accesses WeChat payment SDK 2022 version Android

In the past year, I switched to UE development. The blog update is relatively small, and the technology stack is much wider. I will update as much as I can in the future, and it is also convenient to summarize and remember.

There are many pitfalls in the whole process of Unity’s access to WeChat payment. The previous tutorials on the Internet are either old or fragmented.

Development environment, Windows11, Unity2020.3.24f1c2, Android Studio2021.2.1 Patch2

1. Register the WeChat open platform, register the application, and apply for WeChat payment to obtain the necessary parameters for calling the SDK, which will not be expanded here ( https://open.weixin.qq.com/)
2. Make sure that the development environment is installed, jdk, sdk, etc. Unity's Android environment can be installed with the one that comes with Unity Hub, or you can use the global environment variable
3.Android Studio side development, export aar

New Construction

Set the package name, pay attention to the same as the package name of the unity project

Switch to the Project view, create a new module, and select Android Library

Keep the package name the same

Both the WeChat library and the Unity library (the Android side needs to actively notify the Unity side after WeChat payment is successful) need to be added to the lib folder in the project

Unity's library is in this location, classes.jar file, according to your own needs to choose il2cpp or mono, release or dev, a total of four

Right-click Unity's library image and add it to the gradle configuration

The new version of classes.jar file does not contain the UnityPlayerActivity class, you need to copy the UnityPlayerActivity.java file from the path of your editor Editor\2020.3.24f1c2\Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player

Then go back to the editor, uncheck the selection line in the picture, you can make the package name folder hierarchical

Create a new first-level WeChat package

Drag the UnityPlayerActivity.java file directly under wx

Then we started to introduce the library of WeChat. WeChat officially no longer provides jar or aar downloads directly, and has changed to gradle and released it to Maven Central

This is convenient for Android project integration, but we need to type out the aar package for use by unity. If we directly export aar, it does not include the WeChat library. There are two ways to solve it.
1) It is a plug-in from Google. The Unity plug-in Play Services Resolver for Unity is used to complete the dependencies of the aar library on the Unity side. This can even complete the dependencies of the ios platform. https://github.com/googlesamples/unity-jar-resolver
2) Download through Google Maven, search for wechat, then select the version, select the aar package to download locally

The aar package contains jar, we need to extract the jar package with decompression software, and then change the name

Finally, put the WeChat jar package under lib and right-click to add it to the project

At this time, when we rebuild the project, we can see the aar package that was typed, under this path

Another point, this aar package contains the unity library, we don't need it, this will cause us to pack an error, modify the build.gradle, change the unity library to only reference, the package does not contain

At this point, our lib dependency part is completed. Let's start adding Java logic. First, there are two WeChat activities, which are used for calling from Android to Unity, one for login and one for payment.

The code is here, remember, don't forget to replace the APP_ID with your own application
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 = "replace yourself";
    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 = "replace yourself";		// When calling WeChat Pay, set the variable value

    @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,"WeChat API_ING");
    }

    @Override
    protected void onNewIntent(Intent intent)
    {
        super.onNewIntent(intent);
        setIntent(intent);

        api.handleIntent(intent, this);
    }

    @Override
    public void onReq(BaseReq req)
    {

    }


    /** WeChat returns the payment result and will call this function*/
    @Override
    public void onResp(BaseResp resp)
    {
        showText("onPayFinish, errCode = " + resp.errCode);

        if (resp.errCode != 0 && resp.errCode != -2)
        {
            showToast(this, "WeChat payment failed, errCode: " + resp.errCode);
        }

        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX)
        {
            // AlertDialog.Builder builder = new AlertDialog.Builder(this);
            // builder.setTitle("Title");
            // builder.setMessage("WeChat payment result: " + resp.errCode);
            // builder.show();

            if(resp.errCode == 0)
            {
                // PaySuccess(this); // You can add the application's own payment result statistics related logic here
                showToast(this, "WeChat payment success");
            }
            else if(resp.errCode == -2) showToast(this, "User cancels payment");
            else showToast(this, "Payment failure, other abnormal situations" );
        }
        showToast(this, GameObjectName+","+CallBackFuncName );
        UnityPlayer.UnitySendMessage(GameObjectName,CallBackFuncName,"Payment callback:"+resp.errCode);
        this.finish();
    }


    /** output log information */
    public static void showText(final String info)
    {
        Log.d(TAG, info);
    }

    /** Output Toast message */
    private void showToast(Context context, final String info)
    {
        Toast.makeText(context, info, Toast.LENGTH_SHORT).show();
        Log.d(TAG, info);
    }
}

Then we need to create a new MainActivity that inherits from UnityPlayerActivity, which currently only implements the creation of wxapi and a payment logic

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 = "replace yourself";
        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);
    }
}

Hold on mate! Rebuild Project! Our aar is freshly baked! I am so proud of you!

4.Unity side development
First, create a new unity project, make sure the package name is the same, and throw our aar into the position in the figure

Switch to the Android platform, set your keystore signature, without this, you can't call up WeChat normally (associated with Tip1), check Custon Main Manifest, we need to create a custom AndroidManifest.xml file

AndroidManifest writes like this

<?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" />   // Specify the WeChat package name
  </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>
 
 

Pay attention to Android 11 and above, you must add this paragraph, otherwise you will not be able to tune up WeChat (tears)

 <queries>
    <package android:name="com.tencent.mm" />   // Specify the WeChat package name
  </queries>

The last C# makes a simple call

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", 
            "yours APP_ID",
            "",
            "",
            "com.myvision.myapp",
            "",
            "",
            "",
            "Test",
            "WXCallback");
    }

    public void WXCallback(string str) {
        print("WXCallback");
        ui2.text = str;
    }
}

This is probably what the Editor looks like. Bind the corresponding events to the buttons by yourself.

Then you can pack it, sign it and type it out and install it on your phone. You need to download the WeChat signature acquisition tool: https://res.wx.qq.com/wxdoc/dist/assets/media/Gen_Signature_Android.e481f889.zip
Enter the package name in it to get the signature, and fill in the signature in the app information corresponding to the WeChat Kaiping platform, otherwise it will not be able to be activated normally

After updating the signature on the platform (it takes about half a day for the review), and then re-run the app, you can call WeChat Pay. I haven't connected the back-end server part yet, so there is no real WeChat payment parameters, but after passing in the app_id, WeChat can be adjusted normally (but it has not been adjusted, and the relevant payment parameters need to be correct), and the payment callback from Android is received to the Unity side, so it is not a complete process, and I will have the opportunity to add more details later.

It's over, the students who like it, please support three consecutive times, thank you~

Thanks to the following bloggers for sharing:

https://www.bilibili.com/video/BV1Dr4y1T7nE/?spm_id_from=333.788.recommend_more_video.-1&vd_source=4f7f14539886b3de3b8a98d2e2b3c90d

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

Tags: Android U3D

Posted by rline101 on Wed, 21 Sep 2022 02:40:51 +0930