你笑了

你的笑,是星星跳跃浪花的笑

0%

支付宝APP支付

APP支付

  • 在商家移动端APP内使用支付宝支付功能

  • 用户在商家APP内消费,在支付时选择支付宝付款,调起支付宝APP完成支付

开发文档

接入准备

  1. 创建网页/移动应用

    • 使用企业账号登录支付宝开发平台

    • 创建网页/移动应用

      自动生成唯一标识 APPID,用于调用API

  2. 开通 APP 支付

    • 使用应用所属账号登录商家平台开通
    • 如果是个人账号申请,需提供营业执照,且登录账号名称需与营业执照主体一致
  3. 绑定APP支付

  4. 配置应用信息

配置应用信息

配置项检测

  • 接口加签方式

    使用密钥方式,平台生成RSA2密钥

    通过平台生成的私钥是PKCS8格式的,需要转换为 PKCS1 格式,否则报错ASN1_CHECK_TLEN

    应用私钥:用来给应用消息进行签名,请务必要妥善保管,避免遗失或泄露。

    应用公钥:需要提供给支付宝开放平台,平台会对应用发送的消息进行签名验证

    支付宝公钥:应用收到支付宝发送的同步、异步消息时,使用支付宝公钥验证签名信息。

  • 支付宝网关

    固定为 https://openapi.alipay.com/gateway.do

  • 应用网关

    接收支付宝异步通知消息,需要传入 http(s) 公网可访问网页地址

  • 接口内容加密方式【选填】

    对请求业务内容和响应内容进行AES加密

结算

收款账户:默认收款到签约账号的支付宝余额账户,实时到账

接入

交互流程图

  • 第 1 步用户在商户 App 客户端/小程序中购买商品下单

  • 第 2 步商户 App 客户端/小程序将用户订单信息发送到商户服务端

  • 第 3 步商户服务端通过支付宝服务端 SDK生成 orderStr(orderStr 中包含了订单信息和签名)

  • 第 4 步商户服务端将 orderStr 返回给商户 App 客户端/小程序

    服务端根据订单信息生成 orderStr(只是加签数据),不经过支付宝服务端,直接发给App客户端,由App客户端调起支付宝App,根据 orderStr 向支付宝服务端发送请求

  • 第 5 步商户客户端/小程序发起支付,调起支付宝,将 orderStr 发送给支付宝。

  • 第 6 步支付预下单:支付宝客户端将会按照商家客户端提供的请求参数进行支付预下单。正常场景下,会唤起支付宝收银台等待用户核身;异常场景下,会返回异常信息。

  • 第 11 步返回商家 App/小程序:用户在支付宝 App 完成支付后,会跳转回商家页面,并返回最终的支付结果(即同步通知)

  • 第 13 步支付结果异步通知,支付宝会根据步骤3 传入的异步通知地址 notify_url,发送异步通知

下单

业务逻辑
防止重复下单

通过请求中的 request_id 判重

金额
  • amount 字段,单位为元
支付宝订单
  • 用户在支付宝App输入正确的支付密码后创建
  • 支付宝订单号 trade_no
商户订单
  • 商户App将订单信息发送给商户服务端后创建
  • 商户订单号 out_trade_no

支付

业务逻辑
防止重复支付

https://learnku.com/laravel/t/64089

https://mp.weixin.qq.com/s/7JdYEh57eRUZqKZ7yucseg

  • 不同网关重复支付

    1. 加redis锁
    2. 后支付的自动退款
  • 相同网关重复支付

    通过支付日志 paymentLog解决

API

formData

1
2
3
4
5
6
7
8
9
10
11
12
13
> 'https://openapi.alipaydev.com/gateway.do?method=alipay.trade.pay&app_id=2021000118646670&charset=utf-8&version=1.0&sign_type=RSA2&timestamp=2022-03-23 22:21:56&notify_url=https://api-dev.paihaole.cn/payment/listener/alipay&sign=r1VW6cRRgJqXAquJcTRE+b7Zsyo1bBk0YmINn9hAXwnHNMMVN0q2/sF+4i8hbIkApkAQLS4j0yfFNzvgfx6pSX+hVI8aC7hX50JdtYDWzJJP9mxlEIGJMQ2kFBiGI02GHRanLj8LiKYduy9o2VDYmz75z5hQp35Tff/7eUYeSJHsTL/AcZT2q4AKH0p5MBgciBmIak/8okv1at+8jF85enwMa6uUG0MOmlTAQC9cdUqf4UwaDp783yiBPmBpjLrrjMiTs6nLVVVZDJSEJluKxOWElw2IbJPv4aOi23BW6gChzh+J61A/UgNE9yxxuYdHM9yAh0g/TrS8YTI1jHcyCw==&alipay_sdk=alipay-sdk-nodejs-3.2.0&biz_content={"out_trade_no":"AQP164804531604457","total_amount":0.01,"auth_code":"286806172615687397","subject":"动力引擎-天津店-商品","store_id":"409","goods_detail":[{"goods_id":"service_353","goods_name":"体验课","quantity":1,"price":1}],"terminal_id":"::1","query_options":["1464-8888890657"],"product_code":"OFFLINE_PAYMENT","scene":"bar_code","timeout_express":"30m"}'.split('&')
[
'https://openapi.alipaydev.com/gateway.do?method=alipay.trade.pay',
'app_id=2021000118646670',
'charset=utf-8',
'version=1.0',
'sign_type=RSA2',
'timestamp=2022-03-23 22:21:56',
'notify_url=https://api-dev.paihaole.cn/payment/listener/alipay',
'sign=r1VW6cRRgJqXAquJcTRE+b7Zsyo1bBk0YmINn9hAXwnHNMMVN0q2/sF+4i8hbIkApkAQLS4j0yfFNzvgfx6pSX+hVI8aC7hX50JdtYDWzJJP9mxlEIGJMQ2kFBiGI02GHRanLj8LiKYduy9o2VDYmz75z5hQp35Tff/7eUYeSJHsTL/AcZT2q4AKH0p5MBgciBmIak/8okv1at+8jF85enwMa6uUG0MOmlTAQC9cdUqf4UwaDp783yiBPmBpjLrrjMiTs6nLVVVZDJSEJluKxOWElw2IbJPv4aOi23BW6gChzh+J61A/UgNE9yxxuYdHM9yAh0g/TrS8YTI1jHcyCw==',
'alipay_sdk=alipay-sdk-nodejs-3.2.0',
'biz_content={"out_trade_no":"AQP164804531604457","total_amount":0.01,"auth_code":"286806172615687397","subject":"动力引擎-天津店-商品","store_id":"409","goods_detail":[{"goods_id":"service_353","goods_name":"体验课","quantity":1,"price":1}],"terminal_id":"::1","query_options":["1464-8888890657"],"product_code":"OFFLINE_PAYMENT","scene":"bar_code","timeout_express":"30m"}'
]
超时时间
订单超时时间
  • 由商户控制,订单超时后由商户服务端向支付宝服务端发起[交易关闭]操作
支付超时时间
  • 可在交易创建时指定一个超时时间,设置范围5min-15d
  • 支付宝默认超时时间为15天(第15天24点后,交易关闭)

退款

交易发生后的一段时间内,由于业务原因(如金额错误、用户退款或者对账不平等)需要退款

默认交易发生后的 12 个月内,商家可退款。退款资金按原路退还至用户账户。

退款退费:退款时服务费不退回。

业务逻辑
防止重复退款

通过 refund 表记录

API
FAQ
如何判断退款是否成功
异步通知如何判断对应哪笔退款交易

关闭

API

返回

1
2
3
4
5
6
7
{
msg: 'Business Failed',
code: '40004',
subMsg: '交易不存在',
subCode: 'ACQ.TRADE_NOT_EXIST',
traceId: '218f458e16992764550397859e6d83'
}

交易状态

  • 前端查询交易状态都直接向支付宝查询最新的,不要从数据库获取
状态机
  • wait_buyer_pay 交易创建

    等待用户付款

  • trade_success 交易成功

  • trade_finished 交易完成

    不可退款

  • trade_closed 交易关闭

  • 一直部分退款退完所有交易金额则交易状态转为 TRADE_CLOSED
  • 如果未退完所有交易金额,超过有效退款时间后交易状态转为 TRADE_FINISHED 不可退款
支付状态
  • 异步或查询接口返回的 trade_status(交易状态)为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功
API

放弃交易后查询

1
2
3
4
5
6
7
8
9
10
11
12
{
msg: 'Business Failed',
code: '40004',
outTradeNo: 'AOA20231110001750232632264',
subMsg: '交易不存在',
subCode: 'ACQ.TRADE_NOT_EXIST',
receiptAmount: '0.00',
pointAmount: '0.00',
buyerPayAmount: '0.00',
invoiceAmount: '0.00',
traceId: '21909e0d16995466857567049e43c3'
}

退款后查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
code: '10000',
msg: 'Success',
buyerLogonId: '134******66',
buyerPayAmount: '0.00',
buyerUserId: '2088702467896261',
invoiceAmount: '0.00',
outTradeNo: 'AOA1699460480307',
pointAmount: '0.00',
receiptAmount: '0.00',
sendPayDate: '2023-11-09 00:21:28',
totalAmount: '0.01',
tradeNo: '2023110922001496261434959156',
tradeStatus: 'TRADE_CLOSED',
traceId: '0b2282e516994613443961354e3323'
}
退款状态
API

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
code: '10000',
msg: 'Success',
buyerLogonId: '134******66',
buyerUserId: '2088702467896261',
fundChange: 'Y',
gmtRefundPay: '2023-11-09 00:35:12',
outTradeNo: 'AOA1699460480307',
refundDetailItemList: [ [Object] ],
refundFee: '0.01',
sendBackFee: '0.01',
tradeNo: '2023110922001496261434959156',
traceId: '21974fbc16994613118301255e2ecc'
}

异步通知

  • 支付宝通过 POST 请求向下单时传入的 notify_url 发送通知

  • 异步地址(notify_url)需保证无任何字符,如空格、HTML 标签,且不能重定向

  • 商户服务端需要及时响应

    响应值 描述 异步是否重试发送
    fail 消息获取失败 重试
    success 消息获取成功 不重试

    成功返回 success 字符串,失败返回 fail 字符串,否则支付宝会认为通知失败,会通过一定的策略定期重新发起通知。通知的间隔频率为:4m、10m、10m、1h、2h、6h、15h

    针对同一条异步通知重试时,异步通知参数中的 notify_id 保持不变

触发条件
==状态变化==
trade_finished

触发条件:

  • 不支持退款功能且用户付款成功
  • 支持退款功能且超时未退款
trade_success

触发条件:

  • 支持退款功能且用户付款成功
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
{
gmt_create: '2023-11-09 00:41:18',
charset: 'utf-8',
seller_email: 'daweikeji@daweiai.email',
subject: '大沩科技-售卖机',
sign: 'ml5rW53kp0aaWxWrfYd8g4yevGU9kXKH+exx21d84VpWoyqOYv+ebIYXYV/eOUwfmsHv2oOt5i9GUYGSe7/S6Apje7q7QkgE7zIu722bGDerh+oZG2uV2hdje8B49k/zembzhpovfITsnVFd0jRcEYAH7VC9HCf+nsyLLrLD28cDCIb36On7mQiKQ0uW6WyUl6uSd6R3mItmQd28ccU3/Ze7VJsJEtYKF4xWQ06uKlvNv/0+F6kjJE38loussGmPKuL7GBwJmnKnVGDheYNnEJwmUjLvmVaO/xrg8yFsyWl8D6yts9u5F/90E0jtwweAAC9KMWnJJIPSxhplrcJ6mQ==',
buyer_id: '2088702467896261',
invoice_amount: '0.01',
notify_id: '2023110901222004119096261416968100',
fund_bill_list: '[{"amount":"0.01","fundChannel":"ALIPAYACCOUNT"}]',
notify_type: 'trade_status_sync',
trade_status: 'TRADE_SUCCESS',
receipt_amount: '0.01',
app_id: '2021004108649284',
buyer_pay_amount: '0.01',
sign_type: 'RSA2',
seller_id: '2088641506079905',
gmt_payment: '2023-11-09 00:41:18',
notify_time: '2023-11-09 00:41:19',
version: '1.0',
out_trade_no: 'AOA20231109004114058985527',
total_amount: '0.01',
trade_no: '2023110922001496261426916626',
auth_app_id: '2021004108649284',
buyer_logon_id: '134****2066',
point_amount: '0.00'
}
trade_closed

触发条件

  1. 全额退款
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
{
gmt_create: '2023-11-09 00:21:28',
charset: 'utf-8',
gmt_payment: '2023-11-09 00:21:28',
seller_email: 'daweikeji@daweiai.email',
notify_time: '2023-11-09 00:35:12',
subject: '大沩科技-售卖机',
gmt_refund: '2023-11-09 00:35:11.994',
sign: 'MCYUw/mpmdfcFsQRVkF1O6BkZuRbgHfkd54kzNPuT+1IohjuAwuQ+gaPT0PBtncbxgtZC4KDb2KJWPjelZuwFDUek/noMj+xLh85riRFEEt80KempQ68S+e9btjlCSASZg7xHKDcmk4vdE+p7BKLAC1k0NJOF5IJeuKzX58nMGAHdbTzn2NKA2ge9srkJaznnlT30zWiKjIp7ZHhA5blgfKvdLT3VSyaRPjxUs7hak4WkUwTmul2fDWwL20q7vCAPrUyUNrEcylnJ6bxSOIwvfF8UeptSLhh4rnN1Ilrh7Ri4TNg7f2Xy0kNN5GzM+S63ebV/d+3BLylblQrMj35kQ==',
buyer_id: '2088702467896261',
out_biz_no: 'RFD20231109003511789560588', // 商家退款号
version: '1.0',
notify_id: '2023110901222003512096261415550867',
notify_type: 'trade_status_sync',
out_trade_no: 'AOA1699460480307',
total_amount: '0.01', // 总交易金额
trade_status: 'TRADE_CLOSED',
refund_fee: '0.01', // 总退款金额
trade_no: '2023110922001496261434959156',
auth_app_id: '2021004108649284',
gmt_close: '2023-11-09 00:35:11',
buyer_logon_id: '134****2066',
app_id: '2021004108649284',
sign_type: 'RSA2',
seller_id: '2088641506079905'
}
验证
验证签名
  • 使用支付宝sdk 中的 checkNotifySign 方法
校验数据
  1. 过滤重复的通知

  2. 验证订单信息

    out_trade_no 是否为商家系统中创建的订单号

    total_amount 是否确实为该订单的实际金额

  3. 验证 app_id 是否为该商家本身

FAQ

退款接口是否会触发异步通知

接入FAQ

接口报错排查