This commit is contained in:
Your Name
2026-04-10 14:43:58 +08:00
parent fdf714f833
commit 4909ec6daa
38 changed files with 6549 additions and 735 deletions
+169 -168
View File
@@ -47,7 +47,7 @@ class OrderLogic
$order->status = 1; // 待支付
$order->remark = $params['remark'] ?? '';
$order->save();
return $order;
} catch (\Exception $e) {
self::setError($e->getMessage());
@@ -102,146 +102,146 @@ class OrderLogic
$cursor = '';
do {
$resp = $service->getBillList($beginTime, $endTime, $payeeUserid, $cursor, 100);
if (($resp['errcode'] ?? -1) !== 0) {
$result['errors'][] = '获取账单失败: ' . ($resp['errmsg'] ?? '未知错误');
break;
}
$billList = $resp['bill_list'] ?? [];
$cursor = $resp['next_cursor'] ?? '';
foreach ($billList as $bill) {
$tradeState = (int)($bill['trade_state'] ?? 0);
// 1:已完成(已支付) 3:已完成有退款 — 见企业微信 get_bill_list 文档
if (!in_array($tradeState, [1, 3], true)) {
$result['skipped']++;
continue;
if (($resp['errcode'] ?? -1) !== 0) {
$result['errors'][] = '获取账单失败: ' . ($resp['errmsg'] ?? '未知错误');
break;
}
$targetStatus = $tradeState === 3 ? 4 : 2; // 4=已退款 2=已支付
$billList = $resp['bill_list'] ?? [];
$cursor = $resp['next_cursor'] ?? '';
$orderNo = (string)($bill['out_trade_no'] ?? $bill['trade_no'] ?? '');
$totalFee = (int)($bill['total_fee'] ?? $bill['total_amount'] ?? 0);
$tradeNo = (string)($bill['transaction_id'] ?? $bill['trade_no'] ?? '');
$payTime = $bill['pay_time'] ?? $bill['time_end'] ?? '';
$billPayeeUserid = (string)($bill['payee_userid'] ?? '');
if (empty($orderNo) || $totalFee <= 0) {
$result['skipped']++;
continue;
}
$amount = round($totalFee / 100, 2);
$orderType = ($amount == 5.00) ? 1 : $defaultOrderType;
$creatorId = 0;
if ($billPayeeUserid) {
$admin = Admin::where('work_wechat_userid', $billPayeeUserid)->whereNull('delete_time')->find();
if ($admin) {
$creatorId = (int)$admin->id;
}
}
$payerExternalUserid = (string)($bill['external_userid'] ?? '');
$paymentTimeStr = $payTime
? (is_numeric($payTime) ? date('Y-m-d H:i:s', (int)$payTime) : (string)$payTime)
: date('Y-m-d H:i:s');
$order = Order::where('order_no', $orderNo)->find();
if ($order) {
$needSave = false;
$currentStatus = (int)$order->status;
if ($currentStatus !== $targetStatus) {
// 待支付:随账单变为已支付或已退款(含未同步到「已支付」即发生退款)
if ($currentStatus === 1) {
$order->status = $targetStatus;
$needSave = true;
} elseif ($currentStatus === 2 && $targetStatus === 4) {
$order->status = 4;
$needSave = true;
} elseif ($currentStatus === 4 && $targetStatus === 2) {
// 账单从「有退款」变回「已完成」等异常纠偏
$order->status = 2;
$needSave = true;
}
// 已取消(3) 不自动改支付状态,避免覆盖后台取消
}
if ($currentStatus === 1 || $targetStatus === 2) {
if ($order->payment_method !== 'wechat') {
$order->payment_method = 'wechat';
$needSave = true;
}
if ($paymentTimeStr !== '' && (string)$order->payment_time !== $paymentTimeStr) {
$order->payment_time = $paymentTimeStr;
$needSave = true;
}
}
if ($tradeNo !== '' && (string)$order->trade_no !== $tradeNo) {
$order->trade_no = $tradeNo;
$needSave = true;
}
if (abs((float)$order->amount - $amount) > 0.000001) {
$order->amount = $amount;
$needSave = true;
}
$defaultCreatorIdInt = (int)$defaultCreatorId;
if ($billPayeeUserid && $creatorId !== $defaultCreatorIdInt && (int)$order->creator_id === $defaultCreatorIdInt) {
$order->payee_userid = $billPayeeUserid;
$order->payer_external_userid = $payerExternalUserid;
$order->creator_id = $creatorId;
$needSave = true;
} elseif ($billPayeeUserid !== '' && (string)$order->payee_userid !== $billPayeeUserid) {
$order->payee_userid = $billPayeeUserid;
$needSave = true;
}
if ($payerExternalUserid !== '' && (string)$order->payer_external_userid !== $payerExternalUserid) {
$order->payer_external_userid = $payerExternalUserid;
$needSave = true;
}
if ($amount == 5.00 && (int)$order->order_type !== 1) {
$order->order_type = 1;
$needSave = true;
}
if ($needSave) {
$order->save();
$result['updated']++;
} else {
foreach ($billList as $bill) {
$tradeState = (int)($bill['trade_state'] ?? 0);
// 1:已完成(已支付) 3:已完成有退款 — 见企业微信 get_bill_list 文档
if (!in_array($tradeState, [1, 3], true)) {
$result['skipped']++;
continue;
}
} else {
try {
$order = new Order();
$order->order_no = $orderNo;
$order->patient_id = null;
$order->creator_id = $creatorId;
$order->order_type = $orderType;
$order->amount = $amount;
$order->status = $targetStatus;
$order->payment_method = 'wechat';
$order->payment_time = $paymentTimeStr;
$order->trade_no = $tradeNo;
$remark = '企业微信直接收款同步,待关联患者';
if ($tradeState === 3) {
$refundCent = (int)($bill['total_refund_fee'] ?? 0);
if ($refundCent > 0) {
$remark .= '(账单含退款' . round($refundCent / 100, 2) . '元)';
$targetStatus = $tradeState === 3 ? 4 : 2; // 4=已退款 2=已支付
$orderNo = (string)($bill['out_trade_no'] ?? $bill['trade_no'] ?? '');
$totalFee = (int)($bill['total_fee'] ?? $bill['total_amount'] ?? 0);
$tradeNo = (string)($bill['transaction_id'] ?? $bill['trade_no'] ?? '');
$payTime = $bill['pay_time'] ?? $bill['time_end'] ?? '';
$billPayeeUserid = (string)($bill['payee_userid'] ?? '');
if (empty($orderNo) || $totalFee <= 0) {
$result['skipped']++;
continue;
}
$amount = round($totalFee / 100, 2);
$orderType = ($amount == 5.00) ? 1 : $defaultOrderType;
$creatorId = 0;
if ($billPayeeUserid) {
$admin = Admin::where('work_wechat_userid', $billPayeeUserid)->whereNull('delete_time')->find();
if ($admin) {
$creatorId = (int)$admin->id;
}
}
$payerExternalUserid = (string)($bill['external_userid'] ?? '');
$paymentTimeStr = $payTime
? (is_numeric($payTime) ? date('Y-m-d H:i:s', (int)$payTime) : (string)$payTime)
: date('Y-m-d H:i:s');
$order = Order::where('order_no', $orderNo)->find();
if ($order) {
$needSave = false;
$currentStatus = (int)$order->status;
if ($currentStatus !== $targetStatus) {
// 待支付:随账单变为已支付或已退款(含未同步到「已支付」即发生退款)
if ($currentStatus === 1) {
$order->status = $targetStatus;
$needSave = true;
} elseif ($currentStatus === 2 && $targetStatus === 4) {
$order->status = 4;
$needSave = true;
} elseif ($currentStatus === 4 && $targetStatus === 2) {
// 账单从「有退款」变回「已完成」等异常纠偏
$order->status = 2;
$needSave = true;
}
// 已取消(3) 不自动改支付状态,避免覆盖后台取消
}
if ($currentStatus === 1 || $targetStatus === 2) {
if ($order->payment_method !== 'wechat') {
$order->payment_method = 'wechat';
$needSave = true;
}
if ($paymentTimeStr !== '' && (string)$order->payment_time !== $paymentTimeStr) {
$order->payment_time = $paymentTimeStr;
$needSave = true;
}
}
$order->remark = $remark;
$order->payee_userid = $billPayeeUserid;
$order->payer_external_userid = $payerExternalUserid;
$order->save();
$result['created']++;
} catch (\Exception $e) {
$result['errors'][] = "订单 {$orderNo}: " . $e->getMessage();
Log::error("企业微信账单同步创建订单失败: {$orderNo}, " . $e->getMessage());
if ($tradeNo !== '' && (string)$order->trade_no !== $tradeNo) {
$order->trade_no = $tradeNo;
$needSave = true;
}
if (abs((float)$order->amount - $amount) > 0.000001) {
$order->amount = $amount;
$needSave = true;
}
$defaultCreatorIdInt = (int)$defaultCreatorId;
if ($billPayeeUserid && $creatorId !== $defaultCreatorIdInt && (int)$order->creator_id === $defaultCreatorIdInt) {
$order->payee_userid = $billPayeeUserid;
$order->payer_external_userid = $payerExternalUserid;
$order->creator_id = $creatorId;
$needSave = true;
} elseif ($billPayeeUserid !== '' && (string)$order->payee_userid !== $billPayeeUserid) {
$order->payee_userid = $billPayeeUserid;
$needSave = true;
}
if ($payerExternalUserid !== '' && (string)$order->payer_external_userid !== $payerExternalUserid) {
$order->payer_external_userid = $payerExternalUserid;
$needSave = true;
}
if ($amount == 5.00 && (int)$order->order_type !== 1) {
$order->order_type = 1;
$needSave = true;
}
if ($needSave) {
$order->save();
$result['updated']++;
} else {
$result['skipped']++;
}
} else {
try {
$order = new Order();
$order->order_no = $orderNo;
$order->patient_id = null;
$order->creator_id = $creatorId;
$order->order_type = $orderType;
$order->amount = $amount;
$order->status = $targetStatus;
$order->payment_method = 'wechat';
$order->payment_time = $paymentTimeStr;
$order->trade_no = $tradeNo;
$remark = '企业微信直接收款同步,待关联患者';
if ($tradeState === 3) {
$refundCent = (int)($bill['total_refund_fee'] ?? 0);
if ($refundCent > 0) {
$remark .= '(账单含退款' . round($refundCent / 100, 2) . '元)';
}
}
$order->remark = $remark;
$order->payee_userid = $billPayeeUserid;
$order->payer_external_userid = $payerExternalUserid;
$order->save();
$result['created']++;
} catch (\Exception $e) {
$result['errors'][] = "订单 {$orderNo}: " . $e->getMessage();
Log::error("企业微信账单同步创建订单失败: {$orderNo}, " . $e->getMessage());
}
}
}
}
} while ($cursor);
}
@@ -295,7 +295,7 @@ class OrderLogic
self::setError('订单不存在');
return false;
}
if (isset($params['remark'])) {
$order->remark = $params['remark'];
}
@@ -307,7 +307,7 @@ class OrderLogic
if (isset($params['order_type'])) {
$order->order_type = (int)$params['order_type'];
}
$order->save();
return true;
} catch (\Exception $e) {
@@ -330,17 +330,17 @@ class OrderLogic
self::setError('订单不存在');
return false;
}
if ($order->status != 1) {
self::setError('订单状态不允许支付');
return false;
}
$order->status = 2; // 已支付
$order->payment_method = $paymentMethod;
$order->payment_time = date('Y-m-d H:i:s');
$order->save();
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
@@ -361,15 +361,15 @@ class OrderLogic
self::setError('订单不存在');
return false;
}
if ($order->status != 1) {
self::setError('只有待支付的订单才能取消');
return false;
}
$order->status = 3; // 已取消
$order->save();
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
@@ -390,15 +390,15 @@ class OrderLogic
self::setError('订单不存在');
return false;
}
if ($order->status != 2) {
self::setError('只有已支付的订单才能退款');
return false;
}
$order->status = 4; // 已退款
$order->save();
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
@@ -419,10 +419,10 @@ class OrderLogic
self::setError('订单不存在');
return false;
}
// 删除订单
$order->delete();
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
@@ -466,11 +466,11 @@ class OrderLogic
{
$order = Order::with(['patient', 'creator'])
->find($id);
if (!$order) {
return null;
}
return $order->toArray();
}
@@ -496,10 +496,10 @@ class OrderLogic
{
// 移除sign字段
unset($params['sign']);
// 按键排序
ksort($params);
// 构建签名字符串
$signStr = '';
foreach ($params as $key => $value) {
@@ -508,12 +508,12 @@ class OrderLogic
}
}
$signStr = rtrim($signStr, '&');
// 使用私钥签名
$privateKeyResource = openssl_pkey_get_private($privateKey);
openssl_sign($signStr, $sign, $privateKeyResource, OPENSSL_ALGO_SHA256);
openssl_free_key($privateKeyResource);
return base64_encode($sign);
}
@@ -527,10 +527,10 @@ class OrderLogic
{
// 移除sign字段
unset($params['sign']);
// 按键排序
ksort($params);
// 构建签名字符串
$signStr = '';
foreach ($params as $key => $value) {
@@ -539,7 +539,7 @@ class OrderLogic
}
}
$signStr .= 'key=' . $apiKey;
// MD5签名
return strtoupper(md5($signStr));
}
@@ -606,14 +606,14 @@ class OrderLogic
// 获取订单号
$orderNo = is_array($order) ? $order['order_no'] : $order->order_no;
$amount = is_array($order) ? ($order['amount'] ?? 0) : $order->amount;
// 获取支付宝配置
$alipayConfig = config('pay.alipay');
if (empty($alipayConfig['app_id']) || empty($alipayConfig['merchant_private_key'])) {
throw new \Exception('支付宝配置不完整');
}
// 使用支付宝SDK生成支付URL
$params = [
'app_id' => $alipayConfig['app_id'],
@@ -632,14 +632,14 @@ class OrderLogic
'body' => '订单号:' . $orderNo,
], JSON_UNESCAPED_UNICODE),
];
// 生成签名
$sign = self::generateAlipaySign($params, $alipayConfig['merchant_private_key']);
$params['sign'] = $sign;
// 生成支付URL
$payUrl = $alipayConfig['gateway_url'] . '?' . http_build_query($params);
return $payUrl;
} catch (\Exception $e) {
self::setError($e->getMessage());
@@ -658,14 +658,14 @@ class OrderLogic
// 获取订单号
$orderNo = is_array($order) ? $order['order_no'] : $order->order_no;
$amount = is_array($order) ? ($order['amount'] ?? 0) : $order->amount;
// 获取微信配置
$wechatConfig = config('pay.wechat');
if (empty($wechatConfig['app_id']) || empty($wechatConfig['mch_id']) || empty($wechatConfig['api_key'])) {
throw new \Exception('微信支付配置不完整');
}
// 生成微信支付数据
$payData = [
'appid' => $wechatConfig['app_id'],
@@ -678,11 +678,11 @@ class OrderLogic
'notify_url' => $wechatConfig['notify_url'] ?: config('app.url') . '/api/order/wechat-notify',
'trade_type' => 'NATIVE', // 二维码支付
];
// 生成签名
$sign = self::generateWechatSign($payData, $wechatConfig['api_key']);
$payData['sign'] = $sign;
// 返回支付数据
return [
'pay_url' => $wechatConfig['gateway_url'] . '/pay/unifiedorder',
@@ -918,7 +918,7 @@ class OrderLogic
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
return true;
}
$supervisorRoles = [0, 3];
$supervisorRoles = config('project.order_edit_all_roles', [0, 3]);
$myRoles = array_map('intval', $adminInfo['role_id'] ?? []);
return count(array_intersect($myRoles, $supervisorRoles)) > 0;
@@ -985,6 +985,7 @@ class OrderLogic
if ($busy && ! $allowed) {
continue;
}
$out[] = $row;
}
@@ -998,7 +999,7 @@ class OrderLogic
*/
public static function assertPayOrdersLinkable(array $ids, int $diagnosisId, int $adminId, array $adminInfo): ?string
{
$ids = array_values(array_unique(array_filter(array_map('intval', $ids), static fn (int $v): bool => $v > 0)));
$ids = array_values(array_unique(array_filter(array_map('intval', $ids), static fn(int $v): bool => $v > 0)));
if ($diagnosisId <= 0) {
return '诊单无效';
}