首页 > Unity3D专栏 > 【Unity3D】 UnityAndroid平台接入支付宝SDK
2018
01-05

【Unity3D】 UnityAndroid平台接入支付宝SDK

本文章主要将Unity 、Eclipse Android平台、接入支付宝SDK支付功能的步骤以及注意事项

1、 unity项目准备
项目名字:XXXXXX
项目包名:com.visizen.alipay
2、 支付宝开发账户准备
准备一个支付宝公司帐号,目前个人是不能使用支付宝支付功能的。公司的支付宝帐号必须在支付宝的蚂蚁金服开放中心通过信息审核。具体审核所需信息和材料请根据网站来完成,审核通过之后在主账号的账户中心扩展自己所需要的合作伙伴角色,等待审核完成之后即可使用相应的开放功能。

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第1张  | Unity3D虚拟世界

3、 进入开发者中心,选择支付接入(这里以App内接入支付为例)

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第2张  | Unity3D虚拟世界

4、 根据自己的需要选择使用场景并填写应用的名字

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第3张  | Unity3D虚拟世界

5、 进入创建的应用概览信息页面,根据项目的内容设置Icon以及功能选项,功能部分内容根据应用的需要进行签约,签约之后功能才能使用。

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第4张  | Unity3D虚拟世界

6、 签约

点击立即签约之后根据系统提示进入签约页面。填写完毕之后点击下一步等待蚂蚁金服审核。审核之后之前选择的功能才可使用。

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第5张  | Unity3D虚拟世界

7、 概览界面的开发设置
注意:接口加签方式(标号3)是必须填写的,1,2,4是可填可不填,根据应用的需要来决定。

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第6张  | Unity3D虚拟世界

8、 接口加签方式(配置密钥)
配置密钥是支付这一环节很重要的因素,也是分了两个步骤,生成密钥和配置密钥,工具下载地址:https://docs.open.alipay.com/291/106097
8、1生成密钥
找到下载好的签名工具,双击“RSA签名验签工具.bat”,如图

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第7张  | Unity3D虚拟世界

8、2配置签名

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第8张  | Unity3D虚拟世界

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第9张  | Unity3D虚拟世界

在2中填写应用公钥2048中的内容,保存提交即可,至此开放中心配置完成。
这个时候你需要记录应用的APPID 和RSA签名工具生成的密钥2048.

9、 下载SDK&demo
下载地址:https://docs.open.alipay.com/54/104509

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第10张  | Unity3D虚拟世界

10、 新建一个Eclipse Android项目
注意: Package Name必须和unity中包名一致!!!Application Name随意。并且生成MainActivity。

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第11张  | Unity3D虚拟世界

11、 Libs包的导入
找到自己的unity安装目录,并且找到[安装目录]Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes下的classes.jar 文件以及之前下载的SDK目录中的alipaySdk-20170922.jar文件以及gson.jar文件(gson.jar文件自行下载亦可使用我的工程里面的gson)

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第12张  | Unity3D虚拟世界

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第13张  | Unity3D虚拟世界

12、 将刚刚拖入到libs的三个jar包加入build path

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第14张  | Unity3D虚拟世界

13、 复制代码并修改错误

将demo中src下的代码全部复制到刚刚新建的Eclipse工程目录的src下面,注意文件包名。之后修改代码因包名导致的错误。将PayDemoActivity.java中的代码全部复制到MainActivity.java中,删除PayDemoActivity.java和ExternalFragment.java。并且新建一个java类名字为OrderBodyInfo,内容写先空着。

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第15张  | Unity3D虚拟世界

14、 修改AndroidManifest.xml

将新建的项目点 AndroidManifest.xml内容修改为如:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.visizen.alipay"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="4"
        android:targetSdkVersion="18"
        tools:ignore="OldTargetApi" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


    <application
        android:allowBackup="true"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Light.NoTitleBar" >
        <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>

15、 修改proguard-project.txt

将demo中proguard-project.txt的内容复制到新项目的proguard-project.txt中,并且修改2处的alipaysdk的名字和1处的相同

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第16张  | Unity3D虚拟世界

16、 修改MainActivity.java

1、修改import区域和继承类

package com.visizen.alipay;

import android.annotation.SuppressLint;
//import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
//import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.util.Log;
//import android.view.View;
import android.widget.Toast;

import java.util.Map;

import com.alipay.sdk.app.PayTask;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity; 


public class MainActivity extends UnityPlayerActivity  {

2、填写APPID 和密钥2048,新建一个String productid。APPID请在开发中心查看,密钥2048使用之前RSA工具生成的。

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第17张  | Unity3D虚拟世界

17、 完成16步之后删除剩下的所有代码,然后编写如下代码

@Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
    }

    @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();
                // 判断resultStatus 为9000则代表支付成功
                if (TextUtils.equals(resultStatus, "9000")) 
                {
                    // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。
                    Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                    //处理支付结果
                    PayResultToUnity( productid);
                } 
                else
                {
                    // 该笔订单真实的支付结果,需要依赖服务端的异步通知。
                    Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show();
                //  PayResultToUnity( productid);
                }
                break;
            }

            default:
                break;
            }
        };
    };
    /**
     * 支付宝支付业务
     * 
     * @param v
     */
    public String Alipay(String name,String price,String productid) 
    {
       this.productid=productid;
       boolean rsa2 = (RSA2_PRIVATE.length() > 0);
        Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID,name,price,productid, rsa2);
        String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

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

        Runnable payRunnable = new Runnable() 
        {

            @Override
            public void run() 
            {
                PayTask alipay = new PayTask(MainActivity.this);
                Map<String, String> result = alipay.payV2(orderInfo, true);
                Log.i("msp", result.toString());
                Log.i("orderInfo===", orderInfo);

                Message msg = new Message();
                msg.what = SDK_PAY_FLAG;
                msg.obj = result;
                mHandler.sendMessage(msg);
            }
        };

        Thread payThread = new Thread(payRunnable);
        payThread.start();
        return orderInfo;
    }
    //返回给Unity
   public   void   PayResultToUnity(String productid)
   {   
                                 //物体名字,   方法名字    方法的参数 
    UnityPlayer.UnitySendMessage("MainCamera","PayResult",productid);

    }

18、OrderBodyInfo类

研究OrderInfoUtil2_0.java发现订单信息是由json格式组成的,所以用OrderBodyInfo类来动态的修改订单的相关信息。App支付请求参数说明:https://docs.open.alipay.com/204/105465/
OrderBodyInfo类只实现了几个必填参数和一个自定义参数,这些参数的解释见上面的 参数说明。其代码如下:

package com.visizen.alipay;

public class OrderBodyInfo
{
    public OrderBodyInfo(String body, String subject, String out_trade_no, String timeout_express, String total_amount,
            String  product_id) {
        super();
        this.body = body;
        this.subject = subject;
        this.out_trade_no = out_trade_no;
        this.timeout_express = timeout_express;
        this.total_amount = total_amount;
        this.product_code="QUICK_MSECURITY_PAY";

        this.product_id = product_id;
    }


    //支付宝业务参数信息
    //必填信息
    public String body;//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。如:Iphone6 16G
    public String subject;//商品的标题/交易标题/订单标题/订单关键字等。如:大乐透,既是显示在订单信息界面的
    public String out_trade_no;//商户网站唯一订单号.如:70501111111S001111119
    public String timeout_express;//该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
                                  //注:若为空,则默认为15d。如:90m
    public String total_amount;//订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
    public String product_code;//销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY

    //以下信息为可选
    public String goods_type;//商品主类型:0—虚拟类商品,1—实物类商品 注:虚拟类商品不支持使用花呗渠道
    public String passback_params;//公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝
    public String promo_params;//优惠参数   注:仅与支付宝协商后可用. 如: {"storeIdType":"1"}
    public String extend_params;//业务扩展参数,详见下面的“业务扩展参数说明”     如:   {"sys_service_provider_id":"2088511833207846"}

    public String enable_pay_channels;//可用渠道,用户只能在指定渠道范围内支付当有多个渠道时用“,”分隔  注:与disable_pay_channels互斥.   如:  pcredit,moneyFund,debitCardExpress
    public String disable_pay_channels;//禁用渠道,用户不可用指定渠道支付当有多个渠道时用“,”分隔    注:与enable_pay_channels互斥.         如:  pcredit,moneyFund,debitCardExpress
    public String store_id;//商户门店编号。该参数用于请求参数中以区分各门店,非必传项            如:NJ_001

    //自定义信息
    public String product_id;//销售的商品id          

}

19、 订单信息处理类OrderInfoUtil2_0.java

找到buildOrderParamMap()方法并且替换为如下代码:

   /**
 * 构造支付订单参数列表
 * @param pid
 * @param productname
 * @param productprice
* @param productid
 * @return
 */

    public static Map<String, String> buildOrderParamMap(String app_id, String productname,String    productprice,String  productid,boolean rsa2) {

        Map<String, String> keyValues = new HashMap<String, String>();

        keyValues.put("app_id", app_id);

        OrderBodyInfo sss=new  OrderBodyInfo("xx",productname,getOutTradeNo(),"30m",productprice,productid);
        Gson gson=new   Gson();
        String str = gson.toJson(sss);

        keyValues.put("biz_content", str);
        keyValues.put("charset", "utf-8");

        keyValues.put("method", "alipay.trade.app.pay");

        keyValues.put("sign_type", rsa2 ? "RSA2" : "RSA");

        keyValues.put("timestamp", "2016-07-29 16:55:53");

        keyValues.put("version", "1.0");

        return keyValues;
    }

并且在头文件中添加:
Import com.google.gson.Gson
之后保存并修改工程中的可能因粗心出现的错误。
20、 导出jar包

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第18张  | Unity3D虚拟世界

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第19张  | Unity3D虚拟世界

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第20张  | Unity3D虚拟世界

21、 jar包导入到unity
找到unity项目中的Plugins目录下的Android文件下的bin文件,没有就新建上面三个文件夹。将20步导出的jar拖到bin文件夹下面。再将之前的alipaysdk和gson这两个包拖到Android目录下的libs目录下。复制Eclipse工程中的整个res文件夹和AndroidManifest.xml到unity的Android文件夹下面。最后的如图:

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第21张  | Unity3D虚拟世界

22、 unity端处理
新建一个场景并保存,名字任意,新建一个C#文件,名字任意,并赋给MainCamera
C#代码如下:

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


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

}
public class PayPay : MonoBehaviour
{
    public List<Button> buttons = null;
    public List<PayInfo> payInfos = null;
    private AndroidJavaObject currentActivity = null;
    public Text orderinfo;
    private string ordersss;
    void Start()
    {

        for (int i = 0; i < buttons.Count; i++)
        {
            var payInfo = payInfos[i];
            buttons[i].GetComponentInChildren<Text>().text = payInfos[i].subject;
            buttons[i].onClick.AddListener(() =>
            {
                Alipaypay(payInfo);
            });
        }
    }
    public void Alipaypay(PayInfo payInfo)
    {
        // AlipayClient是Android里的方法名字,写死.  
        // payInfo.money是要付的钱,只能精确分.  
        // payInfo.title是商品描述信息,注意不能有空格.  
        // 固定写法  
        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        currentActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");


        ordersss = currentActivity.Call<string>("Alipay", payInfo.title, payInfo.money.ToString(), payInfo.productid);
        Formatsss(ordersss);
    }
    private void Formatsss(string ss)
    {
        orderinfo.text = null;
        string[] temp = ss.Split('&');
        for (int i = 0; i < temp.Length; i++)
        {
            orderinfo.text = orderinfo.text + temp[i] + "\n";
        }
    }

    public void PayResult(string productid)
    {
        buttons[int.Parse(productid)].gameObject.GetComponent<Image>().color = Color.red;
    }

}

23、 场景设置与打包

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第22张  | Unity3D虚拟世界

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第23张  | Unity3D虚拟世界

25、 安装测试

【Unity3D】 UnityAndroid平台接入支付宝SDK - 第24张  | Unity3D虚拟世界

付款或者取消之后界面上显示的红字是刚刚的订单信息。请自行分析。不解释了

26、 说明:

1、unity调用jar包中方法:

        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        currentActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");


      currentActivity.Call<string>("Alipay", payInfo.title, payInfo.money.ToString(), payInfo.productid);

前两行为固定写法,第三行为可变写法,具体的请参照unity官方文档。

2、jar包中调用unity方法:

UnityPlayer.UnitySendMessage("MainCamera","PayResult",productid);

 

本文转自Elvira_Z,谢谢提供优质材料。



虚拟世界提醒您:如果您觉得本文不错,快快将这篇文章分享出去吧 ,感谢您的支持和关注,谢谢!
最后编辑:
作者:虚拟世界
专注互联网技术及资讯 技术研究中心|有相关Unity3D问题或者作事宜请联系我哦!
捐 赠如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝或者微信直接向我捐款,在此非常感谢您对虚拟世界的捐赠。

留下一个回复

你的email不会被公开。