Unity Android平台接入支付宝

额,最近折腾在unity项目中接入支付宝,记录下流程。
先来个官方文档:https://docs.open.alipay.com/204/106079/

配置

创建应用,配置应用参考上面的给的官网文档。

支付宝SDK

链接 https://doc.open.alipay.com/doc2/detail.htm?treeId=54&articleId=104509&docType=1

下载SDK&Demo。解压之后会有两个文件夹:alipay_demo和alipay_sdk,别急后面会用到。

创建android库工程

这里用AndroidStudio来创建Android工程,不用Eclipse了,配环境好蛋疼。。。

1.

创建一个新的Android工程,Package Name要和Unity -> PlayerSettings里的Bundle Identifier保持一致。

2.

Minimum API Level就直接默认得了,大部分通用

3.

选择Activity的模版,我们选择Empty Activity。因为不需要编写Android原生界面。

4.

然后是设置Activity的名字界面,因为我们不需要编程Android界面,所以取消勾选Generate Layout File选项。不取消也可以,可以创建工程后手动删除Layout文件夹。

5.

创建工作完成,下面对照着下图删除没用东西。

只保留了两个文件—— AndroidManifest.xml和MainActivity

6.

修改AndroidManifest,修改后如下:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.xxl.youxigame">

        <application
            android:allowBackup="true"
            android:supportsRtl="true">
            <activity android:name=".MainActivity">
                <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>
        </application>

    </manifest>

7.

打开Gradle Scripts(Gradle是一种安卓构建脚本)下的build.gradle(Moudle:app),修改如下(这是因为库文件不能设置applcation Id,另外build.gradle会包含单元测试的配置,也需要删除):

        //apply plugin: 'com.android.application'
        apply plugin: 'com.android.library'

        android {
            compileSdkVersion 24
            buildToolsVersion "24.0.2"

            defaultConfig {
                minSdkVersion 15
                targetSdkVersion 24
                versionCode 1
                versionName "1.0"
            }
            buildTypes {
                release {
                    minifyEnabled false
                    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                }
            }
        }

基本环境配置完毕,接下来就是接入支付宝SDK了。

接入支付宝

首先我们需要引入支付宝SDK的jar包,将alipay_sdk下的alipaySdk-20XXXXXX.jar和Unity提供的jar包拷贝到项目路径/app/libs文件夹下,

    Unity提供的jar包路径是:
    Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar
    如果你的项目采用il2cpp编译,那么路径则是:
    Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Classes\classes.jar

然后回到AndroidStudio,菜单栏选择File -> Project Structure界面,点击app -> Dependencies如所示:

点击旁边的减号,删掉目前这三个以来库,然后点击加号 -> Jar Dependency,选择刚才拷贝到Libs下面的那两个jar文件,点击确定。可以发现build.gradle(Moudle:app)下depedencies里出现了支付宝的Sdk jar包,完整的build.gradle如下:

        //apply plugin: 'com.android.application'
        apply plugin: 'com.android.library'

        android {
            compileSdkVersion 24
            buildToolsVersion "24.0.2"

            defaultConfig {
                minSdkVersion 15
                targetSdkVersion 24
                versionCode 1
                versionName "1.0"
            }
            buildTypes {
                release {
                    minifyEnabled false
                    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                }
            }
        }

        dependencies {
            compile files('libs/alipaySdk-20170710.jar')
            compile files('libs/classes.jar')
        }

到这里后,我们先来测试一下配置是否正确,再进行下面的步骤。
点击Android Studio左下角的Build Variants,如图:

将debug修改为release:

最后点击菜单栏Build -> Build APK,稍等,如果出现Build Successfully的提示,说明一切正常。如图:

点击Show in Explorer,选择outputs -> aar,会发现一个app-release.aar。这就是build生成的文件,aar可以视为jar的升级版。其实它们都只是一个zip文件。

    注意:
    生成的aar文件里,我们需要删除libs/class.jar!将aar文件后缀改为zip,使用压缩软件删除即可。因为Unity在打包时,会将自带的那个classes.jar拷贝进apk,如果aar里的classes.jar不删除,打包时就会产出冲突,得到下面的错误:
    IOException: Failed to Move File / Directory from 'Temp/StagingArea\android-libraries\app-release\classes.jar' to 'Temp/StagingArea\android-libraries\app-release\libs\classes.jar'.
    也就是说,每次我们测试后,都需要将aar里的这个jar包手动删除。

封装支付宝支付接口

把alipay_demo下文件直接拖到androidstudio工程中,需要如图这些文件:

对就是AuthResult、Base64、OrderInfoUtil2_0、PayResult、SignUtils这五个类即可,MainActivity创建时就有。

我们需要做的就是修改MainActivity这个类,其他都是工具定义相关的类,看下官方提供的注释就行。直接上代码了:

        package com.xxl.youxigame;

        import android.annotation.SuppressLint;
        import android.os.Bundle;
        import android.os.Handler;
        import android.os.Message;
        import android.text.TextUtils;
        import android.widget.Toast;

        import com.unity3d.player.*;
        import com.alipay.sdk.app.PayTask;

        import java.util.Map;

        public class MainActivity extends UnityPlayerActivity {

            private static final  int SDK_PAY_FLAG=1;
            private static final int SDK_AUTH_FLAG = 2;
            private static final String RESULT_SUCCESS="9000";
            private static final String TIP_PAY_SUCCESS="支付成功";
            private static final String TIP_PAY_FAILED="支付失败";

            // 支付结果回调,仅作参考,以服务端确认为准!
            @SuppressLint("HandlerLeak")
            private Handler mHandler=new Handler(){
                @SuppressWarnings("unused")
                public void handleMessage(Message msg) {
                    switch (msg.what)
                    {
                        case SDK_PAY_FLAG:
                        {
                            @SuppressWarnings("unchecked")
                            PayResult payResult = new PayResult((Map<String, String>) msg.obj);
                            String resultInfo = payResult.getResult();
                            String resultStatus = payResult.getResultStatus();
                            if (TextUtils.equals(resultStatus, RESULT_SUCCESS))
                            {
                                Toast.makeText(MainActivity.this, TIP_PAY_SUCCESS, Toast.LENGTH_SHORT).show();
                            } else
                            {
                                Toast.makeText(MainActivity.this, TIP_PAY_FAILED, Toast.LENGTH_SHORT).show();
                            }
                            break;
                        }
                        case SDK_AUTH_FLAG: {
                            @SuppressWarnings("unchecked")
                            AuthResult authResult = new AuthResult((Map<String, String>) msg.obj, true);
                            String resultStatus = authResult.getResultStatus();

                            // 判断resultStatus 为“9000”且result_code
                            // 为“200”则代表授权成功,具体状态码代表含义可参考授权接口文档
                            if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
                                // 获取alipay_open_id,调支付时作为参数extern_token 的value
                                // 传入,则支付账户为该授权账户
                                Toast.makeText(MainActivity.this,
                                        "授权成功\n" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT)
                                        .show();
                            } else {
                                // 其他状态值则为授权失败
                                Toast.makeText(MainActivity.this,
                                        "授权失败" + String.format("authCode:%s", authResult.getAuthCode()), Toast.LENGTH_SHORT).show();

                            }
                            break;
                        }
                        default:
                            break;
                    }
                }
            };

              //这些参数根据自己实际情况填入,参见第一步配置中的官网文档链接
            /** 支付宝支付业务:入参app_id */
            public static final String APPID = "2017061500021222";
            /** 支付宝账户登录授权业务:入参pid值 */
            public static final String PID = "2088102123816631";
            /** 支付宝账户登录授权业务:入参target_id值 */
            public static final String TARGET_ID = "kkkkk091125";
             //测试用的私钥
            public static final String RSA2_PRIVATE = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJkhXBA/IH5uU8KcIw4p5x4i0zu+LZVAnff/z3Fd/JGc/iKrIFMJ+Gdkzd9lc9pM3pEkb8Hr7zuNb4YAZOYwxUJGt18IIhsr/DImCd+4hnbaP+X61jArJugnhV05zsI8IJtu4N6whpcHhB4RPKYB4VyFnyr6em6DqY0dXe7bdtm3AgMBAAECgYEAl7/ZbjhAyUooM2lry/N2mATG9COJJKl+Ym/dcWlEjEDaEB0p0WDGDCB3bHUrlCAtSASlw7U9xPRqmo71brDSKU0+PSSjpYPVk2rByL4rqWOhuJM/jz2LkdKhlDJLGu72JpdldA8WVKPpEYpDVUQHiWVVHQFR2u96p45uj2ExjRECQQDLbqmB/NLkJUNHisIzNHDijU+YO6fPN/7zDOlnRjhigY0gTTP4zGUbtFHuTHQsKP2suSNlPFWjlJ+6k4kjpV41AkEAwLMmc4eWsRJematJ03m98mtP6TahoRFvZ47KemAPVTDCjnLTk1n4bQ/4lgydzzSNn9YCUq/YxwWU+/dNZgQFuwJAdF8/lF5+fYhbbmeQJB6RnOfdamZl3oJX083FDxD6XE9j3eCMJH04MZr7a2hM5J4mT1IxT04uZz80CFUxlDSbKQJAfRfPblAm0uxJ3RgE5POzCxv+1DZS1myrFV7ssmSJj5QHuNFx58YQLzye80ldaJWFGq2i9GqTHx/Qh4ETDZau4QJBALFwmdH3I+f5/Fjkc9CNdMOJfdp6JP+vkMjS966IKbhk21PKwAkhmSSMx6CVFuATFovRrWD2YlXfu+4d8HXsTWM=";

            public static final String RSA_PRIVATE = "";
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
            }
            //Unity中调用
            public  void Pay(final String orderInfo)
            {
                if (TextUtils.isEmpty(APPID) || (TextUtils.isEmpty(RSA2_PRIVATE) && TextUtils.isEmpty(RSA_PRIVATE))) {
                    ShowToast("需要配置APPID | RSA_PRIVATE");
                    return;
                }

                //这里为了测试参数orderInfo并没有使用,而是直接拼接的orderInfo1
                boolean rsa2 = (RSA2_PRIVATE.length() > 0);
                Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2);
                String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

                String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE;
                String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2);
                final String orderInfo1 = orderParam + "&" + sign;

                Runnable payRunnable=new Runnable() {
                    @Override
                    public void run() {
                        PayTask alipay=new PayTask(MainActivity.this);
                        Map<String,String> result=alipay.payV2(orderInfo1,true);
                        Message msg=new Message();
                        msg.obj=result;
                        mHandler.sendMessage(msg);
                    }
                };

                Thread payThead=new Thread(payRunnable);
                payThead.start();
            }

            public  void ShowToast(final String message)
            {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
                    }
                });
            }
        }

注意:orderInfo可以在客户端生成,需要AppId,pid以及RSA等等,这样做不安全,推荐的做法是由服务端生成订单信息并加密(生成相关的逻辑在Demo里已经给出了),然后传递给客户端,客户端支付完成后,支付宝将执行一个配置好的URL,例如通知服务端支付完毕,而客户端在支付完成后提示支付成功与否的信息只能作为参考。

Unity中如何调用

unity中调用java有固定的方法,官方文档:https://docs.unity3d.com/ScriptReference/AndroidJavaObject.Call.html

直接上代码洛:

        using UnityEngine;
        using UnityEngine.UI;
        using System.Collections.Generic;

        [System.Serializable]
        public class PayInfo
        {
            public string subject;  // 显示在按钮上的内容,跟支付无关系  
            public float money;     // 商品价钱  
            public string title;    // 商品描述  
        }

        public class AlipayUI : MonoBehaviour
        {
            public List<Button> buttons = null;
            public List<PayInfo> payInfos = null;
            private AndroidJavaObject currentActivity = null;

            void Start()
            {
        #if UNITY_ANDROID && !UNITY_EDITOR  
                // 固定写法  
                AndroidJavaClass javaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");  
                currentActivity = javaClass.GetStatic<AndroidJavaObject>("currentActivity");  
        #endif

                // Init UI  
                for (int i = 0; i < buttons.Count; i++)
                {
                    var payInfo = payInfos[i];
                    buttons[i].GetComponentInChildren<Text>().text = payInfos[i].subject;
        #if UNITY_ANDROID && !UNITY_EDITOR  
                    buttons[i].onClick.AddListener(() =>   
                    {  
                         SHow();  
                         AliPay(payInfo);
                    });  
        #endif
                }
            }

            public void SHow()
            {
                currentActivity.Call("ShowToast", "Hello World!");
            }
            public void AliPay(PayInfo payInfo)
            {
                currentActivity.Call("Pay", "ddd");
            }
        }  

上面这个类挂在MainCamera上就行,参数如下图配置:


选择Android平台打包测试即可,额,写文档好累啊。

附录

参考链接如下:

http://blog.csdn.net/zhangdi2017/article/details/63254563
http://www.voidcn.com/blog/qq_16131393/article/p-6168930.html

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值