代码提交优化

This commit is contained in:
wong
2025-11-03 14:06:58 +08:00
parent e3afa24795
commit 367a76a54f
9 changed files with 444 additions and 64 deletions

View File

@@ -16,38 +16,74 @@ use app\common\model\Order;
class PaymentService
{
/**
* 下单
* 统一支付下单接口
* 支持扫码付款、微信支付、支付宝支付
*
* @param array $order
* - out_trade_no: string 商户订单号(必填)
* - total_fee: int 金额(分,必填)
* - body: string 商品描述(必填)
* - notify_url: string 异步通知地址(可覆盖配置
* - attach: string 附加数据(可选)
* - time_expire: string 订单失效时间(可选)
* - client_ip: string 终端IP可选
* - sign_type: string MD5/RSA_1_256/RSA_1_1可选默认MD5
* - pay_type: string 支付场景,如 JSAPI/APP/H5可选)
* @return array
* @throws \Exception
* - orderNo: string 商户订单号(必填)
* - money: int 金额(分,必填)
* - goodsName: string 商品描述(必填)
* - service: string 支付服务类型(可选
* - 'wechat' 或 'pay.weixin.jspay': 微信JSAPI支付
* - 'alipay' 或 'pay.alipay.jspay': 支付宝JSAPI支付
* - 不传或空: 默认扫码付款
* - openid: string 微信用户openid微信JSAPI支付必填
* - buyer_id: string 支付宝用户ID支付宝JSAPI支付可选)
* - notify_url: string 异步通知地址(可选)
* @return string JSON格式响应
*/
public function createOrder(array $order)
{
// 确定service类型支持简写形式 wechat/alipay或完整的 service 值
$serviceType = $order['service'] ?? '';
// 映射简写形式到完整的 service 值
if ($serviceType === 'wechat' || $serviceType === 'pay.weixin.jspay') {
$service = 'pay.weixin.jspay';
} elseif ($serviceType === 'alipay' || $serviceType === 'pay.alipay.jspay') {
$service = 'pay.alipay.jspay';
} elseif ($serviceType === 'qrCode' || $serviceType === 'unified.trade.native') {
$service = 'unified.trade.native';
} else {
// 默认扫码支付
$service = 'unified.trade.native';
}
// 构建基础参数
$params = [
'service' => 'unified.trade.native',
'service' => $service,
'sign_type' => PaymentUtil::SIGN_TYPE_MD5,
'mch_id' => Env::get('payment.mchId'),
'out_trade_no' => $order['orderNo'],
'body' => $order['goodsName'] ?? '',
'total_fee' => $order['money'] ?? 0,
'mch_create_ip' => Request::ip(),
'notify_url' => Env::get('payment.notify_url', '127.0.0.1'),
'notify_url' => $order['notify_url'] ?? Env::get('payment.notify_url', '127.0.0.1'),
'nonce_str' => PaymentUtil::generateNonceStr(),
];
$ddd = new GetOpenid();
$ddd->index();
exit_data(1111);
// 微信JSAPI支付需要openid
if ($service == 'pay.weixin.jspay') {
// $params['sub_openid'] = 'oB44Yw1T6bfVAZwjj729P-6CUSPE';
$params['is_raw'] = 0;
$params['mch_app_name'] = '存客宝';
$params['mch_app_id'] = 'https://kr-op.quwanzhi.com';
}
// 支付宝JSAPI支付需要buyer_id可选
if ($service == 'pay.alipay.jspay') {
$params['is_raw'] = 0;
$params['quit_url'] = $params['notify_url'];
$params['buyer_id'] = '';
}
Db::startTrans();
try {
// 过滤空值签名
// 签名
$secret = Env::get('payment.key');
$params['sign_type'] = 'MD5';
$params['sign'] = PaymentUtil::generateSign($params, $secret, 'MD5');
@@ -57,7 +93,7 @@ class PaymentService
throw new \Exception('支付网关地址未配置');
}
//创建订单
// 创建订单
Order::create([
'mchId' => $params['mch_id'],
'companyId' => isset($order['companyId']) ? $order['companyId'] : 0,
@@ -73,17 +109,43 @@ class PaymentService
'nonceStr' => isset($order['nonceStr']) ? $order['nonceStr'] : '',
'createTime' => time(),
]);
// XML POST 请求
$xmlBody = $this->arrayToXml($params);
$response = $this->postXml($url, $xmlBody);
$parsed = $this->parseXmlOrRaw($response);
exit_data($parsed);
if ($parsed['status'] == 0 && $parsed['result_code'] == 0) {
Db::commit();
return json_encode(['code' => 200, 'msg' => '订单创建成功', 'data' => $parsed['code_img_url']]);
// 根据service类型返回不同的数据格式仅返回接口文档中的字段
$responseData = null;
if ($service == 'unified.trade.native') {
// 扫码支付返回二维码URL
$responseData = $parsed['code_img_url'] ?? '';
} elseif ($service == 'pay.weixin.jspay') {
// 微信JSAPI支付返回支付参数仅返回接口文档中存在的字段
$responseData = [];
if (isset($parsed['appid'])) $responseData['appid'] = $parsed['appid'];
if (isset($parsed['time_stamp'])) $responseData['time_stamp'] = $parsed['time_stamp'];
if (isset($parsed['nonce_str'])) $responseData['nonce_str'] = $parsed['nonce_str'];
if (isset($parsed['package'])) $responseData['package'] = $parsed['package'];
if (isset($parsed['sign_type'])) $responseData['sign_type'] = $parsed['sign_type'];
if (isset($parsed['pay_sign'])) $responseData['pay_sign'] = $parsed['pay_sign'];
} elseif ($service == 'pay.alipay.jspay') {
// 支付宝JSAPI支付返回订单信息仅返回接口文档中存在的字段
$responseData = [];
if (isset($parsed['order_info'])) $responseData['order_info'] = $parsed['order_info'];
if (isset($parsed['order_string'])) $responseData['order_string'] = $parsed['order_string'];
}
return json_encode(['code' => 200, 'msg' => '订单创建成功', 'data' => $responseData]);
} else {
Db::rollback();
return json_encode(['code' => 500, 'msg' => '订单创建失败:' . $parsed['err_msg']]);
return json_encode(['code' => 500, 'msg' => '订单创建失败:' . ($parsed['err_msg'] ?? '未知错误')]);
}
} catch (\Exception $e) {
@@ -194,54 +256,104 @@ class PaymentService
/**
* 支付结果异步通知
* - 威富通回调为 XML需校验签名与业务字段并更新订单
* - 回应:成功回"success",失败回"fail"
* @return void
* - 支持扫码付款、微信支付、支付宝支付的通知
* - 回应成功返回XML格式SUCCESS失败返回XML格式FAIL
* @return string XML响应
*/
public function notify()
{
$rawBody = file_get_contents('php://input');
$payload = $this->parseXmlOrRaw($rawBody);
if (!is_array($payload) || empty($payload)) {
return json_encode(['code' => 500, 'msg' => 'XML解析错误']);
\think\facade\Log::error('支付通知XML解析错误', ['rawBody' => $rawBody]);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[XML解析错误]]></return_msg></xml>';
}
// 验证签名
$secret = Env::get('payment.key');
if (!empty($secret) && isset($payload['sign'])) {
$signType = $payload['sign_type'] ?? 'MD5';
if (!PaymentUtil::verifySign($payload, $secret, $signType)) {
\think\facade\Log::error('支付通知:签名验证失败', ['payload' => $payload]);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名验证失败]]></return_msg></xml>';
}
}
if ($payload['status'] != 0 || $payload['result_code'] != 0) {
$errMsg = (isset($payload['err_msg']) ? $payload['err_msg'] : isset($payload['err_msg'])) ? $payload['err_msg'] : '未知错误';
return json_encode(['code' => 500, 'msg' => $errMsg]);
// 检查通信状态
if (isset($payload['status']) && $payload['status'] != 0) {
$errMsg = $payload['err_msg'] ?? '通信失败';
\think\facade\Log::error('支付通知:通信失败', ['payload' => $payload]);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[' . $errMsg . ']]></return_msg></xml>';
}
// 检查业务结果
if (isset($payload['result_code']) && $payload['result_code'] != 0) {
$errMsg = $payload['err_msg'] ?? '业务处理失败';
\think\facade\Log::error('支付通知:业务处理失败', ['payload' => $payload]);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[' . $errMsg . ']]></return_msg></xml>';
}
// 业务处理:更新订单
Db::startTrans();
try {
$outTradeNo = $payload['out_trade_no'];
$pay_result = $payload['pay_result'];
$time_end = $payload['time_end'];
$outTradeNo = $payload['out_trade_no'] ?? '';
$pay_result = $payload['pay_result'] ?? 0;
$time_end = $payload['time_end'] ?? '';
if (empty($outTradeNo)) {
Db::rollback();
\think\facade\Log::error('支付通知:订单号为空', ['payload' => $payload]);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[订单号为空]]></return_msg></xml>';
}
$order = Order::where('orderNo', $outTradeNo)->find();
if (!$order) {
Db::rollback();
return json_encode(['code' => 500, 'msg' => '该订单不存在']);
\think\facade\Log::error('支付通知:订单不存在', ['out_trade_no' => $outTradeNo]);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[订单不存在]]></return_msg></xml>';
}
// 如果订单已支付,直接返回成功(防止重复处理)
if ($order->status == 1) {
Db::rollback();
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
}
if ($pay_result != 0) {
$order->payInfo = $payload['pay_info'];
$order->payInfo = $payload['pay_info'] ?? '支付失败';
$order->status = 3;
$order->save();
Db::commit();
return json_encode(['code' => 500, 'msg' => $payload['pay_info']]);
\think\facade\Log::error('支付通知:支付失败', ['orderNo' => $outTradeNo, 'pay_info' => $payload['pay_info'] ?? '']);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[' . ($payload['pay_info'] ?? '支付失败') . ']]></return_msg></xml>';
}
$order->payType = $payload['trade_type'] == 'pay.wechat.jspay' ? 1 : 2;
// 根据trade_type判断支付方式
$tradeType = $payload['trade_type'] ?? '';
if (strpos($tradeType, 'wechat') !== false || strpos($tradeType, 'weixin') !== false) {
$order->payType = 1; // 微信支付
} elseif (strpos($tradeType, 'alipay') !== false) {
$order->payType = 2; // 支付宝支付
} else {
// 默认根据原有逻辑判断
$order->payType = $tradeType == 'pay.wechat.jspay' ? 1 : 2;
}
$order->status = 1;
$order->payTime = $this->parsePayTime($time_end);
$order->transactionId = $payload['transaction_id'] ?? '';
$order->save();
//订单处理
$this->processOrder($order);
Db::commit();
return json_encode(['code' => 200, 'msg' => '付款成功']);
// 返回成功响应XML格式
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
} catch (\Exception $e) {
Db::rollback();
return json_encode(['code' => 500, 'msg' => '付款失败' . $e->getMessage()]);
\think\facade\Log::error('支付通知:处理异常', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
return '<?xml version="1.0" encoding="UTF-8"?><xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理异常]]></return_msg></xml>';
}
}
@@ -359,12 +471,12 @@ class PaymentService
//订单处理
$this->processOrder($order);
Db::commit();
return json_encode(['code' => 200, 'msg' => '支付成功'] );
return json_encode(['code' => 200, 'msg' => '支付成功']);
} catch (\Exception $e) {
Db::rollback();
return json_encode(['code' => 500, 'msg' => '付款失败' . $e->getMessage()]);
}
}else{
} else {
$order = Order::where('orderNo', $resp['out_trade_no'])->lock(true)->find();
if ($order) {
$order->status = 3;
@@ -373,8 +485,8 @@ class PaymentService
}
return json_encode(['code' => 500, 'msg' => '支付失败', 'data' => $resp]);
}
}else{
} else {
return json_encode(['code' => 500, 'msg' => '通信失败']);
}
}
@@ -413,7 +525,7 @@ class PaymentService
$record->form = 5;
$record->wechatAccountId = 0;
$record->friendIdOrGroupId = 0;
$record->remarks = '购买算力【'.$goodsSpecs['name'].'】';
$record->remarks = '购买算力【' . $goodsSpecs['name'] . '】';
$record->tokens = $goodsSpecs['tokens'];
$record->balanceTokens = $newTokens;
$record->createTime = time();
@@ -423,4 +535,5 @@ class PaymentService
return true;
}
}