From 83f68eae3f0d95ed6c4b86f6eb6a6666d12b9da4 Mon Sep 17 00:00:00 2001 From: haoyuntao Date: Thu, 18 Jul 2024 18:11:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/controller/Retail.php | 160 ++-------- app/api/model/Retail.php | 83 +++++- app/api/model/user/Retail.php | 20 ++ app/api/model/user/RetailOrder.php | 121 ++++++++ app/api/service/Retail.php | 142 +++++++++ app/api/service/Retail/PaySuccess.php | 409 ++++++++++++++++++++++++++ app/api/service/Retail/Payment.php | 344 ++++++++++++++++++++++ app/common/model/Retail.php | 15 + 8 files changed, 1164 insertions(+), 130 deletions(-) create mode 100644 app/api/model/user/Retail.php create mode 100644 app/api/model/user/RetailOrder.php create mode 100644 app/api/service/Retail.php create mode 100644 app/api/service/Retail/PaySuccess.php create mode 100644 app/api/service/Retail/Payment.php diff --git a/app/api/controller/Retail.php b/app/api/controller/Retail.php index c7c1eb8d..5503a1da 100644 --- a/app/api/controller/Retail.php +++ b/app/api/controller/Retail.php @@ -50,140 +50,42 @@ class Retail extends Controller /** - * 购买会员 + * 获取零售批发会员列表 + * @param int $retailType * @return Json */ - public function purchase(): Json - { $model = new RetailModel(); - $date = $this->request->post(); - // print_r($date); - // exit; - // $detail = $model->where('retail_price_id',$date['retail_price_id'])->where('retail_status',10)->find(); - $detail = $model::detail($date); - if(empty($detail)){ - return $this->renderError("该会员不存在"); + public function retailPayList(): Json + { + $client = $this->request->post(); + if (!$client['client']) { + return $this->renderError('客户端不能为空'); } - $data = [ - 'user_id'=>$this->user['user_id'], - 'retail_order_number'=>$date['num'], + $model =new \app\api\model\user\Retail(); + $list = $model->userCenter($client); - ]; - print_r($this->user['user_id']); - return $this->renderSuccess(compact('pk')); + return $this->renderSuccess(compact('list')); } - - // /** - // * 订单提交 - // * @param string $mode - // * @return Json - // * @throws \think\db\exception\DataNotFoundException - // * @throws \think\db\exception\DbException - // * @throws \think\db\exception\ModelNotFoundException - // * @throws \cores\exception\BaseException - // */ - // public function submit(string $mode = 'buyNow'): Json - // { - // return $this->order($mode); - // } - - // public function order(string $mode = 'buyNow'): Json - // { - // if ($mode === 'buyNow') { - // return $this->buyNow(); - // // } elseif ($mode === 'cart') { - // // return $this->cart(); - // } - // return $this->renderError('结算模式不合法'); - // } - - // /** - // * 订单确认-立即购买 - // * @return Json - // * @throws \think\db\exception\DataNotFoundException - // * @throws \think\db\exception\DbException - // * @throws \think\db\exception\ModelNotFoundException - // * @throws \cores\exception\BaseException - // */ - // private function buyNow(): Json - // { - // // 实例化结算台服务 - // $Checkout = new CheckoutService; - // // 订单结算api参数 - // $params = $Checkout->setParam($this->getParam([ - // 'goodsId' => 0, - // 'goodsSkuId' => '', - // 'goodsNum' => 0, - // ])); - // // print_r($params); - // // 表单验证 - // if (!$this->getValidate()->scene('buyNow')->check($params)) { - // return $this->renderError($this->getValidate()->getError(), ['isCreated' => false]); - // } - // // 立即购买:获取订单商品列表 - // $model = new RetailOrderModel; - // $goodsList = $model->getOrderGoodsListByNow( - // (int)$params['goodsId'], - // (string)$params['goodsSkuId'], - // (int)$params['goodsNum'] - // ); - // $merchantId = 0; - - // foreach ($goodsList as $g) { - // $merchantId = $g['merchant_id']; - // } - // // 获取订单确认信息 - // $orderInfo = $Checkout->onCheckout($goodsList); - // // echo "
";
-    //     // print_r($orderInfo['goodsList']->toArray());
-    //     // exit;
-    //    // print_r($this->request->isGet());
-    //     if ($this->request->isGet()) {
-    //         return $this->renderSuccess([
-    //             'order' => $orderInfo,
-    //             'personal' => $Checkout->getPersonal(),
-    //             'setting' => $Checkout->getSetting(),
-    //         ]);
-    //     }
-    //     // 验证订单是否存在错误
-    //     if ($Checkout->hasError()) {
-    //         return $this->renderError($Checkout->getError(), ['isCreated' => false]);
-    //     }
-    //     // 创建订单 增加订单
-    //     $orderInfo['merchantId'] = $merchantId; 
-    //     if ($merchantId) {
-    //         $model = \app\store\model\Merchant::detail($merchantId, $this->storeId);
-    //         $orderInfo['commission_ratio'] = $model['commission_ratio'];
-    //     }
-    //     //print_r($orderInfo);die;
-    //     if (!$Checkout->createOrder($orderInfo)) {
-    //         return $this->renderError($Checkout->getError() ?: '订单创建失败', ['isCreated' => false]);
-    //     }
-    //     // 返回状态
-    //     return $this->renderSuccess(['orderId' => $Checkout->model['order_id']], '订单创建成功');
-    // }
-
-    //     /**
-    //  * 获取结算台验证器
-    //  * @return CheckoutValidate
-    //  */
-    // private function getValidate(): CheckoutValidate
-    // {
-    //     if (is_null($this->validate)) {
-    //         $this->validate = new CheckoutValidate;
-    //     }
-    //     return $this->validate;
-    // }
-
-    //     /**
-    //  * 订单结算提交的参数
-    //  * @param array $define
-    //  * @return array
-    //  */
-    // private function getParam(array $define = []): array
-    // {
-    //     return array_merge($define, $this->request->param());
-    // }
-
+    public function submit(): Json
+    {
+        $method = $this->request->post('method');
+        if (!$method) {
+            return $this->renderError('支付方式不能为空');
+        }
+        $client = $this->request->post('client');
+        if (!$client) {
+            return $this->renderError('客户端不能为空');
+        }
+        $retailPriceId = intval($this->request->post('retail_price_id'));
+        if (!$retailPriceId) {
+            return $this->renderError('缺少必要参数');
+        }
+        $service = new \app\api\service\Retail();
+        $data = $service->setMethod($method)
+            ->setClient($client)
+            ->orderPay($retailPriceId);
+        return $this->renderSuccess($data, $service->getMessage() ?: '下单成功');
+    }
+    
 
 }
\ No newline at end of file
diff --git a/app/api/model/Retail.php b/app/api/model/Retail.php
index 9962933b..e260138a 100644
--- a/app/api/model/Retail.php
+++ b/app/api/model/Retail.php
@@ -12,13 +12,56 @@ declare (strict_types=1);
 
 namespace app\api\model;
 use app\common\model\Retail as RetailModel;
+use app\api\model\Payment as PaymentModel;
+use app\api\service\identity\Payment;
+use app\api\service\User as UserService;
 
 class Retail extends RetailModel
-{
+{   
+    // 提示信息
+    private string $message = '';
+
+    // 支付方式 (微信支付、支付宝、余额)
+    private string $method;
+
+    // 下单的客户端
+    private string $client;
+
+    //隐藏字段
+    protected $hidden = [
+        'create_time',
+        'update_time',
+        'store_id',
+    ];
+
+    public function setMethod(string $method): Retail
+    {
+        $this->method = $method;
+        return $this;
+    }
     public static function getRetailList()
     {
         return self::select();
     }
+    /**
+     * 设置下单的客户端
+     * @param string $client 客户端
+     * @return $this
+     */
+    public function setClient(string $client): Retail
+    {
+        $this->client = $client;
+        return $this;
+    }
+
+    /**
+     * 返回消息提示
+     * @return string
+     */
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
 
 
     public static function detail(array $where = [])
@@ -30,4 +73,42 @@ class Retail extends RetailModel
        
        return RetailModel::where($where)->select();
     }
+
+
+
+    private function cheapPrice($data): array
+    {   
+        $one_data = $data[0];
+        
+        foreach ($data as $key => $value) {
+            $data[$key]['cheap_price'] = 0;
+            if (!empty($one_data)) {
+                if ($key > 0) {
+                    $price = $value['month'] * $one_data['price'];
+                    $data[$key]['cheap_price'] = $price - $value['price'];
+                }
+            }
+        }
+        return $data;
+    }
+
+    /**
+     * 确认订单支付事件
+     * @param int $identityId
+     * @param array $extra 附加数据
+     * @return array[]
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function orderPay(int $identityId, array $extra = []): array
+    {
+        $PaymentService = new Payment();
+        $result = $PaymentService->setMethod($this->method)
+            ->setClient($this->client)
+            ->orderPay($identityId, $extra);
+        $this->message = $PaymentService->getMessage();
+        return $result;
+    }
 }
\ No newline at end of file
diff --git a/app/api/model/user/Retail.php b/app/api/model/user/Retail.php
new file mode 100644
index 00000000..e0e231fb
--- /dev/null
+++ b/app/api/model/user/Retail.php
@@ -0,0 +1,20 @@
+ UserService::getCurrentLoginUserId(),//用户id
+            'order_no' => OrderService::createOrderNo(),//订单号
+            'retail_price_id' => $identityInfo['retail_price_id'],//会员id
+            'order_type' => $identityInfo['retail_type'],//订单类型
+            'pay_price' => $price,
+            'year' => $identityInfo['year'],
+            'platform' => getPlatform(),
+            'pay_method' => $method,
+            'store_id' => self::$storeId,
+        ];
+        return $this->save($data);
+    }
+
+    /**
+     * 获取订单详情 (待付款状态)
+     * @param string $orderNo 订单号
+     * @return array|null|static
+     */
+    public static function getPayDetail(string $orderNo)
+    {
+        return self::detail(['order_no' => $orderNo]);
+    }
+
+    /**
+     * @notes:编辑
+     * @param $data
+     * @return bool
+     * @author: wanghousheng
+     */
+    public function edit($data): bool
+    {
+        return $this->save($data) !== false;
+    }
+
+    public function identity(): HasOne
+    {
+        return $this->hasOne(Identity::class, 'identity_id', 'identity_id')
+            ->bind(['identity_name' => 'name']);
+    }
+
+    /**
+     * @notes:开卡记录
+     * @param array $where
+     * @return array
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @author: wanghousheng
+     */
+    public function cardList(array $where = []): array
+    {
+        $userId = UserService::getCurrentLoginUserId();
+        $params['user_id'] = $userId;
+        $params['pay_status'] = PayStatus::SUCCESS;
+        $where = array_merge($where, $params);
+        $list = $this->where($where)
+            ->with(['identity'])
+            ->order('pay_time', 'desc')
+            ->limit(20)
+            ->select();
+        $data = [];
+        if (!empty($list)) {
+            foreach ($list as $value) {
+                $end_time = date("Y-m-d", strtotime("+{$value['month']} months", $value['pay_time']));
+                $is_valid = false;
+                if (strtotime(date("Y-m-d")) < strtotime($end_time)) {
+                    $is_valid = true;
+                }
+                $data[] = [
+                    'start_time' => date("Y-m-d", $value['pay_time']),
+                    'end_time' => $end_time,
+                    'name' => $value['identity_name'],
+                    'month' => $value['month'],
+                    'is_valid' => $is_valid
+                ];
+            }
+        }
+        return $data;
+    }
+}
\ No newline at end of file
diff --git a/app/api/service/Retail.php b/app/api/service/Retail.php
new file mode 100644
index 00000000..f10baaad
--- /dev/null
+++ b/app/api/service/Retail.php
@@ -0,0 +1,142 @@
+method = $method;
+        return $this;
+    }
+
+    /**
+     * 设置下单的客户端
+     * @param string $client 客户端
+     * @return $this
+     */
+    public function setClient(string $client): Retail
+    {
+        $this->client = $client;
+        return $this;
+    }
+
+    /**
+     * 开通会员页面数据
+     * @param string $client 当前客户端
+     * @return array
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function userCenter(array $client): array
+    {
+        // 当期用户信息
+        $userInfo = UserService::getCurrentLoginUser(true);
+//        //是否分销商
+//        if (UserService::isDealerMember() || UserService::isStore()) {
+//            throwError('非法操作');
+//        }
+        // 获取充值方案列表
+        $model = new RetailModel();
+        $planList = $model->getList(['retail_type' => $client['retail_type']]);
+        if (!$planList->isEmpty()) {
+           // $planList = $this->cheapPrice($planList->toArray());
+        }
+        //计算优惠价格
+        // 根据指定客户端获取可用的支付方式
+        $PaymentModel = new PaymentModel;
+        $methods = $PaymentModel->getMethodsByClient($client['client']);
+        // 返回数据
+        return [
+            'personal' => $userInfo,
+            'list' => $planList,
+            'paymentMethods' => $methods
+        ];
+    }
+
+    private function cheapPrice($data): array
+    {
+        $one_data = $data[0];
+        foreach ($data as $key => $value) {
+            $data[$key]['cheap_price'] = 0;
+            if (!empty($one_data)) {
+                if ($key > 0) {
+                    $price = $value['month'] * $one_data['price'];
+                    $data[$key]['cheap_price'] = $price - $value['price'];
+                }
+            }
+        }
+        return $data;
+    }
+
+    /**
+     * 确认订单支付事件
+     * @param int $identityId
+     * @param array $extra 附加数据
+     * @return array[]
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function orderPay(int $identityId, array $extra = []): array
+    {   
+        $PaymentService = new Payment();
+        $result = $PaymentService->setMethod($this->method)
+            ->setClient($this->client)
+            ->orderPay($identityId);
+        $this->message = $PaymentService->getMessage();
+        return $result;
+    }
+
+    /**
+     * 交易查询
+     * 查询第三方支付订单是否付款成功
+     * @param string $outTradeNo 商户订单号
+     * @return bool
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function tradeQuery(string $outTradeNo): bool
+    {
+        $PaymentService = new Payment();
+        return $PaymentService->setMethod($this->method)->setClient($this->client)->tradeQuery($outTradeNo);
+    }
+
+    /**
+     * 返回消息提示
+     * @return string
+     */
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
+}
\ No newline at end of file
diff --git a/app/api/service/Retail/PaySuccess.php b/app/api/service/Retail/PaySuccess.php
new file mode 100644
index 00000000..76cd928f
--- /dev/null
+++ b/app/api/service/Retail/PaySuccess.php
@@ -0,0 +1,409 @@
+
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\api\service\identity;
+
+use app\api\model\PaymentTrade as PaymentTradeModel;
+use app\api\model\recharge\Order as OrderModel;
+use app\api\model\User as UserModel;
+use app\api\model\user\BalanceLog as BalanceLogModel;
+use app\api\model\user\IdentityOrder;
+use app\common\enum\order\PayStatus;
+use app\common\enum\payment\Method as PaymentMethodEnum;
+use app\common\enum\recharge\order\PayStatus as PayStatusEnum;
+use app\common\enum\user\balanceLog\Scene as SceneEnum;
+use app\common\enum\user\IdentityEnum;
+use app\common\enum\user\UserTypeEnum;
+use app\common\library\Lock;
+use app\common\library\Log;
+use app\common\service\BaseService;
+use app\store\model\dealer\User;
+use cores\exception\BaseException;
+
+/**
+ * 余额充值订单支付成功服务类
+ * Class PaySuccess
+ * @package app\api\service\order
+ */
+class PaySuccess extends BaseService
+{
+    // 当前订单信息
+    public IdentityOrder $orderInfo;
+
+    // 当前用户信息
+    private UserModel $userInfo;
+
+    // 当前订单号
+    private string $orderNo;
+
+    // 当前订单ID
+    private int $orderId;
+
+    // 订单支付方式
+    private string $method;
+
+    // 第三方交易记录ID
+    private ?int $tradeId = null;
+
+    // 第三方支付成功返回的数据
+    private array $paymentData = [];
+
+    private int $type;
+
+    /**
+     * 设置支付的订单ID
+     * @param int $orderId 订单ID
+     */
+    public function setOrderId(int $orderId): PaySuccess
+    {
+        $this->orderId = $orderId;
+        return $this;
+    }
+
+    public function setType($type): PaySuccess
+    {
+        $this->type = $type;
+        return $this;
+    }
+
+    /**
+     * 设置当前的订单号
+     * @param string $orderNo
+     * @return $this
+     */
+    public function setOrderNo(string $orderNo): PaySuccess
+    {
+        $this->orderNo = $orderNo;
+        return $this;
+    }
+
+    /**
+     * 设置订单支付方式
+     * @param string $method
+     * @return $this
+     */
+    public function setMethod(string $method): PaySuccess
+    {
+        $this->method = $method;
+        return $this;
+    }
+
+    /**
+     * 第三方支付交易记录ID
+     * @param int|null $tradeId
+     * @return $this
+     */
+    public function setTradeId(?int $tradeId = null): PaySuccess
+    {
+        $this->tradeId = $tradeId;
+        return $this;
+    }
+
+    /**
+     * 第三方支付成功返回的数据
+     * @param array $paymentData
+     * @return $this
+     */
+    public function setPaymentData(array $paymentData): PaySuccess
+    {
+        $this->paymentData = $paymentData;
+        return $this;
+    }
+
+    /**
+     * 订单支付成功业务处理
+     * @return bool
+     * @throws BaseException
+     */
+    public function handle(): bool
+    {
+        // 验证当前参数是否合法
+        $this->verifyParameters();
+        // 当前订单开启并发锁
+        $this->lockUp();
+        // 验证当前订单是否允许支付
+        if ($this->checkOrderStatusOnPay()) {
+            // 更新订单状态为已付款
+            $this->updatePayStatus();
+        }
+        // 当前订单解除并发锁
+        $this->unLock();
+        return true;
+    }
+
+    /**
+     * 验证当前参数是否合法
+     * @throws BaseException
+     */
+    private function verifyParameters()
+    {
+        if (empty($this->orderNo)) {
+            throwError('orderNo not found');
+        }
+        if (empty($this->method)) {
+            throwError('method not found');
+        }
+        if ($this->tradeId) {
+            empty($this->paymentData) && throwError('PaymentData not found');
+            !isset($this->paymentData['tradeNo']) && throwError('PaymentData not found');
+        }
+        // 记录日志
+        Log::append('PaySuccess', [
+            'orderNo' => $this->orderNo, 'method' => $this->method,
+            'tradeId' => $this->tradeId, 'paymentData' => $this->paymentData
+        ]);
+    }
+
+    /**
+     * 订单模型
+     * @return IdentityOrder|null
+     * @throws BaseException
+     */
+    private function orderModel(): ?IdentityOrder
+    {
+        return $this->getOrderInfo();
+    }
+
+    /**
+     * 订单已付款事件
+     * @return void
+     * @throws BaseException
+     */
+    private function updatePayStatus(): void
+    {
+        // 记录日志
+        Log::append('PaySuccess --updatePayStatus', ['title' => '订单已付款事件']);
+        // 当前订单信息
+        $orderInfo = $this->getOrderInfo();
+        // 事务处理
+        $this->orderModel()->transaction(function () use ($orderInfo) {
+            // 更新订单状态
+            $this->updateOrderStatus();
+            // 累积用户总消费金额
+            UserModel::setIncPayMoney($orderInfo['user_id'], (float)$orderInfo['pay_price']);
+            // 记录订单支付信息
+            $this->updatePayInfo();
+            //更改会员角色
+            $this->activate();
+        });
+    }
+
+
+    /**
+     * 记录订单支付的信息
+     * @throws BaseException
+     */
+    private function updatePayInfo()
+    {
+        // 当前订单信息
+        $orderInfo = $this->getOrderInfo();
+        // 余额支付
+        if ($this->method == PaymentMethodEnum::BALANCE) {
+            // 更新用户余额
+            UserModel::setDecBalance((int)$orderInfo['user_id'], (float)$orderInfo['pay_price']);
+            // 新增余额变动记录
+            $type = SceneEnum::MEMBER;
+            if ($this->type == IdentityEnum::DEALER) {
+                $type = SceneEnum::DEALER;
+            }
+            BalanceLogModel::add($type, [
+                'user_id' => (int)$orderInfo['user_id'],
+                'money' => -$orderInfo['pay_price'],
+            ], ['order_no' => $orderInfo['order_no']]);
+        }
+        // 将第三方交易记录更新为已支付状态
+        if (in_array($this->method, [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY])) {
+            $this->updateTradeRecord();
+        }
+    }
+
+    /**
+     * 将第三方交易记录更新为已支付状态
+     */
+    private function updateTradeRecord()
+    {
+        if ($this->tradeId && !empty($this->paymentData)) {
+            PaymentTradeModel::updateToPaySuccess($this->tradeId, $this->paymentData['tradeNo']);
+        }
+    }
+
+    /**
+     * 更新订单状态
+     * @throws BaseException
+     */
+    private function updateOrderStatus(): void
+    {
+        // 更新订单状态
+        $this->orderModel()->save([
+            'pay_method' => $this->method,
+            'pay_status' => PayStatus::SUCCESS,
+            'pay_time' => time(),
+            'trade_id' => $this->tradeId ?: 0,
+        ]);
+    }
+
+    /**
+     * 获取买家用户信息
+     * @return UserModel|array|null
+     * @throws BaseException
+     */
+    private function getUserInfo()
+    {
+        if (empty($this->userInfo)) {
+            $this->userInfo = UserModel::detail($this->getOrderInfo()['user_id']);
+        }
+        if (empty($this->userInfo)) {
+            throwError('未找到买家用户信息');
+        }
+        return $this->userInfo;
+    }
+
+    /**
+     * 验证当前订单是否允许支付
+     * @return bool
+     * @throws BaseException
+     */
+    private function checkOrderStatusOnPay(): bool
+    {
+        // 当前订单信息
+        $orderInfo = $this->getOrderInfo();
+        // 验证余额支付时用户余额是否满足
+        if ($this->method == PaymentMethodEnum::BALANCE) {
+            if ($this->getUserInfo()['balance'] < $orderInfo['pay_price']) {
+                throwError('账户余额不足,无法使用余额支付');
+            }
+        }
+        // 检查订单状态是否为已支付
+        if ($orderInfo['pay_status'] == PayStatusEnum::SUCCESS) {
+            $this->onOrderPaid();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 处理订单已支付的情况
+     * @throws BaseException
+     */
+    private function onOrderPaid()
+    {
+        // 记录日志
+        Log::append('PaySuccess --onOrderPaid', ['title' => '处理订单已支付的情况']);
+        // 当前订单信息
+        $orderInfo = $this->getOrderInfo();
+        // 余额支付直接返回错误信息
+        if ($this->method == PaymentMethodEnum::BALANCE) {
+            throwError('当前订单已支付,无需重复支付');
+        }
+        // 第三方支付判断是否为重复下单 (因异步回调可能存在网络延迟的原因,在并发的情况下会出现同时付款两次,这里需要容错)
+        // 如果订单记录中已存在tradeId并且和当前支付的tradeId不一致, 那么判断为重复的订单, 需进行退款处理
+        if ($this->tradeId > 0 && $orderInfo['trade_id'] != $this->tradeId) {
+            // 执行原路退款
+            throwError('当前订单异常');
+        }
+    }
+
+
+    /**
+     * 获取当前订单的详情信息
+     * @return OrderModel|null
+     * @throws BaseException
+     */
+    private function getOrderInfo(): ?IdentityOrder
+    {
+        // 获取订单详情 (待支付状态)
+        if (empty($this->orderInfo)) {
+            $this->orderInfo = IdentityOrder::getPayDetail($this->orderNo);
+        }
+        // 判断订单是否存在
+        if (empty($this->orderInfo)) {
+            throwError('未找到该订单信息');
+        }
+        return $this->orderInfo;
+    }
+
+    /**
+     * 订单锁:防止并发导致重复支付
+     * @throws BaseException
+     */
+    private function lockUp()
+    {
+        $orderInfo = $this->getOrderInfo();
+        Lock::lockUp("IdentityOrderPaySuccess_{$orderInfo['order_id']}");
+    }
+
+    /**
+     * 订单锁:防止并发导致重复支付
+     * @throws BaseException
+     */
+    private function unLock()
+    {
+        $orderInfo = $this->getOrderInfo();
+        Lock::unLock("IdentityOrderPaySuccess_{$orderInfo['order_id']}");
+    }
+
+    /**
+     * @notes:修改会员身份信息
+     * @throws BaseException
+     * @author: wanghousheng
+     */
+    private function activate(): void
+    {
+        $orderInfo = $this->getOrderInfo();
+        $userInfo = $this->getUserInfo();
+        //判断当前用户角色
+        $orderType = $orderInfo['order_type'];
+        $userType = $userInfo['user_type'];
+        if ($userType == UserTypeEnum::STORE) {
+            return;
+        }
+        $userModel = new UserModel();
+        $up = [];
+        $time = date('Y-m-d');
+        //已经是会员或者未开通会员
+        if ($orderType == IdentityEnum::MEMBER && $userType != UserTypeEnum::DEALER) {
+            $up['user_type'] = UserTypeEnum::MEMBER;
+            //已经是会员
+            if ($userType == UserTypeEnum::MEMBER) {
+                //是否到期
+                if (!empty($userInfo['effective_time']) && strtotime($userInfo['effective_time']) > strtotime(date('Y-m-d'))) {
+                    $time = $userInfo['effective_time'];
+                }
+            }
+            $up['effective_time'] = date("Y-m-d", strtotime("+{$orderInfo['month']} months", strtotime($time)));
+        } else {
+            $up['user_type'] = UserTypeEnum::DEALER;
+            //已经是分销商
+            if ($userType == UserTypeEnum::DEALER) {
+                //是否到期
+                if (!empty($userInfo['fx_effective_time']) && strtotime($userInfo['fx_effective_time']) > strtotime(date('Y-m-d'))) {
+                    $time = $userInfo['fx_effective_time'];
+                }
+            }
+            if (!User::isDealerUser($userInfo['user_id'])) {
+                // 新增分销商用户
+                $model = new UserModel();
+                $mobile = $model->where(['user_id' => $userInfo['user_id']])->value('mobile');
+                User::add($userInfo['user_id'], [
+                    'real_name' => $mobile,
+                    'mobile' => $mobile,
+                    'store_id' => $userInfo['store_id'] ?? 0,
+                ]);
+            } else {
+                //更新分销用户
+                User::update(['is_delete' => 0], ['user_id' => $userInfo['user_id']]);
+            }
+            $up['fx_effective_time'] = date("Y-m-d", strtotime("+{$orderInfo['month']} months", strtotime($time)));
+        }
+        $userModel->where(['user_id' => $userInfo['user_id']])->save($up);
+    }
+}
\ No newline at end of file
diff --git a/app/api/service/Retail/Payment.php b/app/api/service/Retail/Payment.php
new file mode 100644
index 00000000..609d68ab
--- /dev/null
+++ b/app/api/service/Retail/Payment.php
@@ -0,0 +1,344 @@
+
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\api\service\Retail;
+
+use app\api\model\Payment as PaymentModel;
+use app\api\model\PaymentTrade as PaymentTradeModel;
+use app\api\model\Retail as RetailModel;
+use app\api\model\user\Retail;
+use app\api\model\user\RetailOrder;
+use app\api\service\identity\PaySuccess as RetailPaySuccessService;
+use app\api\service\Order as OrderService;
+use app\api\service\User as UserService;
+use app\common\enum\Client as ClientEnum;
+use app\common\enum\OrderType as OrderTypeEnum;
+use app\common\enum\payment\Method as PaymentMethodEnum;
+use app\common\enum\user\IdentityEnum;
+use app\common\library\payment\Facade as PaymentFacade;
+use app\common\service\BaseService;
+use cores\exception\BaseException;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+
+/**
+ * 开通会员/分销商订单付款服务类
+ * Class Payment
+ * @package app\api\controller
+ */
+class Payment extends BaseService
+{
+    // 提示信息
+    private string $message = '';
+
+    // 订单信息
+    private RetailOrder $orderInfo;
+
+    // 支付方式 (微信支付、支付宝,余额)
+    private string $method = '';
+
+    // 下单的客户端
+    private string $client = '';
+
+    private int $type;
+
+    /**
+     * 设置当前支付方式
+     * @param string $method 支付方式
+     * @return $this
+     */
+    public function setMethod(string $method): Payment
+    {
+        $this->method = $method;
+        return $this;
+    }
+
+    public function setType($type): Payment
+    {
+        $this->type = $type;
+        return $this;
+    }
+
+    /**
+     * 设置下单的客户端
+     * @param string $client 客户端
+     * @return $this
+     */
+    public function setClient(string $client): Payment
+    {
+        $this->client = $client;
+        return $this;
+    }
+
+    /**
+     * 确认订单支付事件
+     * @param int $retailPriceId
+     * @param array $extra 附加数据
+     * @return array[]
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function orderPay(int $retailPriceId, array $extra = []): array
+    {   
+        // 创建订单信息
+        $this->orderInfo = $this->createOrder($retailPriceId);
+        // 订单支付事件
+        $this->orderPayEvent();
+        // 构建第三方支付请求的参数
+        $payment = $this->unifiedorder($extra);
+        // 记录第三方交易信息
+        $order_type = OrderTypeEnum::MEMBER;//开通会员
+        if ($this->orderInfo['order_type'] == IdentityEnum::DEALER) {
+            $order_type = OrderTypeEnum::DEALER;//开通分销商
+        }
+        $this->recordPaymentTrade($payment, $order_type);
+        // 返回结果
+        return compact('payment');
+    }
+
+    /**
+     * 订单支付事件
+     * @return void
+     * @throws BaseException
+     * @author: wanghousheng
+     */
+    private function orderPayEvent(): void
+    {
+        // 余额支付
+        if ($this->method == PaymentMethodEnum::BALANCE) {
+            $this->setType($this->orderInfo['order_type'])->orderPaySuccess($this->orderInfo['order_no']);
+        }
+    }
+
+    /**
+     * 订单支付成功事件
+     * @param string $orderNo 当前订单号
+     * @param int|null $tradeId
+     * @param array $paymentData
+     * @return void
+     * @throws BaseException
+     * @author: wanghousheng
+     */
+    private function orderPaySuccess(string $orderNo, ?int $tradeId = null, array $paymentData = []): void
+    {
+        $service = new RetailPaySuccessService();
+        // 订单支付成功业务处理
+        $service->setOrderNo($orderNo)
+            ->setMethod($this->method)
+            ->setTradeId($tradeId)
+            ->setType($this->type)
+            ->setPaymentData($paymentData);
+        if (!$service->handle()) {
+            throwError($service->getError() ?: '订单支付失败');
+        }
+        $this->message = '恭喜您,订单支付成功';
+    }
+
+    /**
+     * 创建订单
+     * @param int $identityId
+     * @return RetailOrder
+     * @throws BaseException
+     */
+    private function createOrder(int $retailPriceId ,array $extra = []): RetailOrder
+    {   
+        $extra = $this->request->post('year');
+        $model = new RetailOrder();
+        $info = Retail::detail(['retail_price_id' => $retailPriceId]);
+        $info['year'] = $extra;
+        if ($info->isEmpty()) {
+            throwError('记录不存在');
+        }
+        //店主不可操作
+        if (UserService::isStore()) {
+            throwError('非法操作');
+        }
+        if (UserService::isDealerMember() && $info['type'] != IdentityEnum::DEALER) {
+            throwError('非法操作');
+        }
+        if (!$model->createOrder($info->toArray(), $this->method)) {
+            throwError($model->getError() ?: '创建订单失败');
+        }
+        $model['order_id'] = (int)$model['order_id'];
+        return $model;
+    }
+
+    /**
+     * 查询订单是否支付成功 (仅限第三方支付订单)
+     * @param string $outTradeNo 商户订单号
+     * @return bool
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function tradeQuery(string $outTradeNo): bool
+    {
+        // 获取支付方式的配置信息
+        $options = $this->getPaymentConfig();
+        // 构建支付模块
+        $Payment = PaymentFacade::store($this->method)->setOptions($options, $this->client);
+        // 执行第三方支付查询API
+        $result = $Payment->tradeQuery($outTradeNo);
+        // 订单支付成功事件
+        if (!empty($result) && $result['paySuccess']) {
+            // 获取第三方交易记录信息
+            $tradeInfo = PaymentTradeModel::detailByOutTradeNo($outTradeNo);
+            // 订单支付成功事件
+            $this->orderPaySuccess($tradeInfo['order_no'], $tradeInfo['trade_id'], $result);
+        }
+        // 返回订单状态
+        return $result ? $result['paySuccess'] : false;
+    }
+
+    /**
+     * 记录第三方交易信息
+     * @param array $payment 第三方支付数据
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    private function recordPaymentTrade(array $payment, int $orderType): void
+    {
+        if ($this->method != PaymentMethodEnum::BALANCE) {
+            PaymentTradeModel::record(
+                $this->orderInfo,
+                $this->method,
+                $this->client,
+                $orderType,
+                $payment
+            );
+        }
+    }
+
+    /**
+     * 返回消息提示
+     * @return string
+     */
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
+
+    /**
+     * 构建第三方支付请求的参数
+     * @param array $extra 附加数据
+     * @return array
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    private function unifiedorder(array $extra = []): array
+    {
+        // 判断支付方式是否合法
+        if (!in_array($this->method, [PaymentMethodEnum::WECHAT, PaymentMethodEnum::ALIPAY])) {
+            return [];
+        }
+        // 生成第三方交易订单号 (并非主订单号)
+        $outTradeNo = OrderService::createOrderNo();
+        // 获取支付方式的配置信息
+        $options = $this->getPaymentConfig();
+        // 整理下单接口所需的附加数据
+        $extra = $this->extraAsUnify($extra);
+        // 构建支付模块
+        $Payment = PaymentFacade::store($this->method)->setOptions($options, $this->client);
+        // 执行第三方支付下单API
+        if (!$Payment->unify($outTradeNo, (string)$this->orderInfo['pay_price'], $extra)) {
+            throwError('第三方支付下单API调用失败');
+        }
+        // 返回客户端需要的支付参数
+        return $Payment->getUnifyResult();
+    }
+
+    /**
+     * 获取支付方式的配置信息
+     * @return mixed
+     * @throws BaseException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    private function getPaymentConfig()
+    {
+        $PaymentModel = new PaymentModel;
+        $templateInfo = $PaymentModel->getPaymentInfo($this->method, $this->client, $this->getStoreId());
+        return $templateInfo['template']['config'][$this->method];
+    }
+
+    /**
+     * 整理下单接口所需的附加数据
+     * @param array $extra
+     * @return array
+     * @throws BaseException
+     */
+    private function extraAsUnify(array $extra = []): array
+    {
+        // 微信支付时需要的附加数据
+        if ($this->method === PaymentMethodEnum::WECHAT) {
+            // 微信小程序端和微信公众号端需要openid
+            if (in_array($this->client, [ClientEnum::WXOFFICIAL, ClientEnum::MP_WEIXIN])) {
+                $extra['openid'] = $this->getWechatOpenid();
+            }
+        }
+        // 支付宝支付时需要的附加数据
+        if ($this->method === PaymentMethodEnum::ALIPAY) {
+            // 支付宝小程序端需要buyerId
+            if ($this->client == ClientEnum::MP_ALIPAY) {
+                $extra['buyerId'] = $this->getAlipayBuyerId();
+            }
+        }
+        return $extra;
+    }
+
+    /**
+     * 获取微信端的用户openid(仅微信小程序和微信公众号)
+     * @return null
+     * @throws BaseException
+     */
+    private function getWechatOpenid()
+    {
+        if (in_array($this->client, [ClientEnum::MP_WEIXIN, ClientEnum::WXOFFICIAL])) {
+            // 当前登录用户信息
+            $useInfo = UserService::getCurrentLoginUser(true);
+            if (!$useInfo['currentOauth'] || empty($useInfo['currentOauth']['oauth_id'])) {
+                throwError('很抱歉,您当前不存在openid 无法发起微信支付');
+            }
+            // 当前第三方用户标识
+            return $useInfo['currentOauth']['oauth_id'];
+        }
+        return null;
+    }
+
+    /**
+     * 获取支付宝端的用户buyerId(仅支付宝小程序端)
+     * @return null
+     * @throws BaseException
+     */
+    private function getAlipayBuyerId()
+    {
+        if ($this->client == ClientEnum::MP_ALIPAY) {
+            // 当前登录用户信息
+            $useInfo = UserService::getCurrentLoginUser(true);
+            if (!$useInfo['currentOauth'] || empty($useInfo['currentOauth']['oauth_id'])) {
+                throwError('很抱歉,您当前不存在buyerId 无法发起支付宝支付');
+            }
+            // 当前第三方用户标识
+            return $useInfo['currentOauth']['oauth_id'];
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/app/common/model/Retail.php b/app/common/model/Retail.php
index 802d986d..8cc5eb98 100644
--- a/app/common/model/Retail.php
+++ b/app/common/model/Retail.php
@@ -30,6 +30,21 @@ class Retail extends BaseModel
      // 更新时间字段
      protected $updateTime = 'update_time';
 
+     public function getList(array $where)
+     {
+         return $this->where($where)->order('sort', 'asc')->select();
+     }
      
+    /**
+     * @notes:详情
+     * @param $where
+     * @param array $with
+     * @return static|array|null
+     * @author: wanghousheng
+     */
+    public static function detail($where, array $with = [])
+    {
+        return static::get($where, $with);
+    }
 
 }
\ No newline at end of file