采用WordPress搭建的网站,并使用WooCommerce插件,现在需要接入支付宝支付功能。
使用支付宝账号登录开放平台:
登录之后是如下界面:
开发文档中说“根据实际需求创建应用(如”支付应用“)”,我在这个页面没看到这一项,只有“支付接入”、“自定义接入”、“商业零售”、“交通出行”、“政务民生”、“医疗教育”这几项。不知道这几项的具体含义。暂时先选择“支付接入”吧!
这里要求选择“使用场景”,有第三方法应用和自用型应用两个选项,第一个是指开发出来给别人用的,第二个是指开发给自己用的。选择自用型,填入应用名称后,跳转到下面的页面:
这个页面包含基础信息、功能选项、开发配置三块。上面的图只截取到了前两块。
基础信息中有应用名称和应用图标。应用名称之前已经填过了,现在上传自己的应用图标就行了。应用基础信息在开发应用过程中可以无需审核随时完善。但在应用申请上线时需要进行审核。
功能选项模块中包含各种功能,你可以选择自己需要的功能添加到功能列表中,现在默认添加了当面付、手机网站支付、APP支付功能。不同的功能有不同的使用条件,如果某个功能的使用条件是签约,那么在使用此项功能之前,需要签约对应产品。点击“+ 继续添加”,跳到添加功能页面,这里有非常多的功能供选择:
添加了“电脑网站支付”功能。
支付宝网关:已有默认值。
应用网关:用于接收支付宝异步通知,这里可以不用设置。
授权回调地址:第三方授权或者用户信息授权后回调地址。授权链接中配置的redirect_uri值必须与此值保持一致。
RSA2(SHA256)密钥(推荐):开发者要保证接口中使用的秘钥与此处的公钥匹配,否则无法调用接口。接口参数sign_type=RSA2。
RSA(SHA1)密钥:同上,接口参数为sign_type=RSA。
对接口加签方式中的“设置应用公钥”进行设置,会弹出如下窗口:
选择设置应用公钥后弹出下面窗口:
填写校验码后,弹出窗口:
这个框框里面需要填入商户自己的公钥。简单介绍一下商户公钥、商户私钥和支付宝公钥的概念:
商户应用公钥:商户自己生成的RSA公钥,生成之后需要上传公钥到支付宝开放平台以便支付宝使用该公钥验证交易是否由该商户发起的;
商户应用私钥:商户自己生成的RSA私钥,商户开发者使用生成的私钥对请求字符串进行加签;
支付宝公钥:支付宝的RSA公钥,商户使用该公钥验证结果是否由支付宝返回的。
生成商户应用私钥和应用公钥:
点击右边的链接:https://docs.open.alipay.com/291/105971,这里介绍了生成商户RSA密钥的方法。根据指导,生成了应用公钥2048.txt
和应用私钥2048.txt
两个文件。生成的私钥一定要妥善保管。私钥需要填写到代码中供签名时使用;公钥需要上传到支付宝开放平台。
上传商户应用公钥到支付宝平台:
把应用公钥2048.txt
中的内容复制粘贴到前面的框框中。然后保存,弹出如下窗口:
现在在RSA2(SHA256)密钥(推荐)右边如下:
可以看到,除了商户的应用公钥之外,还有支付宝公钥。
可以随时修改应用公钥。
使用应用私钥生成请求签名
把AppID、应用私钥、支付宝公钥配置在代码中,对请求内容进行签名,并对支付宝返回的内容进行验签。
支付宝开放平台SDK封装了签名和验签过程,只需配置账号和密钥参数即可,推荐使用SDK。这个在开发过程中会介绍。
创建应用时的应用状态为“开发中”,无法在线上正式调用接口。按照上面的步骤设置好后,提交审核。
应用审核通过后,变成已上线状态。现在我们可以尝试开发支付宝网站接口了。
为了帮助开发者调用开放接口,支付宝开放平台提供了“开放平台服务端SDK”,包含JAVA、PHP和.NET三个版本,封装了签名&验签、HTTP接口请求等基础功能。
https://docs.open.alipay.com/54/103419,选择你熟悉的语言的SDK。我下载的是PHP版本的。这个页面中有关于各语言版本SDK的详细使用说明,可以仔细阅读一遍。
将下载的alipay-sdk-PHP-20171121170331.zip
解压到项目目录中去,比如项目文件夹为alipay/
,那么解压后的SDK为alipay/alipay-sdk-PHP-20171121170331/
。
在SDK调用前需要进行初始化,代码如下:
require_once("alipay-sdk-PHP-20171121170331/AopSdk.php");
//构造参数
$aop = new AopClient ();
$aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do'; // 向这个网址发送支付、退款、查询等请求
$aop->appId = '请填写APPID';
$aop->rsaPrivateKey = '请填写商户私钥';
$aop->apiVersion = '1.0';
$aop->signType = 'RSA2'; // 对字符串进行前ing时使用的签名算法类型
$aop->postCharset= 'utf-8';
$aop->format='json';
接下来,就可以用$aop
来调用具体的API了。$aop
只需要初始化一次,后续调用不同的API都可以使用同一个$aop
对象。
通过向支付宝网关发送alipay.trade.page.pay
请求进行支付。
$request = new AlipayTradePagePayRequest ();
$request->setReturnUrl('请填写您的页面同步跳转地址'); // 在支付完成之后,支付宝服务器会跳转到这个页面,同时GET方式传送支付结果参数
$request->setNotifyUrl('请填写您的异步通知地址'); // 支付完成后,支付宝服务器会向这个网址发送异步通知消息,支付结果必须以异步通知为准,不能依赖同步跳转
$request->setBizContent('{"product_code":"FAST_INSTANT_TRADE_PAY","out_trade_no":"20150320010101001","subject":"Iphone6 16G","total_amount":"88.88","body":"Iphone6 16G"}');
// 请求
$result = $aop->pageExecute ($request); // $resule是一个表单
// 输出
echo $result;
报文请求时会自动用应用私钥进行签名;支付宝收到请求之后,首先用应用公钥对请求参数验签,然后返回表单$result
,打印这个表单会把用户重定向到支付页面。
请求返回的结果$result
的内容如下:
<form id='alipaysubmit' name='alipaysubmit' action='https://openapi.alipaydev.com/gateway.do?charset=UTF-8' method='POST'><input type='hidden' name='biz_content' value='{"product_code":"FAST_INSTANT_TRADE_PAY","body":"hah","subject":"测试","total_amount":"0.01","out_trade_no":"201711279339773"}'/><input type='hidden' name='app_id' value='2016090800411111'/><input type='hidden' name='version' value='1.0'/><input type='hidden' name='format' value='json'/><input type='hidden' name='sign_type' value='RSA2'/><input type='hidden' name='method' value='alipay.trade.page.pay'/><input type='hidden' name='timestamp' value='2017-11-27 10:26:48'/><input type='hidden' name='alipay_sdk' value='alipay-sdk-php-20161101'/><input type='hidden' name='notify_url' value='http://www.example.com'/><input type='hidden' name='return_url' value='http://www.example.com'/><input type='hidden' name='charset' value='UTF-8'/><input type='hidden' name='sign' value='nZG55zzL2PtHywMt0z93uCx+1W3JSo9tUk8AM32N2fvzeeapg6g55nVjGmdGRrSLDQzYibEP3imOqmS6I5u9e222v8BeZKPtZJUb4GMrvot0NXVSqRRDi/kmyURAI7d8+8wkpgQP3mEKg9YM4JddcWYQRFdM6W0kzKPd2N+hThjdchJ30wwwDtCAgZNs916t3YTW18ZTDxSSjDCHDDPd065PkUwNmLc1YwvumS+dKVEVDAy2/gcUjAyFTQx1A9fYW2kibyp2ohGQbjksogTEgOKE2yIuLVZWMTMcZ5k2en826OWV47UmKH07NzCjhqI45Wrkg8sXoY1mUZdvnXUvRQ=='/><input type='submit' value='ok' style='display:none;''></form><script>document.forms['alipaysubmit'].submit();</script>
当用户付过钱后,会跳转到设置的return url
中,并以GET方式返回支付结果参数。
由于同步返回的不可靠性,支付结果必须以异步通知或查询接口返回为准,不能依赖同步跳转。
支付成功后,支付宝除了向return url
发送同步通知外,还会以POST方式向notify url
发送异步通知。商户系统受到异步通知后,首先需要用支付宝公钥进行验签,确定消息是否来自支付宝。SDK中封装了验签接口。
$arr = $_POST;
$arr['fund_bill_list'] = stripslashes($arr['fund_bill_list']);
$aop = new AopClient();
$aop->alipayrsaPublicKey = '支付宝公钥';
$signtype = 'RSA2'
$flag = $aop->rsaCheckV1($arr, '支付宝公钥', $signtype);
if ($flag) {
//验签成功
// 进行通知数据的二次检验
// 根据交易状态进行商户的自身业务
echo 'success';
}
else {
// 验签失败,记录异常日志
echo 'fail';
}
刚开始的时候,出现了验签失败的结果。后来在网上搜了一下,发现这是因为PHP自动将fund_bill_list
中的特殊字符前加了转义符,需要把转义字符去掉才行。所以如果验签没通过,不妨加上$arr['fund_bill_list'] = stripslashes($arr['fund_bill_list']);
试试。
验签通过后,需要按照以下步骤检验数据的正确性:
上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
注意:
状态TRADE_SUCCESS的通知触发条件是商户签约的产品支持退款功能的前提下,买家付款成功;
交易状态TRADE_FINISHED的通知触发条件是商户签约的产品不支持退款功能的前提下,买家付款成功;或者,商户签约的产品支持退款功能的前提下,交易已经成功并且已经超过可退款期限。
在验签、二次校通过后,根据trade_status
进行后续业务处理。
// 交易状态
$trade_status = $_POST['trade_status'];
if($trade_status == 'TRADE_FINISHED' || $trade_status=='TRADE_SUCCESS') {
// 判断该订单是否在商户网站中已经做过处理,如果没有的话执行商户的业务程序
}
1. 调试错误,请回到请求来源地,重新发起请求。
错误代码 missing-signature 错误原因: 缺少签名参数
解答:
这是因为alipay.trade.page.pay请求结果里面没有sign,为什么呢?https://openclub.alipay.com/read.php?tid=2333&fid=46给出了原因。
php环境必须5.5以上,而现在的服务器上通过php -v
命令查看,版本是PHP 5.3.28。升级之后这个问题解决了。
2. 支付请求提交后,返回“订单信息无法识别,建议联系卖家
”的错误提示?
解答:
$request->setBizContent();
中每个参数值都应该是字符串,比如'"' . $value1 . '"'
。
下一篇:WooCommerce接入支付宝支付功能(二)——WooCommerce中添加新的支付网关
[1] 电脑网站支付快速接入
[2] 创建应用
[3] 生成RSA密钥
[4] 上传应用公钥并获取支付宝公钥
[5] 使用应用私钥生成请求签名
[6] 服务端SDK
[7] alipay.trade.page.pay
[8] 电脑网站支付结果异步通知