一、概述

本系列博客将讨论基于微信支付的项目开发中,涉及到的下单与支付、退款、以及订单查询的后端代码实现。在本系列博客中,将以代码片段作为示例,来讨论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 version="1.0" encoding="utf-8"?>';

$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');

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

  1. 微信签名算法验证通过,但微信仍然返回签名错误的解决

    问题描述: 使用springBoot中RestTemplate发送post请求,使用HMAC-SHA256加密方式,通过签名验证工具校验签名通过但是仍然返回签名错误状态提示. 微信提供的签名验证工具: ...

  2. 微信小程序支付返回签名错误_PHP微信小程序支付——签名错误

    先分清几个概念:微信公众平台.微信开放平台.微信商户平台 1.微信公众平台.微信开放平台.微信商户平台是三个不同的平台 2.微信公众平台:用于公众号.小程序等等的设置平台,包括APPID.APPSEC ...

  3. 微信小程序支付返回签名错误_java 微信小程序微信支付统一下订单及数字签名错误问题(后端)...

    今天来分享一下之前做微信小程序微信支付遇到的一些坑,博主这里是微信小程序支付功能,因此选择的微信支付方式是JSAPI支付方式(温馨提示左下角有音乐哦). 首先我们肯定是要在小程序后台绑定一个商户号的, ...

  4. php获取prepay_id时报错,微信支付获取prepay_id返回签名错误,官方demo中的签名方法MD5验证有问题...

    引用官方V3微信支付PHP版的demo做的改动,在获取prepay_id发现总是返回签名错误,经与腾讯官方的"微信公众平台支付接口调试工具"对比发现MD5不一样,找到demo中代码 ...

  5. 微信退款返回58 linux,小程序微信支付申请退款返回cUrl错误,错误码:58

    2019-04-03 15:15:29 如何看待微信公开课小程序热门讨论「小程序微信支付申请退款返回cUrl错误,错误码:58」 摘要:小程序微信支付申请退款返回cUrl错误,错误码:58 展开:调用 ...

  6. 微信小游戏获取用户相关api返回签名错误87009的解决方案

    大家在用微信小游戏经常会通过小程序的appid和secret来获取访问权限,这样就能获取用户的加密串,或者查询用户的记录. 不过微信社区在一些问题上更新并不及时,或者不活跃导致很多用户使用过程中经常遇 ...

  7. 解决公众号开发 安卓正常 iOS调微信SDK失败 签名错误

    项目场景: 公众号网页开发 请求微信授权 调用微信SDK 扫一扫 相机/相册接口 问题描述: 项目在安卓上顺利运行 在iOS 无法调起微信SDK 报错为签名错误 原因分析: 在安卓能跑通 说明后端的签 ...

  8. 微信 android 平台 应用签名错误,IOS微信上Vue单页面应用JSSDK签名失败解决方案

    背景 手机型号: 型号:iphone 7 / iphone xs max 版本:ios 10.3.1 / ios 12.1 微信版本:WeChat 6.7.3 问题还原: Vue应用(vue-rout ...

  9. App微信分享包签名错误和更改

    [本文出处: http://blog.csdn.net/leytton/article/details/63262915] 场景:调试Android应用的微信分享功能,包签名更改后无法分享. 之前看了 ...

最新文章

  1. 【整理】SYSCOMMAND的wParam值的宏定义
  2. 【计算理论】计算复杂性 ( 计算理论内容概览 | 计算问题的有效性 | 时间复杂性度量 | 输入表示 | 时间复杂度 )
  3. JSPatch defineProtocol 实现详解
  4. 线程和进程的对比之优缺点
  5. 应该是最全的算法学习路线了吧法学习路线了吧
  6. spring security原理
  7. 54失败是成功之母二
  8. sql replace 双引号变单引号_sql-汇总、排序以及分析思路
  9. VS2010 C++ 插件 VissualAssistX 安装
  10. java B2B2C 仿淘宝电子商城系统-eureka 基础
  11. (笔记)Linux内核学习(三)之进程调度
  12. centos5安装PHP5时遇到问题
  13. linux模拟进程调度,Linux进程调度模拟3
  14. gprs发送消息给服务器,gprs发送到云服务器
  15. Pam x86_64 and i686 have conflicting man pages
  16. 给自己的django项目配置域名
  17. qq邮箱发html版式是乱的,为什么在Word里编辑的内容到QQ邮箱里发给别人是乱的,我用附件发的呀...
  18. word中使用通配符替换【持续更新系列】
  19. 蓝桥杯 算法训练 合集1 C++
  20. openssh8.3p1 RPM 升级

热门文章

  1. Magento微信跨境支付模块V2.1发布
  2. 海岛奇兵无线无法连接服务器,别被骗了!海岛奇兵bug真没无限兵/无限能量|教程解析仅双倍...
  3. 情人节送什么礼物给男朋友合适?送男朋友最实用的礼物
  4. 网络了解编程五层协议
  5. 复旦发布类ChatGPT模型Moss;Linux 6.2 发布|极客头条
  6. 在VSCode中将Maven项目打包成jar文件
  7. 周鸿祎:互联网的十大启示
  8. upload上传和下载文件
  9. java jframe教程_Java Swing JFrame窗口的实现
  10. Codeforces科学刷题指南