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 相关文章推荐
360通用php防护代码(使用操作详解)
Jun 18 PHP
如何使用PHP批量去除文件UTF8 BOM信息
Aug 05 PHP
php四种基础算法代码实例
Oct 29 PHP
PHP下通过QRCode类库创建中间带网站LOGO的二维码
Jul 12 PHP
PHP中怎样防止SQL注入分析
Oct 23 PHP
php实现高效获取图片尺寸的方法
Dec 12 PHP
Yii2.0 Basic代码中路由链接被转义的处理方法
Sep 21 PHP
PHP中STDCLASS用法实例分析
Nov 11 PHP
使用Yii2实现主从数据库设置
Nov 20 PHP
PHP实现的mysql主从数据库状态检测功能示例
Jul 20 PHP
PHP实现的随机红包算法示例
Aug 14 PHP
PHP生成推广海报的方法分享
Apr 22 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
用mysql_fetch_array()获取当前行数据的方法详解
2013/06/05 PHP
PHP使用mysql_fetch_object从查询结果中获取对象集的方法
2015/03/18 PHP
PHP实现的mongoDB数据库操作类完整实例
2018/04/10 PHP
childNodes.length与children.length的区别
2009/05/14 Javascript
js中的window.open返回object的错误的解决方法
2009/08/15 Javascript
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
2011/01/17 Javascript
jQuery1.5.1 animate方法源码阅读
2011/04/05 Javascript
JS防止用户多次提交的简单代码
2013/08/01 Javascript
jQuery中 prop() attr()使用详解
2015/05/19 Javascript
js获取html的span标签的值方法(超简单)
2016/07/26 Javascript
详解Vue 开发模式下跨域问题
2017/06/06 Javascript
easyui datagrid 表格中操作栏 按钮图标不显示的解决方法
2017/07/27 Javascript
使用SVG基本操作API的实例讲解
2017/09/14 Javascript
vue2+el-menu实现路由跳转及当前项的设置方法实例
2017/11/07 Javascript
为什么说JavaScript预解释是一种毫无节操的机制详析
2018/11/18 Javascript
Vue组件为什么data必须是一个函数
2020/06/11 Javascript
js实现微信聊天界面
2020/08/09 Javascript
[01:20]辉夜杯背景故事宣传片《辉夜传说》
2015/12/25 DOTA
Python字符编码判断方法分析
2016/07/01 Python
分享一个可以生成各种进制格式IP的小工具实例代码
2017/07/28 Python
利用Python将数值型特征进行离散化操作的方法
2018/11/06 Python
python 通过麦克风录音 生成wav文件的方法
2019/01/09 Python
分析运行中的 Python 进程详细解析
2019/06/22 Python
python sklearn库实现简单逻辑回归的实例代码
2019/07/01 Python
jupyter notebook中美观显示矩阵实例
2020/04/17 Python
UI自动化定位常用实现方法代码示例
2020/10/27 Python
python动态规划算法实例详解
2020/11/22 Python
C#面试常见问题
2013/02/25 面试题
酒店财务经理岗位职责
2015/04/08 职场文书
婚庆答谢词大全
2015/09/29 职场文书
2019年“红色之旅”心得体会1000字(3篇)
2019/09/27 职场文书
您对思维方式了解多少?
2019/12/09 职场文书
如何使用php生成zip压缩包
2021/04/21 PHP
oracle通过存储过程上传list保存功能
2021/05/12 Oracle
go select编译期的优化处理逻辑使用场景分析
2021/06/28 Golang
Windows下载并安装MySQL8.0.x 版本的完整教程
2022/04/10 MySQL