php 微信支付-退款(支付金额原路退回)
封面图
•
2025-10-25
•
PHP
308
0
0
0
在 PHP 中实现 **微信支付的退款功能(原路退回)**,需要使用 **微信支付 API 的退款接口**。以下是实现该功能的基本步骤和代码示例。 --- ## ✅ 一、前提条件 1. **商户号(MCHID)** 2. **API 密钥(API Key)** 3. **证书文件(apiclient_cert.pem 和 apiclient_key.pem)** 4. **已开通微信退款权限** 5. **订单号(out_trade_no)或交易单号(transaction_id)** --- ## ✅ 二、退款流程概述 1. **调用微信退款接口(`https://api.mch.weixin.qq.com/secapi/pay/refund`)** 2. **发送请求参数(如:商户订单号、退款金额、退款原因等)** 3. **处理返回结果(成功/失败)** --- ## ✅ 三、PHP 实现代码示例 ```php <?php // 微信退款配置 $merchantId = '你的商户号'; // MCHID $apiKey = '你的API密钥'; // API KEY $certPath = __DIR__ . '/apiclient_cert.pem'; // 证书路径 $keyPath = __DIR__ . '/apiclient_key.pem'; // 私钥路径 // 请求参数 $outTradeNo = '商户订单号'; // 商户订单号 $transactionId = '微信交易号'; // 可选,若无可用out_trade_no则用此 $refundAmount = 100; // 退款金额,单位:分 $totalAmount = 100; // 原订单总金额,单位:分 $nonceStr = md5(time() . mt_rand(1000, 9999)); // 随机字符串 // 构造请求参数 $data = array( 'appid' => '你的AppID', // 应用ID 'mch_id' => $merchantId, 'nonce_str' => $nonceStr, 'out_trade_no' => $outTradeNo, 'out_refund_no' => '退款订单号', // 退款单号(可自定义) 'total_fee' => $totalAmount, 'refund_fee' => $refundAmount, 'op_user_id' => $merchantId, // 操作员ID(一般为商户号) ); // 签名 ksort($data); $stringToSign = ''; foreach ($data as $k => $v) { $stringToSign .= $k . '=' . $v . '&'; } $stringToSign .= 'key=' . $apiKey; $sign = strtoupper(md5($stringToSign)); $data['sign'] = $sign; // 将数组转为 XML 格式 $xmlData = '<xml>'; foreach ($data as $k => $v) { $xmlData .= "<$k><![CDATA[$v]]></$k>"; } $xmlData .= '</xml>'; // 发送请求 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://api.mch.weixin.qq.com/secapi/pay/refund'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 验证证书 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 验证域名 curl_setopt($ch, CURLOPT_SSLCERT, $certPath); // 证书路径 curl_setopt($ch, CURLOPT_SSLKEY, $keyPath); // 私钥路径 curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $apiKey); // 私钥密码(通常与API密钥一致) $response = curl_exec($ch); curl_close($ch); // 处理响应 $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA); if ((string)$xml->return_code == 'SUCCESS') { if ((string)$xml->result_code == 'SUCCESS') { echo '退款成功!'; // 可以在这里更新数据库状态 } else { echo '退款失败:' . (string)$xml->err_code_des; } } else { echo '请求失败:' . (string)$xml->return_msg; } ``` --- ## ✅ 四、注意事项 - **证书文件必须正确**:`apiclient_cert.pem` 是微信提供的证书,`apiclient_key.pem` 是私钥。 - **签名方式**:使用 MD5 + API Key 进行签名。 - **退款金额不能超过原订单金额**。 - **退款只能针对已支付成功的订单**。 - **退款后需等待一段时间才能再次退款**(部分场景下)。 --- ## ✅ 五、常见错误及解决方法 | 错误码 | 描述 | 解决方法 | |--------|------|----------| | `ORDERNOTEXIST` | 订单不存在 | 检查 `out_trade_no` 或 `transaction_id` 是否正确 | | `NOAUTH` | 接口权限不足 | 检查是否开通了退款权限 | | `SIGNERROR` | 签名错误 | 检查签名算法是否正确 | | `SYSTEMERROR` | 微信系统错误 | 稍后再试 | --- ## ✅ 六、推荐工具 - 使用 [WeChatPay](https://github.com/wechatpay-apiv3/wechatpay-php) 官方 SDK(更安全、更规范) - 或者使用第三方封装好的类库(如:[Laravel WeChat](https://github.com/overtrue/wechat)) --- 如果你使用的是 Laravel 框架,我也可以提供基于 Laravel 的实现方案。 是否需要我帮你写一个 Laravel 版本的退款代码?
上一篇:
java后台调用接口及处理跨域问题的方法是什么
标题录入,一次不能超过6条
返回顶部
留言
留言
评论