当前位置:首页 > PHP教程 > php高级应用 > 列表

php app支付宝回调(异步通知)详解

发布:smiling 来源: PHP粉丝网  添加日期:2021-10-19 19:37:39 浏览: 评论:0 

这篇文章主要为大家详细介绍了php app支付宝回调的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。

之前写过支付宝app支付的支付的后台代码,现在来说一下异步通知:

个人感觉支付宝的异步通知,步骤比微信简单点,但里面的坑可是没少多少,就一个验签就把我整的快疯了….

异步通知:

1,先确定在支付的时候写的回调地址的正确性!!!!!!

2.找到支付宝封装的验签类,rsaCheckV1(这个也是在app2.0接口里面)

3.验证回调参数

*4.检验订单

先确定在支付的时候写的回调地址的正确性!!!!!!

一定要确定回调地址的写的是否指到是你写回调验证的那个放里面,别到时候在回头找错误的时候,抓耳挠腮..

找到支付宝封装的验签类,rsaCheckV1(这个也是在app2.0接口里面)

这是支付宝已经封装好的类:

  1. /** rsaCheckV1 & rsaCheckV2 
  2.   * 验证签名 
  3.   * 在使用本方法前,必须初始化AopClient且传入公钥参数。 
  4.   * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。 
  5.   **/ 
  6.  public function rsaCheckV1($params$rsaPublicKeyFilePath,$signType='RSA') { 
  7.   $sign = $params['sign']; 
  8.   $params['sign_type'] = null; 
  9.   $params['sign'] = null; 
  10.   $this->alipayrsaPublicKey = $rsaPublicKeyFilePath
  11.  
  12.   return $this->verify($this->getSignContent($params), $sign$rsaPublicKeyFilePath,$signType); 
  13.  } 
  14.  public function rsaCheckV2($params$rsaPublicKeyFilePath$signType='RSA') { 
  15.   $sign = $params['sign']; 
  16.   $params['sign'] = null; 
  17.   return $this->verify($this->getSignContent($params), $sign$rsaPublicKeyFilePath$signType); 
  18.  } 
  19.  function verify($data$sign$rsaPublicKeyFilePath$signType = 'RSA') { 
  20.  
  21.   if($this->checkEmpty($this->alipayPublicKey)){ 
  22.  
  23.    $pubKey$this->alipayrsaPublicKey; 
  24.    $res = "-----BEGIN PUBLIC KEY-----\n" . 
  25.     wordwrap($pubKey, 64, "\n", true) . 
  26.     "\n-----END PUBLIC KEY-----"
  27.   }else { 
  28.    //读取公钥文件 
  29.    $pubKey = file_get_contents($rsaPublicKeyFilePath); 
  30.    //转换为openssl格式密钥 
  31.    $res = openssl_get_publickey($pubKey); 
  32.   } 
  33.  
  34.   ($resor die('支付宝RSA公钥错误。请检查公钥文件格式是否正确');  
  35.  
  36.   //调用openssl内置方法验签,返回bool值 
  37.   if ("RSA2" == $signType) { 
  38.    $result = (bool)openssl_verify($database64_decode($sign), $res, OPENSSL_ALGO_SHA256); 
  39.   } else { 
  40.    $result = (bool)openssl_verify($database64_decode($sign), $res); 
  41.   } 
  42.  
  43.   if(!$this->checkEmpty($this->alipayPublicKey)) { 
  44.    //释放资源 
  45.    openssl_free_key($res); 
  46.   } 
  47.  
  48.   return $result
  49.  } 

还有就是别把这两个方法混淆了,前者需要传signtype,后者不需要(前面两个方法都会调用第三个方法),还有一点很重要,就是这个方法的本身是从文件里面提取公钥的的,但是本人是直接传的,就把这个方法稍加改动了一下,让它直接读取我传的公钥.这个验签方法返回的是(bool)true或者(bool)false,来判断验签是否成功.

在这里要注意三点:

1—注意公钥的正确性,还有用的是支付宝公钥不是你当初生成的公钥

2—区别这里的方法和支付宝接口本身方法的公钥获取方式

3—注意接口方法本身的注释,很重要

验证回调参数

支付宝的回调参数是以post的方式回传的,但是我们在测试的时候可以直接把回调url直接写在地址栏里面,然后用get方式接受,这样就不用拼参数了,结果是一样的(回调url可以记录在log文件里面),还有就是验签的时候需要所有的回传参数原封不动的去验签,而这里自己需要什么参数就接收什么参数就可以,这里就不多说了,就是正常的接受参数的问题.下面给出我在验证参数时,检验订单金额和商家编号的代码,仅做参考(我用的tp5):

  1. public function check($receipt_amount,$buyer_pay_amount,$order_price,$app_id,$seller_email){ 
  2.   if($receipt_amount !== $order_price || $buyer_pay_amount !== $order_price){ 
  3. //    echo 1; 
  4.    return $this->log('订单支付金额有误!'); 
  5.   } 
  6.   //支付宝支付的所有参数 
  7.   $alipay_config = Config::get('alipay_config'); 
  8.   if($app_id !== $alipay_config['appid']){ 
  9. //   echo 2; 
  10.     return $this->log('商家编号有误!'); 
  11.   } 
  12.  
  13.   //验证收款商家是否正确 
  14.   if($seller_email !== $alipay_config['seller_id']){ 
  15. //   echo 3; 
  16.    return $this->log('收款商家有误!'); 
  17.   } 
  18.   return 'success'
  19.  } 

检验订单

这里主要就是检验库存,这里最好用事物处理,(虽然你的订单量可能不一定回到这个地步),下面给出我的代码,仅做参考(tp5):

  1. public function index($order_sn=''
  2.  { 
  3.   if(isset($_POST['order_sn']) && emptyempty($order_sn)){ 
  4.    $order_sn = $_POST['order_sn']; 
  5.   } 
  6.  
  7.   $table = self::order_info($order_sn); 
  8.   if($table == 'failure'){return 'false';} 
  9.   $oid = $table['order_id']; 
  10.   //通过订单id $oid 查询出订单中物品的id 
  11.   $goodsTable = Db::name('goods'); 
  12.   $allgoods = Db::name("test1")->where('o_id'$oid)->field('g_id,g_num')->select(); 
  13.   foreach ($allgoods as $k => $v) { 
  14.    //事务处理 
  15.    $goodsTable->startTrans();//事物开始 
  16.    try { 
  17.     //判断库存数量 
  18.     $goodsTable->query('update test2 set g_num = g_num-' . $v['g_num'] . ' where g_num >= ' . $v['g_num'] . ' and gid =' . $v['g_id']); 
  19.  
  20.    } catch (\Exception $e) { 
  21.     $goodsTable->rollBack();//事物回滚 
  22.    } 
  23.  
  24.    $goodsTable->commit();// 事物提交 
  25.   } 
  26.  
  27.   //修改订单 
  28.   $res = Db::name('test3')->where('order_sn',$order_sn)->update(['order_state' => '1','pay_time'=>time()]); 
  29.   if($res != 0){ 
  30.    return 'success'
  31.   } 
  32.  } 

接下来就是把结果返回给支付宝就可以,失败:return ‘failure';成功:return ‘success';到这里就结束了.

还有就是在出错后和在找bug的时候都平心静气一些,理智的找问题才会更快的找到问题 ( 如果实在不行就去找支付宝的人工支持,他会为你调试你的代码,会给出一个差不多的结论,然后你再去改就会容易很多 :) ).

最后希望大家支付,回调都可以成功!

Tags: app支付宝回调 php异步通知

分享到: