<?php
//退款方法-根据退款单号--纯原生,不依赖支付插件
public static function wxAppRefund($refund_no)
{
$refund = OrderAftersales::where('refund_no',$refund_no)->find();
if(empty($refund) || $refund['status'] != 1){
throw new Exception("退款不存在或已处理");
}
$number = $refund['refund'];
$orders = self::where('id',$refund['order_id'])->find();
if(empty($orders)){
throw new Exception("订单不存在");
}
if(($orders['orderstate'] != 4) && ($orders['paystate'] != 1) ){
throw new Exception('订单状态有误');
}
$appid = ''; //微信appid
$mch_key = '';//微信支付key
$mch_id = '';//微信商户id
$config = ['app_id' => $appid,'mch_id' => $mch_id,'mch_key' => $mch_key];
if(!$config || !$config['mch_id'] || !$config['mch_key']){
throw new Exception('请正确配置微信商户信息');
}
$appid = $config['app_id'];
$mch_id = $config['mch_id'];
$key = $config['mch_key'];
// 修复证书路径 - 使用绝对路径
$cert_path = ROOT_PATH . 'public/uploads/apppay/apiclient_cert.pem';
$key_path = ROOT_PATH . 'public/uploads/apppay/apiclient_key.pem';
// 检查证书文件是否存在
if (!file_exists($cert_path)) {
throw new Exception('证书文件不存在: ' . $cert_path);
}
if (!file_exists($key_path)) {
throw new Exception('私钥文件不存在: ' . $key_path);
}
$order_no = $orders['order_sn'];
$nonce_str = md5(uniqid(mt_rand(), true));
$params = [
'appid' => $appid,
'mch_id' => $mch_id,
'nonce_str' => $nonce_str,
'out_trade_no' => $order_no, // 原支付订单号
'out_refund_no' => $refund_no, // 退款单号,需唯一
'total_fee' => intval($orders['payamount'] * 100), // 原订单金额(分)
'refund_fee' => intval($number * 100), // 退款金额(分)
'op_user_id' => $mch_id, // 操作员,默认传商户号
// 'notify_url' => 'https://your.domain/refund_notify', // 如需回调可配置
];
// 生成签名(过滤空值)
$signParams = array_filter($params, function($v){ return $v !== '' && $v !== null; });
ksort($signParams);
$string = urldecode(http_build_query($signParams)) . "&key={$key}";
$params['sign'] = strtoupper(md5($string));
// 转XML
$xml = '<xml>';
foreach ($params as $k => $v) {
$xml .= "<{$k}>{$v}</{$k}>";
}
$xml .= '</xml>';
// 请求微信退款API
$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
$res = self::wx_ssl_post($url, $xml, $cert_path, $key_path);
// 解析返回
$result = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') {
// 退款成功,处理业务逻辑
return true;
} else {
// 退款失败,记录详细错误信息
$error_msg = '退款失败: ';
if (isset($result->err_code)) {
$error_msg .= '错误码: ' . $result->err_code . ', ';
}
if (isset($result->err_code_des)) {
$error_msg .= '错误描述: ' . $result->err_code_des;
}
throw new Exception($error_msg);
}
}
// 带证书的POST请求
public static function wx_ssl_post($url, $data, $cert_path, $key_path)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// 证书设置
curl_setopt($ch, CURLOPT_SSLCERT, $cert_path);
curl_setopt($ch, CURLOPT_SSLKEY, $key_path);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, ''); // 证书密码,如果有的话
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, ''); // 私钥密码,如果有的话
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$res = curl_exec($ch);
$error = curl_errno($ch);
$error_msg = curl_error($ch);
curl_close($ch);
if ($res) {
return $res;
} else {
throw new \Exception('微信退款接口请求失败,CURL错误码:' . $error . ',错误信息:' . $error_msg);
}
}
微信退款代码
于 2025-11-26 17:53:20 首次发布
298

被折叠的 条评论
为什么被折叠?



