431 lines
12 KiB
PHP
431 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\adminapi\logic\order;
|
|
|
|
use app\common\model\Order;
|
|
use app\common\model\OrderDetail;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* 订单业务逻辑
|
|
* Class OrderLogic
|
|
* @package app\adminapi\logic\order
|
|
*/
|
|
class OrderLogic
|
|
{
|
|
/**
|
|
* @notes 生成订单号
|
|
* @return string
|
|
*/
|
|
public static function generateOrderNo(): string
|
|
{
|
|
return 'ORD' . date('YmdHis') . mt_rand(100000, 999999);
|
|
}
|
|
|
|
/**
|
|
* @notes 创建订单
|
|
* @param array $params
|
|
* @return Order|false
|
|
*/
|
|
public static function create(array $params)
|
|
{
|
|
try {
|
|
$order = new Order();
|
|
$order->order_no = self::generateOrderNo();
|
|
$order->patient_id = $params['patient_id'];
|
|
$order->creator_id = $params['creator_id'];
|
|
$order->order_type = $params['order_type'];
|
|
$order->amount = $params['amount'];
|
|
$order->status = 1; // 待支付
|
|
$order->remark = $params['remark'] ?? '';
|
|
$order->save();
|
|
|
|
return $order;
|
|
} catch (\Exception $e) {
|
|
self::setError($e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 编辑订单
|
|
* @param int $id
|
|
* @param array $params
|
|
* @return bool
|
|
*/
|
|
public static function edit(int $id, array $params): bool
|
|
{
|
|
try {
|
|
$order = Order::find($id);
|
|
if (!$order) {
|
|
self::setError('订单不存在');
|
|
return false;
|
|
}
|
|
|
|
if (isset($params['remark'])) {
|
|
$order->remark = $params['remark'];
|
|
}
|
|
|
|
$order->save();
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
self::setError($e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 支付订单
|
|
* @param int $id
|
|
* @param string $paymentMethod
|
|
* @return bool
|
|
*/
|
|
public static function pay(int $id, string $paymentMethod): bool
|
|
{
|
|
try {
|
|
$order = Order::find($id);
|
|
if (!$order) {
|
|
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());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 取消订单
|
|
* @param int $id
|
|
* @return bool
|
|
*/
|
|
public static function cancel(int $id): bool
|
|
{
|
|
try {
|
|
$order = Order::find($id);
|
|
if (!$order) {
|
|
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());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 退款订单
|
|
* @param int $id
|
|
* @return bool
|
|
*/
|
|
public static function refund(int $id): bool
|
|
{
|
|
try {
|
|
$order = Order::find($id);
|
|
if (!$order) {
|
|
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());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 删除订单
|
|
* @param int $id
|
|
* @return bool
|
|
*/
|
|
public static function delete(int $id): bool
|
|
{
|
|
try {
|
|
$order = Order::find($id);
|
|
if (!$order) {
|
|
self::setError('订单不存在');
|
|
return false;
|
|
}
|
|
|
|
// 删除订单
|
|
$order->delete();
|
|
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
self::setError($e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 获取订单详情
|
|
* @param int $id
|
|
* @return array|null
|
|
*/
|
|
public static function detail(int $id): ?array
|
|
{
|
|
$order = Order::with(['patient', 'creator'])
|
|
->find($id);
|
|
|
|
if (!$order) {
|
|
return null;
|
|
}
|
|
|
|
return $order->toArray();
|
|
}
|
|
|
|
private static $error = '';
|
|
|
|
public static function setError(string $error): void
|
|
{
|
|
self::$error = $error;
|
|
}
|
|
|
|
public static function getError(): string
|
|
{
|
|
return self::$error;
|
|
}
|
|
|
|
/**
|
|
* @notes 生成支付宝签名
|
|
* @param array $params
|
|
* @param string $privateKey
|
|
* @return string
|
|
*/
|
|
private static function generateAlipaySign(array $params, string $privateKey): string
|
|
{
|
|
// 移除sign字段
|
|
unset($params['sign']);
|
|
|
|
// 按键排序
|
|
ksort($params);
|
|
|
|
// 构建签名字符串
|
|
$signStr = '';
|
|
foreach ($params as $key => $value) {
|
|
if ($value !== '' && $value !== null) {
|
|
$signStr .= $key . '=' . $value . '&';
|
|
}
|
|
}
|
|
$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);
|
|
}
|
|
|
|
/**
|
|
* @notes 生成微信签名
|
|
* @param array $params
|
|
* @param string $apiKey
|
|
* @return string
|
|
*/
|
|
private static function generateWechatSign(array $params, string $apiKey): string
|
|
{
|
|
// 移除sign字段
|
|
unset($params['sign']);
|
|
|
|
// 按键排序
|
|
ksort($params);
|
|
|
|
// 构建签名字符串
|
|
$signStr = '';
|
|
foreach ($params as $key => $value) {
|
|
if ($value !== '' && $value !== null) {
|
|
$signStr .= $key . '=' . $value . '&';
|
|
}
|
|
}
|
|
$signStr .= 'key=' . $apiKey;
|
|
|
|
// MD5签名
|
|
return strtoupper(md5($signStr));
|
|
}
|
|
|
|
/**
|
|
* @notes 生成随机字符串
|
|
* @param int $length
|
|
* @return string
|
|
*/
|
|
private static function generateNonceStr(int $length = 32): string
|
|
{
|
|
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
$str = '';
|
|
for ($i = 0; $i < $length; $i++) {
|
|
$str .= $chars[mt_rand(0, strlen($chars) - 1)];
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
/**
|
|
* @notes 支付宝支付
|
|
* @param $order
|
|
* @return string|false
|
|
*/
|
|
public static function alipayPay($order)
|
|
{
|
|
try {
|
|
// 这里调用支付宝SDK生成支付链接
|
|
// 示例:生成支付宝支付URL
|
|
$payUrl = self::generateAlipayUrl($order);
|
|
return $payUrl;
|
|
} catch (\Exception $e) {
|
|
self::setError($e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 微信支付
|
|
* @param $order
|
|
* @return array|false
|
|
*/
|
|
public static function wechatPay($order)
|
|
{
|
|
try {
|
|
// 这里调用微信SDK生成支付二维码或链接
|
|
// 示例:生成微信支付数据
|
|
$payData = self::generateWechatPayData($order);
|
|
return $payData;
|
|
} catch (\Exception $e) {
|
|
self::setError($e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 生成支付宝支付URL
|
|
* @param $order
|
|
* @return string
|
|
*/
|
|
private static function generateAlipayUrl($order): string
|
|
{
|
|
try {
|
|
// 获取订单号
|
|
$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'],
|
|
'method' => 'alipay.trade.page.pay',
|
|
'charset' => 'UTF-8',
|
|
'sign_type' => 'RSA2',
|
|
'timestamp' => date('Y-m-d H:i:s'),
|
|
'version' => '1.0',
|
|
'notify_url' => $alipayConfig['notify_url'] ?: config('app.url') . '/api/order/alipay-notify',
|
|
'return_url' => $alipayConfig['return_url'] ?: config('app.url') . '/order',
|
|
'biz_content' => json_encode([
|
|
'out_trade_no' => $orderNo,
|
|
'product_code' => 'FAST_INSTANT_TRADE_PAY',
|
|
'total_amount' => $amount,
|
|
'subject' => '订单支付',
|
|
'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());
|
|
return '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @notes 生成微信支付数据
|
|
* @param $order
|
|
* @return array
|
|
*/
|
|
private static function generateWechatPayData($order): array
|
|
{
|
|
try {
|
|
// 获取订单号
|
|
$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'],
|
|
'mch_id' => $wechatConfig['mch_id'],
|
|
'nonce_str' => self::generateNonceStr(),
|
|
'body' => '订单支付',
|
|
'out_trade_no' => $orderNo,
|
|
'total_fee' => (int)($amount * 100), // 转换为分
|
|
'spbill_create_ip' => request()->ip() ?: '127.0.0.1',
|
|
'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',
|
|
'pay_data' => $payData,
|
|
'order_no' => $orderNo,
|
|
];
|
|
} catch (\Exception $e) {
|
|
self::setError($e->getMessage());
|
|
return [];
|
|
}
|
|
}
|
|
}
|