Unity 、Eclipse Android平台、接入支付宝SDK

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

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

这里写图片描述

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

这里写图片描述

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

这里写图片描述

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

这里写图片描述

6、 签约

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

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

这里写图片描述

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

8、2配置签名

这里写图片描述

这里写图片描述

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

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

这里写图片描述

10、 新建一个Eclipse Android项目
注意: Package Name必须和unity中包名一致!!!Application Name随意。并且生成MainActivity。
在这里插入图片描述

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

这里写图片描述

这里写图片描述

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

这里写图片描述

13、 复制代码并修改错误

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

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.???.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处的相同

在这里插入图片描述

16、 修改MainActivity.java

1、修改import区域和继承类

package com.????.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工具生成的。

这里写图片描述

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.????.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包

这里写图片描述

这里写图片描述

这里写图片描述

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

这里写图片描述

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、 场景设置与打包
场景设置

在这里插入图片描述

25、 安装测试

这里写图片描述

这里写图片描述
付款或者取消之后界面上显示的红字是刚刚的订单信息。请自行分析。不解释了
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);

3、unity版本:5.6.0f3
Eclispe版本:
这里写图片描述

至于官方说的什么签名啊验证啊订单信息啊以及签名密钥啊这些需要在服务端生成了就请自行完成了。

猜你喜欢

转载自blog.csdn.net/z502768095/article/details/78297151