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重定向的3种方式
Mar 07 PHP
浅析php面向对象public private protected 访问修饰符
Jun 30 PHP
php jq jquery getJSON跨域提交数据完整版
Sep 13 PHP
php实现计数器方法小结
Jan 05 PHP
php单例模式示例分享
Feb 12 PHP
php计算整个目录大小的方法
Jun 01 PHP
Symfony2之session与cookie用法小结
Mar 18 PHP
基于PHP生成简单的验证码
Jun 01 PHP
PHP操作mysql数据库分表的方法
Jun 09 PHP
php 实现Hash表功能实例详解
Nov 29 PHP
PHP ADODB实现分页功能简单示例
May 25 PHP
YII2框架中ActiveDataProvider与GridView的配合使用操作示例
Mar 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
php判断用户是否手机访问代码
2015/06/08 PHP
thinkphp微信开之安全模式消息加密解密不成功的解决办法
2015/12/02 PHP
php生成酷炫的四个字符验证码
2016/04/22 PHP
Yii2增删改查之查询 where参数详细介绍
2016/08/08 PHP
手把手编写PHP框架 深入了解MVC运行流程
2016/09/19 PHP
php分页查询的简单实现代码
2017/03/14 PHP
Yii框架页面渲染操作实例详解
2019/07/19 PHP
javaScript 判断字符串是否为数字的简单方法
2009/07/25 Javascript
JS判断页面加载状态以及添加遮罩和缓冲动画的代码
2012/10/11 Javascript
JavaScript计算器网页版实现代码分享
2016/07/15 Javascript
Google 地图事件实例讲解
2016/08/06 Javascript
SelecT下拉框选中和取值的解决方法
2016/11/22 Javascript
Node.js利用Net模块实现多人命令行聊天室的方法
2016/12/23 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
2017/01/10 Javascript
基于JQuery的购物车添加删除以及结算功能示例
2017/03/08 Javascript
使用canvas及js简单生成验证码方法
2017/04/02 Javascript
详解使用PM2管理nodejs进程
2017/10/24 NodeJs
AngularJs的UI组件ui-Bootstrap之Tooltip和Popover
2018/07/13 Javascript
vue+axios 前端实现登录拦截的两种方式(路由拦截、http拦截)
2018/10/24 Javascript
Angular6 Filter实现页面搜索的示例代码
2018/12/02 Javascript
javascript中可能用得到的全部的排序算法
2020/03/05 Javascript
[01:19]DOTA2城市挑战赛报名开始 开启你的城市传奇
2018/03/23 DOTA
[33:28]完美世界DOTA2联赛PWL S3 PXG vs GXR 第三场 12.19
2020/12/24 DOTA
解决python3 json数据包含中文的读写问题
2018/05/10 Python
对python指数、幂数拟合curve_fit详解
2018/12/29 Python
对python列表里的字典元素去重方法详解
2019/01/21 Python
python面向对象实现名片管理系统文件版
2019/04/26 Python
Prometheus开发中间件Exporter过程详解
2020/11/30 Python
python中altair可视化库实例用法
2021/01/26 Python
最耐用行李箱,一箱永流传:Briggs & Riley(全球终身保修)
2017/12/07 全球购物
美国婴儿和儿童家具网上商店:ABaby.com
2018/07/02 全球购物
adidas泰国官网:adidas TH
2020/07/11 全球购物
物价局领导班子四风问题整改措施
2014/10/26 职场文书
事业单位年度考核个人总结
2015/02/12 职场文书
2015年房地产销售工作总结
2015/04/20 职场文书
Flask使用SQLAlchemy实现持久化数据
2021/07/16 Python