开放支付
开放支付,是在友好速搭中的网站,拥有的支付基础设施。开发者可以使用网站中,配置好的支持体系,为客户定制特殊的收款业务。流程图如下:
使用过程如下:
1.获得 open_secret 以及 payment_method
参考 Shop ,获得 open_secret,该字段用于加密参数验证请求。
参考 PaymentMethod ,获得 payment_method 相关信息,用于选择支付方式。
2.准备支付参数
字段名 | 说明 | 必须 |
---|---|---|
custom_trade_no | 该笔支付请求的编号 | 是 |
amount | 支付金额,单位为分 | 是 |
pay_type | 支付方式类型(第一步中获取,具体描述可见 PaymentMethod 和附录) | 是 |
payment_method_id | 支付方式 ID(第一步中获取) | 是 |
bank_code_id | 银行代码(附录) | 根据pay_type,见附录 |
notify_url | 异步通知地址 | 是 |
return_url | 同步通知地址 | 否 |
expired_at | 支付过期时间,格式为 YYYY-MM-DDTHH:mm:ss | 是 |
sign | 详见签名 | 是 |
拼接后的参数如下
?custom_trade_no=TEST0008715&amount=1&pay_type=alipay¬ify_url=www.example.com&expired_at=2016-4-1T19%3A19%3A00&payment_method_id=1&sign=6dee3827ca9dee726c056f4e69e719d5
3.跳转到支付页面
拼接好支付相关参数之后,就可以通过开放支付,跳转到网站的支付页:
http://www.your_site_url.com/open_trade?custom_trade_no=TEST0008715&amount=1&pay_type=alipay¬ify_url=www.example.com&expired_at=2016-4-1T19%3A19%3A00&payment_method_id=1&sign=6dee3827ca9dee726c056f4e69e719d5
4.接收通知
在用户完成支付后,开放支付会发起 POST 请求至参数中 notify_url 所填的地址,其参数如下:
字段名 | 说明 |
---|---|
id | 该次支付生成 ID |
custom_trade_no | 该笔支付请求的编号 |
gateway_trade_no | 支付平台交易编号 |
amount | 支付金额,单位为分 |
pay_type | 用户所选择的支付方式 |
bank_code_id | 银行代码 |
notify_url | 异步通知地址 |
expired_at | 支付过期时间,格式为 YYYY-MM-DDTHH:mm:ss |
status | 支付是否成功 |
sign | 详见签名 |
如:
http://yournotifyurl.com/?custom_trade_no=75b1559856a240a88****&amount=1&status=paid&pay_type=alipay¬ify_url=http://yournotifyurl.com&expired_at=2016-03-07T12%3A11%3A27&sign=5e9613c93ffe08c36fef675b64a277d5
为了验证该次请求是否是开放支付发出,你需要剔除 sign 参数后,用其它参数与 open_secret 字符串拼接后的 md5 结果与 sign 的值做匹配,若一致,则说明该次请求是开放支付发起。
5.示例代码
require "openssl"
require 'cgi'
require 'digest/md5'
# 每个store里有一个open_secret字段 即下面的open_secret
# 数据
options = {
:custom_trade_no => 'TEST000177015551343', # 必填
:amount => '1', # 必填
:pay_type => 'alipay', # 必填
:bank_code_id => '', # 银行支付必填
:notify_url => 'http://www.example.com', # 必填
:expired_at => '2016-3-10T14:19:00', # 过期时间,可选范围1m到15d
:payment_method_id => '141337' # 必填
}
open_secret = 'OPEN_SECRET' # 替换成你自己的open_secret
pay_url = 'SHOP_URL.youhaosuda.com/open_trade' # 替换成你自己的店铺地址
temp_options = options.clone
to_sign = temp_options.sort.map{|option| "#{option[0].to_s}=#{CGI.unescape(option[1].to_s)}"}.join('&') + open_secret
signature = Digest::MD5.hexdigest(to_sign)
options[:sign] = signature
final_url = pay_url + '?' + options.map{|k, v| "#{k}=#{CGI.escape(v)}"}.join("&")
puts "final_url:" + final_url.to_s
附录
签名
跳转支付和接受支付回调都需要用到签名,签名生成步奏如下:
筛选参数。如果是回调则要剔除sign参数,存在空值的参数必须剔除。
排序参数。在参数集合中,根据参数(不是参数对应的值)的第一个字符的键值ASCII码递增排序,如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推。
拼接参数。在参数集合中,把每个参数及其值组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来。例如:
amount=1&custom_trade_no=TEST0008715&expired_at=2016-4-1T19:19:00¬ify_url=www.example.com&pay_type=alipay&payment_method_id=1
把 open_secret 拼接在待签名字符串尾部。例如:
amount=1&custom_trade_no=TEST0008715&expired_at=2016-4-1T19:19:00¬ify_url=www.example.com&pay_type=alipay&payment_method_id=17105eda80a8b46af9e8fef611fdc3c02
调用md5加密函数,对已经与MD5密钥拼接好的新字符串做加密运算。例如,上一步加密结果:
6dee3827ca9dee726c056f4e69e719d5
错误信息
错误信息 | 具体信息 |
---|---|
EXPIRED_AT_ERROR: 过期时间设置错误. | 过期时间必须在 1m~15d 范围内。 |
BANK_CODE_ID_ERROR: 银行 ID 错误. | 如果使用银行支付必须提供银行 ID。 |
PAYMENT_METHOD_ERROR: 支付方法不存在. | 需要确保 payment_method_id 和 pay_type 一致并且该支付方式处于使用中状态。 |
AMOUNT_ERROR | 请提供大于 0 的整数,单位是分。 |
SIGN_ERROR: 签名错误. | 参考示例代码保证 sign 正确。 |
支持的支付方式
支付方式 | 值 | 必须银行代码 |
---|---|---|
微信支付 | wppay | × |
支付宝(即时到帐) | alipay | × |
支付宝(手机网站) | alipay_wap_user | × |
支付宝(担保交易) | alipay_partner | × |
支付宝(网银直联) | alipay_bank | √ |
财付通(即时到帐) | tenpay | × |
财付通(网银直联) | tenpay_bank | √ |
百度钱包 | baifubao | × |
快钱 | kuaipay | × |
支持的银行代码
银行 | 代码 | 支持支付宝 | 支持财付通 |
---|---|---|---|
中国银行 | 1 | √ | √ |
中国工商银行 | 2 | √ | √ |
中国建设银行 | 3 | √ | √ |
中国农业银行 | 4 | √ | √ |
招商银行 | 5 | √ | √ |
上海浦东发展银行 | 6 | √ | √ |
兴业银行 | 7 | √ | √ |
广东发展银行 | 8 | √ | × |
中国民生银行 | 9 | √ | √ |
中信银行 | 10 | √ | √ |
杭州银行 | 11 | √ | × |
中国光大银行 | 12 | √ | √ |
上海银行 | 13 | √ | √ |
宁波银行 | 14 | √ | × |
平安银行 | 15 | √ | √ |
北京农村商业银行 | 16 | √ | × |
富滇银行 | 17 | √ | × |
中国邮政储蓄银行 | 18 | √ | √ |
交通银行 | 19 | × | √ |
华夏银行 | 20 | × | √ |
北京银行 | 21 | × | √ |