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开发GUI
Oct 09 PHP
PHP实现分页的一个示例
Oct 09 PHP
一个PHP分页类的代码
May 18 PHP
php中读写文件与读写数据库的效率比较分享
Oct 19 PHP
PHP中使用asort进行中文排序失效的问题处理
Aug 18 PHP
php使用pdo连接sqlite3的配置示例
May 27 PHP
php常用数组array函数实例总结【赋值,拆分,合并,计算,添加,删除,查询,判断,排序】
Dec 07 PHP
利用php-cli和任务计划实现刷新token功能的方法
May 03 PHP
详解PHP字符串替换str_replace()函数四种用法
Oct 13 PHP
php 可变函数使用小结
Jun 12 PHP
在 Laravel 6 中缓存数据库查询结果的方法
Dec 11 PHP
php使用event扩展的io复用测试的示例
Oct 20 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
PHP不用递归遍历目录下所有文件的代码
2014/07/04 PHP
php实现异步将远程链接上内容(图片或内容)写到本地的方法
2016/11/30 PHP
非常不错的一个javascript 类
2006/11/07 Javascript
HTA版JSMin(省略修饰语若干)基于javascript语言编写
2009/12/24 Javascript
Javascript解决常见浏览器兼容问题的12种方法
2010/01/04 Javascript
js动态生成指定行数的表格
2013/07/11 Javascript
使用jquery修改表单的提交地址基本思路
2014/06/04 Javascript
javascript实现日期格式转换
2014/12/16 Javascript
jQuery三级下拉列表导航菜单代码分享
2020/04/15 Javascript
jQuery+CSS3实现3D立方体旋转效果
2015/11/10 Javascript
jQuery获取同级元素的简单代码
2016/07/09 Javascript
jQuery使用serialize()表单序列化时出现中文乱码问题的解决办法
2016/07/27 Javascript
AngularJs  Creating Services详解及示例代码
2016/09/02 Javascript
微信小程序 监听手势滑动切换页面实例详解
2017/06/15 Javascript
Vue.js 十五分钟入门图文教程
2018/09/12 Javascript
JS拖动选择table里的单元格完整实例【基于jQuery】
2019/05/28 jQuery
简单了解Javscript中兄弟ifream的方法调用
2019/06/17 Javascript
JavaScript工具库MyTools详解
2020/01/01 Javascript
微信小程序实现登录注册功能
2020/12/29 Javascript
[01:05:36]VP vs TNC Supermajor小组赛B组 BO3 第二场 6.2
2018/06/03 DOTA
python使用ctypes模块调用windowsapi获取系统版本示例
2014/04/17 Python
python中元类用法实例
2014/10/10 Python
在Pycharm中项目解释器与环境变量的设置方法
2018/10/29 Python
浅析Python与Mongodb数据库之间的操作方法
2019/07/01 Python
python写文件时覆盖原来的实例方法
2020/07/22 Python
html5-websocket基于远程方法调用的数据交互实现
2012/12/04 HTML / CSS
彪马日本官网:PUMA日本
2019/01/31 全球购物
澳大利亚领先的时尚内衣零售商:Bras N Things
2020/07/28 全球购物
最新大学毕业求职简历的自我评价
2013/10/18 职场文书
十佳大学生村官事迹
2014/01/09 职场文书
项目申报专员岗位职责
2014/07/09 职场文书
2015年社区纪检工作总结
2015/04/21 职场文书
一篇合格的广告文案,其主要目的是什么?
2019/07/12 职场文书
MySql存储过程之逻辑判断和条件控制
2021/05/26 MySQL
Apache POI的基本使用详解
2021/11/07 Servers
mysql5.7的安装及Navicate长久免费使用的实现过程
2021/11/17 MySQL