您的位置:首页 > 移动开发 > Unity3D

Unity Android平台接入支付宝SDK

2017-03-18 15:07 239 查看
这篇文章前面讲的创建Android Studio工程的流程是不正确的!!!

正确的流程请参见:Unity Android平台下插件/SDK开发通用流程

最近帮一个群里的朋友接了一下支付宝的SDK,开发环境是Unity 5.4.x + 最新的Android Studio2.3版本,最终Android Studio输出的文件格式是aar而不是之前的jar,鉴于网上的文章大多数是基于Eclipse + jar包,所以记录一下基于Android Studio进行开发的过程,供大家参考。

下载与整理支付宝SDK

首先下载最新的支付宝SDK,解压缩后找到alipay_demo和alipay_sdk文件夹,它们分别是Eclipse demo工程和是支付宝的jar包。接下来的步骤的会用到这两个文件夹里的内容。

创建并配置Android Studio工程

创建一个新的Android工程,Package Name要和Unity -> PlayerSettings里的Bundle Identifier保持一致,Minimum API Level最好也保持一致,防止出现意外的问题(没测过)。
设置Application Name和Company Name。当然Package Name在创建工程后也能修改,不过很麻烦就是了(代码里的可以批量修改,但是AndroidManifest里的需要手动修改)。



设置Minimum API Level,API Level越低所能支持的设备越多,但为了向下兼容低版本的SDK,高版本的一些特有功能将无法使用。这里我选择了API Level 9,即Android 2.3.1,这样发布出来的插件可以跑在100%的安卓手机上了。



Unity中Identification设置示例如下(Unity里的必须是小写!因为Android Studio导出的PackageName是小写):



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



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



至此,完成创建,工程结构应该如图所示:



这里面有许多不需要的东西,比如测试工程,图标资源文件和安卓原生主题的配置文件。我们将其全部删除,删除完毕后工程清单如下所示:



可以看到,我们只保留了两个文件—— AndroidManifest.xml和MainActivity。打开自动生成的AndroidManifest.xml,可以发现有许多关于应用的配置:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.soulgame.magicgame">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>
这里的android:icon,android:label,android:roundIcon和android:theme是不需要的,删除它们。同时必须在<activity>标签里插入一行<meta-data>属性,应该是Unity打包时Merge AndroidManifest时需要的,修改后如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.soulgame.magicgame">

<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>
最后,因为我们输出的是一个库而不是一个apk,所以需要修改输出的结果,打开Gradle Scripts(Gradle是一种安卓构建脚本)下的build.gradle(Moudle:app),将第一行的:
apply plugin: 'com.android.application'
修改为:
apply plugin: 'com.android.library'
点击上方的sync now,会出现错误提示:
Error:Library projects cannot set applicationId. applicationId is set to 'com.soulgame.magicgame' in default config.
这是因为库文件不能设置applcation Id,另外build.gradle会包含单元测试的配置,也需要删除,如下图所示:



重新点击sync now,提示错误已经消失了。注意这个过程可能会发生其他的问题,如提示build-tools或platform版本过低的提示等等,这时候按照提示给出的方案更新SDK即可。
至此,基本环境配置完毕,接下来就是接入支付宝SDK了。

接入支付宝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.library'

android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 9
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile files('libs/alipaySdk-20170309.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包手动删除。

接下来就是正式开始参考支付宝提供的Demo和官方文档写支付方法了,包括添加混肴规则,修改AndroidManifest.xml增加Activity以及相关的权限设置等等。
其中添加混肴规则需要在Gradle Scripts/proguard-rules.pro里添加对应的规则:
-libraryjars libs/alipaySDK-20XXXXXX.jar //这里改成你所使用的SDK jar版本

-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}


研究支付宝给出的Demo可以发现,支付宝支付函数只需要一个加密后的订单信息字符串:
public void Pay(final String orderInfo)
{
Runnable payRunnable = new Runnable()
{

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

Thread payThread = new Thread(payRunnable);
payThread.start();
}
orderInfo可以在客户端生成,需要AppId,pid以及RSA等等,这样做不安全,推荐的做法是由服务端生成订单信息并加密(生成相关的逻辑在Demo里已经给出了),然后传递给客户端,客户端支付完成后,支付宝将执行一个配置好的URL,例如通知服务端支付完毕,而客户端在支付完成后提示支付成功与否的信息只能作为参考。
最后,附上一份由服务端传入订单信息的代码:
package com.soulgame.magicgame;

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.alipay.sdk.app.PayTask;
import com.unity3d.player.*;

import java.util.Map;

public class MainActivity extends UnityPlayerActivity
{
private static final int SDK_PAY_FLAG = 1;
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;
}
default:
break;
}
}

;
};

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
// Unity中调用
public void Pay(final String orderInfo) { Runnable payRunnable = new Runnable() { @Override public void run() { PayTask alipay = new PayTask(MainActivity.this); Map<String, String> result = alipay.payV2(orderInfo, true); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; mHandler.sendMessage(msg); } }; Thread payThread = new Thread(payRunnable); payThread.start(); }
}

在Unity中进行调用

在Assets下创建Plugins文件夹,然后在Plugins下创建Android文件夹,将aar和AndroidManifest.xml文件复制到该文件夹下。使用起来可以参考Unity官方文档
下面演示了客户端生成字符串的C#脚本,注意商品描述不能有空格!
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()
{
// 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(() =>
{
Alipay(payInfo);
});
#endif
}
#if UNITY_ANDROID && !UNITY_EDITOR
// 固定写法
AndroidJavaClass javaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
currentActivity = javaClass.GetStatic<AndroidJavaObject>("currentActivity");
#endif
}

public void Alipay(PayInfo payInfo)
{
// AlipayClient是Android里的方法名字,写死.
// payInfo.money是要付的钱,只能精确分.
// payInfo.title是商品描述信息,注意不能有空格.
currentActivity.Call("AlipayClient", payInfo.money, payInfo.title, "");
}
}
运行结果:



总结

1.前一部分配置AndroidStudio适用于所有的SDK。
2.支付宝Demo里有授权信息的方法,手机app内支付用不到,删除即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Unity Android SDK 支付宝