Unity Android平台接入支付宝支付全流程

  Unity3D接入支付宝支付的流程非常复杂,涉及到很多方面(有任何问题都可以在评论区留言,我尽量尽快回复)所以写篇文章记录一下。支付宝支付和微信支付以及其它支付差不多,但是支付宝有沙箱环境,可以很方便地调试,所以选用支付宝平台作为演示。
  此教程使用了三个非常大的编辑器:Unity3D 2021.3.29f1c1、Visual Studio 2022、Android Studio 2022.3,其它版本也可以,不过缺一不可。主要流程大概是:编写Unity3D服务端、编写Android Studio SDK、编写Unity3D客户端。

1.准备工作

打开下面这个链接,可以进入到支付宝沙箱控制台。
支付宝沙箱控制台
在沙箱工具页面可以下载到手机端的沙箱APP,用于测试。一定要下载到你的手机上,不能用原生的支付宝!
在这里插入图片描述
在沙箱应用页面,登录后可以看到你的应用的详细信息,一会儿要用到这里的很多信息,我这里会把用的到信息标注出来。
支付宝网关地址,默认是 https://openapi-sandbox.dl.alipaydev.com/gateway.do
在这里插入图片描述
APPID
在这里插入图片描述
应用私钥
在这里插入图片描述
在这里插入图片描述
应用公钥
在这里插入图片描述

2.编写Unity3D服务端

  说是Unity3D服务端,但其实不是用Unity3D写的。编写服务端主要用微软的ASP.NET Core Web API技术进行服务提供,此教程中要确保你的手机和电脑能连接同一个Wifi或是路由器。
  我们首先打开Visual Studio 2022,点击创建新项目。
在这里插入图片描述
找到ASP.NET Core Web API应用,注意不要找错了,微软的东西有特别多名称极其相似的项目模板。点击下一步。
在这里插入图片描述
指定一个项目名称,例如我的是:test_Alipay,点击下一步。
在这里插入图片描述
为了演示,我用了如下配置,建议和我的配置是一样的。最好选.NET6.0。点击创建。
在这里插入图片描述
打开Program.cs可以看到如下代码。
在这里插入图片描述
在左侧的依赖项这里,右键-管理NuGet程序包,切换到浏览标签下。
在这里插入图片描述
搜索AlipaySDKNet,可以找到AlipaySDKNet.Core,点击右面的安装。
在这里插入图片描述
搜索Newtonsoft,可以找到Microsoft.AspNetCore.Mvc.NewtonsoftJson,指定版本号和你的.Net版本一致,点击右面的安装。
在这里插入图片描述

C#安装包是肯定不会失败的。
打开左侧的appsettings.json文件,加入一行

  "Urls": "http://0.0.0.0:8880",

代表服务从所有IP(0.0.0.0)的8880端口提供,需要服务时只需请求这个IP+端口。
在这里插入图片描述

右键Controller文件夹,-添加-新建项,新建一个AlipayController.cs文件。
在这里插入图片描述
在这里插入图片描述
在新建的AlipayController.cs文件里插入如下代码:

using Aop.Api.Request;
using Aop.Api.Response;
using Aop.Api;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

//改成你自己的项目名称加上“.Controllers”
namespace test_Alipay.Controllers
{
    [ApiController]
    [Route("Alipay")]
    public class AlipayController : ControllerBase
    {
        /// <summary>支付宝网关地址</summary>
        private const string serverUrl = "支付宝网关地址";
        /// <summary>APPID</summary>
        private const string appId = "APPID";
        /// <summary>应用私钥</summary>
        private const string privateKeyPem = @"
应用私钥
应用私钥
";
        /// <summary>应用公钥</summary>
        private const string alipayPublicKey = @"
应用公钥
应用公钥
";

        [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() ?? "测试商品";
            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");

            //商品明细信息,按需传入
            //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);

            //扩展信息,按需传入
            //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();
        }
    }
}

注意,将这个类的所有const类型的字符串都改成你自己的设置,详细信息参见代码里的注释对应《准备工作》中的一些参数
为了测试,可以将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对象
            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();
        }
    }
}

可以试着运行一下程序,没问题的话,就进行下一步了。可以看到获取到了order,也就是订单号,在Unity3D中,使用这个东西就可以向支付宝发出支付请求了。
在这里插入图片描述

注意事项:安装AlipaySDKNet.Core NuGet包,如果没有Microsoft.AspNetCore.Mvc.NewtonsoftJson的话也要安装一个。

3. 编写Android Studio SDK

  由于作者没开发过Android原生APP,所以对Android Studio不是很熟悉,如有错误,请多包涵,可以去其他博主那里看看他们的文章参考一下。
打开Android Studio 2022.3。
新建项目,选择Empty Views Activity,点击Next。
在这里插入图片描述
应用如下配置:这里记住你的Package name,一会儿有用!(而且包名必须和Unity3D中的包名一致,请注意!)
在这里插入图片描述
点击Finish后,就可以创建工程了,第一次创建会极其地慢,需要耐心等待,并且可能会出现网络连接问题。
在这里插入图片描述
等待右下角进度条消失…
点击顶部菜单栏File-Project Structure,
在这里插入图片描述
这里删去原有的模块。
在这里插入图片描述
顶部菜单栏,File-New-New Module,
在这里插入图片描述
选中Android Library,必须是Library,指定一个Module name(随意,不过最好和我一样),Package name是项目包名.模块名。
在这里插入图片描述
切换到Project视图,可以看到目录结构。
在这里插入图片描述
这里我们需要三个东西:支付宝官方的SDK(.aar包)、Unity的SDK、Unity的Java类。
以下是支付宝的SDK的下载链接,链接是我自己的链接,所以时间久了可能会失效。不过网上有很多这个资源,支付宝开放平台上也可以下载的到,或者直接从Android Studio里安装包也可以(不过需要导出aar包,因为Unity里要用到)
链接: 支付宝aar包:alipaysdk-android-15.8.16.aar
下载好了后,复制到桌面(一会儿用),并直接复制到项目的Alipay模块的libs文件夹下,注意:路径别错了。
![在这里插入图片描述](https://img-blog.csdnimg.cn/6940c92cc0bd4e68b875dbabe9e91b9b.png
在这里插入图片描述
接下来需要准备Unity的JavaSDK和Unity的Java类,这两个东西在Unity编辑器安装的位置下能找得到。
打开Unity Editor安装的位置,不知道的可以去Unity Hub里找位置:
在这里插入图片描述
在这里插入图片描述
搜索classes.jar,找到后复制到桌面上。一共有4个,找到il2cpp\Release\目录下的。(或Mono的也可以)
在这里插入图片描述
在这里插入图片描述
再搜索UnityPlayerActivity,找到后复制到桌面上。
在这里插入图片描述
classes.jar放到这里,
在这里插入图片描述
UnityPlayerActivity.java放到这里,
在这里插入图片描述
然后打开build.gradle文件:
在这里插入图片描述
在最下面加入一行:点击同步设置

    compileOnly fileTree(include: ['*.jar','*.aar'], dir: 'libs')

在这里插入图片描述
打开UnityPlayerActivity.java脚本,加入三行引用:

import com.unity3d.player.IUnityPlayerLifecycleEvents;
import com.unity3d.player.MultiWindowSupport;
import com.unity3d.player.UnityPlayer;

在这里插入图片描述
接下来新建一个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)
    {
        // 沙箱环境时需要这行代码,正式环境下删除掉!!!
        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回调接收
                UnityPlayer.UnitySendMessage(callBackObjectName, CallBackFuncName, result);
            }
        };
        Thread payThread = new Thread(payRun);
        payThread.start();
    }
}

做完了这些就可以打包了(如果没有编译错误),顶部菜单栏Build-Make Module,
在这里插入图片描述
找到这个文件(Build出来的文件):Alipay-debug.aar
在这里插入图片描述
右键,在文件夹中打开:
在这里插入图片描述
复制到桌面上,有了这两个文件(Alipay-debug.aar、alipaysdk-android-15.8.16.aar)就可以在Unity中很方便地进行调用了。
在这里插入图片描述

4.编写Unity3D客户端

  做着做着,都忘了自己要做啥了,终于开始咱们的Unity项目,接下来就到了咱们熟悉的领域了。下面的教程就没有那么详细了,不过步骤还是不能少的。
新建Unity项目。(2D核心模板也可以,其实都一样,我的这个2D Mobile模板是有bug的,打包不了)
在这里插入图片描述
在Build Settings里切换一下平台。
在这里插入图片描述
在Player Settings里改一下包名:一定要和Android Studio里的项目包名一致(我的是com.csdn.test_alipay)。
在这里插入图片描述
再将API Level改成7.0(24)
在这里插入图片描述

可以先打个包看看有没有问题,没问题就进行接下来的内容:

1.调用Unity服务端的服务获取order字符串

安装Newtonsoft.Json包,
在这里插入图片描述
在这里插入图片描述

新建脚本文件AlipayManager.cs,并挂载到一个物体上。
在这里插入图片描述
在这里插入图片描述
这个物体的名称一会儿还会用到,所以这个记住了。
打开脚本,将脚本改成如下:

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("点击支付的按钮")]
    public Button payButton;
    [Header("用于输出调试信息的文本")]
    public Text debugText;

    private void Awake()
    {
        //绑定按钮事件
        payButton.onClick.AddListener(OnPayButtonClick);
    }

    /// <summary>
    /// 点击支付的按钮 按下时调用
    /// </summary>
    private void OnPayButtonClick()
    {
        StartCoroutine(GetOrderStr(orderStr =>
        {
            if(string.IsNullOrEmpty(orderStr))
            {
                return;
            }
            //原生调用支付宝支付
            ShowALiPay(orderStr);
        }));
    }
    /// <summary>
    /// 原生调用支付宝支付
    /// <param name="orderInfo">临时的订单号</param>
    /// </summary>
    private void ShowALiPay(string orderInfo)
    {
        debugText.text += "\n服务器返回订单号 >>>> " + orderInfo.Substring(0, 20);
        Debug.Log("服务器返回订单号 >>>> " + orderInfo);  // 此处是后端返回的订单信息
#if UNITY_ANDROID
        //固定不变
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        //固定不变
        AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        //这里要改成你自己的 包名.模块名.AlipayActivity !!!!!!
        AndroidJavaObject utils = new AndroidJavaObject("com.csdn.test_alipay.Alipay.AlipayActivity");
        //这里的第一个参数是Java函数名,第四个参数是当前脚本挂载物体的名称,一定要对!!!!!!
        //最后一个参数是回调的Unity3D中的函数名,下面有
        utils.Call("AliPay", orderInfo, currentActivity, "AlipayManager", "ALiPayResult");
#endif
    }
    /// <summary>
    ///  支付宝 支付回调
    /// </summary>
    /// <param name="result">支付结果通知,支持本地通知和云通知(结果传回到你的服务端中),这里为了简单只展示了本地通知</param>
    public void ALiPayResult(string result)
    {
        debugText.text += "\n unity 获取支付宝回调>>>> " + result;
        Debug.Log(" unity 获取支付宝回调>>>> " + result);
    }
    /// <summary>
    /// 向当前网络的本机请求订单号
    /// </summary>
    /// <param name="callback"></param>
    /// <returns></returns>
    private IEnumerator GetOrderStr(Action<string> callback)
    {
        //构建请求体
        JObject request = new JObject();
        request["out_trade_no"] = UnityEngine.Random.Range(1,100000000).ToString();
        request["total_amount"] = 0.01f;
        request["subject"] = "测试商品";
        request["product_code"] = "QUICK_MSECURITY_PAY";
        //初始化WebRequest  这里的地址要改成你网络的地址!!!!!!
        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");
        //设置超时时间(秒)
        webRequest.timeout = 10;
        //设置发送消息的缓存区
        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);
            //获取订单号
            string orderStr = jObject["order"].ToString();
            //回调
            callback.Invoke(orderStr);
        }
        else
        {
            debugText.text += "\n错误信息:" + webRequest.error;
            Debug.Log("错误信息:" + webRequest.error);
            debugText.text += "\n向当前网络的本机请求订单号失败,可能是Unity服务端程序(Web API)没有开始,或是IP和端口号没有设置正确";
            Debug.Log("向当前网络的本机请求订单号失败,可能是Unity服务端程序(Web API)没有开始,或是IP和端口号没有设置正确");
            //失败回调
            callback.Invoke(null);
        }
        webRequest.Dispose();
        yield break;
    }
}

这里面有几个参数很重要:
查看注释带有6个感叹号的参数,一定要根据你自己设置的参数进行修改,其中最后一个参数我要说明一下:
UnityWebRequest webRequest = UnityWebRequest.Post(“http://183.173.67.199:8880/Alipay/GetOrderStr/”, string.Empty);
这个参数要查看你的Wifi的IPv4的地址,找到你的Wifi的属性:
在这里插入图片描述
最下面的这行IP地址填入到你的代码中:
将"http://183.173.67.199:8880/Alipay/GetOrderStr/"中的183.173.67.199改成你自己的。
在这里插入图片描述

2.根据order字符串请求支付

在Unity场景中添加一个用于支付的按钮和调试文本框:
在这里插入图片描述
将这两个物体拖到脚本中:
在这里插入图片描述
最后有个很重要的事:将刚才生成的两个arr包拖到Unity3D的资源文件夹下,文件夹的路径要和我一样!要不然Unity可能检测不到。
在这里插入图片描述

5.运行测试

先启动服务程序(ASP.NET Core Web API),如图所示开启成功。
在这里插入图片描述
在这里插入图片描述
确保你的手机和你的电脑连接的是同一个Wifi或是路由器,要不然访问不到!
接下来打开Unity Android端的APP,点击支付
在这里插入图片描述
如图所示即为支付成功:
在这里插入图片描述
在这里插入图片描述
可以看到有一行:“msg”:“Success”。

如果对本教程有任何问题,欢迎在评论区评论,我看到后一定尽快回复。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高思宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值