php app支付宝回调(异步通知)详解
之前写过支付宝app支付的支付的后台代码,现在来说一下异步通知:
个人感觉支付宝的异步通知,步骤比微信简单点,但里面的坑可是没少多少,就一个验签就把我整的快疯了….
异步通知:
1,先确定在支付的时候写的回调地址的正确性!!!!!!
2.找到支付宝封装的验签类,rsaCheckV1(这个也是在app2.0接口里面)
3.验证回调参数
*4.检验订单
先确定在支付的时候写的回调地址的正确性!!!!!!
一定要确定回调地址的写的是否指到是你写回调验证的那个放里面,别到时候在回头找错误的时候,抓耳挠腮..
找到支付宝封装的验签类,rsaCheckV1(这个也是在app2.0接口里面)
这是支付宝已经封装好的类:
/**rsaCheckV1&rsaCheckV2
*验证签名
*在使用本方法前,必须初始化AopClient且传入公钥参数。
*公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
**/
publicfunctionrsaCheckV1($params,$rsaPublicKeyFilePath,$signType='RSA'){
$sign=$params['sign'];
$params['sign_type']=null;
$params['sign']=null;
$this->alipayrsaPublicKey=$rsaPublicKeyFilePath;
return$this->verify($this->getSignContent($params),$sign,$rsaPublicKeyFilePath,$signType);
}
publicfunctionrsaCheckV2($params,$rsaPublicKeyFilePath,$signType='RSA'){
$sign=$params['sign'];
$params['sign']=null;
return$this->verify($this->getSignContent($params),$sign,$rsaPublicKeyFilePath,$signType);
}
functionverify($data,$sign,$rsaPublicKeyFilePath,$signType='RSA'){
if($this->checkEmpty($this->alipayPublicKey)){
$pubKey=$this->alipayrsaPublicKey;
$res="-----BEGINPUBLICKEY-----\n".
wordwrap($pubKey,64,"\n",true).
"\n-----ENDPUBLICKEY-----";
}else{
//读取公钥文件
$pubKey=file_get_contents($rsaPublicKeyFilePath);
//转换为openssl格式密钥
$res=openssl_get_publickey($pubKey);
}
($res)ordie('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
//调用openssl内置方法验签,返回bool值
if("RSA2"==$signType){
$result=(bool)openssl_verify($data,base64_decode($sign),$res,OPENSSL_ALGO_SHA256);
}else{
$result=(bool)openssl_verify($data,base64_decode($sign),$res);
}
if(!$this->checkEmpty($this->alipayPublicKey)){
//释放资源
openssl_free_key($res);
}
return$result;
}
还有就是别把这两个方法混淆了,前者需要传signtype,后者不需要(前面两个方法都会调用第三个方法),还有一点很重要,就是这个方法的本身是从文件里面提取公钥的的,但是本人是直接传的,就把这个方法稍加改动了一下,让它直接读取我传的公钥.这个验签方法返回的是(bool)true或者(bool)false,来判断验签是否成功.
在这里要注意三点:
1—注意公钥的正确性,还有用的是支付宝公钥不是你当初生成的公钥
2—区别这里的方法和支付宝接口本身方法的公钥获取方式
3—注意接口方法本身的注释,很重要
验证回调参数
支付宝的回调参数是以post的方式回传的,但是我们在测试的时候可以直接把回调url直接写在地址栏里面,然后用get方式接受,这样就不用拼参数了,结果是一样的(回调url可以记录在log文件里面),还有就是验签的时候需要所有的回传参数原封不动的去验签,而这里自己需要什么参数就接收什么参数就可以,这里就不多说了,就是正常的接受参数的问题.下面给出我在验证参数时,检验订单金额和商家编号的代码,仅做参考(我用的tp5):
publicfunctioncheck($receipt_amount,$buyer_pay_amount,$order_price,$app_id,$seller_email){
if($receipt_amount!==$order_price||$buyer_pay_amount!==$order_price){
//echo1;
return$this->log('订单支付金额有误!');
}
//支付宝支付的所有参数
$alipay_config=Config::get('alipay_config');
if($app_id!==$alipay_config['appid']){
//echo2;
return$this->log('商家编号有误!');
}
//验证收款商家是否正确
if($seller_email!==$alipay_config['seller_id']){
//echo3;
return$this->log('收款商家有误!');
}
return'success';
}
检验订单
这里主要就是检验库存,这里最好用事物处理,(虽然你的订单量可能不一定回到这个地步),下面给出我的代码,仅做参考(tp5):
publicfunctionindex($order_sn='')
{
if(isset($_POST['order_sn'])&&empty($order_sn)){
$order_sn=$_POST['order_sn'];
}
$table=self::order_info($order_sn);
if($table=='failure'){return'false';}
$oid=$table['order_id'];
//通过订单id$oid查询出订单中物品的id
$goodsTable=Db::name('goods');
$allgoods=Db::name("test1")->where('o_id',$oid)->field('g_id,g_num')->select();
foreach($allgoodsas$k=>$v){
//事务处理
$goodsTable->startTrans();//事物开始
try{
//判断库存数量
$goodsTable->query('updatetest2setg_num=g_num-'.$v['g_num'].'whereg_num>='.$v['g_num'].'andgid='.$v['g_id']);
}catch(\Exception$e){
$goodsTable->rollBack();//事物回滚
}
$goodsTable->commit();//事物提交
}
//修改订单
$res=Db::name('test3')->where('order_sn',$order_sn)->update(['order_state'=>'1','pay_time'=>time()]);
if($res!=0){
return'success';
}
}
接下来就是把结果返回给支付宝就可以,失败:return‘failure';成功:return‘success';到这里就结束了.
还有就是在出错后和在找bug的时候都平心静气一些,理智的找问题才会更快的找到问题(如果实在不行就去找支付宝的人工支持,他会为你调试你的代码,会给出一个差不多的结论,然后你再去改就会容易很多:)).
最后希望大家支付,回调都可以成功!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。