热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

php微信退款返回签名错误,PHP微信支付开发(2)退款

一、概述本系列博客将讨论基于微信支付的项目开发中,涉及到的下单与支付、退款、以及订单查询的后端代码实现。在本系列博客中,将以代码片段作为示例࿰

一、概述

本系列博客将讨论基于微信支付的项目开发中,涉及到的下单与支付、退款、以及订单查询的后端代码实现。在本系列博客中,将以代码片段作为示例,来讨论ThinkPHP 后端接口实现的过程。

在本系列的接口示例中,返回的状态码标识如下:

0: 业务成功

-1: 业务失败

开发环境如果:

ThinkPHP 6 或者 ThinkPHP 5 / 5.1

PHP 7 运行环境

本文是第二篇,我们讨论退款。

二、退款申请

订单支付成功之后即可退款,退款的金额可以小于或者等于订单的下单金额。请求参数相对下单接口略有变化,如下代码:

$order = Order::where('id',request()->params('id'))->find();

$order['out_refund_no'] = date('YmdHis').mt_rand(1000, 9999);

$params = [

'appid' => config('wx.app_id'),

'mch_id' => config('wx.mch_id'),

'nonce_str' => md5(time()),

'sign_type' => 'MD5',

'transaction_id' => $order['transaction_id'],

'out_trade_no' => $order['out_trade_no'],

'out_refund_no' => $order['out_refund_no'],

'total_fee' => $order['fee'] * 100,

'refund_fee' => $order['fee'] * 100,

'refund_desc' => $params['refund_desc'],

'notify_url' => 'https://test.com/orders/callback_refund',//通知地址

];

构造xml

//创建xml

$xml = '';

$xml .= '';

//遍历参数

$stringA = '';

//根据键名对参数进行字典排序

ksort($params);

foreach ($params as $key => $value) {

$stringA .= $key . '=' . $value . '&';

$xml .= '' . $value . '' . $key . '>';

}

$signTmp = $stringA . 'key=' . config('wx.mch_key');//与商户API秘钥进行拼接

$sign = strtoupper(md5($signTmp));//签名后的32位字符

//将签名添加到请求参数中

$xml .= '' . $sign . '';

$xml .= '';

退款申请需要安全证书(在微信商户号里申请),我们重新定义在common.php一个用于请求的方法

function order_refund_request($url, $data = null)

{

$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, $url);

if (!empty($data)) {

curl_setopt($curl, CURLOPT_POST, 1);

curl_setopt($curl, CURLOPT_POSTFIELDS, $data);

}

curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

//证书设置

curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');

curl_setopt($curl, CURLOPT_SSLCERT, dirname(__FILE__) . '/cert/apiclient_cert.pem');//客户端cert路径

curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');

curl_setopt($curl, CURLOPT_SSLKEY, dirname(__FILE__) . '/cert/apiclient_key.pem');//客户端key路径

$output = curl_exec($curl);

curl_close($curl);

return $output;

}

这里要注意证书的路径,一定要匹配。接着发送退款请求

$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';

$res_xml = order_refund_request($url, $xml);

trace('微信中台申请退款,返回信息');

trace($res_xml);

$simpleXMLElement = simplexml_load_string($res_xml, 'SimpleXMLElement', LIBXML_NOCDATA);

//将SimpleXMLElement转为数组

$jsonStr = json_encode($simpleXMLElement);

$jsonArray = json_decode($jsonStr, true);

if (isset($jsonArray['return_code']) && $jsonArray['return_code'] == 'SUCCESS') {

// 退款申请成功,更新订单状态

$order['status'] = 2;

return json(['code'=>0,'msg'=>'成功']);

} else {

//响应失败

return json(['code'=>-1,'msg'=>'响应失败']);

}

三、退款回调

退款回调返回的数据是加密的,回调地址是退款申请中的通知地址。我们需要先解密返回数据,再根据返回数据去更新订单状态。首先在当前类里定义解密方法

private function refundDecrypt($str, $key)

{

$key = md5($key);

$str = base64_decode($str);

return openssl_decrypt($str, 'aes-256-ecb', $key, OPENSSL_RAW_DATA);

}

接下来,获取参数并解密

$xml = file_get_contents('php://input');

if (!$xml) {

exit(0);

}

$simpleXMLElement = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);

//将SimpleXMLElement转为数组

$jsonStr = json_encode($simpleXMLElement);

$jsonArray = json_decode($jsonStr, true);

// 中台返回数据解密

if (!isset($jsonArray['req_info'])) {

exit(0);

}

$decryptStr = $this->refundDecrypt($jsonArray['req_info'],

//将xml解析为array

$simpleXMLElement = simplexml_load_string($decryptStr, 'SimpleXMLElement', LIBXML_NOCDATA);

//将SimpleXMLElement对象转为数组

$jsonStr = json_encode($simpleXMLElement);

// 解析字段

$jsonResArr = json_decode($jsonStr, true);

// 验证参数

if (!(isset($jsonResArr['out_refund_no']) && isset($jsonResArr['refund_status']) && (strval($jsonResArr['refund_status']) === 'SUCCESS'))) {

exit(0);//参数错误,终止程序

}

// 通过退款订单号查询订单

$order = Order::where('out_refund_no',$jsonResArr['out_refund_no'])->find();

if (!$order) {

exit(0);//查询不到相应订单,终止程序

}

// 更新订单状态

if ($order['status'] !== 3) {

// 更新订单状态

trace('微信退款回调,正在更新订单状态');

$order['status'] = 3;

$order['transaction_id'] = $jsonResArr['transaction_id'];

$order['refund_fee'] = round($jsonResArr['refund_fee'] / 100, 2);

$order['refund_time'] = time();

$saveOrder = $order->save();

}

// 给微信返回数据

$xml = '';

$xml .= '' . '' . '';

$xml .= '' . '' . '';

$xml .= '';

return response($xml, 200, [], 'xml');



推荐阅读
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 一、Advice执行顺序二、Advice在同一个Aspect中三、Advice在不同的Aspect中一、Advice执行顺序如果多个Advice和同一个JointPoint连接& ... [详细]
  • 本文详细介绍了如何在 Ubuntu 14.04 系统上搭建仅使用 CPU 的 Caffe 深度学习框架,包括环境准备、依赖安装及编译过程。 ... [详细]
  • 本文详细介绍了在 Red Hat Linux 系统上安装 GCC 4.4.2 的步骤,包括必要的依赖库的安装及常见问题的解决方法。 ... [详细]
  • 如何将955万数据表的17秒SQL查询优化至300毫秒
    本文详细介绍了通过优化SQL查询策略,成功将一张包含955万条记录的财务流水表的查询时间从17秒缩短至300毫秒的方法。文章不仅提供了具体的SQL优化技巧,还深入探讨了背后的数据库原理。 ... [详细]
  • 调试利器SSH隧道
    在开发微信公众号或小程序的时候,由于微信平台规则的限制,部分接口需要通过线上域名才能正常访问。但我们一般都会在本地开发,因为这能快速的看到 ... [详细]
  • 本文详细介绍了 `org.apache.tinkerpop.gremlin.structure.VertexProperty` 类中的 `key()` 方法,并提供了多个实际应用的代码示例。通过这些示例,读者可以更好地理解该方法在图数据库操作中的具体用途。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • CRZ.im:一款极简的网址缩短服务及其安装指南
    本文介绍了一款名为CRZ.im的极简网址缩短服务,该服务采用PHP和SQLite开发,体积小巧,约10KB。本文还提供了详细的安装步骤,包括环境配置、域名解析及Nginx伪静态设置。 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 本文将从基础概念入手,详细探讨SpringMVC框架中DispatcherServlet如何通过HandlerMapping进行请求分发,以及其背后的源码实现细节。 ... [详细]
  • 深入体验Python的高级交互式Shell - IPython
    IPython 是一个增强型的 Python 交互式 Shell,提供了比标准 Python 控制台更为强大的功能,适用于开发和调试过程。它不仅支持直接执行 Linux 命令,还提供了丰富的特性来提高编程效率。 ... [详细]
  • Bootstrap Paginator 分页插件详解与应用
    本文深入探讨了Bootstrap Paginator这款流行的JavaScript分页插件,提供了详细的使用指南和示例代码,旨在帮助开发者更好地理解和利用该工具进行高效的数据展示。 ... [详细]
  • ThinkPHP模板中函数调用的开发技巧与实践 ... [详细]
author-avatar
找唐娃娃_622
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有