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


Posted in PHP onJuly 25, 2018

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

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

异步通知:

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

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

3.验证回调参数

*4.检验订单

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

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

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

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

/** rsaCheckV1 & rsaCheckV2
  * 验证签名
  * 在使用本方法前,必须初始化AopClient且传入公钥参数。
  * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。
  **/
 public function rsaCheckV1($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);
 }
 public function rsaCheckV2($params, $rsaPublicKeyFilePath, $signType='RSA') {
  $sign = $params['sign'];
  $params['sign'] = null;
  return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath, $signType);
 }
 function verify($data, $sign, $rsaPublicKeyFilePath, $signType = 'RSA') {

  if($this->checkEmpty($this->alipayPublicKey)){

   $pubKey= $this->alipayrsaPublicKey;
   $res = "-----BEGIN PUBLIC KEY-----\n" .
    wordwrap($pubKey, 64, "\n", true) .
    "\n-----END PUBLIC KEY-----";
  }else {
   //读取公钥文件
   $pubKey = file_get_contents($rsaPublicKeyFilePath);
   //转换为openssl格式密钥
   $res = openssl_get_publickey($pubKey);
  }

  ($res) or die('支付宝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):

public function check($receipt_amount,$buyer_pay_amount,$order_price,$app_id,$seller_email){
  if($receipt_amount !== $order_price || $buyer_pay_amount !== $order_price){
//    echo 1;
   return $this->log('订单支付金额有误!');
  }
  //支付宝支付的所有参数
  $alipay_config = Config::get('alipay_config');
  if($app_id !== $alipay_config['appid']){
//   echo 2;
    return $this->log('商家编号有误!');
  }

  //验证收款商家是否正确
  if($seller_email !== $alipay_config['seller_id']){
//   echo 3;
   return $this->log('收款商家有误!');
  }
  return 'success';
 }

检验订单

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

public function index($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 ($allgoods as $k => $v) {
   //事务处理
   $goodsTable->startTrans();//事物开始
   try {
    //判断库存数量
    $goodsTable->query('update test2 set g_num = g_num-' . $v['g_num'] . ' where g_num >= ' . $v['g_num'] . ' and gid =' . $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的时候都平心静气一些,理智的找问题才会更快的找到问题 ( 如果实在不行就去找支付宝的人工支持,他会为你调试你的代码,会给出一个差不多的结论,然后你再去改就会容易很多 :) ).

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
用PHP查询域名状态whois的类
Nov 25 PHP
PHP获取网卡地址的代码
Apr 09 PHP
thinkphp3.0 模板中函数的使用
Nov 13 PHP
ThinkPHP视图查询详解
Jun 30 PHP
php与flash as3 socket通信传送文件实现代码
Aug 16 PHP
PHP实现通过get方式识别用户发送邮件的方法
Jul 16 PHP
PHP版本升级到7.x后wordpress的一些修改及wordpress技巧
Dec 25 PHP
yii,CI,yaf框架+smarty模板使用方法
Dec 29 PHP
Smarty简单生成表单元素的方法示例
May 23 PHP
Thinkphp5行为使用方法汇总
Dec 21 PHP
PHP7.1实现的AES与RSA加密操作示例
Jun 15 PHP
tp5 sum某个字段相加得到总数的例子
Oct 18 PHP
php支付宝APP支付功能
Jul 29 #PHP
PHP多个图片压缩成ZIP的方法
Aug 18 #PHP
PHP上传文件及图片到七牛的方法
Jul 25 #PHP
详解PHP版本兼容之openssl调用参数
Jul 25 #PHP
PHP实现的多维数组去重操作示例
Jul 21 #PHP
php实现生成PDF文件的方法示例【基于FPDF类库】
Jul 21 #PHP
记录Yii2框架开发微信公众号遇到的问题及解决方法
Jul 20 #PHP
You might like
一个odbc连mssql分页的类
2006/10/09 PHP
下拉列表多级联动dropDownList示例代码
2013/06/27 PHP
php实现水仙花数的4个示例分享
2014/04/08 PHP
jquery form 加载数据示例
2014/04/21 Javascript
JS利用cookie记忆当前位置的防刷新导航效果
2015/10/15 Javascript
jquery之别踩白块游戏的简单实现
2016/07/25 Javascript
详解javascript中对数据格式化的思考
2017/01/23 Javascript
JScript实现地址选择功能
2017/08/15 Javascript
jQuery Datatables表头不对齐的解决办法
2017/11/27 jQuery
解决vue 按钮多次点击重复提交数据问题
2018/05/10 Javascript
创建Vue项目以及引入Iview的方法示例
2018/12/03 Javascript
jQuery实现表格的增、删、改操作示例
2019/01/27 jQuery
简单了解node npm cnpm的具体使用方法
2019/02/27 Javascript
[01:39:42]Fnatic vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[49:17]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第三场 1月26日
2021/03/11 DOTA
Python简单实现enum功能的方法
2016/04/25 Python
Python 异常处理的实例详解
2017/09/11 Python
python实现周期方波信号频谱图
2018/07/21 Python
python实现Dijkstra算法的最短路径问题
2019/06/21 Python
利用python计算windows全盘文件md5值的脚本
2019/07/27 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
2020/02/09 Python
python针对Oracle常见查询操作实例分析
2020/04/30 Python
如何对python的字典进行排序
2020/06/19 Python
Python性能测试工具Locust安装及使用
2020/12/01 Python
纯CSS3实现给头像加个光芒四射且旋转的背景动画效果
2014/05/07 HTML / CSS
viagogo法国票务平台:演唱会、体育比赛、戏剧门票
2017/03/27 全球购物
复古斯堪的纳维亚儿童服装:Baby go Retro
2017/09/09 全球购物
印尼美容产品购物网站:PerfectBeauty.id
2017/12/01 全球购物
阿玛尼意大利官网:Armani意大利
2018/10/30 全球购物
医院深入开展党的群众路线教育实践活动实施方案
2014/08/27 职场文书
党员民主生活会整改措施
2014/09/26 职场文书
学校领导四风问题整改措施思想汇报
2014/10/09 职场文书
学生逃课检讨书1000字
2014/10/20 职场文书
2014旅游局党组书记党建工作汇报材料
2014/11/02 职场文书
德劲DE1108畅想
2021/04/22 无线电
python之django路由和视图案例教程
2021/07/26 Python