一.支付宝支付相关文档地址:
支付宝支付相关的文档地址:https://open.alipay.com/api
电脑网站支付:https://opendocs.alipay.com/open/270/105898?ref=api
手机网站支付:https://opendocs.alipay.com/open/203/105288?ref=api
App支付:https://opendocs.alipay.com/open/204/105051?ref=api
通用开发工具以及SDK包:
通用文档:https://opendocs.alipay.com/common/02kg67
开发工具包(SDK)下载:https://opendocs.alipay.com/open/54/103419
二.手机网站支付详解
产品介绍
1.1介绍
手机网站支付是指商家在移动端网页展示商品或服务,用户在商家页面确认使用支付宝支付后,浏览器自动跳转支付宝 App 或支付宝网页完成付款的支付产品
1.2申请条件
签约申请提交材料要求:
提供网站地址,网站能正常访问且页面显示完整,网站需要明确经营内容且有完整的商品信息。
网站必须通过 ICP 备案,且备案主体需与支付宝账号主体一致。若网站备案主体与当前账号主体不同时需上传授权函。
个人账号申请,需提供营业执照,且支付宝账号名称需与营业执照主体一致。
注意:需按照要求提交材料,若部分材料不合格,收款额度将受到限制(单笔收款 ≤ 2000 元,单日收款 ≤ 20000 元)。若签约时未能提供相关材料(如营业执照),请在合约生效后的 30 天内补全,否则会影响正常收款。点此查看详情
1.3接入方式
开通:点击 立即开通,按要求填写并提交产品开通申请,点此查询 产品开通情况。
开发:点此查看 开发文档
2.接入准备
商家或服务商可根据实际情况通过以下方式接入该产品:
商家自研:商家自助完成产品开通与接口调用。接入步骤详情可查看本文自研商家接入 。
服务商代开发:服务商在获得商家授权后,可获得通过第三方应用调用支付宝的接口能力。接入步骤详情可查看本文 服务商代开发模式接入 。
2.1自研商家接入
商家自研接入流程
2.1.1创建应用
登录支付宝开放平台创建 网页/移动应用。
说明:生成的应用唯一标识 APPID 可用于调用开放产品接口。
2.1.2配置应用
产品绑定
网页/移动应用
创建应用后,在应用详情页 产品绑定 菜单下,点击 绑定产品 ,添加 手机网站支付。
2.2开发设置
在 开发 > 开发设置 中配置应用信息。
2.2.1接口加签方式
必填。用于防止数据篡改,保障应用和支付宝交互的安全性,可查看 接口加签方式。
2.2.2服务器 IP 白名单
选填。用于提高应用访问开放平台的安全性,避免因应用私钥泄漏等原因导致业务受损,保障用户资金安全,可查看 服务器 IP 白名单。
2.2.3支付宝网关
必填。开发者调用 OpenAPI 发送 http(s) 请求至支付宝的目标地址(gateway),固定为 https://openapi.alipay.com/gateway.do。
2.2.4应用网关
必填。用于接收支付宝异步通知消息,需要传入 http(s) 公网可访问网页地址,可查看 应用网关。
2.2.5接口内容加密方式
选填。用于加 / 解密 OpenAPI bizContent 报文内容,可大幅提升接口内容传输的安全性。可查看 接口内容加密方式。
2.2.6授权回调地址
选填。网页/移动应用 指定的回调页面 URL,用户信息授权 成功后,将在该 URL 后携带授权码等信息并跳转至该页面。
说明:授权链接中配置的 redirect_uri 的值必须与此回调地址保持一致 (如:https://www.alipay.com) 。
2.2.7订阅消息服务
选填。异步消息通知,用于提高应用 API 的调用效率。详情可查看 主动推送服务(From 蚂蚁)和 消息回流服务(To 蚂蚁)。
2.3上线应用
网页/移动应用:需要手动上线。提交审核后,预计 1 个工作日的审核时间。详细步骤可点击查看上线应用。应用上线后,还需要完成产品开通才能在线上环境(生产环境)使用产品。
2.4绑定商家账号
可选操作。在支付宝开放平台创建的应用归属于对应的开放平台账号。如果要在应用中使用支付和资金等相关产品,需要将应用和支付宝商家平台账号绑定,应用才可调用需要商家开通的产品,具体步骤可查看 绑定应用。
2.5开通产品
应用上线后,还需要完成开通才能使用 当面付。请在 商家平台 > 产品中心 的 手机网站支付产品详情页 点击 立即开通,填写并提交相关信息完成产品开通。详情可点击查看 开通产品 。
如您已经开通当面付,则无需再次开通,开通状态可点击 产品开通情况查询
3.接入指南
3.1 手机网站支付快速接入
完成 接入准备后,商家/服务商可根据本文指引快速接入 手机网站支付。手机网站支付是商家在网页浏览器(H5)中调用支付宝提供的网页支付接口调起支付宝客户端内的支付模块,本文主要介绍服务端使用手机网站支付 下单、退款、异步通知、以及支付完成页面跳转、中途退出、部分退款 等相关说明引导。
说明:
支付产品全面升级,若开发者使用的是旧版接口,请查看旧版 手机网站支付 文档。新老版本过渡期间老版支付接口创建的订单可以使用新版的退款接口退款;另外新版支付接口创建的订单不支持使用老版的退款接口进行退款,过渡期结束后需使用新版接口,不建议新老版本长期混用。
开发者需要关注安装了支付宝和未安装支付宝的两种测试场景,对于商家 App 内嵌 webview 中的支付场景,如果安装了支付宝却没有唤起,大部分原因是支付宝不在当前浏览器配置的白名单内,建议集成支付宝 App支付 产品。或者可以使用 手机网站支付转Native支付 的方案,不建议在商家 App 中直接接入手机网站支付。
支持沙箱环境下调试。
3.1.1支付流程
系统交互流程
3.1.2创建订单
请求 alipay.trade.wap.pay(手机网站支付接口2.0接口)生成 form 表单数据返回给前端,前端模拟表单提交唤起收银台,用户输入支付密码确认支付后创建订单。
注意:订单创建实际创建时间也为用户支付时间,非唤起收银台时间。
重要入参说明
参数名称 | 参数说明 |
out_trade_no | 商户订单号,需保证在商家系统中唯一。 |
subject | 商品的标题/交易标题/订单标题/订单关键字等。不可使用特殊字符,如 /,=,& 等。 |
total_amount | 订单金额。 |
quit_url | 用户付款中途退出返回商户网站的地址。 |
time_expire | 非必填,过期时间,用户多长时间不支付订单关闭,如果不传默认是和签约协议保持一致。 |
enable_pay_channels | 非必填,可用渠道,用户只能在指定渠道范围内支付 。当有多个渠道时用 “,” 分隔 。 |
disable_pay_channels | 非必填,禁用渠道,用户不可用指定渠道支付 ,当有多个渠道时用 “,” 分隔 。enable_pay_channels 与 disable_pay_channels 互斥。具体支持的支付渠道可查看 常见问题。 |
return_url | 支付成功后点击完成会自动跳转回商家页面地址, 同时在 URL 地址上附带支付结果参数,回跳参数可查看本文 附录 > 前台回跳参数说明。在 iOS 系统中,唤起支付宝客户端支付完成后,不会自动回到浏览器或商家 App。用户可手工切回到浏览器或商家 App。 |
notify_url | 异步通知地址,用于接收支付宝推送给商户的支付/退款成功的消息。 |
business_params | 非必填 ,业务信息,具体值要和支付宝约定。关于安全方面的可以参考 商户风险联防数据回传合作。 |
passback_params | 非必填,商户自定义参数,需要UrlEncode处理之后传入。passback_params只在异步通知中返回,同步通知不返回。 |
注意:由于前台回跳的不可靠性,前台回跳只能作为商家支付结果页的入口,最终支付结果必须以异步通知或查询接口返回为准,不能依赖前台回跳。
3.1.3支付成功异步通知
异步通知示例
支付宝会通过 POST 请求的方式将支付结果作为参数通知到notify_url(创建订单时设置的地址) ,商户收到异步通知后可以根据sdk提供的异步验签方法做安全性校验,判断消息来源是支付宝后再对自身业务做逻辑处理。
http://notifyurl?gmt_create=2022-10-08 10%3A48%3A07&charset=utf-8&seller_email=$$$&subject=%E6%96%87%E5%85%B7%E6%9D%82%E7%89%A9%E7%AE%B1&sign=$$$&buyer_id=2088********2180&invoice_amount=0.01¬ify_id=202210080022210********56620&fund_bill_list=%5B%7B%22amount%22%3A%220.01%22%2C%22fundChannel%22%3A%22ALIPAYACCOUNT%22%7D%5D¬ify_type=trade_status_sync&trade_status=TRADE_SUCCESS&receipt_amount=0.01&buyer_pay_amount=0.01&app_id=20141****13222&sign_type=RSA2&seller_id=2088**********35&gmt_payment=2022-10-08 10%3A48%3A08¬ify_time=2022-10-08 10%3A48%3A09&version=1.0&out_trade_no=20221008010102211&total_amount=0.01&trade_no=20221008**********2692&auth_app_id=2014********3222&buyer_logon_id=156****8305&point_amount=0.00
关键通知参数说明
参数名称 | 参数说明 |
trade_no | 支付宝 28 位交易号。 |
trade_status | 交易状态。 |
total_amount | 订单金额。 |
可查看更多 异步通知参数说明 及异步推送重试机制。
异步验签
商户可以根据sdk提供的验签方法传入支付宝公钥进行安全性校验。验收是来自支付宝推送的消息后必须打印输出 success。如果商家反馈给支付宝的字符不是 success 这7个字符,服务器会不断重发通知,直到超过24小时22分钟。
一般情况下,25小时以内完成8次通知(通知的间隔频率一般是 4m、10m、10m、1h、2h、6h、15h);接收程序执行完成后,该页面不能执行页面跳转。如果执行页面跳转,支付宝会接收不到 success 字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知。
Map<String, String>paramsMap= ... //将异步通知中收到的所有参数都存放到map中booleansignVerified=AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE) //调用SDK验证签名if(signVerified){
// TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure}else{
// TODO 验签失败则记录异常日志,并在response中返回failure.}
3.2异步通知说明
对于手机网站支付产生的交易,支付宝会根据原始支付 API 中传入的异步通知地址 notify_url,通过 POST 请求的形式将支付结果作为参数通知到商户系统。详情可查看 支付宝异步通知说明 。
3.2.1异步通知参数
参数 | 类型 | 是否必读 | 最大长度 | 描述 | 示例值 |
notify_time | Date | 是 | - | 通知的发送时间。格式为 yyyy-MM-dd HH:mm:ss。 | 2015-04-27 15:45:58 |
notify_type | String | 是 | 64 | 通知的类型。 | trade_status_sync |
notify_id | String | 是 | 128 | 通知校验 ID。 | ac05099524730693a8b330c5ecf72da9786 |
app_id | String | 是 | 32 | 支付宝分配给开发者的应用 ID。 | 20214072300007148 |
charset | String | 是 | 10 | 编码格式,如 utf-8、gbk、gb2312 等。 | utf-8 |
version | String | 是 | 3 | 调用的接口版本,固定为:1.0。 | 1.0 |
sign_type | String | 是 | 10 | 商家生成签名字符串所使用的签名算法类型,目前支持 RSA2 和 RSA,推荐使用 RSA2。 | RSA2 |
sign | String | 是 | 344 | 签名。详情可查看 异步返回结果的验签。 | 601510b7970e52cc63db0f4497cf70e |
trade_no | String | 是 | 64 | 支付宝交易凭证号。 | 2013112011001004330000121536 |
out_trade_no | String | 是 | 64 | 原支付请求的商户订单号。 | 6823789339978248 |
out_biz_no | String | 否 | 64 | 商户业务 ID,主要是退款通知中返回退款申请的流水号。 | HZRF001 |
buyer_id | String | 否 | 16 | 买家支付宝账号对应的支付宝唯一用户号。以 2088 开头的纯 16 位数字。 | 2088102122524333 |
buyer_logon_id | String | 否 | 100 | 买家支付宝账号。 | 159****20 |
seller_id | String | 否 | 30 | 卖家支付宝用户号。 | 2088101106499364 |
seller_email | String | 否 | 100 | 卖家支付宝账号。 | zhu***@alitest.com |
trade_status | String | 否 | 32 | 交易目前所处的状态。详情可查看 交易状态说明。 | TRADE_CLOSED |
total_amount | Number | 否 | 11 | 本次交易支付的订单金额,单位为人民币(元)。 | 20 |
receipt_amount | Number | 否 | 11 | 商家在收益中实际收到的款项,单位人民币(元)。 | 15 |
invoice_amount | Number | 否 | 11 | 用户在交易中支付的可开发票的金额。 | 10.00 |
buyer_pay_amount | Number | 否 | 11 | 用户在交易中支付的金额。 | 13.88 |
point_amount | Number | 否 | 11 | 使用集分宝支付的金额。 | 12.00 |
refund_fee | Number | 否 | 11 | 退款通知中,返回总退款金额,单位为人民币(元),支持两位小数。 | 2.58 |
subject | String | 否 | 256 | 商品的标题/交易标题/订单标题/订单关键字等,是请求时对应的参数,原样通知回来。 | XXX交易 |
body | String | 否 | 400 | 订单的备注、描述、明细等。对应请求时的 body 参数,原样通知回来。 | XXX交易内容 |
gmt_create | Date | 否 | - | 该笔交易创建的时间。格式为 yyyy-MM-dd HH:mm:ss。 | 2015-04-27 15:45:57 |
gmt_payment | Date | 否 | - | 该笔交易 的买家付款时间。格式为 yyyy-MM-dd HH:mm:ss。 | 2015-04-27 15:45:57 |
gmt_refund | Date | 否 | - | 该笔交易的退款时间。格式 yyyy-MM-dd HH:mm:ss.S。 | 2015-04-28 15:45:57.320 |
gmt_close | Date | 否 | 512 | 该笔交易结束时间。格式为 yyyy-MM-dd HH:mm:ss。 | 2015-04-27 15:45:57 |
fund_bill_list | String | 否 | 512 | 支付成功的各个渠道金额信息。详情可查看 资金明细信息说明。 | [{ "amount":"15.00", "fundChannel":"ALIPAYACCOUNT" }] |
passback_params | String | 否 | 512 | 公共回传参数,如果请求时传递了该参数,则返回给商家时会在异步通知时将该参数原样返回。本参数必须进行 UrlEncode 之后才可以发送给支付宝。 | merchantBizType%3d3c%26merchantBizNo%3d2016010101111 |
voucher_detail_list | String | 否 | - | 本交易支付时所有优惠券信息,详情可查看 优惠券信息说明。 | [{ "amount":"0.20", "merchan tContribute":"0.00", "other_contribute":"0.20", "type":"ALIPAYACCOUNT", "memo":"学生卡8折优惠" }] |
3.2.2交易状态说明
枚举名称 | 枚举说明 |
WAIT_BUYER_PAY | 交易创建,等待买家付款。 |
TRADE_CLOSED | 未付款交易超时关闭,或支付完成后全额退款。 |
TRADE_SUCCESS | 交易支付成功。 |
TRADE_FINISHED | 交易结束,不可退款。 |
3.2.3通知触发条件
触发条件名 | 触发条件描述 | 触发条件默认值 |
TRADE_FINISHED | 交易完成 | true(触发通知) |
TRADE_SUCCESS | 支付成功 | true(触发通知) |
WAIT_BUYER_PAY | 交易创建 | false(不触发通知) |
TRADE_CLOSED | 交易关闭 | true(触发通知) |
3.2.4资金明细信息说明
参数 | 类型 | 是否必填 | 最大长度 | 参数说明 | 示例值 |
fundChannel | String | 否 | - | 支付渠道。详情可查看 支付渠道说明。 | ALIPAYACCOUNT |
amount | String | 否 | 11 | 使用指定支付渠道支付的金额,单位为人民币(元)。 | 15.00 |
3.2.5支付渠道说明
支付渠道代码 | 支付渠道 |
COUPON | 支付宝红包 |
ALIPAYACCOUNT | 支付宝余额 |
POINT | 集分宝 |
DISCOUNT | 折扣券 |
PCARD | 预付卡 |
FINANCEACCOUNT | 余额宝 |
MCARD | 商家储值卡 |
MDISCOUNT | 商户优惠券 |
MCOUPON | 商户红包 |
PCREDIT | 蚂蚁花呗 |
3.2.6优惠券信息说明
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
voucherId | String | 是 | 32 | 券 ID | 2015102600073002039000002D5O |
templateId | String | 否 | 64 | 券模板 ID | 20171030000730015359000EMZP0 |
name | String | 是 | 64 | 券名称 | 5 元代金券 |
type | String | 是 | 32 | 优惠类型。当前支持以下几种主要类型:
注意:不排除未来新增其它类型的可能,商家接入时请注意兼容性,避免硬编码。 | ALIPAY_BIZ_VOUCHER |
amount | Number | 是 | 11 | 优惠金额。优惠金额中,由商家出资的金额。 | 10.00 |
merchantContribute | Number | 否 | 11 | 商家出资金额。优惠金额中,由商家出资的金额。 | 9.00 |
otherContribute | Number | 否 | 11 | 其他出资方出资金额。可能是支付宝,可能是品牌商,或者其他方,也可能是他们的共同出资。 | 1.00 |
otherContributeDetail | ContributeDetail[] | 否 | 优惠券的其他出资方明细 | ||
L contributeType | String | 否 | 32 | 出资方类型,如品牌商出资、支付宝平台出资等。 | PLATFORM |
L contributeAmount | Number | 否 | 8 | 出资方金额 | 0.18 |
memo | String | 否 | 256 | 优惠券备注信息。 | 学生专用优惠 |
3.2.7异步通知特性
在进行异步通知交互时,如果支付宝收到的应答不是 success,支付宝会认为通知失败,会通过一定的策略定期重新发起通知。通知的间隔频率为:4m、10m、10m、1h、2h、6h、15h。
商家设置的异步地址(notify_url)需保证无任何字符,如空格、HTML 标签,且不能重定向。(如果重定向,支付宝会收不到 success 字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知)
支付宝是用 POST 方式发送通知信息,商户获取参数的方式如下:request.Form("out_trade_no")、$_POST['out_trade_no']。
支付宝针对同一条异步通知重试时,异步通知参数中的 notify_id 是不变的。
3.2.8异步返回结果的验签
为了帮助开发者调用开放接口,支付宝提供了 开放平台服务端DEMO&SDK,包含 Java、PHP 、.NET、PYTHON 和 NodeJS 五种语言版本,封装了签名&验签、HTTP 接口请求等基础功能。
建议先下载对应语言版本的 SDK 并引入开发工程进行快速接入。
某商家设置的通知地址为 https://api.xx.com/receive_notify.htm,对应接收到通知的示例如下:
https://api.xx.com/receive_notify.htm?total_amount=2.00&buyer_id=2088102116773037&body=大乐透2.1&trade_no=2016071921001003030200089909&refund_fee=0.00¬ify_time=2016-07-19 14:10:49&subject=大乐透2.1&sign_type=RSA2&charset=utf-8¬ify_type=trade_status_sync&out_trade_no=0719141034-6418&gmt_close=2016-07-19 14:10:46&gmt_payment=2016-07-19 14:10:47&trade_status=TRADE_SUCCESS&version=1.0&sign=kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=&gmt_create=2016-07-19 14:10:44&app_id=2015102700040153&seller_id=2088102119685838¬ify_id=4a91b7a78a503640467525113fb7d8bg8e
在通知返回参数列表中,除去 sign、sign_type 两个参数外,凡是通知返回回来的参数皆是待验签的参数。将剩下参数进行 url_decode,,并进行字典排序,组成字符串,得到待签名字符串:
body=大乐透2.1&buyer_id=2088102116773037&charset=utf-8&gmt_close=2016-07-1914:10:46&gmt_payment=2016-07-1914:10:47¬ify_time=2016-07-1914:10:49¬ify_type=trade_status_sync&out_trade_no=0719141034-6418&refund_fee=0.00&subject=大乐透2.1&total_amount=2.00&trade_no=2016071921001003030200089909&trade_status=TRADE_SUCCESS&version=1.0
将签名参数(sign)使用 base64 解码为字节码串;
使用 RSA 的验签方法,通过签名字符串、签名参数(经过base64解码)及支付宝公钥验证签名。
需要严格按照如下描述校验通知数据的正确性:
商家需要验证该通知数据中的 out_trade_no 是否为商家系统中创建的订单号。
判断 total_amount 是否确实为该订单的实际金额(即商户订单创建时的金额)。
校验通知中的 seller_id(或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方(有的时候,一个商家可能有多个 seller_id/seller_email)。
验证 app_id 是否为该商家本身。
说明:上述 1、2、3、4 有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商家必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
注意:
状态 TRADE_SUCCESS 的通知触发条件是商家开通的产品支持退款功能的前提下,买家付款成功。
交易状态 TRADE_FINISHED 的通知触发条件是商家开通的产品不支持退款功能的前提下,买家付款成功;或者,商家开通的产品支持退款功能的前提下,交易已经成功并且已经超过可退款期限
3.3手机网站支付转Native支付
见官网:https://opendocs.alipay.com/open/203/106493?ref=api
3.4 手机网站支付通过alipays协议唤起支付宝APP
见官网:https://opendocs.alipay.com/open/203/107091?ref=api
3.5 沙箱环境联调
沙箱环境是支付宝开放平台为开发者提供的与生产环境完全隔离的联调测试环境,开发者在沙箱环境中完成的调用不会对生产环境中的数据造成任何影响。
沙箱环境会自动完成或忽略一些场景的业务门槛,例如:开发者无需等待产品签约,即可直接在沙箱环境调用接口,使得开发集成工作可以与商务流程并行,从而提高项目整体的交付效率。
注意:
由于沙箱环境并非 100% 与生产环境一致,接口的实际响应逻辑请以生产环境为准,沙箱环境开发调试完成后,仍然需要在生产环境进行测试验收。
沙箱环境拥有完全独立的数据体系,沙箱环境下返回的数据(比如用户 ID 等)在生产环境中都是不存在的,开发者不可将沙箱环境返回的数据与生产环境中的数据混淆。
本文仅说明如何在沙箱环境中调试手机网站支付能力,非调试通用说明。
3.5.1沙箱功能范围
支持的接口
接口类型 | 接口中文名 | 接口英文名称 | 沙箱环境是否支持 | 沙箱环境调用注意事项 |
手机网站支付 | 手机网站支付接口2.0 | 支持 | - | |
辅助接口 | 统一收单线下交易查询 | 支持 | - | |
统一收单交易退款接口 | 支持 | - | ||
统一收单交易退款查询接口 | 支持 | - | ||
统一收单交易关闭接口 | 支持 | - | ||
查询对账单下载地址 | 支持 | 沙箱环境只做模拟调用,下载账单为模板,账单内没有实际数据。 | ||
From 蚂蚁消息接口 | 收单退款冲退完成通知 | 不支持 | 沙箱环境不支持银行卡支付,无法模拟测试。 |
3.5.2沙箱调试注意事项
建议只传必传参数测试,避免部分参数只对生产环境兼容。
参数注意事项
alipay.trade.wap.pay 沙箱参数区别如下
参数 | 描述说明 |
timeout_express | 相对超时参数
|
time_expire | 绝对超时参数 沙箱环境:不可超过当前时间 15 小时。 |
extend_params | 花呗分期:不支持设置,沙箱不支持花呗分期测试。 示例:"extend_params":{"hb_fq_num":"3","hb_fq_seller_percent":"100"} |
ext_user_info | 外部指定买家,不支持设置。 沙箱环境无法校验买家身份信息。 |
支付注意事项
沙箱测试只支持余额支付,不支持银行卡、余额宝、花呗等其它支付方式。
沙箱测试会扣手续费,但沙箱扣款手续费比例不代表生产环境的情况,生产环境手续费请以签约协议为准。
若使用纯客户端 Demo 测试(不结合服务端请求),建议 Demo 中配置的密钥为 pkcs8 格式。
注意:测试完后正式上线,建议结合服务端请求,避免私钥设置在客户端导致泄漏、资损。
手机安装有正式的支付宝钱包和沙箱钱包,测试(若无相关提示选择使用哪个钱包)一般默认是唤起的正式支付宝钱包支付,此时由于生产环境的支付宝钱包支付沙箱数据导致报错。该情况下,需可以查看支付页面背景是否是生产环境支付宝钱包页面进行判断,建议修改为沙箱钱包支付。
手机网站支付若要在移动端模拟唤起沙箱钱包支付,请在 Android 手机中测试(目前沙箱支付宝钱包只有 Android 版),在 iOS 中只能模拟 H5 页面登陆支付场景。
3.5.3沙箱控制台操作指南
使用沙箱环境进行调试前,开发者需根据 操作指引完成沙箱控制台及接口调用配置。
注意:请使用沙箱应用信息以及沙箱网关:https://openapi.alipaydev.com/gateway.do
3.6 SDK & Demo 获取
为了帮助开发者调用开放接口,提供了开放平台服务端SDK,包含JAVA、PHP和.NET三语言版本封装了签名&验签、HTTP接口请求等基础功能。 详见 下载和使用教程 。
手机网站支付 Demo
4.手机网站支付接口2.0
外部商户创建订单并支付
4.1公共请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
app_id | String | 必选 | 32 | 支付宝分配给开发者的应用ID | 2014072300007148 |
method | String | 必选 | 128 | 接口名称 | alipay.trade.wap.pay |
format | String | 可选 | 40 | 仅支持JSON | JSON |
return_url | String | 可选 | 256 | HTTP/HTTPS开头字符串 | |
charset | String | 必选 | 10 | 请求使用的编码格式,如utf-8,gbk,gb2312等 | utf-8 |
sign_type | String | 必选 | 10 | 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 | RSA2 |
sign | String | 必选 | 344 | 商户请求参数的签名串,详见签名 | 详见示例 |
timestamp | String | 必选 | 19 | 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" | 2014-07-24 03:07:50 |
version | String | 必选 | 3 | 调用的接口版本,固定为:1.0 | 1.0 |
notify_url | String | 可选 | 256 | 支付宝服务器主动通知商户服务器里指定的页面http/https路径。 | |
app_auth_token | String | 可选 | 40 | 详见应用授权概述 | |
biz_content | String | 必选 | 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 |
4.2请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
out_trade_no | String | 必选 | 64 | 商户网站唯一订单号 | 70501111111S001111119 |
total_amount | Price | 必选 | 9 | 订单总金额。 单位为元,精确到小数点后两位,取值范围:[0.01,100000000] 。 | 9.00 |
subject | String | 必选 | 256 | 订单标题。 注意:不可使用特殊字符,如 /,=,& 等。 | 大乐透 |
auth_token | String | 可选 | 40 | 针对用户授权接口,获取用户相关数据时,用于标识用户授权关系 | appopenBb64d181d0146481ab6a762c00714cC27 |
quit_url | String | 可选 | 400 | 用户付款中途退出返回商户网站的地址 | |
goods_detail | GoodsDetail[] | 可选 | 订单包含的商品列表信息,json格式,其它说明详见商品明细说明 | ||
time_expire | String | 可选 | 32 | 绝对超时时间,格式为yyyy-MM-dd HH:mm:ss。超时时间范围:1m~15d。 | 2016-12-31 10:05:00 |
extend_params | ExtendParams | 可选 | 业务扩展参数 | ||
business_params | String | 可选 | 512 | 商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式 | {"mc_create_trade_ip":"127.0.0.1"} |
passback_params | String | 可选 | 512 | 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在同步返回(包括跳转回商户网站)和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。 | merchantBizType%3d3C%26merchantBizNo%3d2016010101111 |
merchant_order_no | String | 可选 | 32 | 商户原始订单号,最大长度限制32位 | 20161008001 |
ext_user_info | ExtUserInfo | 可选 | 外部指定买家 |
4.3公共响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
code | String | 必选 | - | 网关返回码,详见文档 | 40004 |
msg | String | 必选 | - | 网关返回码描述,详见文档 | Business Failed |
sub_code | String | 可选 | - | 业务返回码,参见具体的API接口文档 | ACQ.TRADE_HAS_SUCCESS |
sub_msg | String | 可选 | - | 业务返回码描述,参见具体的API接口文档 | 交易已被支付 |
sign | String | 必选 | - | 签名,详见文档 | DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo= |
4.4响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
out_trade_no | String | 必选 | 64 | 商户网站唯一订单号 | 70501111111S001111119 |
trade_no | String | 必选 | 64 | 该交易在支付宝系统中的交易流水号。最长64位。 | 2014112400001000340011111118 |
total_amount | Price | 必选 | 9 | 该笔订单的资金总额,单位为人民币(元),取值范围为 0.01~100000000.00,精确到小数点后两位。 | 9.00 |
seller_id | String | 必选 | 16 | 收款支付宝账号对应的支付宝唯一用户号。 以2088开头的纯16位数字 | 2088111111116894 |
merchant_order_no | String | 必选 | 32 | 商户原始订单号,最大长度限制32位 | 20161008001 |
4.5请求示例
$aop = new AopClient ();
$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = 'your app_id';
$aop->rsaPrivateKey = '请填写开发者私钥去头去尾去回车,一行字符串';
$aop->alipayrsaPublicKey='请填写支付宝公钥,一行字符串';
$aop->apiVersion = '1.0';
$aop->signType = 'RSA2';
$aop->postCharset='GBK';
$aop->format='json';
/******必传参数******/
$object = new stdClass();
//商户订单号,商家自定义,保持唯一性
$object->out_trade_no = '20210817010101004';
//支付金额,最小值0.01元
$object->total_amount = 0.01;
//订单标题,不可使用特殊符号
$object->subject = '测试商品';
/******可选参数******/
//手机网站支付默认传值FAST_INSTANT_TRADE_PAY
$object->product_code ='QUICK_WAP_WAY';
$object->time_expire = '2022-08-01 22:00:00';
商品信息明细,按需传入
// $goodsDetail = [
// [
// 'goods_id'=>'goodsNo1',
// 'goods_name'=>'子商品1',
// 'quantity'=>1,
// 'price'=>0.01,
// ],
// ];
// $object->goodsDetail = $goodsDetail;
// //扩展信息,按需传入
// $extendParams = [
// 'sys_service_provider_id'=>'2088511833207846',
// ];
// $object->extend_params = $extendParams;
$json = json_encode($object);
$request = new AlipayTradeWapPayRequest();
//异步接收地址,仅支持http/https,公网可访问
$request->setNotifyUrl('');
//同步跳转地址,仅支持http/https
$request->setReturnUrl('');
$request->setBizContent($json);
$result = $aop->pageExecute ( $request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultCode = $result->$responseNode->code;
if(!empty($resultCode)&&$resultCode == 10000){
echo "成功";
} else {
echo "失败";
}
4.6响应示例
{
"alipay_trade_wap_pay_response": {
"code": "10000",
"msg": "Success",
"app_id": "2014072300007148",
"auth_app_id": "2014072300007148",
"charset": "UTF-8",
"timestamp": "2016-10-11 17:43:36",
"out_trade_no": "081622560194853",
"total_amount": "9.00",
"trade_no": "2016081621001004400236957647",
"seller_id": "2088702849871851"
},
"sign": "NGfStJf3i3ooWBuCDIQSumOpaGBcQz+aoAqyGh3W6EqA/gmyPYwLJ********",
"sign_type": "RSA2"
}
4.7异常示例
{
"alipay_trade_wap_pay_response": {
"code": "20000",
"msg": "Service Currently Unavailable",
"sub_code": "isp.unknow-error",
"sub_msg": "系统繁忙"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
4.8错误码
公共错误码
业务错误码
错误码 | 错误描述 | 解决方案 |
ACQ.SYSTEM_ERROR | 接口返回错误 | 请立即调用查询订单API,查询当前订单的状态,并根据订单状态决定下一步的操作,如果多次调用依然报此错误码,请联系支付宝客服。 |
ACQ.INVALID_PARAMETER | 参数无效 | 检查请求参数,修改后重新发起请求 |
ACQ.ACCESS_FORBIDDEN | 无权限使用接口 | 未签约条码支付或者合同已到期 |
ACQ.EXIST_FORBIDDEN_WORD | 订单信息中包含违禁词 | 修改订单信息后,重新发起请求 |
ACQ.PARTNER_ERROR | 应用APP_ID填写错误 | 联系支付宝小二,确认APP_ID的状态 |
ACQ.TOTAL_FEE_EXCEED | 订单总金额不在允许范围内 | 修改订单金额再发起请求 |
ACQ.CONTEXT_INCONSISTENT | 交易信息被篡改 | 更换商家订单号后,重新发起请求 |
ACQ.TRADE_HAS_SUCCESS | 交易已被支付 | 确认该笔交易信息是否为当前买家的,如果是则认为交易付款成功,如果不是则更换商家订单号后,重新发起请求 |
ACQ.TRADE_HAS_CLOSE | 交易已经关闭 | 更换商家订单号后,重新发起请求 |
ACQ.PAYMENT_REQUEST_HAS_RISK | 支付有风险 | 更换其它付款方式 |
ACQ.RISK_MERCHANT_IP_NOT_EXIST | 当前交易未传入IP信息,创单失败,请传入IP后再发起支付 | 检查请求参数是否已经传入用户IP信息 |
4.9触发通知类型
通知类型 | 描述 | 默认开启 |
tradeStatus.TRADE_CLOSED | 交易关闭 | 1 |
tradeStatus.TRADE_FINISHED | 交易完结 | 1 |
tradeStatus.TRADE_SUCCESS | 支付成功 | 1 |
tradeStatus.WAIT_BUYER_PAY | 交易创建 | 0 |
具体手机网站支付见官网:https://opendocs.alipay.com/open/203/105288?ref=api
三.App支付详解
产品介绍
1.1 介绍
App 支付是指商家在商家移动端 App 中集成支付宝 SDK,调起支付宝来完成付款的一种支付产品。适用于在商家移动端 App 内使用支付宝支付功能的场景
1.2 申请条件
签约申请提交材料要求如下:
如应用已上架,需提供应用名称和已上架的应用市场;若应用未上架,需提供 Demo 或产品说明文档。
应用必须包含明确的经营内容和价格信息;且经营内容须与营业执照经营范围一致。
如应用开发者与支付宝账号名称不一致需提供开发者授权函。
个人账号申请,需提供营业执照,且支付宝账号名称需与营业执照主体一致。
注意:需按照要求提交材料,若部分材料不合格,收款额度将受到限制(单笔收款 ≤ 2000 元,单日收款 ≤ 20000 元)。若签约时未能提供相关材料(如营业执照),请在合约生效后的 30 天内补全,否则会影响正常收款。 点此查看详情
1.3 接入方式
开通:点击 立即开通,按要求填写并提交产品开通申请。点此查询 产品开通情况 。
开发:点此查询 开发文档
2.接入准备
商家或服务商可根据实际情况通过以下方式接入该产品:
商家自研:商家自助完成产品开通与接口调用。接入步骤详情可查看本文 自研商家接入 。
服务商代开发:服务商在获得商家授权后,可获得通过第三方应用调用支付宝的接口能力。接入步骤详情可查看本文 服务商代开发模式接入
2.1自研商家接入
商家自研接入流程
2.1.1创建应用
登录支付宝开放平台,点击创建小程序应用或 网页/移动应用。(仅支持应用类型为 移动应用 接入)。
说明:
生成的应用唯一标识 APPID 可用于调用开放产品接口。
iOS:
Bundle ID:即项目中配置的 Bundle Identifler 的 value 值。
Android:
应用包名:安卓项目中的 AndroidManifest.xml 文件内找到 package 对应的值。
应用签名:应用签名由开发者签名该应用的 keystore 文件决定。
应用签名的获取:在Android 接入指南 点击下载 Android分享SDK包 或 Android分享DEMO包 ,其中会附带 GenSignature.apk(应用签名获取工具) ,如下图所示。
2.1.2配置应用
产品绑定
小程序
创建应用后,在应用详情页下 开发 > 产品绑定菜单下,点击 绑定产品 ,添加 APP支付。
网页/移动应用
创建应用后,在应用详情页 产品绑定 菜单下,点击 绑定产品 ,添加 APP支付。
2.2开发设置
在 开发 > 开发设置 中配置应用信息。
2.2.1接口加签方式
必填。用于防止数据篡改,保障应用和支付宝交互的安全性,可查看 接口加签方式。
2.2.2服务器 IP 白名单
选填。用于提高应用访问开放平台的安全性,避免因应用私钥泄漏等原因导致业务受损,保障用户资金安全,可查看 服务器 IP 白名单。
2.2.3支付宝网关
必填。开发者调用 OpenAPI 发送 http(s) 请求至支付宝的目标地址(gateway),固定为 https://openapi.alipay.com/gateway.do。
2.2.4应用网关
必填。用于接收支付宝异步通知消息,需要传入 http(s) 公网可访问网页地址,可查看 应用网关。
2.2.5接口内容加密方式
选填。用于加 / 解密 OpenAPI bizContent 报文内容,可大幅提升接口内容传输的安全性。可查看 接口内容加密方式。
2.2.6服务器域名白名单
选填。小程序 若需要获取客户端域外资源(例如获取图片、服务端数据等),需要配置服务器域名白名单。
2.2.7 H5域名
选填。小程序 使用 web-view H5 页面承载组件 时需要配置 H5 页面中所有域名地址(含静态资源地址,如图片、.js 文件地址等),详情可查看 配置 H5 域名。
2.2.8 授权回调地址
选填。网页/移动应用 指定的回调页面 URL,用户信息授权 成功后,将在该 URL 后携带授权码等信息并跳转至该页面。
说明:授权链接中配置的 redirect_uri 的值必须与此回调地址保持一致 (如:https://www.alipay.com) 。
2.2.9订阅消息服务
选填。异步消息通知,用于提高应用 API 的调用效率。详情可查看 主动推送服务(From 蚂蚁)和 消息回流服务(To 蚂蚁)。
2.3上线应用
小程序应用:审核通过后自动上线。
网页/移动应用:需要手动上线。提交审核后,预计 1 个工作日的审核时间,请耐心等待,详细步骤可查看 上线应用。应用上线后,还需要完成开通产品才能在线上环境(生产环境)使用产品。
2.4绑定商家账号
可选操作。在支付宝开放平台创建的应用归属于对应的开放平台账号。如果要在应用中使用支付和资金等相关产品,需要将应用和支付宝商家平台账号绑定,应用才可调用需要商家开通的产品,具体步骤可查看 绑定应用。
2.5开通产品
应用上线后,还需要完成开通才能使用 APP支付。请在 商家平台 > 产品中心 的 APP支付产品详情页 点击 立即开通,填写并提交相关信息。详情可查看 开通产品 。
3.接入指南
3.1 APP 支付快速接入
3.1.1 支付流程
完成接入准备后,商家/服务商可根据本文指引快速接入 App 支付。
说明:
支持沙箱环境调试。
需要服务端和客户端结合请求唤起支付。
整体交互流程图
以下对重点步骤做简要说明:
第 1 步用户在商户 App 客户端/小程序中购买商品下单。
第 2 步商户订单信息由商户 App 客户端/小程序发送到服务端。
第 3 步商家服务端调用 alipay.trade.app.pay(app支付接口2.0)通过支付宝服务端 SDK 获取 orderStr(orderStr 中包含了订单信息和签名)。
第 4 步商家将 orderStr 发送给商户 App 客户端/小程序。
第 5 步商家在客户端/小程序发起请求,将 orderStr 发送给支付宝。
第 6 步进行支付预下单:支付宝客户端将会按照商家客户端提供的请求参数进行支付预下单。正常场景下,会唤起支付宝收银台等待用户核身;异常场景下,会返回异常信息。
第 11 步返回商家 App/小程序:用户在支付宝 App 完成支付后,会跳转回商家页面,并返回最终的支付结果(即同步通知),可查看 同步通知参数说明。
第 13 步支付结果异步通知,支付宝会根据步骤3 传入的异步通知地址 notify_url,发送异步通知,可查看 异步通知参数说明。
除了正向支付流程外,支付宝也提供交易查询、关闭、退款、退款查询以及对账等配套 API。
重要说明
首先确认已完成开通产品、创建应用、绑定产品、应用上线等步骤,详情可查看 接入准备 。
构造交易数据并签名必须在商家服务端完成,商家的应用私钥绝对不能保存在商家 APP 客户端中,也不能从服务端下发。
服务端生成的orderStr只是加签数据,并未请求到支付宝,只有客户端/小程序请求后,支付宝才会收到商户的订单信息。
同步返回的数据,只是一个简单的结果通知,商家确定该笔交易付款是否成功需要依赖服务端收到支付宝异步通知的结果进行判断,建议通过异步+查询方式判断避免错失异步漏失交易信息。
商家系统接收到通知以后,必须通过验签(验证通知中的 sign 参数)来确保支付通知是由支付宝发送的。建议使用支付宝提供的 SDK 来完成,详细验签规则可查看异步通知验签 。
订单创建时间:支付宝订单将在用户输入正确完整的支付密码后创建,并非唤起收银台时创建(余额不足等情况会导致交易处于订单创建等待支付状态)。
订单支付超时时间:订单创建后未支付,默认最晚付款时间为 15 天,若超过第 15 天当天 24 点订单超时关闭不可支付(超时参数设置范围 5min~15d)。
异步或查询接口返回的 trade_status(交易状态)为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
判断退款成功:退款接口返回 fund_change=Y 或者退款查询接口返回 refund_status=REFUND_SUCCESS。
注意:fund_change 只表示本次接口请求是否资金变动,不是指该笔交易是否资金变动。如果第一次退款成功,返回 Y,但是相同参数(如 out_request_no 不变)第二次请求则会返回 N,因此当 fund_change=N 时,建议通过退款查询接口进一步判断。
交易状态流程
随着订单支付成功、退款、关闭等操作,订单交易的每一个环节 trade_status(交易状态)也不同。
交易创建成功后,用户支付成功,交易状态转为 TRADE_SUCCESS(交易成功)。
交易成功后,规定退款时间内没有退款,交易状态转为 TRADE_FINISHED(交易完成)。
交易支付成功后,交易部分退款,交易状态仍为 TRADE_SUCCESS(交易成功)。
交易成功后,交易全额退款,交易状态转为 TRADE_CLOSED(交易关闭)。
交易创建成功后,用户未付款交易超时关闭,交易状态转为 TRADE_CLOSED(交易关闭)。
交易创建成功后,用户支付成功后,若用户商品不支持退款,交易状态直接转为 TRADE_FINISHED(交易完成)。
注意:交易成功后部分退款,交易状态仍为 TRADE_SUCCESS(交易成功)。
如果一直部分退款退完所有交易金额则交易状态转为 TRADE_CLOSED(交易关闭)。
如果未退完所有交易金额,超过有效退款时间后交易状态转为 TRADE_FINISHED(交易完成)不可退款。
3.1.2 服务端接入流程
服务端获取 orderStr
开发者可通过外部商家 App 唤起服务端 SDK ,建议调用alipay.trade.app.pay(app支付接口2.0) 获取 orderStr。
注意:支付宝订单将在用户输入支付密码后创建,并非唤起收银台时创建。订单实际创建时间也为用户支付时间,非唤起收银台时间。
请求示例
方式一:使用支付宝SDK (推荐)
示例代码、参数说明及错误码等信息,可查看 alipay.trade.app.pay(app支付接口2.0)接口文档。
注意:证书模式加签也需通过 alipayClient.sdkExecute(request); 方法发起请求,获取 orderStr。
orderStr 示例代码:
alipay_sdk=alipay-sdk-java-dynamicVersionNo&app_id=2014100900010000&biz_content=%7B%22total_amount%22%3A%220.01%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22subject%22%3A%22%E5%93%88%E5%93%88%E5%93%88%E5%93%88%E5%93%88%E5%A4%A7%E4%B9%90%E9%80%8F%22%2C%22out_trade_no%22%3A%2220220530000000011111101%22%7D&charset=utf-8&format=json&method=alipay.trade.app.pay&sign=iuO%2FTso2zr236p%2F%2FgyVoM9B7JGhyQqHHlL82siLLPI90xUruDVRt8hIOAroNid%2FTCbYUENSV4FkIZ5krrXm1qDFLHUnvtsUA3kToEojxyKilR8czZFYm6w91oxJseFZQJe0Os6IJg8oG29tYRf9TiXjB0leSwGQ3Ax8VilW2ATsne9L4A9Xah5fz7PTlKURTMYFqU166J2RH769wtTOjOb5Gs74aSdB3ymlZ486%2FGAcFwyXSvd3i8FEzsx3obLaM3oRQGQ%2Fx2jn8aL5qH3nVkGFIKA4xAUOZAaZSrj4EFw17HPFBYvcPwG55DQlmyLluh5lb4Ibi3j1ZxR4NiB0YFQ%3D%3D&sign_type=RSA2×tamp=2022-05-30+17%3A43%3A28&version=1.0
方式二:自行构建请求 (不推荐)
若开发者无法使用支付宝 SDK,可根据以下步骤自行构建请求:
请求参数组装分下列 3 步,以最后第三步获取到的请求为准。 请求参数按照 key=value&key=value 方式拼接的未签名原始字符串:
app_id=2015052600090779&biz_content={"timeout_express":"30m","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.01","subject":"1","body":"我是测试数据","out_trade_no":"IQJZSRC1YMQB5HU"}&charset=utf-8&format=json&method=alipay.trade.app.pay¬ify_url=http://domain.merchant.com/payment_notify&sign_type=RSA2×tamp=2016-08-25 20:26:31&version=1.0
再对原始字符串进行签名,可查看 自行实现签名 。
app_id=2015052600090779&biz_content={"timeout_express":"30m","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.01","subject":"1","body":"我是测试数据","out_trade_no":"IQJZSRC1YMQB5HU"}&charset=utf-8&format=json&method=alipay.trade.app.pay¬ify_url=http://domain.merchant.com/payment_notify&sign_type=RSA2×tamp=2016-08-25 20:26:31&version=1.0&sign=cYmuUnKi5QdBsoZEAbMXVMmRWjsuUj+y48A2DvWAVVBuYkiBj13CFDHu2vZQvmOfkjE0YqCUQE04kqm9Xg3tIX8tPeIGIFtsIyp/M45w1ZsDOiduBbduGfRo1XRsvAyVAv2hCrBLLrDI5Vi7uZZ77Lo5J0PpUUWwyQGt0M4cj8g=
最后对请求字符串的所有一级 value(biz_content 作为一个 value)进行 encode,编码格式按请求串中的 charset 为准,没传 charset 按 UTF-8 处理,获得最终的请求字符串。
app_id=2015052600090779&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%22IQJZSRC1YMQB5HU%22%7D&charset=utf-8&format=json&method=alipay.trade.app.pay¬ify_url=http%3A%2F%2Fdomain.merchant.com%2Fpayment_notify&sign_type=RSA2×tamp=2016-08-25%2020%3A26%3A31&version=1.0&sign=cYmuUnKi5QdBsoZEAbMXVMmRWjsuUj%2By48A2DvWAVVBuYkiBj13CFDHu2vZQvmOfkjE0YqCUQE04kqm9Xg3tIX8tPeIGIFtsIyp%2FM45w1ZsDOiduBbduGfRo1XRsvAyVAv2hCrBLLrDI5Vi7uZZ77Lo5J0PpUUWwyQGt0M4cj8g%3D
3.2异步通知说明
异步通知是指一笔订单支付完成后,支付宝会将该笔订单的变更信息,沿着商家调用支付请求时所传入的异步通知地址 notify_url,通过 POST 请求的形式将支付结果作为参数通知到商家系统。
异步回调地址状态码 (http 状态码) 为 200 时表示异步通知成功,返回码为 404 或 500 时则表示服务器内部错误,需要商家自行排查。
3.2.1异步通知参数
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
notify_time | Date | 是 | - | 通知时间。通知的发送时间。格式为 yyyy-MM-dd HH:mm:ss。 | 2020-12-27 06:20:30 |
notify_type | String | 是 | 64 | 通知类型。 枚举值:trade_status_sync。 | trade_status_sync |
notify_id | String | 是 | 128 | 通知校验 ID。 | ac05099524730693a8b330c5ecf72da9786 |
sign_type | String | 是 | 10 | 签名类型。商家生成签名字符串所使用的签名算法类型,目前支持 RSA2 和 RSA,推荐使用 RSA2(如果开发者手动验签,不使用 SDK 验签,可以不传此参数)。 | RSA2 |
sign | String | 是 | 344 | 签名。可查看异步返回结果的验签(如果开发者手动验签,不使用 SDK 验签,可以不传此参数)。 | 601510b7970e52cc63db0f44997cf70e |
trade_no | String | 是 | 64 | 支付宝交易号。支付宝交易凭证号。 | 20213112011001004330000121536 |
app_id | String | 是 | 32 | 开发者的 app_id。支付宝分配给开发者的应用 APPID。 | 2014072300007148 |
auth_app_id | String | 是 | 32 | 开发者的 app_id,在服务商调用的场景下为授权方的 app_id。 | 2014072300007148 |
out_trade_no | String | 是 | 64 | 商户订单号。 | 6823789339978248 |
out_biz_no | String | 否 | 64 | 商家业务号。商家业务 ID,主要是退款通知中返回退款申请的流水号。 | HZRF001 |
buyer_id | String | 否 | 16 | 买家支付宝用户号。买家支付宝账号对应的支付宝唯一用户号。 | 2088102122524333 |
buyer_logon_id | String | 否 | 100 | 买家支付宝账号。 | 180****0062 |
seller_id | String | 否 | 30 | 卖家支付宝用户号。 | 2088101106499364 |
seller_email | String | 否 | 100 | 卖家支付宝账号。 | |
trade_status | String | 是 | 32 | 交易状态。咨询目前所处的状态。 | TRADE_CLOSED |
total_amount | Number | 是 | 11 | 订单金额。本次交易支付的订单金额,单位为人民币(元)。支持小数点后两位。 | 20 |
receipt_amount | Number | 是 | 11 | 实收金额。商家在交易中实际收到的款项,单位为人民币(元)。支持小数点后两位。 | 15 |
invoice_amount | Number | 否 | 11 | 开票金额。用户在交易中支付的可开发票的金额。支持小数点后两位。 | 10.00 |
buyer_pay_amount | Number | 否 | 11 | 付款金额。用户在咨询中支付的金额。支持小数点后两位。 | 13.88 |
point_amount | Number | 否 | 11 | 集分宝金额。使用集分宝支付的金额。支持小数点后两位。 | 12.00 |
refund_fee | Number | 否 | 11 | 总退款金额。退款通知中,返回总退款金额,单位为元,支持小数点后两位。 | 2.58 |
send_back_fee | Number | 否 | 11 | 实际退款金额。商家实际退款给用户的金额,单位为元,支持小数点后两位。 | 2.08 |
subject | String | 否 | 256 | 订单标题。商品的标题/交易标题/订单标题/订单关键字等,是请求时对应的参数,原样通知回来。 | XXX交易 |
body | String | 否 | 400 | 商品描述。该订单的备注、描述、明细等。对应请求时的 body 参数,原样通知回来。 | XXX交易内容 |
passback_params | String | 否 | 512 | 公共回传参数,如果请求时传递了该参数,则返回给商家时会在异步通知时将该参数原样返回。本参数必须进行 UrlEncode 之后才可以发送给支付宝。 | - |
gmt_create | Date | 否 | - | 交易创建时间。该笔交易创建的时间。格式 为 yyyy-MM-dd HH:mm:ss。 | 2015-04-27 15:45:57 |
gmt_payment | Date | 否 | - | 交易 付款时间。该笔交易的买家付款时间。格式为 yyyy-MM-dd HH:mm:ss。 | 2015-04-27 15:45:57 |
gmt_refund | Date | 否 | - | 交易退款时间。该笔交易的退款时间。格式 为 yyyy-MM-dd HH:mm:ss.SS。 | 2015-04-28 15:45:57.320 |
gmt_close | Date | 否 | - | 交易结束时间。该笔交易结束时间。格式为 yyyy-MM-dd HH:mm:ss。 | 2015-04-29 15:45:57 |
fund_bill_list | String | 否 | 512 | 支付金额信息。支付成功的各个渠道金额信息,详请可查看下表 资金明细信息说明 。 | [{"amount":"15.00", "fundChannel":"ALIPAYACCOUNT" }] |
voucher_detail_list | String | 否 | - | 优惠券信息。本交易支付时所使用的所有优惠券信息,详请可查看下表 优惠券信息说明 。 | [{"amount":"0.20", "merchantContribute":"0.00", "name":"一键创建券模板的券名称", "otherContribute":"0.20", "type":"ALIPAY_BIZ_VOUCHER", "memo":"学生8折优惠" }] |
3.2.2交易状态说明
枚举名称 | 枚举说明 |
WAIT_BUYER_PAY | 交易创建,等待买家付款。 |
TRADE_CLOSED | 未付款交易超时关闭,或支付完成后全额退款。 |
TRADE_SUCCESS | 交易支付成功。 |
TRADE_FINISHED | 交易结束,不可退款。 |
3.2.3通知触发条件
触发条件名 | 触发条件描述 | 触发条件默认值 |
TRADE_FINISHED | 交易完成 | true(触发通知) |
TRADE_SUCCESS | 支付成功 | true(触发通知) |
TRADE_CLOSED | 交易关闭 | true(触发通知) |
WAIT_BUYER_PAY | 交易创建 | false(不触发通知) |
3.2.4资金明细信息说明
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
fundChannel | String | 否 | - | 支付渠道。详情可查看 支付渠道说明。 | ALIPAYACCOUNT |
amount | String | 否 | 11 | 支付金额。使用指定支付渠道支付的金额,单位为元。 | 15.00 |
3.2.5异步通知特性
在进行异步通知交互时,如果支付宝收到的应答不是 success,支付宝会认为通知失败,会通过一定的策略定期重新发起通知。通知的间隔频率为:4m、10m、10m、1h、2h、6h、15h。
商家设置的异步地址(notify_url)需保证无任何字符,如空格、HTML 标签,且不能重定向。(如果重定向,支付宝会收不到 success 字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知)
支付宝是用 POST 方式发送通知信息,商户获取参数的方式如下:request.Form("out_trade_no")、$_POST['out_trade_no']。
支付宝针对同一条异步通知重试时,异步通知参数中的 notify_id 是不变的。
3.2.6异步返回结果验签
某商家设置的通知地址为 https://api.xx.com/receive_notify.htm,对应接收到通知的示例如下:
注意:以下示例报文仅供参考,实际返回的详细报文请以实际返回为准。
https://api.xx.com/receive_notify.htm?gmt_payment=2015-06-11 22:33:59¬ify_id=42af7baacd1d3746cf7b56752b91edcj34&seller_email=testyufabu07@alipay.com¬ify_type=trade_status_sync&sign=kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=&trade_no=2015061121001004400068549373&out_trade_no=21repl2ac2eOutTradeNo322&gmt_create=2015-06-11 22:33:46&seller_id=2088211521646673¬ify_time=2015-06-11 22:34:03&subject=FACE_TO_FACE_PAYMENT_PRECREATE中文&trade_status=TRADE_SUCCESS&sign_type=RSA2
第一步:在通知返回参数列表中,除去 sign、sign_type 两个参数外,通知返回的参数均为待验签的参数。
第二步: 将剩下参数进行 URLDecode,然后进行字典排序,组成字符串,得到待签名字符串:
gmt_create=2015-06-11 22:33:46&gmt_payment=2015-06-11 22:33:59¬ify_id=42af7baacd1d3746cf7b56752b91edcj34¬ify_time=2015-06-11 22:34:03¬ify_type=trade_status_sync&out_trade_no=21repl2ac2eOutTradeNo322&seller_email=testyufabu07@alipay.com&seller_id=2088211521646673&subject=FACE_TO_FACE_PAYMENT_PRECREATE中文&trade_no=2015061121001004400068549373&trade_status=TRADE_SUCCESS
第三步: 将签名参数(sign)使用 base64 解码为字节码串。
第四步: 使用 RSA 的验签方法,通过签名字符串、签名参数(经过 base64 解码)及支付宝公钥验证签名。
第五步:在步骤四验证签名正确后,必须再严格按照如下描述校验通知数据的正确性。
商家需要验证该通知数据中的 out_trade_no 是否为商家系统中创建的订单号。
判断 total_amount 是否确实为该订单的实际金额(即商家订单创建时的金额)。
校验通知中的 seller_id(或者 seller_email ) 是否为 out_trade_no 这笔单据的对应的操作方(有的时候,一个商家可能有多个seller_id/seller_email)。
验证 app_id 是否为该商家本身。
上述 1、2、3、4 有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商家必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
注意:
状态 TRADE_SUCCESS 的通知触发条件是商家开通的产品支持退款功能的前提下,买家付款成功。
交易状态 TRADE_FINISHED 的通知触发条件是商家开通的产品不支持退款功能的前提下,买家付款成功或商家开通的产品支持退款功能的前提下,交易已经成功并且已经超过可退款期限。
响应值
响应值 | 描述 | 异步是否重试发送 |
fail | 消息获取失败 | 重试 |
success | 消息获取成功 | 不重试 |
3.3手机网站支付转 APP 支付
当开发者已完成 手机网站支付服务端接入 后可以通过 Native 支付方式唤起支付宝 App。
为了节约开发成本,商家在自有App内嵌H5页接入手机网站支付,由于手机网站支付的网络依赖比较严重,通常需要经过更多的验证, 这样会降低支付的成功率。为了能够帮助商家使用 Native-H5 混合 App 以极低的接入成本 极大的 提升支付成功率,平台推出了手机网站支付转 Native 支付方式,商家下载使用 支付宝标准版 SDK 内置的功能完成手机网站支付。
注意:若未安装支付宝App参考下图,点击下载支付宝App付款下载之后再进行支付。
下面以淘宝为例对比手机网站支付和手机网站转 Native 支付的流程。
3.3.1手机网站支付流程
在手机端浏览器中访问淘宝主页 www.taobao.com,在页面挑选商品并进行付款,点击 立即支付 进入付款详情页面(H5 页面)。
iOS
Android
3.3.2手机网站转 Native 支付流程
下载 并运行 Demo,将 Demo App 安装到手机上即可体验该流程,并在 Demo 中打开淘宝主页 www.taobao.com,挑选商品并进行付款。
注意:请确保手机上安装了支付宝客户端。
iOS
点击 URLPay > openUrl,输入 www.taobao.com 并点击 Go,然后在淘宝主页选中商品并付款。
Android
点击 网页支付转native然后在淘宝主页选中商品并付款。
3.3.3对比总结
手机网站支付与手机网站转 Native 支付的主要区别为:
如果用户手机安装了支付宝客户端,手机网站转 Native 支付方式将跳转到支付宝客户端中进行订单支付,用户体验和支付成功率均优于手机网站支付方式。除此之外,还能使用手机网站支付没有提供的指纹支付、手环、手表支付、免密支付等功能。
如果用户手机没有安装支付宝客户端,将在 SDK 提供的 Web-view 中打开 H5 页面进行支付。即便如此,由于 SDK 与服务端的交互携带账号信息,仍比不携带任何账号信息的普通手机网站支付体验更好。
3.3.4如何实现手机网站转Native支付
要实现上述功能需接入支付宝提供的 SDK。接入过程十分简单,可以以上述 Demo 为参考,该 Demo 程序只有一个功能:创建一个 Web-view,在 Web-view 中拦截每个 URL,然后调用 SDK 提供的接口检查该 URL 是否是有效的支付宝订单支付 URL,如果是则将该 URL 传给 SDK 提供的支付接口进行支付。
3.4沙箱环境联调
沙箱环境是支付宝开放平台为开发者提供的与生产环境完全隔离的联调测试环境,开发者在沙箱环境中完成的调用不会对生产环境中的数据造成任何影响。
沙箱环境会自动完成或忽略一些场景的业务门槛,例如:开发者无需等待产品签约,即可直接在沙箱环境调用接口,使得开发集成工作可以与商务流程并行,从而提高项目整体的交付效率。
注意:
由于沙箱环境并非 100% 与生产环境一致,接口的实际响应逻辑请以生产环境为准,沙箱环境开发调试完成后,仍然需要在生产环境进行测试验收。
沙箱环境拥有完全独立的数据体系,沙箱环境下返回的数据(比如用户 ID 等)在生产环境中都是不存在的,开发者不可将沙箱环境返回的数据与生产环境中的数据混淆。
本文仅说明如何在沙箱环境中调试 App 支付能力,非调试通用说明。
3.4.1沙箱功能范围
支持的接口
接口类型 | 接口中文名 | 接口英文名称 | 沙箱环境是否支持 | 沙箱环境调用注意事项 |
app支付 | app支付接口2.0 | 支持 | - | |
辅助接口 | 统一收单线下交易查询 | 支持 | - | |
统一收单交易退款接口 | 支持 | - | ||
统一收单交易退款查询接口 | 支持 | - | ||
统一收单交易关闭接口 | 支持 | - | ||
查询对账单下载地址 | 支持 | 沙箱环境只做模拟调用,下载账单为模板,账单内没有实际数据。 | ||
From 蚂蚁消息接口 | 收单退款冲退完成通知 | 不支持 | 沙箱环境不支持银行卡支付,无法模拟测试。 |
3.4.2沙箱调试注意事项
建议只传必传参数测试,避免部分参数只对生产环境兼容。
参数注意事项
alipay.trade.app.pay 沙箱参数区别如下
参数 | 描述说明 |
timeout_express | 相对超时参数
|
time_expire | 绝对超时参数 沙箱环境:不可超过当前时间 15 小时。 |
extend_params | 花呗分期,不支持设置,沙箱不支持花呗分期测试。 示例:"extend_params":{"hb_fq_num":"3","hb_fq_seller_percent":"100"} |
ext_user_info | 外部指定买家,不支持设置。 沙箱环境无法校验买家身份信息。 |
支付注意事项
沙箱测试只支持余额支付,不支持银行卡、余额宝、花呗等其它支付方式。
沙箱测试会扣手续费,但沙箱扣款手续费比例不代表生产环境的情况,生产环境手续费请以签约协议为准。
若使用纯客户端 Demo 测试(不结合服务端请求),建议 Demo 中配置的密钥为 pkcs8 格式。
注意:测试完后正式上线,建议结合服务端请求,避免私钥设置在客户端导致泄漏、资损。
手机安装有正式的支付宝钱包和沙箱钱包,测试(若无相关提示选择使用哪个钱包)一般默认是唤起的正式支付宝钱包支付,此时由于生产环境的支付宝钱包支付沙箱数据会导致报错。该情况下,需查看支付页面背景是否是生产环境支付宝钱包页面进行判断,建议修改为沙箱钱包支付。
App 支付只支持 Android 版接入,在使用 SDK 时,在支付接口前调用如下方法用于切换沙箱环境与生产环境; 如果不使用此方法,默认使用生产环境。
EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);
方法调用位置如下图所示:
注意:在生产环境,必须将此代码注释。
3.4.3沙箱控制台操作指南
使用沙箱环境进行调试前,开发者需根据 操作指引完成沙箱控制台及接口调用配置。
注意:请使用沙箱应用信息以及沙箱网关:https://openapi.alipaydev.com/gateway.do
3.5 SDK & DEMO 获取
在接入 App 支付客户端 SDK 前,请先阅读 App 支付产品介绍文档 。
如果开发者使用的是老版本移动支付接口 mobile.securitypay.pay ,请参考 老版本移动支付文档 。
3.5.1 DEMO&SDK 获取
集成前请仔细阅读 App 支付客户端 SDK 隐私政策。
资源内容 | 资源版本 | 获取方式 |
Android 支付 SDK 和示例 Demo | * | 目前 SDK 已发布到 Maven Central,开发者可使用 gradle 编译、更新支付宝支付 SDK。 在 build.gradle 文件中,需添加如下依赖: dependencies { api 'com.alipay.sdk:alipaysdk-android:+@aar' } |
点击下载 示例 Demo。 | ||
iOS 支付 SDK 和示例 Demo | 15.8.11 | 点击下载 SDK & 示例 Demo 。 |
鸿蒙支付 SDK 和示例 Demo | 15.8.01 | 点击下载 SDK & 示例 Demo ,SDK 使用详情可查看 鸿蒙 SDK 接入说明 。 |
3.5.2注意
接入后请对设备上 已安装支付宝 App 和 未安装支付宝 App 两种情况分别测试支付流程。
支付参数签名过程和私钥 必须在 App 服务端 完成,示例项目中的签名流程仅供开发时参考。
iOS 构建时可能发生 utdid 库相关的冲突,此时请改用兼容版 SDK。
如果 App 正在使用 mPaaS 移动开发平台,构建时可能发生内部类冲突,请查看mPaaS 技术文档提供的冲突解决方案,接入 mPaaS 版本的支付 SDK。
接入过程中如果遇到问题,请点击查看App 支付常见问题,或在文档中心搜索
4.App支付接口2.0
外部商户APP唤起快捷SDK创建订单并支付
4.1公共请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
app_id | String | 必选 | 32 | 支付宝分配给开发者的应用ID | 2014072300007148 |
method | String | 必选 | 128 | 接口名称 | alipay.trade.app.pay |
format | String | 可选 | 40 | 仅支持JSON | JSON |
charset | String | 必选 | 10 | 请求使用的编码格式,如utf-8,gbk,gb2312等 | utf-8 |
sign_type | String | 必选 | 10 | 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 | RSA2 |
sign | String | 必选 | 344 | 商户请求参数的签名串,详见签名 | 详见示例 |
timestamp | String | 必选 | 19 | 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" | 2014-07-24 03:07:50 |
version | String | 必选 | 3 | 调用的接口版本,固定为:1.0 | 1.0 |
notify_url | String | 可选 | 256 | 支付宝服务器主动通知商户服务器里指定的页面http/https路径。 | |
app_auth_token | String | 可选 | 40 | 详见应用授权概述 | |
biz_content | String | 必选 | 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 |
4.2请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
out_trade_no | String | 必选 | 64 | 商户网站唯一订单号。 由商家自定义,64个字符以内,仅支持字母、数字、下划线且需保证在商户端不重复。 | 70501111111S001111119 |
total_amount | String | 必选 | 9 | 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000],金额不能为0 | 9.00 |
subject | String | 必选 | 256 | 订单标题。 注意:不可使用特殊字符,如 /,=,& 等。 | 大乐透 |
goods_detail | GoodsDetail[] | 可选 | 订单包含的商品列表信息,json格式,其它说明详见商品明细说明 | ||
time_expire | String | 可选 | 32 | 绝对超时时间,格式为yyyy-MM-dd HH:mm:ss | 2016-12-31 10:05:00 |
extend_params | ExtendParams | 可选 | 业务扩展参数 | ||
business_params | String | 可选 | 512 | 商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式 | {"mc_create_trade_ip":"127.0.0.1"} |
passback_params | String | 可选 | 512 | 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在同步返回(包括跳转回商户网站)和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。 | merchantBizType%3d3C%26merchantBizNo%3d2016010101111 |
merchant_order_no | String | 可选 | 32 | 商户原始订单号,最大长度限制32位 | 20161008001 |
ext_user_info | ExtUserInfo | 可选 | 外部指定买家 | ||
query_options | String[] | 可选 | 1024 | 返回参数选项。 商户通过传递该参数来定制同步需要额外返回的信息字段,数组格式。包括但不限于:["hyb_amount","enterprise_pay_info"] | ["hyb_amount","enterprise_pay_info"] |
4.3公共响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
code | String | 必选 | - | 网关返回码,详见文档 | 40004 |
msg | String | 必选 | - | 网关返回码描述,详见文档 | Business Failed |
sub_code | String | 可选 | - | 业务返回码,参见具体的API接口文档 | ACQ.TRADE_HAS_SUCCESS |
sub_msg | String | 可选 | - | 业务返回码描述,参见具体的API接口文档 | 交易已被支付 |
sign | String | 必选 | - | 签名,详见文档 | DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo= |
4.4响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
out_trade_no | String | 必选 | 64 | 商户网站唯一订单号 | 70501111111S001111119 |
trade_no | String | 必选 | 64 | 该交易在支付宝系统中 | 2014112400001000340011111118 |
total_amount | String | 必选 | 9 | 该笔订单的资金总额,单位为人民币(元),取值范围为 0.01~100000000.00,精确到小数点后两位。 | 9.00 |
seller_id | String | 必选 | 16 | 收款支付宝账号对应的支付宝唯一用户号。 以2088开头的纯16位数字 | 2088111111116894 |
merchant_order_no | String | 必选 | 32 | 商户原始订单号,最大长度限制32位 | 20161008001 |
4.5请求示例
$aop = new AopClient ();
$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = 'your app_id';
$aop->rsaPrivateKey = '请填写开发者私钥去头去尾去回车,一行字符串';
$aop->alipayrsaPublicKey='请填写支付宝公钥,一行字符串';
$aop->apiVersion = '1.0';
$aop->signType = 'RSA2';
$aop->postCharset='GBK';
$aop->format='json';
$object = new stdClass();
$object->out_trade_no = '20210817010101004';
$object->total_amount = 0.01;
$object->subject = '测试商品';
$object->product_code ='QUICK_MSECURITY_PAY';
$object->time_expire = '2022-08-01 22:00:00';
商品信息明细,按需传入
// $goodsDetail = [
// [
// 'goods_id'=>'goodsNo1',
// 'goods_name'=>'子商品1',
// 'quantity'=>1,
// 'price'=>0.01,
// ],
// ];
// $object->goodsDetail = $goodsDetail;
// //扩展信息,按需传入
// $extendParams = [
// 'sys_service_provider_id'=>'2088511833207846',
// ];
// $object->extend_params = $extendParams;
$json = json_encode($object);
$request = new AlipayTradeAppPayRequest();
$request->setNotifyUrl('');
$request->setBizContent($json);
$result = $aop->sdkExecute ( $request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultCode = $result->$responseNode->code;
if(!empty($resultCode)&&$resultCode == 10000){
echo "成功";
} else {
echo "失败";
}
4.6响应示例
{
"alipay_trade_app_pay_response": {
"code": "10000",
"msg": "Success",
"app_id": "2014072300007148",
"auth_app_id": "2014072300007148",
"charset": "utf-8",
"timestamp": "2016-10-11 17:43:36",
"out_trade_no": "081622560194853",
"total_amount": "9.00",
"trade_no": "2016081621001004400236957647",
"seller_id": "2088702849871851"
},
"sign": "NGfStJf3i3ooWBuCDIQSumOpaGBcQz+aoAqyGh3W6EqA/gmyPYwLJ********",
"sign_type": "RSA2"
}
4.7异常示例
{
"alipay_trade_app_pay_response": {
"code": "20000",
"msg": "Service Currently Unavailable",
"sub_code": "isp.unknow-error",
"sub_msg": "系统繁忙"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
4.8错误码
公共错误码
业务错误码
错误码 | 错误描述 | 解决方案 |
ACQ.SYSTEM_ERROR | 接口返回错误 | 请立即调用查询订单API,查询当前订单的状态,并根据订单状态决定下一步的操作 |
ACQ.ACCESS_FORBIDDEN | 无权限使用接口 | 联系支付宝小二签约 |
ACQ.EXIST_FORBIDDEN_WORD | 订单信息中包含违禁词 | 修改订单信息后,重新发起请求 |
ACQ.PARTNER_ERROR | 应用APP_ID填写错误 | 联系支付宝小二,确认APP_ID的状态 |
ACQ.TOTAL_FEE_EXCEED | 订单总金额不在允许范围内 | 修改订单金额再发起请求 |
ACQ.BUYER_SELLER_EQUAL | 买卖家不能相同 | 更换买家重新付款 |
ACQ.BUYER_ENABLE_STATUS_FORBID | 买家状态非法 | 用户联系支付宝小二,确认买家状态为什么非法 |
ACQ.SELLER_BEEN_BLOCKED | 商家账号被冻结 | 联系支付宝小二,解冻账号 |
ACQ.INVALID_PARAMETER | 参数无效 | 若存在参数无效具体错误信息描述,请参考描述检查请求参数后,重新发起 |
ACQ.TRADE_HAS_CLOSE | 交易已经关闭 | 确认该笔交易信息是否为当前买家的已存订单,如果是则认为交易已经关闭,如果不是则更换商家订单号后,重新发起请求 |
ACQ.CONTEXT_INCONSISTENT | 交易信息被篡改 | 确认该笔交易信息是否为当前买家的已存订单,如果是则认为本次请求参数与已存交易不一致,如果不是则更换商家订单号后,重新发起请求 |
ACQ.TRADE_BUYER_NOT_MATCH | 交易买家不匹配 | 该笔交易已经在支付宝端创建,但请求买家与已存交易中的买家不一致。请商户确认本次请求是否与已存交易有关,若为同一笔交易,则只能用原始买家付款,若无关更换商家订单号后,重新发起请求 |
ACQ.TRADE_HAS_SUCCESS | 交易已被支付 | 确认该笔交易信息是否为当前买家的,如果是则认为交易付款成功,如果不是则更换商家订单号后,重新发起请求 |
ACQ.RISK_MERCHANT_IP_NOT_EXIST | 当前交易未传入IP信息,创单失败,请传入IP后再发起支付 | 检查请求参数是否已经传入用户IP信息 |
4.9触发通知类型
通知类型 | 描述 | 默认开启 |
tradeStatus.TRADE_CLOSED | 交易关闭 | 1 |
tradeStatus.TRADE_FINISHED | 交易完结 | 1 |
tradeStatus.TRADE_SUCCESS | 支付成功 | 1 |
tradeStatus.WAIT_BUYER_PAY | 交易创建 | 0 |
四.电脑网站支付
产品介绍
1.1介绍
电脑网站支付是指商户在电脑网页展示商品或服务,用户在商户页面确认使用支付宝支付时,浏览器自动跳转支付宝电脑网页完成付款的支付产品
1.2申请条件
签约申请提交材料要求如下:
提供网站地址,网站能正常访问且页面显示完整,网站需要明确经营内容且有完整的商品信息。
网站必须通过 ICP 备案,且备案主体需与支付宝账号主体一致。若网站备案主体与当前账号主体不同时需上传授权函。
如以个人账号申请,需提供营业执照,且支付宝账号名称需与营业执照主体一致。
注意:需按照要求提交材料,若部分材料不合格,收款额度将受到限制(单笔收款 ≤ 2000 元,单日收款 ≤ 20000 元)。若签约时未能提供相关材料(如营业执照),请在合约生效后的 30 天内补全,否则会影响正常收款。 点此查看详情
1.3接入方式
开通:点击 立即开通,按要求填写并提交产品开通申请。点此查看 产品开通情况。
开发:点击查看 开发文档
2.接入准备
商家或服务商可根据实际情况通过以下两种方式接入该产品:
商家自研:商家自助完成产品开通与接口调用。接入步骤详情可查看本文 自研商家接入。
服务商代开发:服务商在获得商家授权后,可获得通过第三方应用调用支付宝的接口能力。接入步骤详情可查看本文 服务商代开发模式接入。
2.1自研商家接入
商家自研接入流程
2.1.1创建应用
登录支付宝开放平台创建 网页/移动应用。
说明:生成的应用唯一标识 APPID 可用于调用开放产品接口。
2.2配置应用
产品绑定
网页/移动应用
创建应用后,在应用详情页 产品绑定 菜单下,点击 绑定产品 ,添加 电脑网站支付。
2.3开发设置
在 开发 > 开发设置 中配置应用信息。
2.3.1接口加签方式
必填。用于防止数据篡改,保障应用和支付宝交互的安全性,可查看 接口加签方式。
2.3.2服务器 IP 白名单
选填。用于提高应用访问开放平台的安全性,避免因应用私钥泄漏等原因导致业务受损,保障用户资金安全,可查看 服务器 IP 白名单。
2.3.3支付宝网关
必填。开发者调用 OpenAPI 发送 http(s) 请求至支付宝的目标地址(gateway),固定为 https://openapi.alipay.com/gateway.do。
2.3.4应用网关
必填。用于接收支付宝异步通知消息,需要传入 http(s) 公网可访问网页地址,可查看 应用网关。
2.3.5接口内容加密方式
选填。用于加 / 解密 OpenAPI bizContent 报文内容,可大幅提升接口内容传输的安全性。可查看 接口内容加密方式。
2.3.6授权回调地址
选填。网页/移动应用 指定的回调页面 URL,用户信息授权 成功后,将在该 URL 后携带授权码等信息并跳转至该页面。
说明:授权链接中配置的 redirect_uri 的值必须与此回调地址保持一致 (如:https://www.alipay.com) 。
2.3.7订阅消息服务
选填。异步消息通知,用于提高应用 API 的调用效率。详情可查看 主动推送服务(From 蚂蚁)和 消息回流服务(To 蚂蚁)。
2.4上线应用
网页/移动应用:需要手动上线。提交审核后,预计 1 个工作日的审核时间。详细步骤可点击查看上线应用。应用上线后,还需要完成产品开通才能在线上环境(生产环境)使用产品。
2.5绑定商家账号
可选操作。在支付宝开放平台创建的应用归属于对应的开放平台账号。如果要在应用中使用支付和资金等相关产品,需要将应用和支付宝商家平台账号绑定,应用才可调用需要商家开通的产品,具体步骤可查看 绑定应用。
2.6开通产品
应用上线后,还需要完成开通才能使用 当面付。请在 商家平台 > 产品中心 的 电脑网站支付产品详情页 点击 立即开通,填写并提交相关信息完成产品开通。详情可点击查看 开通产品 。
如您已经开通当面付,则无需再次开通,开通状态可点击 产品开通情况查询
2.7服务商代开发模式接入
见官网: https://opendocs.alipay.com/open/270/01didh?ref=api#%E6%9C%8D%E5%8A%A1%E5%95%86%E4%BB%A3%E5%BC%80%E5%8F%91%E6%A8%A1%E5%BC%8F%E6%8E%A5%E5%85%A5
3.接入指南
3.1电脑网站支付快速接入
完成 接入准备 后,商家/服务商可根据本文指引快速接入 电脑网站支付,完成与支付宝对接的部分,包括支付、退款、关闭交易,下载账单。
说明:
支持沙箱调试。
3.1.1支付流程
电脑网站支付的支付接口 alipay.trade.page.pay(统一收单下单并支付页面接口)调用时序图如下:
调用流程如下:
商家系统调用 alipay.trade.page.pay(统一收单下单并支付页面接口)向支付宝发起支付请求,支付宝对商家请求参数进行校验,而后重新定向至用户登录页面。
用户确认支付后,支付宝通过 get 请求 returnUrl(商户入参传入),返回同步返回参数。
交易成功后,支付宝通过 post 请求 notifyUrl(商户入参传入),返回异步通知参数。
若由于网络等原因,导致商家系统没有收到异步通知,商家可自行调用 alipay.trade.query(统一收单线下交易查询接口)查询交易以及支付信息(商家也可以直接调用该查询接口,不需要依赖异步通知)。
注意:
由于同步返回的不可靠性,支付结果必须以异步通知或查询接口返回为准,不能依赖同步跳转。
商家系统接收到异步通知以后,必须通过验签(验证通知中的 sign 参数)来确保支付通知是由支付宝发送的。详细验签规则可查看 异步通知验签。
接收到异步通知并验签通过后,请务必核对通知中的 app_id、out_trade_no、total_amount 等参数值是否与请求中的一致,并根据 trade_status 进行后续业务处理。
在支付宝端,partnerId 与 out_trade_no 唯一对应一笔单据,商家端保证不同次支付 out_trade_no 不可重复;若重复,支付宝会关联到原单据,基本信息一致的情况下会以原单据为准进行支付。
开放平台提供了支持主流开发语言的 SDK 接入的方式。对于页面跳转类 API,SDK 不会也无法像系统调用类 API 一样自动请求支付宝并获得结果,而是在接受 request 请求对象后,为开发者生成前台页面请求需要的完整 form 表单的 html(包含自动提交脚本),商家直接将这个表单的 String 输出到 http response 中即可。
注意:
付款页面生成的付款码每 2 分钟 会自动刷新一次。
电脑网站支付后使用 商家分账 完成分账,查询结果需使用 alipay.trade.query(统一收单线下交易查询接口) query_options 传入 trade_settle_info 查询分账信息,不能使用 alipay.trade.order.settle.query(交易分账查询接口)查询。
3.1.1.1重要入参说明
注意:请严格按照接口文档中的参数入参,传入非接口文档中的参数是无效的,并且可能会导致请求被拦截或其它异常。
参数名称 | 参数说明 |
subject | 必填,商品的标题/交易标题/订单标题/订单关键字等。 不可使用特殊字符,如 /,=,& 等。 |
product_code | 必填,销售产品码,与支付宝签约的产品码名称。目前电脑支付场景下仅支持 FAST_INSTANT_TRADE_PAY |
total_amount | 必填,订单总金额,单位为元,精确到小数点后两位,取值范围为 [0.01,100000000]。金额不能为0。 |
3.1.3退款流程
当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,支付宝将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退回到买家账号上。
3.1.3.1系统流程
商家可调用 alipay.trade.refund(统一收单交易退款查询接口)进行退款,支付宝同步返回退款参数。调用时序图如下:
若退款接口由于网络等原因返回异常,商家可调用退款查询接口 alipay.trade.fastpay.refund.query(统一收单交易退款查询接口)查询指定交易的退款信息。
支付宝退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。
3.1.3.2退款说明
退款周期:12 个月,即交易发生后 12 个月内可发起退款,超过 12 个月则不可发起退款。
退款方式:资金原路返回用户账号。
退款退费:退款时手续费不退回。
一笔退款失败后重新提交,要采用原来的退款单号。
总退款金额不能超过用户实际支付金额。
退款信息以退款接口同步返回或者 alipay.trade.fastpay.refund.query(统一收单交易退款查询接口)为准。
3.1.3.3退款到银行卡通知
退款存在退到银行卡场景下时,支付宝会调用alipay.trade.refund.depositback.completed(收单退款冲退完成通知接口)根据银行回执消息发送退款完成信息至应用网关地址。
注意:开发者需登录开放平台进入对应应用详情页,在开发设置 > 消息服务 > FROM 平台中订阅alipay.trade.refund.depositback.completed(收单退款冲退完成通知接口)。
3.1.3.4重要参数说明
参数名称 | 参数说明 |
trade_no | 支付宝交易订单号 |
dback_status | 银行卡冲退状态。
|
dback_amount | 银行卡冲退金额 |
bank_ack_time | 银行响应时间,格式为 yyyy-MM-dd HH:mm:ss |
est_bank_receipt_time | 预估银行入账时间,格式为 yyyy-MM-dd HH:mm:ss |
更多 From 蚂蚁消息详情参见 From 蚂蚁消息服务使用。
更多操作见官网: https://opendocs.alipay.com/open/270/105899?ref=api#%E5%85%B3%E9%97%AD%E4%BA%A4%E6%98%93
3.2异步通知说明
对于 PC 网站支付的交易,在用户支付完成之后,支付宝会根据 API 中商家传入的 notify_url,通过 POST 请求的形式将支付结果作为参数通知到商家系统。
3.2.1异步通知参数
公共参数
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
notify_time | Date | 是 | - | 通知的发送时间。格式为 yyyy-MM-dd HH:mm:ss | 2018-10-21 15:45:22 |
notify_type | String | 是 | 64 | 通知类型 | trade_status_sync |
notify_id | String | 是 | 128 | 通知校验 ID | ac05099524730693a8b330c45cf72da943 |
charset | String | 是 | 10 | 编码格式。如 utf-8、gbk、gb312等。 | utf-8 |
version | String | 是 | 3 | 调用的接口版本。固定为1.0 | 1.0 |
sign_type | String | 是 | 10 | 签名类型。签名算法类型,目前支持RSA2和RSA,推荐使用 RSA2 | RSA2 |
sign | String | 是 | 344 | 签名。详情可查看 异步返回结果的验签 | 601510b7970e52cc63db0f44997cf70e |
auth_app_id | String | 是 | 32 | 授权方的APPID。由于本接口暂不开放第三方应用授权,因此 auth_app_id=app_id | 2018072300007418 |
业务参数
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
trade_no | String | 是 | 64 | 支付宝交易号,支付宝交易凭证号。 | 2013112011001004330000121536 |
app_id | String | 是 | 32 | 支付宝应用的APPID。支付宝分配给开发者的应用 ID | 2019082200007148 |
out_trade_no | String | 是 | 64 | 商家订单号。原支付请求的商家订单号 | 6823789339978248 |
out_biz_no | String | 否 | 64 | 商家业务号。商家业务ID,通常是退款通知中返回的退款申请流水号 | HZRF001 |
buyer_id | String | 否 | 16 | 买家支付宝账号 ID。以 2088 开头的纯 16 位数字 | 20881***524333 |
seller_id | String | 否 | 30 | 卖家支付宝账号 ID。以 2088 开头的纯 16 位数字 | 20881***2239364 |
trade_status | String | 否 | 32 | 交易状态。交易目前所处状态,详情可查看下表 交易状态说明 | TRADE_CLOSED |
total_amount | Number | 否 | 11 | 订单金额。本次交易支付订单金额,单位为人民币(元),精确到小数点后 2 位 | 20.00 |
receipt_amount | Number | 否 | 11 | 实收金额。商家在交易中实际收到的款项,单位为人民币(元),精确到小数点后 2 位 | 15.00 |
invoice_amount | Number | 否 | 11 | 开票金额。用户在交易中支付的可开发票的金额,单位为人民币(元),精确到小数点后 2 位 | 13.88 |
buyer_pay_amount | Number | 否 | 11 | 用户在交易中支付的金额,单位为人民币(元),精确到小数点后 2 位 | 12.00 |
point_amount | Number | 否 | 11 | 使用集分宝支付金额,单位为人民币(元),精确到小数点后 2 位 | 12.00 |
refund_fee | Number | 否 | 11 | 总退款金额。退款通知中,返回总退款金额,单位为人民币(元),精确到小数点后 2 位 | 2.58 |
subject | String | 否 | 256 | 订单标题/商品标题/交易标题/订单关键字等,是请求时对应参数,会在通知中原样传回 | XXXX交易 |
body | String | 否 | 400 | 商品描述。该订单的备注、描述、明细等。对应请求时的 body 参数,会在通知中原样传回 | XXX交易内容 |
gmt_create | Date | 否 | - | 交易创建时间。格式为 yyyy-MM-dd HH:mm:ss | 2018-08-25 15:34:42 |
gmt_payment | Date | 否 | - | 交易付款时间。格式为 yyyy-MM-dd HH:mm:ss | 2018-08-25 15:34:42 |
gmt_refund | Date | 否 | - | 交易退款时间。格式为 yyyy-MM-dd HH:mm:ss.S | 2018-08-26 10:34:44.340 |
gmt_close | Date | 否 | - | 交易结束时间。格式为 yyyy-MM-dd HH:mm:ss | 2018-08-26 16:32:30 |
fund_bill_list | String | 否 | 512 | 支付金额信息。支付成功的各个渠道金额信息。详情可查看下文 资金明细信息说明 | [{"amount":"15.00","fundChannel":"ALIPAYACCOUNT"}] |
vocher_detail_list | String | 否 | 512 | 优惠券信息。本交易支付时所使用的所有优惠券信息。详情可查看下表 优惠券信息说明 | [{"amount":"0.20", "merchantContribute":"0.00", "name":"一键创建券模板名称", "otherContribute":"0.20", "type":"ALIAPY_BIZ_VOUCHER","memo":"学生卡8折优惠"}] |
passback_params | String | 否 | 512 | 回传参数,公共回传参数,如果请求时传递了该参数,则返回的异步通知会原样传回。本参数必须进行 UrlEncode 之后才可传入。 | merchantBizType%3d3C%26merchantBizNo%3d201601001111 |
3.2.2交易状态说明
枚举名称 | 枚举说明 |
WAIT_BUYER_PAY | 交易创建,等待买家付款。 |
TRADE_CLOSED | 未付款交易超时关闭,或支付完成后全额退款。 |
TRADE_SUCCESS | 交易支付成功。 |
TRADE_FINISHED | 交易结束,不可退款。 |
3.2.3通知触发条件
触发条件名 | 触发条件描述 | 触发条件默认值 |
TRADE_FINISHED | 交易完成 | false(不触发通知) |
TRADE_SUCCESS | 支付成功 | true(触发通知) |
WAIT_BUYER_PAY | 交易创建 | false(不触发通知) |
TRADE_CLOSED | 交易关闭 | false(不触发通知) |
3.2.4资金明细信息说明
参数 | 类型 | 必填 | 参数说明 |
fundChannel | String | 否 | 支付渠道。详情可查看下文 支付渠道说明。 示例值:ALIPAYACCOUNT |
amount | String | 否 | 支付金额。使用指定支付渠道支付的金额,单位为元。 示例值:15.00 |
3.2.5支付渠道说明
支付渠道代码 | 支付渠道 |
COUPON | 支付宝红包 |
ALIPAYACCOUNT | 支付宝余额 |
POINT | 集分宝 |
DISCOUNT | 折扣券 |
PCARD | 预付卡 |
FINANCEACCOUNT | 余额宝 |
MCARD | 商家储值卡 |
MDISCOUNT | 商户优惠券 |
MCOUPON | 商户红包 |
PCREDIT | 蚂蚁花呗 |
3.2.6异步通知特性
在进行异步通知交互时,如果支付宝收到的应答不是 success,支付宝会认为通知失败,会通过一定的策略定期重新发起通知。通知的间隔频率为:4m、10m、10m、1h、2h、6h、15h。
商家设置的异步地址(notify_url)需保证无任何字符,如空格、HTML 标签,且不能重定向。(如果重定向,支付宝会收不到 success 字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知)
支付宝是用 POST 方式发送通知信息,商户获取参数的方式如下:request.Form("out_trade_no")、$_POST['out_trade_no']。
支付宝针对同一条异步通知重试时,异步通知参数中的 notify_id 是不变的。
3.2.7异步返回结果的验签
某商家设置的通知地址为 https:// 商家网站通知地址,对应接收到通知的示例如下:
https: //商家网站通知地址?voucher_detail_list=[{"amount":"0.20","merchantContribute":"0.00","name":"5折券","otherContribute":"0.20","type":"ALIPAY_DISCOUNT_VOUCHER","voucherId":"2016101200073002586200003BQ4"}]&fund_bill_list=[{"amount":"0.80","fundChannel":"ALIPAYACCOUNT"},{"amount":"0.20","fundChannel":"MDISCOUNT"}]&subject=PC网站支付交易&trade_no=2016101221001004580200203978&gmt_create=2016-10-12 21:36:12¬ify_type=trade_status_sync&total_amount=1.00&out_trade_no=mobile_rdm862016-10-12213600&invoice_amount=0.80&seller_id=2088201909970555¬ify_time=2016-10-12 21:41:23&trade_status=TRADE_SUCCESS&gmt_payment=2016-10-12 21:37:19&receipt_amount=0.80&passback_params=passback_params123&buyer_id=2088102114562585&app_id=2016092101248425¬ify_id=7676a2e1e4e737cff30015c4b7b55e3kh6& sign_type=RSA2&buyer_pay_amount=0.80&sign=***&point_amount=0.00
第一步:在通知返回参数列表中,除去 sign、sign_type 两个参数外,凡是通知返回回来的参数皆是待验签的参数。
第二步:将剩下参数进行 url_decode,然后进行字典排序,组成字符串,得到待签名字符串:
app_id=2016092101248425&buyer_id=2088102114562585&buyer_pay_amount=0.80&fund_bill_list=[{"amount":"0.80","fundChannel":"ALIPAYACCOUNT"},{"amount":"0.20","fundChannel":"MDISCOUNT"}]&gmt_create=2016-10-1221:36:12&gmt_payment=2016-10-1221:37:19&invoice_amount=0.80¬ify_id=7676a2e1e4e737cff30015c4b7b55e3kh6¬ify_time=2016-10-1221:41:23¬ify_type=trade_status_sync&out_trade_no=mobile_rdm862016-10-12213600&passback_params=passback_params123&point_amount=0.00&receipt_amount=0.80&seller_id=2088201909970555&subject=PC网站支付交易&total_amount=1.00&trade_no=2016101221001004580200203978&trade_status=TRADE_SUCCESS&voucher_detail_list=[{"amount":"0.20","merchantContribute":"0.00","name":"5折券","otherContribute":"0.20","type":"ALIPAY_DISCOUNT_VOUCHER","voucherId":"2016101200073002586200003BQ4"}]
第三步:将签名参数(sign)使用 base64 解码为字节码串。
第四步:使用 RSA 的验签方法,通过签名字符串、签名参数(经过 base64 解码)及支付宝公钥验证签名。
第五步:需要严格按照如下描述校验通知数据的正确性:
商家需要验证该通知数据中的 out_trade_no 是否为商家系统中创建的订单号。
判断 total_amount 是否确实为该订单的实际金额(即商家订单创建时的金额)。
校验通知中的 seller_id(或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方(有的时候,一个商家可能有多个 seller_id/seller_email)。
验证 app_id 是否为该商家本身。
上述 1、2、3、4 有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商家必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
注意:
状态 TRADE_SUCCESS 的通知触发条件是商家开通的产品支持退款功能的前提下,买家付款成功。
交易状态 TRADE_FINISHED 的通知触发条件是商家开通的产品不支持退款功能的前提下,买家付款成功;或者,商家开通的产品支持退款功能的前提下,交易已经成功并且已经超过可退款期限
3.3 沙箱环境联调
沙箱环境是支付宝开放平台为开发者提供的与生产环境完全隔离的联调测试环境,开发者在沙箱环境中完成的调用不会对生产环境中的数据造成任何影响。
沙箱环境会自动完成或忽略一些场景的业务门槛,例如:开发者无需等待产品签约,即可直接在沙箱环境调用接口,使得开发集成工作可以与商务流程并行,从而提高项目整体的交付效率。
注意:
由于沙箱环境并非 100% 与生产环境一致,接口的实际响应逻辑请以生产环境为准,沙箱环境开发调试完成后,仍然需要在生产环境进行测试验收。
沙箱环境拥有完全独立的数据体系,沙箱环境下返回的数据(比如用户 ID 等)在生产环境中都是不存在的,开发者不可将沙箱环境返回的数据与生产环境中的数据混淆。
本文仅说明如何在沙箱环境中调试电脑网站支付能力,非沙箱环境调试通用说明。
3.3.1支持的接口
接口类型 | 接口中文名 | 接口英文名称 | 沙箱环境是否支持 | 沙箱环境调用注意事项 |
电脑网站支付 | 统一收单下单并支付页面接口 | 支持 | - | |
辅助接口 | 统一收单线下交易查询 | 支持 | - | |
统一收单交易退款接口 | 支持 | - | ||
统一收单交易退款查询接口 | 支持 | - | ||
统一收单交易关闭接口 | 支持 | - | ||
查询对账单下载地址 | 支持 | 沙箱环境只做模拟调用,下载账单为模板,账单内没有实际数据 | ||
From 蚂蚁消息接口 | 收单退款冲退完成通知 | 不支持 | 沙箱环境不支持银行卡支付,无法模拟测试 |
3.3.2沙箱调试注意事项
建议只传必传参数测试,避免部分参数只对正式环境兼容。
参数注意事项
alipay.trade.page.pay 沙箱参数区别如下
参数 | 描述说明 |
timeout_express | 相对超时参数
|
time_expire | 绝对超时参数 沙箱环境:不可超过当前时间15小时 |
extend_params | 花呗分期:沙箱不支持花呗分期测试 示例:"extend_params":{"hb_fq_num":"3","hb_fq_seller_percent":"100"} |
ext_user_info | 外部指定买家 沙箱环境无法校验买家身份信息 |
支付注意事项
沙箱测试只支持余额支付,不支持银行卡、余额宝、花呗等其他支付方式。
沙箱测试会扣手续费,但沙箱扣款手续费比例不代表正式环境的情况,正式环境手续费请以签约协议为准。
电脑网站支付方式:
电脑网站支付扫码支付必须使用沙箱钱包的扫一扫功能。
电脑网站支付PC端登录支付必须使用沙箱账户登录支付。
正式环境和沙箱环境收银台页面展示效果不同
3.3.3沙箱控制台操作指南
使用沙箱环境进行调试前,开发者需根据 操作指引完成沙箱控制台及接口调用配置。
注意使用沙箱应用信息以及沙箱网关:https://openapi.alipaydev.com/gateway.do。
3.4 SDK & Demo 获取
为了帮助开发者调用开放接口,我们提供了开放平台服务端 SDK,包含 JAVA、PHP、Python、NodeJS 和 .NET 等语言版本,封装了签名&验签、HTTP 接口请求等基础功能。 详见 下载和使用教程 。
Demo 版本 | 运行环境 | 下载链接 |
JAVA 版 | Eclipse+JDK 1.6 及以上+Tomcat 6.0 及以上 | |
PHP 版 | PHP 5.5及以上+Tomcat 6.0 及以上 | |
.NET 版 | Visual Studio 2010 及以上 |
4.统一收单下单并支付页面接口
PC场景下单并支付
4.1公共请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
app_id | String | 必选 | 32 | 支付宝分配给开发者的应用ID | 2014072300007148 |
method | String | 必选 | 128 | 接口名称 | alipay.trade.page.pay |
format | String | 可选 | 40 | 仅支持JSON | JSON |
return_url | String | 可选 | 256 | HTTP/HTTPS开头字符串 | |
charset | String | 必选 | 10 | 请求使用的编码格式,如utf-8,gbk,gb2312等 | utf-8 |
sign_type | String | 必选 | 10 | 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 | RSA2 |
sign | String | 必选 | 344 | 商户请求参数的签名串,详见签名 | 详见示例 |
timestamp | String | 必选 | 19 | 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" | 2014-07-24 03:07:50 |
version | String | 必选 | 3 | 调用的接口版本,固定为:1.0 | 1.0 |
notify_url | String | 可选 | 256 | 支付宝服务器主动通知商户服务器里指定的页面http/https路径。 | |
app_auth_token | String | 可选 | 40 | 详见应用授权概述 | |
biz_content | String | 必选 | 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 |
4.2请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
out_trade_no | String | 必选 | 64 | 商户订单号。 由商家自定义,64个字符以内,仅支持字母、数字、下划线且需保证在商户端不重复。 | 20150320010101001 |
total_amount | Price | 必选 | 11 | 订单总金额,单位为元,精确到小数点后两位,取值范围为 [0.01,100000000]。金额不能为0。 | 88.88 |
subject | String | 必选 | 256 | 订单标题。 注意:不可使用特殊字符,如 /,=,& 等。 | Iphone6 16G |
product_code | String | 必选 | 64 | 销售产品码,与支付宝签约的产品码名称。注:目前电脑支付场景下仅支持FAST_INSTANT_TRADE_PAY | FAST_INSTANT_TRADE_PAY |
qr_pay_mode | String | 可选 | 2 | PC扫码支付的方式。 支持前置模式和跳转模式。 前置模式是将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以 iframe 方式请求支付宝页面。具体支持的枚举值有以下几种: 0:订单码-简约前置模式,对应 iframe 宽度不能小于600px,高度不能小于300px; 1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于600px; 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于75px; 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小。 跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。支持传入的枚举值有: 2:订单码-跳转模式 | 1 |
qrcode_width | Number | 可选 | 4 | 商户自定义二维码宽度。 注:qr_pay_mode=4时该参数有效 | 100 |
goods_detail | GoodsDetail[] | 可选 | 订单包含的商品列表信息,json格式。 | ||
time_expire | String | 可选 | 32 | 订单绝对超时时间。 格式为yyyy-MM-dd HH:mm:ss。超时时间范围:1m~15d。 注:time_expire和timeout_express两者只需传入一个或者都不传,两者均传入时,优先使用time_expire。 | 2016-12-31 10:05:01 |
sub_merchant | SubMerchant | 可选 | 二级商户信息。 直付通模式和机构间连模式下必传,其它场景下不需要传入。 | ||
extend_params | ExtendParams | 可选 | 业务扩展参数 | ||
business_params | String | 可选 | 512 | 商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式 | {"mc_create_trade_ip":"127.0.0.1"} |
promo_params | String | 可选 | 512 | 优惠参数。为 JSON 格式。注:仅与支付宝协商后可用 | {"storeIdType":"1"} |
integration_type | String | 可选 | 16 | 请求后页面的集成方式。 枚举值: ALIAPP:支付宝钱包内 PCWEB:PC端访问 默认值为PCWEB。 | PCWEB |
request_from_url | String | 可选 | 256 | 请求来源地址。如果使用ALIAPP的集成方式,用户中途取消支付会返回该地址。 | https:// |
store_id | String | 可选 | 32 | 商户门店编号。 指商户创建门店时输入的门店编号。 | NJ_001 |
merchant_order_no | String | 可选 | 32 | 商户原始订单号,最大长度限制 32 位 | 20161008001 |
ext_user_info | ExtUserInfo | 可选 | 外部指定买家 | ||
invoice_info | InvoiceInfo | 可选 | 开票信息 |
4.3公共响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
code | String | 必选 | - | 网关返回码,详见文档 | 40004 |
msg | String | 必选 | - | 网关返回码描述,详见文档 | Business Failed |
sub_code | String | 可选 | - | 业务返回码,参见具体的API接口文档 | ACQ.TRADE_HAS_SUCCESS |
sub_msg | String | 可选 | - | 业务返回码描述,参见具体的API接口文档 | 交易已被支付 |
sign | String | 必选 | - | 签名,详见文档 | DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo= |
4.4响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
trade_no | String | 必选 | 64 | 支付宝交易号 | 2013112011001004330000121536 |
out_trade_no | String | 必选 | 64 | 商户订单号 | 6823789339978248 |
seller_id | String | 必选 | 28 | 收款支付宝账号对应的支付宝唯一用户号。 以2088开头的纯16位数字 | 2088111111116894 |
total_amount | Price | 必选 | 11 | 交易金额 | 128.00 |
merchant_order_no | String | 必选 | 32 | 商户原始订单号,最大长度限制32位 | 20161008001 |
4.5请求示例
$aop = new AopClient ();
$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = 'your app_id';
$aop->rsaPrivateKey = '请填写开发者私钥去头去尾去回车,一行字符串';
$aop->alipayrsaPublicKey='请填写支付宝公钥,一行字符串';
$aop->apiVersion = '1.0';
$aop->signType = 'RSA2';
$aop->postCharset='GBK';
$aop->format='json';
//异步接收地址,仅支持http/https,公网可访问
$request->setNotifyUrl('');
//同步跳转地址,仅支持http/https
$request->setReturnUrl('');
/******必传参数******/
$object = new stdClass();
//商户订单号,商家自定义,保持唯一性
$object->out_trade_no = '20210817010101004';
//支付金额,最小值0.01元
$object->total_amount = 0.01;
//订单标题,不可使用特殊符号
$object->subject = '测试商品';
//电脑网站支付场景固定传值FAST_INSTANT_TRADE_PAY
$object->product_code ='FAST_INSTANT_TRADE_PAY';
/******可选参数******/
$object->time_expire = '2022-08-01 22:00:00';
商品信息明细,按需传入
// $goodsDetail = [
// [
// 'goods_id'=>'goodsNo1',
// 'goods_name'=>'子商品1',
// 'quantity'=>1,
// 'price'=>0.01,
// ],
// ];
// $object->goodsDetail = $goodsDetail;
// //扩展信息,按需传入
// $extendParams = [
// 'sys_service_provider_id'=>'2088511833207846',
// ];
// $object->extend_params = $extendParams;
$json = json_encode($object);
$request = new AlipayTradePagePayRequest();
$request->setBizContent($json);
$result = $aop->pageExecute ( $request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultCode = $result->$responseNode->code;
if(!empty($resultCode)&&$resultCode == 10000){
echo "成功";
} else {
echo "失败";
}
4.6响应示例
// 响应为表单格式,可嵌入页面,具体以返回的结果为准
<form name="submit_form" method="post" action="https://openapi.alipay.com/gateway.do?charset=UTF-8&method=alipay.trade.page.pay&sign=k0w1DePFqNMQWyGBwOaEsZEJuaIEQufjoPLtwYBYgiX%2FRSkBFY38VuhrNumXpoPY9KgLKtm4nwWz4DEQpGXOOLaqRZg4nDOGOyCmwHmVSV5qWKDgWMiW%2BLC2f9Buil%2BEUdE8CFnWhM8uWBZLGUiCrAJA14hTjVt4BiEyiPrtrMZu0o6%2FXsBu%2Fi6y4xPR%2BvJ3KWU8gQe82dIQbowLYVBuebUMc79Iavr7XlhQEFf%2F7WQcWgdmo2pnF4tu0CieUS7Jb0FfCwV%2F8UyrqFXzmCzCdI2P5FlMIMJ4zQp%2BTBYsoTVK6tg12stpJQGa2u3%2BzZy1r0KNzxcGLHL%2BwWRTx%2FCU%2Fg%3D%3D¬ify_url=http%3A%2F%2F114.55.81.185%2Fopendevtools%2Fnotify%2Fdo%2Fbf70dcb4-13c9-4458-a547-3a5a1e8ead04&version=1.0&app_id=2014100900013222&sign_type=RSA×tamp=2021-02-02+14%3A11%3A40&alipay_sdk=alipay-sdk-java-dynamicVersionNo&format=json">
<input type="submit" value="提交" style="display:none" >
</form>
<script>document.forms[0].submit();</script>
4.7异常示例
{
"alipay_trade_page_pay_response": {
"code": "20000",
"msg": "Service Currently Unavailable",
"sub_code": "isp.unknow-error",
"sub_msg": "系统繁忙"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
4.8错误码
公共错误码
业务错误码
错误码 | 错误描述 | 解决方案 |
ACQ.SYSTEM_ERROR | 接口返回错误 | 请立即调用查询订单API,查询当前订单的状态,并根据订单状态决定下一步的操作,如果多次调用依然报此错误码,请联系支付宝客服。 |
ACQ.INVALID_PARAMETER | 参数无效 | 检查请求参数,修改后重新发起请求 |
ACQ.ACCESS_FORBIDDEN | 无权限使用接口 | 未签约条码支付或者合同已到期 |
ACQ.EXIST_FORBIDDEN_WORD | 订单信息中包含违禁词 | 修改订单信息后,重新发起请求 |
ACQ.PARTNER_ERROR | 应用APP_ID填写错误 | 联系支付宝小二点这里,确认APP_ID的状态 |
ACQ.TOTAL_FEE_EXCEED | 订单总金额不在允许范围内 | 修改订单金额再发起请求 |
ACQ.CONTEXT_INCONSISTENT | 交易信息被篡改 | 更换商家订单号后,重新发起请求 |
ACQ.TRADE_HAS_SUCCESS | 交易已被支付 | 确认该笔交易信息是否为当前买家的,如果是则认为交易付款成功,如果不是则更换商家订单号后,重新发起请求 |
ACQ.TRADE_HAS_CLOSE | 交易已经关闭 | 更换商家订单号后,重新发起请求 |
ACQ.BUYER_BALANCE_NOT_ENOUGH | 买家余额不足 | 买家绑定新的银行卡或者支付宝余额有钱后再发起支付 |
ACQ.BUYER_BANKCARD_BALANCE_NOT_E | 用户银行卡余额不足 | 建议买家更换支付宝进行支付或者更换其它付款方式 |
ACQ.ERROR_BALANCE_PAYMENT_DISABL | 余额支付功能关闭 | 用户打开余额支付开关后,再重新进行支付 |
ACQ.BUYER_SELLER_EQUAL | 买卖家不能相同 | 更换买家重新付款 |
ACQ.TRADE_BUYER_NOT_MATCH | 交易买家不匹配 | 更换商家订单号后,重新发起请求 |
ACQ.BUYER_ENABLE_STATUS_FORBID | 买家状态非法 | 用户联系支付宝小二点这里,确认买家状态为什么非法 |
ACQ.PAYMENT_FAIL | 支付失败 | 用户刷新条码后,重新发起请求,如果重试一次后仍未成功,更换其它方式付款 |
ACQ.BUYER_PAYMENT_AMOUNT_DAY_LIM | 买家付款日限额超限 | 更换买家进行支付 |
ACQ.BUYER_PAYMENT_AMOUNT_MONTH_L | 买家付款月额度超限 | 买家更换账号后,重新付款或者更换其它付款方式 |
ACQ.ERROR_BUYER_CERTIFY_LEVEL_LI | 买家未通过人行认证 | 用户联系支付宝小二点这里 |
ACQ.PAYMENT_REQUEST_HAS_RISK | 支付有风险 | 更换其它付款方式 |
ACQ.NO_PAYMENT_INSTRUMENTS_AVAIL | 没用可用的支付工具 | 更换其它付款方式 |
ACQ.ILLEGAL_SIGN_VALIDTY_PERIOD | 无效的签约有效期 | 更改接口中传入的签约有效期 |
ACQ.MERCHANT_AGREEMENT_NOT_EXIST | 商户协议不存在 | 建议商户与支付宝确认签约代扣合同 |
ACQ.RISK_MERCHANT_IP_NOT_EXIST | 当前交易未传入IP信息,创单失败,请传入IP后再发起支付 | 检查请求参数是否已经传入用户IP信息 |
4.9触发通知类型
通知类型 | 描述 | 默认开启 |
tradeStatus.TRADE_CLOSED | 交易关闭 | 0 |
tradeStatus.TRADE_FINISHED | 交易完结 | 0 |
tradeStatus.TRADE_SUCCESS | 支付成功 | 1 |
tradeStatus.WAIT_BUYER_PAY | 交易创建 | 0 |
5.统一收单交易退款接口
当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,支付宝将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。
交易超过约定时间(签约时设置的可退款时间)的订单无法进行退款。
支付宝退款支持单笔交易分多次退款,多次退款需要提交原支付订单的订单号和设置不同的退款请求号。一笔退款失败后重新提交,要保证重试时退款请求号不能变更,防止该笔交易重复退款。
同一笔交易累计提交的退款金额不能超过原始交易总金额。
注意:
1. 同一笔交易的退款至少间隔3s后发起
2. 请严格按照接口文档中的参数进行接入。若在此接口中传入【非当前接口文档中的参数】会造成【退款失败或重复退款】。
3. 该接口不可与其他退款产品混用。若商户侧同一笔退款请求已使用了当前接口退款的情况下,【再使用其他退款产品进行退款】可能会造成【重复退款】。
4. 退款成功判断说明:接口返回fund_change=Y为退款成功,fund_change=N或无此字段值返回时需通过退款查询接口进一步确认退款状态。详见退款成功判断指导。注意,接口中code=10000,仅代表本次退款请求成功,不代表退款成功。
5.1公共请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
app_id | String | 必选 | 32 | 支付宝分配给开发者的应用ID | 2014072300007148 |
method | String | 必选 | 128 | 接口名称 | alipay.trade.refund |
format | String | 可选 | 40 | 仅支持JSON | JSON |
charset | String | 必选 | 10 | 请求使用的编码格式,如utf-8,gbk,gb2312等 | utf-8 |
sign_type | String | 必选 | 10 | 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 | RSA2 |
sign | String | 必选 | 344 | 商户请求参数的签名串,详见签名 | 详见示例 |
timestamp | String | 必选 | 19 | 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" | 2014-07-24 03:07:50 |
version | String | 必选 | 3 | 调用的接口版本,固定为:1.0 | 1.0 |
app_auth_token | String | 可选 | 40 | 详见应用授权概述 | |
biz_content | String | 必选 | 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 |
5.2请求参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
out_trade_no | String | 特殊可选 | 64 | 商户订单号。 订单支付时传入的商户订单号,商家自定义且保证商家系统中唯一。与支付宝交易号 trade_no 不能同时为空。 | 20150320010101001 |
trade_no | String | 特殊可选 | 64 | 支付宝交易号。 和商户订单号 out_trade_no 不能同时为空。 | 2014112611001004680073956707 |
refund_amount | Price | 必选 | 11 | 退款金额。 需要退款的金额,该金额不能大于订单金额,单位为元,支持两位小数。 注:如果正向交易使用了营销,该退款金额包含营销金额,支付宝会按业务规则分配营销和买家自有资金分别退多少,默认优先退买家的自有资金。如交易总金额100元,用户支付时使用了80元自有资金和20元无资金流的营销券,商家实际收款80元。如果首次请求退款60元,则60元全部从商家收款资金扣除退回给用户自有资产;如果再请求退款40元,则从商家收款资金扣除20元退回用户资产以及把20元的营销券退回给用户(券是否可再使用取决于券的规则配置)。 | 200.12 |
refund_reason | String | 可选 | 256 | 退款原因说明。 商家自定义,将在会在商户和用户的pc退款账单详情中展示 | 正常退款 |
out_request_no | String | 可选 | 64 | 退款请求号。 标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。 注:针对同一次退款请求,如果调用接口失败或异常了,重试时需要保证退款请求号不能变更,防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。 | HZ01RF001 |
refund_royalty_parameters | OpenApiRoyaltyDetailInfoPojo[] | 可选 | 退分账明细信息。 注: 1.当面付且非直付通模式无需传入退分账明细,系统自动按退款金额与订单金额的比率,从收款方和分账收入方退款,不支持指定退款金额与退款方。 2.直付通模式,电脑网站支付,手机 APP 支付,手机网站支付产品,须在退款请求中明确是否退分账,从哪个分账收入方退,退多少分账金额;如不明确,默认从收款方退款,收款方余额不足退款失败。不支持系统按比率退款。 | ||
query_options | String[] | 可选 | 1024 | 查询选项。 商户通过上送该参数来定制同步需要额外返回的信息字段,数组格式。支持:refund_detail_item_list:退款使用的资金渠道;deposit_back_info:触发银行卡冲退信息通知; | refund_detail_item_list |
5.3公共响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
code | String | 必选 | - | 网关返回码,详见文档 | 40004 |
msg | String | 必选 | - | 网关返回码描述,详见文档 | Business Failed |
sub_code | String | 可选 | - | 业务返回码,参见具体的API接口文档 | ACQ.TRADE_HAS_SUCCESS |
sub_msg | String | 可选 | - | 业务返回码描述,参见具体的API接口文档 | 交易已被支付 |
sign | String | 必选 | - | 签名,详见文档 | DZXh8eeTuAHoYE3w1J+POiPhfDxOYBfUNn1lkeT/V7P4zJdyojWEa6IZs6Hz0yDW5Cp/viufUb5I0/V5WENS3OYR8zRedqo6D+fUTdLHdc+EFyCkiQhBxIzgngPdPdfp1PIS7BdhhzrsZHbRqb7o4k3Dxc+AAnFauu4V6Zdwczo= |
5.4响应参数
参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
trade_no | String | 必选 | 64 | 2013112011001004330000121536 | 支付宝交易号 |
out_trade_no | String | 必选 | 64 | 商户订单号 | 6823789339978248 |
buyer_logon_id | String | 必选 | 100 | 用户的登录id | 159****5620 |
fund_change | String | 必选 | 1 | 本次退款是否发生了资金变化 | Y |
refund_fee | Price | 必选 | 11 | 退款总金额。 指该笔交易累计已经退款成功的金额。 | 88.88 |
refund_detail_item_list | TradeFundBill[] | 可选 | 退款使用的资金渠道。 只有在签约中指定需要返回资金明细,或者入参的query_options中指定时才返回该字段信息。 | ||
store_name | String | 可选 | 512 | 交易在支付时候的门店名称 | 望湘园联洋店 |
buyer_user_id | String | 可选 | 28 | 买家在支付宝的用户id | 2088101117955611 |
send_back_fee | String | 可选 | 11 | 本次商户实际退回金额。 说明:如需获取该值,需在入参query_options中传入 refund_detail_item_list。 | 1.8 |
refund_hyb_amount | String | 可选 | 11 | 本次请求退惠营宝金额 | 10.24 |
refund_charge_info_list | RefundChargeInfo[] | 可选 | 退费信息 |
5.5请求示例
$aop = new AopClient ();
$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
$aop->appId = 'your app_id';
$aop->rsaPrivateKey = '请填写开发者私钥去头去尾去回车,一行字符串';
$aop->alipayrsaPublicKey='请填写支付宝公钥,一行字符串';
$aop->apiVersion = '1.0';
$aop->signType = 'RSA2';
$aop->postCharset='GBK';
$aop->format='json';
$object = new stdClass();
$object->trade_no = '2021081722001419121412730660';
$object->refund_amount = 0.01;
$object->out_request_no = 'HZ01RF001';
返回参数选项,按需传入
//$queryOptions =[
// 'refund_detail_item_list'
//];
//$object->query_options = $queryOptions;
$json = json_encode($object);
$request = new AlipayTradeRefundRequest();
$request->setBizContent($json);
$result = $aop->execute ( $request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultCode = $result->$responseNode->code;
if(!empty($resultCode)&&$resultCode == 10000){
echo "成功";
} else {
echo "失败";
}
5.6响应示例
{
"alipay_trade_refund_response": {
"code": "10000",
"msg": "Success",
"trade_no": "支付宝交易号",
"out_trade_no": "6823789339978248",
"open_id": "2088102122524333",
"buyer_logon_id": "159****5620",
"fund_change": "Y",
"refund_fee": 88.88,
"refund_currency": "USD",
"gmt_refund_pay": "2014-11-27 15:45:57",
"refund_detail_item_list": [
{
"fund_channel": "ALIPAYACCOUNT",
"bank_code": "CEB",
"amount": 10,
"real_amount": 11.21,
"fund_type": "DEBIT_CARD"
}
],
"store_name": "望湘园联洋店",
"buyer_user_id": "2088101117955611",
"send_back_fee": "1.8",
"refund_preset_paytool_list": {
"amount": [
12.21
],
"assert_type_code": "盒马礼品卡:HEMA;抓猫猫红包:T_CAT_COUPON"
},
"refund_charge_amount": "8.88",
"refund_settlement_id": "2018101610032004620239146945",
"present_refund_buyer_amount": "88.88",
"present_refund_discount_amount": "88.88",
"present_refund_mdiscount_amount": "88.88",
"has_deposit_back": "true",
"refund_hyb_amount": "10.24",
"refund_charge_info_list": [
{
"refund_charge_fee": 0.01,
"switch_fee_rate": "0.01",
"charge_type": "trade",
"refund_sub_fee_detail_list": [
{
"refund_charge_fee": 0.1,
"switch_fee_rate": "0.01"
}
]
}
]
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
5.7异常示例
{
"alipay_trade_refund_response": {
"code": "20000",
"msg": "Service Currently Unavailable",
"sub_code": "isp.unknow-error",
"sub_msg": "系统繁忙"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
5.8错误码
公共错误码
业务错误码
错误码 | 错误描述 | 解决方案 |
ACQ.SYSTEM_ERROR | 系统错误 | 接口返回系统错误情况下,当前请求的退款可能成功也可能失败。 1、请使用相同的参数再次重试调用,需要保证退款请求号和退款金额不能变更。如果前一次退款请求已经处理成功,接口会幂等返回成功;如果前一次退款请求没有成功,接口会重试执行退款操作; 2、或者通过退款查询接口查询退款执行结果,发起退款查询接口需要保证间隔退款请求大于5秒以上; |
ACQ.INVALID_PARAMETER | 参数无效 | 请根据接口返回的错误信息,检查请求参数,修改后重新发起请求 |
ACQ.SELLER_BALANCE_NOT_ENOUGH | 卖家余额不足 | 商户支付宝账户充值后重新发起退款即可 |
ACQ.REFUND_AMT_NOT_EQUAL_TOTAL | 退款金额超限 | 1、请检查退款金额是否正确,请求的退款金额不能大于交易总金额; 2、如果不是全额退款,退款请求号必填,请检查是否传入了退款请求号; |
ACQ.REASON_TRADE_BEEN_FREEZEN | 请求退款的交易被冻结 | 联系支付宝小二,确认该笔交易的具体情况 |
ACQ.TRADE_NOT_EXIST | 交易不存在 | 检查请求中的交易号和商户订单号是否正确,确认后重新发起 |
ACQ.TRADE_HAS_FINISHED | 交易已完结 | 该交易已完结(已超过退款期限),不允许进行退款(即使重试也无法成功),建议联系买家进行线下退款处理。 |
ACQ.TRADE_STATUS_ERROR | 交易状态非法 | 查询交易,确认交易是否已经付款 |
ACQ.DISCORDANT_REPEAT_REQUEST | 请求信息不一致 | 退款请求号对应的退款已经执行成功,且本次请求的退款金额与之前请求的金额不一致,请检查传入的退款金额是否正确。 或者通过退款查询接口获取退款执行结果。 |
ACQ.REASON_TRADE_REFUND_FEE_ERR | 退款金额无效 | 同一笔交易累计请求的退款金额不能大于交易总金额,请检查退款请求的金额是否正确。 |
ACQ.TRADE_NOT_ALLOW_REFUND | 当前交易不允许退款 | 检查当前交易的状态是否为交易成功状态以及签约的退款属性是否允许退款,确认后,重新发起请求 |
ACQ.REFUND_FEE_ERROR | 交易退款金额有误 | 请检查传入的退款金额是否正确 |
ACQ.TRADE_HAS_CLOSE | 交易已关闭 | 该交易已关闭,不能再进行退款,请确认请求退款的交易是否未支付或者已完成退款 |
ACQ.BUYER_NOT_EXIST | 买家不存在 | 买家已经注销账号,建议联系买家进行线下退款处理 |
ACQ.BUYER_ENABLE_STATUS_FORBID | 买家状态异常 | 联系支付宝小二确认买家状态异常原因,或者可联系买家进行线下退款处理 |
ACQ.REASON_TRADE_STATUS_INVALID | 交易状态异常 | 查询交易,确认交易是否是支付成功状态,是的话可联系支付宝小二确认交易状态 |
ACQ.NOT_ALLOW_PARTIAL_REFUND | 不支持部分退款 | 由于交易使用了特定的优惠券等场景,该笔交易不支持部分退款,请对交易进行全额退款或者联系买家进行线下退款处理 |
ACQ.ONLINE_TRADE_VOUCHER_NOT_ALLOW_REFUND | 交易不允许退款 | 此交易中核销了购买的代金券,不允许进行退款,可联系买家进行线下退款处理 |
ACQ.BUYER_ERROR | 买家状态异常 | 联系支付宝小二确认买家状态异常原因,或者可联系买家进行线下退款处理 |
ACQ.CURRENCY_NOT_SUPPORT | 退款币种不支持 | 请确认传入的退款币种是否正确 |
ACQ.ALLOC_AMOUNT_VALIDATE_ERROR | 退分账金额超限 | 请调整退分账金额后重试 |
ACQ.USER_NOT_MATCH_ERR | 交易用户不匹配 | 请联系支付宝小二处理 |
ACQ.TRADE_SETTLE_ERROR | 交易结算异常 | 请检查传入的退结算项信息是否正确,如果正确请联系支付宝小二 |
ACQ.REFUND_CHARGE_ERROR | 退收费异常 | 请过一段时间后再重试发起退款 |
ACQ.ENTERPRISE_PAY_BIZ_ERROR | 因公付业务异常 | 如果提示“当前交易不含企业出资”,请确认交易是否包含企业出资,如果不包含则接口入参不能指定enterprise_pay_info参数,如果确认包含则联系支付宝核实。 如果提示“无效企业退款金额”,请检查指定的企业退款金额是否超过当前交易企业支付的金额。 其它情况,请联系支付宝小二。 |
ACQ.OVERDRAFT_ASSIGN_ACCOUNT_INVALID | 垫资退款出资账号和商户信息不一致 | 垫资退款出资账号必须为商户名下支付宝账号,请更换出资账号后重试 |
ACQ.OVERDRAFT_AGREEMENT_NOT_MATCH | 垫资退款接口传入模式和签约配置不一致 | 请检查垫资退款合约中的出资方式,修改合约或接口传参后重试 |
ACQ.REFUND_ACCOUNT_NOT_EXIST | 退款出资账号不存在或账号异常 | 检查退款出资账号状态,账号正常后重试 |
ACQ.CUSTOMER_VALIDATE_ERROR | 账户已注销或者被冻结 | 请查询账户状态:1. 如果账户已注销,请线下处理;2. 如果账户已冻结,请联系支付宝小二确认冻结原因。 |
ACQ.REFUND_ROYALTY_PAYEE_ACCOUNT_NOT_EXIST | 退分账收入方账户不存在 | 退分账收入方账户不存在,请确认收入方账号是否正确,更换账号后重新发起 |
五.服务端php下单以及回调操作流程案例
SDK下载:链接: https://pan.baidu.com/s/1GYPBF-Er0CWiaQGbhaPE5Q 提取码: glmd
支付宝支付流程如下:
1.前端拉起商品列表
用户登录app后,进入商品购买页面,前端请求app商品列表api接口,获取商品列表信息并展示
2.下单
用户点击'购买'操作,发送给服务端一条当前商品信息,服务端保存该商品的相关订单数据,并返回给前端支付所需要的请求数据,前端调用支付sdk,发起支付请求
/**
* 支付宝支付下单
* @param array $params 订单信息
* @return array
*/
public static function Pay($params)
{
//获取商品内部订单号
$innerOno = self::genInnerOno(date("Y-m-d H:i:s"), $params['user_id'], $paymentType);
//生成订单
$order = new Order();
$order->order_id = $innerOno; // 内部订单号
$order->type = $params['type']; // 支付类型:1 支付宝wap支付, 2 支付宝page支付,3 支付宝app支付
$order->product_name = $params['name']; // 商品名称
$order->number = $params['num']; // 购买商品个数
$order->price = $params['price']; // 商品单价, 1个商品价格
$order->total_price = $params['total_price']; // 总的价格
$order->pay_amount = $params['pay_amount']; // 应付总额: 实际应该支付的价格= 总金额 - 优惠金额
$order->count = $params['count']; // 购买后得到商品对应的产品数量
$order->status = 0; // 状态:0 待支付
$order->user_id = $params['user_id']; // 用户游戏ID
$order->expired_at = $params['expired_at']; // 过期时间
$order->created_by = $params['created_by']; // 创建者
$order->updated_by = $params['updated_by']; // 创建者
$result = $order->save();
if (!$result) {
$errors = '';
if ($order->hasErrors()) {
$tmp = $order->getErrors();
foreach ($tmp as $rows) {
foreach ($rows as $row) {
$errors .= $row . '<br/>';
}
}
}
throw new \Exception($errors);
}
$orderId = $order->id;
/ todo 过滤特殊字符, fuck 支付宝支付请求参数中不能有特殊的字符, 会报错, 会报错, 会报错~
$title = $model->product_name;
$title = replaceStr($title);
$price = $model->pay_amount;
$data = [
'out_trade_no' => $model->order_id,
'title' => $title,
'price' => $price,
'body' => $title,
];
header("Content-type: text/html; charset=utf-8");
$dir = Yii::getAlias('@common/alipay/trade/common');
require_once $dir . '/service/AlipayTradeService.php';
// 根据不同的支付引入对应的Builder
if ($tradeType == 1) { // 支付宝wap支付
require_once $dir . '/buildermodel/AlipayTradeWapPayContentBuilder.php';
} elseif ($tradeType == 2) { //支付宝page支付
require_once $dir . '/buildermodel/AlipayTradePagePayContentBuilder.php';
} elseif ($tradeType == 3) { // 支付宝app支付
require_once $dir . '/buildermodel/AlipayTradeAppPayContentBuilder.php';
}
//商户订单号,商户网站订单系统中唯一订单号,必填
$out_trade_no = trim($data['inner_ono']);
//订单名称,必填
$subject = trim($data['title']);
//付款金额,必填
$total_amount = $data['price'];
//商品描述,可空
$body = trim($data['body']);
//超时时间
$timeout_express = "10m";
//构造参数
if ($tradeType == 1) {
$payRequestBuilder = new \AlipayTradeWapPayContentBuilder();
} elseif ($tradeType == 2) {
$payRequestBuilder = new \AlipayTradePagePayContentBuilder();
} elseif ($tradeType == 3) {
$payRequestBuilder = new \AlipayTradeAppPayContentBuilder();
}
$payRequestBuilder->setBody($body);
$payRequestBuilder->setSubject($subject);
$payRequestBuilder->setTotalAmount($total_amount);
$payRequestBuilder->setOutTradeNo($out_trade_no);
$payRequestBuilder->setTimeExpress($timeout_express);
// 获取支付宝相关配置
$config = Yii::$app->params['alipay'];
$aop = new \AlipayTradeService($config);
if ($tradeType == 1) {
$response = $aop->wapPay($payRequestBuilder, $config['return_url'], $config['notify_url']);
} elseif ($tradeType == 2) {
$response = $aop->pagePay($payRequestBuilder, $config['return_url'], $config['notify_url']);
} elseif ($tradeType == 3) {
$response = $aop->appPay($payRequestBuilder, $config['notify_url']);
}
$data = [
"result" => $response
];
return jsonFail($data);
}
/**
* 生成本系统内部订单号, 在向第三方服务商发起支付时需要使用.
*
* 下单时的处理流程:
* 1. 属性 ono 不要赋值, 成功插入(保存)订单.
* 1. 支付前生成本系统内部订单号, 向第三方发起支付请求.
* 1. 接收到支付成功回调通知时, 将第三方订单号保存到本次付款的订单的 ono 字段上.
*
* 格式: 下单时间+支付方式+ 4位数字修正值. 如 "20150930140041+1+1234".
* 最大长度 32 个字符. 这也是 wx 可接受的订单号最大长度.
*
* @param int $createdAt 订单创建时间戳, 即 下单时间戳.
* @param int $createdBy 订单创建人 ID, 即 下单会员 ID.
* @return string
* @throws \Exception
*/
public static function genInnerOno($createdAt, $createdBy)
{
$createdAt = strtotime($createdAt);
if (1 > $createdAt || 1 > $createdBy) {
throw new \Exception('参数错误');
}
// 生成一个修正值, 一定程度上增加订单号的随机性.
$tmp = intval(substr($createdAt, -4)) + intval(substr($createdBy, -2));
if (4 < strlen($tmp)) {
$tmp = substr($tmp, -4);
}
$tmp = date('YmdHis', $createdAt) . $tmp . rand(100, 900);
return $tmp;
}
3. 支付
前端获取服务端返回的支付所需要的请求数据后,拼接支付请求参数,调用支付sdk,拉起支付宝发起支付请求
4. 回调操作
前端支付成功后,支付宝服务器会请求app服务端的回调方法,对支付订单进行校验验签操作,根据验签结果,处理订单业务逻辑
php以yii2框架为参考
/**
* 支付宝支付回调
*/
public function actionNotify()
{
//判断是否post方式
if (!Yii::$app->request->isPost) {
jsonFail("请求错误");
}
//判断通知请求
$trans = Yii::$app->db->beginTransaction();
try {
$dir = Yii::getAlias('@common/alipay/trade/common');
require_once $path . '/service/AlipayTradeService.php';
// 获取支付宝相关配置
$config = Yii::$app->params['alipay'];
//校验签名
$alipaySevice = new \AlipayTradeService($config);
$result = $alipaySevice->check($post);
/* 实际验证过程建议商户添加以下校验。
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
if (!$result) {
throw new \Exception('签名校验失败');
}
//验证成功
/
//请在这里加上商户的业务逻辑程序代
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
//获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
//商户订单号
$order_id = $post['out_trade_no'];
//支付宝交易号
$trade_no = $post['trade_no'];
//交易状态
$tradeStatus = $post['trade_status'];
// 交易付款时间
$paidAt = $post['gmt_payment'];
if ($tradeStatus == 'TRADE_FINISHED') {
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_amount与通知时获取的total_fee为一致的
//如果有做过处理,不执行商户的业务程序
//注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
} else {
if ($tradeStatus == 'TRADE_SUCCESS') {
// todo 支付成功,修改用户订单操作
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//请务必判断请求时的total_amount与通知时获取的total_fee为一致的
//如果有做过处理,不执行商户的业务程序
//注意:
//付款完成后,支付宝系统发送该交易状态通知
// 订单状态
$status = UserOrder::STATUS_BUY;
// 变更订单属性
UserOrder::changeAttribute(
['order_id' => $order_id],
[
'status' => $status,
'paid_at' => strtotime($paidAt),
'trade_no' => $trade_no,
]
);
}
}
$data = [
'result' => "验证签名:成功",
'status' => "订单支付状态:" . $post['trade_status'],
'out_trade_no' => "内部订单号:" . $post['out_trade_no'],
'trade_no' => "支付宝交易号:" . $post['trade_no'],
];
$alipaySevice->writeLog($data);
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
$msg = "success"; //请不要修改或删除
$trans->commit();
} catch (\Exception $e) {
$msg = "fail";
$trans->rollBack();
}
echo $msg;
}
5.上面需要使用到的公共方法
/**
* 操作成功
* @example1 jsonSuccess();
*/
function jsonSuccess($data = NULL, $message = '操作成功')
{
header("Content-Type:application/json");
$json = array();
$json['code'] = 0;
$json['data'] = $data;
$json['message'] = $message;
$json['request_time'] = now();
echo Json::encode($json);
exit();
}
/**
* 错误信息
* @example1 jsonFail();
* @example1 jsonFail("删除失败!");
* @example2 jsonFail($model->getErrors());
*/
function jsonFail($message = '请求失败', $code = 1, $data = null)
{
header("Content-Type:application/json");
$json = array();
$json['code'] = $code;
$json['data'] = $data;
$json['message'] = $message;
$json['request_time'] = now();
echo Json::encode($json);
exit();
}
/**
* 过滤掉特殊的字符
* @param $str
* @param string $replacement
* @return string|string[]|null
*/
function replaceStr($str, $replacement = '')
{
$regex = "/\/|\~|\,|\。|\!|\?|\“|\”|\【|\】|\『|\』|\:|\;|\《|\》|\’|\‘|\ |\·|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\,|\.|\/|\;|\'|\`|\-|\=|\\\|\|/";
$result = preg_replace($regex, $replacement, $str);
return $result;
}
Yii2 支付宝相关配置:params-local.php
<?php
return [
// 支付宝支付配置
'alipay' => [
//应用ID,您的APPID。
'app_id' => "xxx",
//异步通知地址
'notify_url' => "https://xxx/notify",
//同步跳转
'return_url' => "",
//编码格式
'charset' => "UTF-8",
//签名方式
'sign_type' => "RSA2",
//支付宝网关
// 正式环境网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
// 测试环境网关
//'gatewayUrl' => "https://openapi.alipaydev.com/gateway.do",
//支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
'alipay_public_key' => "xxx",
//商户私钥,您的原始格式RSA私钥
'merchant_private_key' => 'xxx',
],
];