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+mysql一个名片库程序
Oct 09 PHP
PHP5函数小全(分享)
Jun 06 PHP
适用于抽奖程序、随机广告的PHP概率算法实例
Apr 09 PHP
ThinkPHP之用户注册登录留言完整实例
Jul 22 PHP
ThinkPHP自动转义存储富文本编辑器内容导致读取出错的解决方法
Aug 08 PHP
php中header跳转使用include包含解决参数丢失问题
May 08 PHP
php目录拷贝实现方法
Jul 10 PHP
php生成动态验证码gif图片
Oct 19 PHP
老生常谈ThinkPHP中的行为扩展和插件(推荐)
May 05 PHP
PHP定义字符串的四种方式详解
Feb 06 PHP
原生JS实现Ajax通过GET方式与PHP进行交互操作示例
May 12 PHP
Laravel框架模板继承操作示例
Jun 11 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中最容易忘记的一些知识点总结
2013/04/28 PHP
php cli模式学习(PHP命令行模式)
2013/06/03 PHP
Javascript - HTML的request类
2007/01/09 Javascript
javascritp实现input输入框相关限制用法
2007/06/29 Javascript
Mootools 图片展示插件(lightbox,ImageMenu)收集集合
2010/05/21 Javascript
JS图片自动轮换效果实现思路附截图
2014/04/30 Javascript
jquery实现LED广告牌旋转系统图片切换效果代码分享
2015/08/26 Javascript
javascript中substring()、substr()、slice()的区别
2015/08/30 Javascript
理解javascript模块化
2016/03/28 Javascript
js入门之Function函数的使用方法【新手必看】
2016/11/22 Javascript
基于JavaScript实现图片剪切效果
2017/03/07 Javascript
解决html input验证只能输入数字,不能输入其他的问题
2017/07/21 Javascript
详解如何在angular2中获取节点
2017/11/23 Javascript
详解使用 Node.js 开发简单的脚手架工具
2018/06/08 Javascript
JavaScript如何借用构造函数继承
2019/11/06 Javascript
[01:03]PWL开团时刻DAY6——别打我
2020/11/05 DOTA
Python实现图像几何变换
2015/07/06 Python
使用sklearn之LabelEncoder将Label标准化的方法
2018/07/11 Python
在Python中居然可以定义两个同名通参数的函数
2019/01/31 Python
python sorted函数原理解析及练习
2020/02/10 Python
python手写均值滤波
2020/02/19 Python
查看已安装tensorflow版本的方法示例
2020/04/19 Python
python中delattr删除对象方法的代码分析
2020/12/15 Python
image-set实现Retina屏幕下图片显示详细介绍
2012/12/24 HTML / CSS
CSS3属性box-sizing使用指南
2014/12/09 HTML / CSS
Get The Label中文官网:英国运动时尚购物平台
2017/04/19 全球购物
什么是继承
2013/12/07 面试题
《雨霖铃》教学反思
2014/02/22 职场文书
我与祖国共奋进演讲稿
2014/09/13 职场文书
对照四风自我剖析材料
2014/10/07 职场文书
2014年银行柜员工作总结
2014/11/12 职场文书
主持人开幕词
2015/01/29 职场文书
详解Python牛顿插值法
2021/05/11 Python
继承Win10缺点!教你关闭Win11烦人的网络搜索
2021/11/23 数码科技
Python IO文件管理的具体使用
2022/03/20 Python
MySQL详细讲解变量variables的用法
2022/06/21 MySQL