Kotlin:支付宝app支付接入,沙箱demo,PHP服务端签名

为了给自己小应用加个捐赠。

用了支付宝的接口。

本篇是算是自己总结吧,一路坎坷。

一个demo图(在服务器签的)

null

应用采用的是Kotlin开发的,为了测试支付宝的接口,就用了一个demo测试。本篇都是这个demo为基础。(kt版demo)

完全兼容支付宝的SDK,此处用得是新版的SDK,AAR格式

首先下载好SDK的aar文件,放入项目的libs文件夹下。

在app级的构建中加上:

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

null

然后同步一下。

null

就是这个啦。然后我们就可以直接使用这里面的东西了。

这里说一下逻辑:

我用的是沙箱版账号(测试用)

在支付宝开发者控制台有的,申请一个账号。

null

一定注意:这里的 APPID,RSA秘钥,支付宝公钥,和我们正式上线的不一样!而且这里注意支付宝公钥和我们自己的公钥是不一样的!它会根据你的公钥自动生成的。

我们的公钥和私钥要用他的工具生成,也有别的方法,就不介绍了,这样,公钥与私钥要匹配!

null

RSA和RSA2是可选的,默认是RSA,如果你设置了2个,就用RSA2,(后面会用!)

我们有了测试用的账号,然后要下载沙箱版支付宝,登录你的测试账号。可以扫码付钱了(只能扫你的商户账号)

现在的情况理一下:

我们有了支付宝,有了商户账号,有了支付账号,有了自己的公钥和私钥还有支付宝的公钥,还有APPID。

再提醒一下:支付宝网关:我们用沙箱版账号,注意是:https://openapi.alipaydev.xxx dev是沙箱用得

https://docs.open.alipay.com/200/105311/

然后我们回到app那边:一个支付,一个输出返回的数据组件

在android的主活动里:

onCreate方法里启动沙箱环境:

null​借得图,as关了,,

上线后记得注释掉。

null

好了,开始正题:逻辑理一下

我们在应用上点击支付->生成订单数据->给服务器端->接收订单,签名->返回给android->android拿到这个签名的数据->启动支付宝支付->支付宝支付完成后,会有两个通知,一个同步通知,返还给andoid本地客户端。另一个是异步通知,给我们服务端的接口(这个接口一会介绍服务端再说)->我们的接口收到支付宝的请求(处理自己的业务逻辑,比如确定订单,或者添加记录),要应答支付宝:success,不然支付宝会一直请求。->支付宝接收success字符,此订单号有效。->下一步,我们可以让android端请求一看看有没有这个记录,有了同步和异步更安全点。

引入SDK,有几个文件,我们要处理。

null

先在说一下服务端逻辑(具体操作,下面会说,逻辑有了,就方便了)

我们根据自己情况,选择服务端的SDK,我这里用的是PHP

null

我们要在自己的接口里,引入AopSDk.php这是SDK的入口文件,我用的是原生PHP

下面是发起支付请求了,我没有做订单处理,需要的可以在这里处理。

请求这里注意:RSA2和之前的对应,默认是RSA,$orderId 是不可以重复的!不然会支付失败,不如ali系列的错误!

这里用到了支付宝公钥和私钥。

PHP的sdk帮我们处理封装好了很多东西。

biz_content里面有很多参数,具体看文档哦.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php





require './AopSdk.php';



/*发起APP阿里支付订单*/

function SubmitAlipaysend($OrderId,$body="jz",$subject="ms",$UserId="123",$PayMoney=5,$PayType="",$NotifyPage = "https://www.xxxxxks.top/MAS/msAlipay/ok.php")

{

try

{

$aop = new AopClient();

$aop->gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

$aop->appId = '2016092xxxx1'; //支付宝分配给开发者的应用ID

$aop->alipayrsaPublicKey = 'xxxxx'; //支付宝公钥

$aop->rsaPrivateKey='xxxxx='; // 请填写开发者私钥去头去尾去回车,一行字符串

$aop->format = "json";//仅支持JSON

$aop->charset = "UTF-8";//请求使用的编码格式,如utf-8,gbk,gb2312

$aop->signType = "RSA2";//目前支持RSA2和RSA,推荐使用RSA2



//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay

$request = new AlipayTradeAppPayRequest();

//SDK已经封装掉了公共参数,这里只需要传入业务参数

$bizcontent = "{\"body\":\"".$body."\","

. "\"subject\": \"".$subject."\","

. "\"out_trade_no\": \"".$OrderId."\","

. "\"timeout_express\": \"30m\","

. "\"total_amount\": \"".$PayMoney."\","

. "\"product_code\":\"QUICK_MSECURITY_PAY\""

. "}";

$request->setNotifyUrl($NotifyPage);

$request->setBizContent($bizcontent);

//这里和普通的接口调用不同,使用的是sdkExecute

$response = $aop->sdkExecute($request);

//htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题

// echo htmlspecialchars($response);

// 可以直接给客户端请求,无需再做处理。

echo $response ;

die();

}

catch (Exception $ex)

{

echo $ex->getMessage();

}

}



SubmitAlipaysend(time());





?>

null

我们在android端拿到这个签名的数据:ResData,result是支付宝支付后返回的同步通知数据,就是我们单击支付,跳转支付界面,支付后会返回数据到android,然后支付宝会再向我们服务端留的地址,发送一个异步通知!到**$NotifyPage**

这里我们解析一点数据如上!数据是一个Map格式的。其中有json字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Thread{

val alipay = PayTask(this@MainActivity)

val result = alipay.payV2(ResData, true)

if( result["resultStatus"] == "9000"){



val sign = JSONObject(result["result"]).getJSONObject("alipay_trade_app_pay_response").getString("trade_no")

checkUser(this,sign)

payId = sign



}

}.start()


null

android端支付完了,我们看看服务端怎么处理的,**$NotifyPage**

下图是部分逻辑:

最重要的验证函数,PHP的sdk帮我们把参数过滤了,并且编码了,不用和java或者别的sdk一样,手动处理。

直接可以把$_POST数据放进去,调用验证方法。

如果流程正常:$flag应该是true

如果是:false

注意:这里是支付宝公钥(字符串或者证书格式,取决于中间的null,null应该传证书路径!否则我们就设置字符串的公钥)

$NotifyPage:这个是异步通知接口,支付宝会发送支付后的数据到这个接口,我们自己的,外网可访问的,在这里我们还要做个验签!

null

null

一定按照文档流程走下去。