??Unity3D接入支付寶支付的流程非常復(fù)雜,涉及到很多方面(有任何問題都可以在評(píng)論區(qū)留言,我盡量盡快回復(fù))所以寫篇文章記錄一下。支付寶支付和微信支付以及其它支付差不多,但是支付寶有沙箱環(huán)境,可以很方便地調(diào)試,所以選用支付寶平臺(tái)作為演示。
??此教程使用了三個(gè)非常大的編輯器:Unity3D 2021.3.29f1c1、Visual Studio 2022、Android Studio 2022.3,其它版本也可以,不過缺一不可。主要流程大概是:編寫Unity3D服務(wù)端、編寫Android Studio SDK、編寫Unity3D客戶端。
1.準(zhǔn)備工作
打開下面這個(gè)鏈接,可以進(jìn)入到支付寶沙箱控制臺(tái)。
支付寶沙箱控制臺(tái)
在沙箱工具頁面可以下載到手機(jī)端的沙箱APP,用于測(cè)試。一定要下載到你的手機(jī)上,不能用原生的支付寶!
在沙箱應(yīng)用頁面,登錄后可以看到你的應(yīng)用的詳細(xì)信息,一會(huì)兒要用到這里的很多信息,我這里會(huì)把用的到信息標(biāo)注出來。
支付寶網(wǎng)關(guān)地址,默認(rèn)是 https://openapi-sandbox.dl.alipaydev.com/gateway.do
APPID
應(yīng)用私鑰
應(yīng)用公鑰
2.編寫Unity3D服務(wù)端
??說是Unity3D服務(wù)端,但其實(shí)不是用Unity3D寫的。編寫服務(wù)端主要用微軟的ASP.NET Core Web API技術(shù)進(jìn)行服務(wù)提供,此教程中要確保你的手機(jī)和電腦能連接同一個(gè)Wifi或是路由器。
??我們首先打開Visual Studio 2022,點(diǎn)擊創(chuàng)建新項(xiàng)目。
找到ASP.NET Core Web API應(yīng)用,注意不要找錯(cuò)了,微軟的東西有特別多名稱極其相似的項(xiàng)目模板。點(diǎn)擊下一步。
指定一個(gè)項(xiàng)目名稱,例如我的是:test_Alipay,點(diǎn)擊下一步。
為了演示,我用了如下配置,建議和我的配置是一樣的。最好選.NET6.0。點(diǎn)擊創(chuàng)建。
打開Program.cs可以看到如下代碼。
在左側(cè)的依賴項(xiàng)這里,右鍵-管理NuGet程序包,切換到瀏覽標(biāo)簽下。
搜索AlipaySDKNet,可以找到AlipaySDKNet.Core,點(diǎn)擊右面的安裝。
搜索Newtonsoft,可以找到Microsoft.AspNetCore.Mvc.NewtonsoftJson,指定版本號(hào)和你的.Net版本一致,點(diǎn)擊右面的安裝。
C#安裝包是肯定不會(huì)失敗的。
打開左側(cè)的appsettings.json文件,加入一行
"Urls": "http://0.0.0.0:8880",
代表服務(wù)從所有IP(0.0.0.0)的8880端口提供,需要服務(wù)時(shí)只需請(qǐng)求這個(gè)IP+端口。
右鍵Controller文件夾,-添加-新建項(xiàng),新建一個(gè)AlipayController.cs文件。
在新建的AlipayController.cs文件里插入如下代碼:
using Aop.Api.Request;
using Aop.Api.Response;
using Aop.Api;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
//改成你自己的項(xiàng)目名稱加上“.Controllers”
namespace test_Alipay.Controllers
{
[ApiController]
[Route("Alipay")]
public class AlipayController : ControllerBase
{
/// <summary>支付寶網(wǎng)關(guān)地址</summary>
private const string serverUrl = "支付寶網(wǎng)關(guān)地址";
/// <summary>APPID</summary>
private const string appId = "APPID";
/// <summary>應(yīng)用私鑰</summary>
private const string privateKeyPem = @"
應(yīng)用私鑰
應(yīng)用私鑰
";
/// <summary>應(yīng)用公鑰</summary>
private const string alipayPublicKey = @"
應(yīng)用公鑰
應(yīng)用公鑰
";
[HttpPost("GetOrderStr")]
public string GetOrderStr(JObject request)
{
string out_trade_no = request["out_trade_no"]?.ToString() ?? Random.Shared.Next(1, 1000000).ToString();
float total_amount = ((float?)request["total_amount"]) ?? 0.01f;
string subject = request["subject"]?.ToString() ?? "測(cè)試商品";
string product_code = request["product_code"]?.ToString() ?? "QUICK_MSECURITY_PAY";
IAopClient client = new DefaultAopClient(
serverUrl
, appId
, privateKeyPem
, "json"
, "1.0"
, "RSA2"
, alipayPublicKey
, "utf-8"
, false);
AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
alipayRequest.SetNotifyUrl("");
Dictionary<string, object> bizContent = new Dictionary<string, object>();
bizContent.Add("out_trade_no", out_trade_no);
bizContent.Add("total_amount", total_amount);
bizContent.Add("subject", subject);
bizContent.Add("product_code", product_code);
//bizContent.Add("time_expire", "2023-10-14 14:58:00");
//商品明細(xì)信息,按需傳入
//List<object> goodsDetails = new List<object>();
//Dictionary<string, object> goods1 = new Dictionary<string, object>();
//goods1.Add("goods_id", "goodsNo1");
//goods1.Add("goods_name", "子商品1");
//goods1.Add("quantity", 1);
//goods1.Add("price", 0.01);
//goodsDetails.Add(goods1);
//bizContent.Add("goods_detail", goodsDetails);
//擴(kuò)展信息,按需傳入
//Dictionary<string, object> extendParams = new Dictionary<string, object>();
//extendParams.Add("sys_service_provider_id", "2088501624560335");
//bizContent.Add("extend_params", extendParams);
string Contentjson = JsonConvert.SerializeObject(bizContent);
alipayRequest.BizContent = Contentjson;
AlipayTradeAppPayResponse response = client.SdkExecute(alipayRequest);
Console.WriteLine(response.Body);
JObject jObject = new JObject();
jObject["order"] = response.Body;
return jObject.ToString();
}
}
}
注意,將這個(gè)類的所有const類型的字符串都改成你自己的設(shè)置,詳細(xì)信息參見代碼里的注釋對(duì)應(yīng)《準(zhǔn)備工作》中的一些參數(shù)
為了測(cè)試,可以將Program.cs文件改為以下代碼:
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
using System.Text;
namespace test_Alipay
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
//使Controller能接受JObject對(duì)象
builder.Services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.MapControllers();
Task.Run(() =>
{
Thread.Sleep(200);
HttpClient httpClient = new HttpClient();
JObject requestBody = new JObject();
StringContent content = new StringContent(requestBody.ToString(), Encoding.UTF8, "application/json");
httpClient.PostAsync("http://127.0.0.1:8880/Alipay/GetOrderStr", content);
});
app.Run();
}
}
}
可以試著運(yùn)行一下程序,沒問題的話,就進(jìn)行下一步了??梢钥吹将@取到了order,也就是訂單號(hào),在Unity3D中,使用這個(gè)東西就可以向支付寶發(fā)出支付請(qǐng)求了。
注意事項(xiàng):安裝AlipaySDKNet.Core NuGet包,如果沒有Microsoft.AspNetCore.Mvc.NewtonsoftJson的話也要安裝一個(gè)。
3. 編寫Android Studio SDK
??由于作者沒開發(fā)過Android原生APP,所以對(duì)Android Studio不是很熟悉,如有錯(cuò)誤,請(qǐng)多包涵,可以去其他博主那里看看他們的文章參考一下。
打開Android Studio 2022.3。
新建項(xiàng)目,選擇Empty Views Activity,點(diǎn)擊Next。
應(yīng)用如下配置:這里記住你的Package name,一會(huì)兒有用!(而且包名必須和Unity3D中的包名一致,請(qǐng)注意!)
點(diǎn)擊Finish后,就可以創(chuàng)建工程了,第一次創(chuàng)建會(huì)極其地慢,需要耐心等待,并且可能會(huì)出現(xiàn)網(wǎng)絡(luò)連接問題。
等待右下角進(jìn)度條消失…
點(diǎn)擊頂部菜單欄File-Project Structure,
這里刪去原有的模塊。
頂部菜單欄,F(xiàn)ile-New-New Module,
選中Android Library,必須是Library,指定一個(gè)Module name(隨意,不過最好和我一樣),Package name是項(xiàng)目包名.模塊名。
切換到Project視圖,可以看到目錄結(jié)構(gòu)。
這里我們需要三個(gè)東西:支付寶官方的SDK(.aar包)、Unity的SDK、Unity的Java類。
以下是支付寶的SDK的下載鏈接,鏈接是我自己的鏈接,所以時(shí)間久了可能會(huì)失效。不過網(wǎng)上有很多這個(gè)資源,支付寶開放平臺(tái)上也可以下載的到,或者直接從Android Studio里安裝包也可以(不過需要導(dǎo)出aar包,因?yàn)閁nity里要用到)
鏈接: 支付寶aar包:alipaysdk-android-15.8.16.aar
下載好了后,復(fù)制到桌面(一會(huì)兒用),并直接復(fù)制到項(xiàng)目的Alipay模塊的libs文件夾下,注意:路徑別錯(cuò)了。
接下來需要準(zhǔn)備Unity的JavaSDK和Unity的Java類,這兩個(gè)東西在Unity編輯器安裝的位置下能找得到。
打開Unity Editor安裝的位置,不知道的可以去Unity Hub里找位置:
搜索classes.jar,找到后復(fù)制到桌面上。一共有4個(gè),找到il2cpp\Release\目錄下的。(或Mono的也可以)
再搜索UnityPlayerActivity,找到后復(fù)制到桌面上。
classes.jar放到這里,
UnityPlayerActivity.java放到這里,
然后打開build.gradle文件:
在最下面加入一行:點(diǎn)擊同步設(shè)置
compileOnly fileTree(include: ['*.jar','*.aar'], dir: 'libs')
打開UnityPlayerActivity.java腳本,加入三行引用:
import com.unity3d.player.IUnityPlayerLifecycleEvents;
import com.unity3d.player.MultiWindowSupport;
import com.unity3d.player.UnityPlayer;
接下來新建一個(gè)java腳本:AlipayActivity.java
將其改為以下代碼:
package com.csdn.test_alipay.Alipay;//換成你自己的包名
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import com.alipay.sdk.app.EnvUtils;
import com.alipay.sdk.app.PayTask;
import com.unity3d.player.UnityPlayer;
public class AlipayActivity extends UnityPlayerActivity {
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
// 支付寶支付
public void AliPay(final String orderInfo, final Context context, String callBackObjectName, String CallBackFuncName)
{
// 沙箱環(huán)境時(shí)需要這行代碼,正式環(huán)境下刪除掉?。?!
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
Log.i("Unity", " >>> enter alipay native");
Runnable payRun = new Runnable() {
@Override
public void run() {
PayTask task=new PayTask((Activity)context);
String result= task.pay(orderInfo, true);
Log.i("Unity", "onALIPayFinish, result = " + result);
// 這里可以自己添加Unity回調(diào)接收
UnityPlayer.UnitySendMessage(callBackObjectName, CallBackFuncName, result);
}
};
Thread payThread = new Thread(payRun);
payThread.start();
}
}
做完了這些就可以打包了(如果沒有編譯錯(cuò)誤),頂部菜單欄Build-Make Module,
找到這個(gè)文件(Build出來的文件):Alipay-debug.aar
右鍵,在文件夾中打開:
復(fù)制到桌面上,有了這兩個(gè)文件(Alipay-debug.aar、alipaysdk-android-15.8.16.aar)就可以在Unity中很方便地進(jìn)行調(diào)用了。
4.編寫Unity3D客戶端
??做著做著,都忘了自己要做啥了,終于開始咱們的Unity項(xiàng)目,接下來就到了咱們熟悉的領(lǐng)域了。下面的教程就沒有那么詳細(xì)了,不過步驟還是不能少的。
新建Unity項(xiàng)目。(2D核心模板也可以,其實(shí)都一樣,我的這個(gè)2D Mobile模板是有bug的,打包不了)
在Build Settings里切換一下平臺(tái)。
在Player Settings里改一下包名:一定要和Android Studio里的項(xiàng)目包名一致(我的是com.csdn.test_alipay)。
再將API Level改成7.0(24)
可以先打個(gè)包看看有沒有問題,沒問題就進(jìn)行接下來的內(nèi)容:
1.調(diào)用Unity服務(wù)端的服務(wù)獲取order字符串
安裝Newtonsoft.Json包,
新建腳本文件AlipayManager.cs,并掛載到一個(gè)物體上。
這個(gè)物體的名稱一會(huì)兒還會(huì)用到,所以這個(gè)記住了。
打開腳本,將腳本改成如下:
using System;
using System.Collections;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Newtonsoft.Json.Linq;
public class AlipayManager : MonoBehaviour
{
[Header("點(diǎn)擊支付的按鈕")]
public Button payButton;
[Header("用于輸出調(diào)試信息的文本")]
public Text debugText;
private void Awake()
{
//綁定按鈕事件
payButton.onClick.AddListener(OnPayButtonClick);
}
/// <summary>
/// 點(diǎn)擊支付的按鈕 按下時(shí)調(diào)用
/// </summary>
private void OnPayButtonClick()
{
StartCoroutine(GetOrderStr(orderStr =>
{
if(string.IsNullOrEmpty(orderStr))
{
return;
}
//原生調(diào)用支付寶支付
ShowALiPay(orderStr);
}));
}
/// <summary>
/// 原生調(diào)用支付寶支付
/// <param name="orderInfo">臨時(shí)的訂單號(hào)</param>
/// </summary>
private void ShowALiPay(string orderInfo)
{
debugText.text += "\n服務(wù)器返回訂單號(hào) >>>> " + orderInfo.Substring(0, 20);
Debug.Log("服務(wù)器返回訂單號(hào) >>>> " + orderInfo); // 此處是后端返回的訂單信息
#if UNITY_ANDROID
//固定不變
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
//固定不變
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
//這里要改成你自己的 包名.模塊名.AlipayActivity ?。。。。。?/span>
AndroidJavaObject utils = new AndroidJavaObject("com.csdn.test_alipay.Alipay.AlipayActivity");
//這里的第一個(gè)參數(shù)是Java函數(shù)名,第四個(gè)參數(shù)是當(dāng)前腳本掛載物體的名稱,一定要對(duì)?。。。。?!
//最后一個(gè)參數(shù)是回調(diào)的Unity3D中的函數(shù)名,下面有
utils.Call("AliPay", orderInfo, currentActivity, "AlipayManager", "ALiPayResult");
#endif
}
/// <summary>
/// 支付寶 支付回調(diào)
/// </summary>
/// <param name="result">支付結(jié)果通知,支持本地通知和云通知(結(jié)果傳回到你的服務(wù)端中),這里為了簡(jiǎn)單只展示了本地通知</param>
public void ALiPayResult(string result)
{
debugText.text += "\n unity 獲取支付寶回調(diào)>>>> " + result;
Debug.Log(" unity 獲取支付寶回調(diào)>>>> " + result);
}
/// <summary>
/// 向當(dāng)前網(wǎng)絡(luò)的本機(jī)請(qǐng)求訂單號(hào)
/// </summary>
/// <param name="callback"></param>
/// <returns></returns>
private IEnumerator GetOrderStr(Action<string> callback)
{
//構(gòu)建請(qǐng)求體
JObject request = new JObject();
request["out_trade_no"] = UnityEngine.Random.Range(1,100000000).ToString();
request["total_amount"] = 0.01f;
request["subject"] = "測(cè)試商品";
request["product_code"] = "QUICK_MSECURITY_PAY";
//初始化WebRequest 這里的地址要改成你網(wǎng)絡(luò)的地址?。。。。?!
UnityWebRequest webRequest = UnityWebRequest.Post("http://183.173.67.199:8880/Alipay/GetOrderStr/", string.Empty);
webRequest.SetRequestHeader("Content-Type", "application/json;");
//webRequest.SetRequestHeader("Accept", "application/json");
//設(shè)置超時(shí)時(shí)間(秒)
webRequest.timeout = 10;
//設(shè)置發(fā)送消息的緩存區(qū)
webRequest.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(request.ToString()));
//等待返回消息
yield return webRequest.SendWebRequest();
//成功接收到消息
if (webRequest.result == UnityWebRequest.Result.Success)
{
//解析Json字符串
JObject jObject = JObject.Parse(webRequest.downloadHandler.text);
//獲取訂單號(hào)
string orderStr = jObject["order"].ToString();
//回調(diào)
callback.Invoke(orderStr);
}
else
{
debugText.text += "\n錯(cuò)誤信息:" + webRequest.error;
Debug.Log("錯(cuò)誤信息:" + webRequest.error);
debugText.text += "\n向當(dāng)前網(wǎng)絡(luò)的本機(jī)請(qǐng)求訂單號(hào)失敗,可能是Unity服務(wù)端程序(Web API)沒有開始,或是IP和端口號(hào)沒有設(shè)置正確";
Debug.Log("向當(dāng)前網(wǎng)絡(luò)的本機(jī)請(qǐng)求訂單號(hào)失敗,可能是Unity服務(wù)端程序(Web API)沒有開始,或是IP和端口號(hào)沒有設(shè)置正確");
//失敗回調(diào)
callback.Invoke(null);
}
webRequest.Dispose();
yield break;
}
}
這里面有幾個(gè)參數(shù)很重要:
查看注釋帶有6個(gè)感嘆號(hào)的參數(shù),一定要根據(jù)你自己設(shè)置的參數(shù)進(jìn)行修改,其中最后一個(gè)參數(shù)我要說明一下:
UnityWebRequest webRequest = UnityWebRequest.Post(“http://183.173.67.199:8880/Alipay/GetOrderStr/”, string.Empty);
這個(gè)參數(shù)要查看你的Wifi的IPv4的地址,找到你的Wifi的屬性:
最下面的這行IP地址填入到你的代碼中:
將"http://183.173.67.199:8880/Alipay/GetOrderStr/"中的183.173.67.199改成你自己的。
2.根據(jù)order字符串請(qǐng)求支付
在Unity場(chǎng)景中添加一個(gè)用于支付的按鈕和調(diào)試文本框:
將這兩個(gè)物體拖到腳本中:
最后有個(gè)很重要的事:將剛才生成的兩個(gè)arr包拖到Unity3D的資源文件夾下,文件夾的路徑要和我一樣!要不然Unity可能檢測(cè)不到。
5.運(yùn)行測(cè)試
先啟動(dòng)服務(wù)程序(ASP.NET Core Web API),如圖所示開啟成功。
確保你的手機(jī)和你的電腦連接的是同一個(gè)Wifi或是路由器,要不然訪問不到!
接下來打開Unity Android端的APP,點(diǎn)擊支付
如圖所示即為支付成功:
可以看到有一行:“msg”:“Success”。文章來源:http://www.zghlxwxcb.cn/news/detail-861743.html
如果對(duì)本教程有任何問題,歡迎在評(píng)論區(qū)評(píng)論,我看到后一定盡快回復(fù)。文章來源地址http://www.zghlxwxcb.cn/news/detail-861743.html
到了這里,關(guān)于Unity Android平臺(tái)接入支付寶支付全流程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!