Browse Source

酒店餐厅活动线下混合支付

Panda 2 weeks ago
parent
commit
5a4acc00d1

+ 1 - 0
application/api/controller/Hotel.php

@@ -199,6 +199,7 @@ class Hotel extends Api
             'days' => $days,
             'order_no' => createUniqueNo('H', $user_id),
             'pay_amount' => bcmul(bcmul($info['price'], $days, 2),$params['num'],2),
+            'status' => 1,
             'create_time' => time()
         ];
         if (!Db::name('hotel_order')->insertGetId($data)) {

+ 30 - 0
application/api/controller/Notify.php

@@ -2,6 +2,7 @@
 
 namespace app\api\controller;
 
+use app\common\business\PaymentBusiness;
 use app\common\controller\Api;
 use app\common\model\PayOrderModel;
 use app\common\model\Wallet;
@@ -54,6 +55,35 @@ class Notify extends Api
         return $pay->success();
     }
 
+    // 酒店 餐厅 活动 线下 支付回调
+    public function bill()
+    {
+        //验签
+        $pay_type = input('pay_type', 'wechat');
+        LogUtil::info("用户充值 {$pay_type}支付回调", self::LOG_MODULE, __FUNCTION__, $this->request->param());
+        if (!$pay = Service::checkNotify($pay_type)) {
+            LogUtil::info('签名错误', self::LOG_MODULE, __FUNCTION__);
+            return $this->error('签名错误 err01');
+        }
+
+        //验证,拿订单号等信息
+        $data         = $pay->verify();
+        $out_trade_no = $data['out_trade_no'];
+        $third_no     = $data['transaction_id'];
+
+        Db::startTrans();
+        // 支付成功,更改支付状态
+        $paymentBusiness = new PaymentBusiness();
+        if (!$paymentBusiness->deal($out_trade_no, $third_no)) {
+            Db::rollback();
+            LogUtil::info($paymentBusiness->getMessage(), self::LOG_MODULE, __FUNCTION__);
+            return $this->error($paymentBusiness->getMessage());
+        }
+        Db::commit();
+        LogUtil::info('处理成功', self::LOG_MODULE, __FUNCTION__);
+        return $pay->success();
+    }
+
     //充值VIP 异步回调对外方法
     public function vip_notify_base()
     {

+ 86 - 10
application/api/controller/Payment.php

@@ -3,7 +3,9 @@
 namespace app\api\controller;
 
 use addons\epay\library\Service;
+use app\common\business\PaymentBusiness;
 use app\common\controller\Api;
+use app\common\model\BillModel;
 use app\common\model\HotelModel;
 use app\common\model\HotelOrderModel;
 use app\common\model\HotelRoomModel;
@@ -21,14 +23,12 @@ class Payment extends Api
 {
     protected $noNeedLogin = [''];
     protected $noNeedRight = ['*'];
-    protected const ORDER_TYPE = [
-        'hotel_order'            => '酒店订单',
-        'hotel_canteen_order'    => '餐厅订单',
-        'university_event_apply' => '活动订单',
-        'offline_shop_order'     => '线下订单',
-    ];
-
-    // 活动列表
+
+    /**
+     * order_no 下级的订单表 订单号
+     * order_type 订单来源:hotel_order=酒店订单;hotel_canteen_order=餐厅订单;university_event_apply=活动订单;offline_shop_order=线下订单
+     * @return true
+     */
     public function page()
     {
         $user_id = $this->auth->id;
@@ -36,8 +36,84 @@ class Payment extends Api
         if (empty($params['order_no']) || empty($params['order_type'])) {
             return $this->error('请选择订单');
         }
-        dd(array_keys(self::ORDER_TYPE));
-        if (!in_array($params['order_type'], array_keys(self::ORDER_TYPE))) {}
+        $tableName = $params['order_type'];
+        $orderNo = $params['order_no'];
+
+        $paymentBusiness = new PaymentBusiness();
+        if (!$paymentBusiness->createOrder($user_id,$orderNo,$tableName)){
+            return $this->error($paymentBusiness->getMessage(),$paymentBusiness->getData());
+        }
+
+        // 支付订单ID
+        $bill_id = $paymentBusiness->getData()['bill_id'];
+
+        // 获取用户余额
+        $wallet = (new Wallet())->getWallet($user_id);
+
+        return $this->success('获取成功',['bill_id'=>$bill_id,'wallet'=>$wallet]);
+    }
 
+    public function submit()
+    {
+        $user_id = $this->auth->id;
+        $params = $this->request->param();
+        if (empty($params['bill_id'])) {
+            return $this->error('请选择订单');
+        }
+
+        if (empty($params['pay_type']) || empty($params['platform'])) {
+            return $this->error('请选择支付方式');
+        }
+
+        $model = new BillModel();
+        $bill = $model->getDetail(['id'=>$params['bill_id']]);
+        if (!$bill || $bill['status'] !== 0) {
+            return $this->error('订单已支付');
+        }
+
+        if (!$model->where('id',$params['bill_id'])->update(['pay_type'=>$params['pay_type'],'platform'=>$params['platform']])){
+            return $this->error('操作失败');
+        }
+
+        // 拉起支付 余额支付
+        $log_type = Wallet::BILL_LOG_TYPE[$bill['table_name']];
+        $remark = Wallet::log_type[$log_type];
+        if ($params['pay_type'] == 'wallet') {
+            Db::startTrans();
+            //钱包更新
+            $walletService = new Wallet();
+            if (!$walletService->change($user_id, -$bill['pay_amount'], 'money', $log_type, $remark, $bill['table_name'], $bill['table_id'])) {
+                Db::rollback();
+                return $this->error($walletService->getMessage());
+            }
+            // 支付成功,更改支付状态
+            $paymentBusiness = new PaymentBusiness();
+            if (!$paymentBusiness->deal($bill['order_no'])){
+                Db::rollback();
+                return $this->error($paymentBusiness->getMessage());
+            }
+            Db::commit();
+            return $this->success('支付成功');
+        }
+
+        // 第三方支付下单
+        $params = [
+            'type'      => $params['pay_type'],
+            'orderid'   => $bill['order_no'],
+            'title'     => $remark,
+            'amount'    => $bill['pay_amount'],
+            'method'    => $params['platform'],
+            'notifyurl' => config('pay_notify_url') . "/api/notify/bill/pay_type/{$params['pay_type']}",
+            'returnurl' => '',
+        ];
+        // 如果是小程序则需要添加 openid
+        if ($params['pay_type'] == 'wechat' && $params['platform'] == 'miniapp') {
+            $params['openid'] = $this->auth->mini_openid;
+        }
+        $res = Service::submitOrder($params);
+        if ($params['pay_type'] == 'wechat') {
+            return $this->success('下单成功', json_decode($res, true));
+        }
+        return $this->success('下单成功', $res);
     }
 }

+ 33 - 0
application/common/business/BusinessResult.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace app\common\business;
+
+class BusinessResult
+{
+    protected $message = '';
+    protected $data    = [];
+
+    protected function success(string $message = 'success', array $data = []): bool
+    {
+        $this->message = $message;
+        $this->data    = $data;
+        return true;
+    }
+
+    protected function error(string $message = 'error', array $data = []): bool
+    {
+        $this->message = $message;
+        $this->data    = $data;
+        return false;
+    }
+
+    public function getMessage(): string
+    {
+        return $this->message;
+    }
+
+    public function getData(): array
+    {
+        return $this->data;
+    }
+}

+ 336 - 0
application/common/business/PaymentBusiness.php

@@ -0,0 +1,336 @@
+<?php
+
+namespace app\common\business;
+
+use app\common\model\BillModel;
+use app\common\model\HotelCanteenOrderModel;
+use app\common\model\HotelOrderModel;
+use app\common\model\OfflineShopOrderModel;
+use app\common\model\UniversityEventApplyModel;
+use app\utils\Common;
+use think\Db;
+
+class PaymentBusiness extends BusinessResult
+{
+    /**
+     * 注释
+     */
+    public const ORDER_TYPE = [
+        'hotel_order'            => '酒店订单',
+        'hotel_canteen_order'    => '餐厅订单',
+        'university_event_apply' => '活动订单',
+        'offline_shop_order'     => '线下订单',
+    ];
+
+    protected int    $userId    = 0;
+    protected string $orderNo   = '';
+    protected string $tableName = '';
+
+    public function __construct() {}
+
+    /**
+     * 订单成交
+     * @param int $bill_id
+     * @param string $third_no
+     * @return bool
+     * @throws \think\Exception
+     * @throws \think\exception\PDOException
+     */
+    public function deal(string $bill_order_no, string $third_no = '')
+    {
+        $model = new BillModel();
+        $bill  = $model->getDetail(['order_no' => $bill_order_no]);
+        if (!$bill || $bill['status'] !== 0) {
+            return $this->error('订单已支付');
+        }
+
+        $update = [
+            'status'   => 1,
+            'third_no' => $third_no,
+            'pay_time' => time(),
+        ];
+        switch ($bill['table_name']) {
+            case 'hotel_order':
+            case 'hotel_canteen_order':
+            case 'university_event_apply':
+                break;
+            case 'offline_shop_order':
+                $update['back_status'] = 1;
+                break;
+        }
+
+        if (!$model->where('id', $bill_id)->update($update)){
+            return $this->error('订单支付失败');
+        }
+        if (!Db::name($bill['table_name'])->where('id', $bill['table_id'])->update(['is_pay'=>1,'pay_time'=>time()])){
+            return $this->error('订单支付失败');
+        }
+        return $this->success('支付成功');
+    }
+
+    /**
+     * 创建订单
+     * @param int $userId
+     * @param string $orderNo
+     * @param string $tableName
+     * @return bool
+     */
+    public function createOrder(int $userId, string $orderNo, string $tableName)
+    {
+        $this->userId    = $userId;
+        $this->orderNo   = $orderNo;
+        $this->tableName = $tableName;
+        if (!$this->{$tableName}) {
+            return $this->error($this->getMessage(), $this->getData());
+        }
+        return $this->success($this->getMessage(), $this->getData());
+    }
+
+    // 酒店订单
+    private function hotel_order()
+    {
+        // 主表校验
+        $model = new HotelOrderModel();
+        $order = $model->getDetail(
+            params: ['order_no', $this->orderNo],
+            with  : [
+                'hotel', 'room'
+            ]
+        );
+        if (!$order) {
+            return $this->error('订单不存在或已取消');
+        }
+        if ($order['is_pay'] == 1) {
+            return $this->error('订单已支付');
+        }
+
+        $billModel = new BillModel();
+        $bill      = $billModel->getDetail(
+            params: ['table_id' => $order['id'], 'table_name' => $this->tableName],
+        );
+        if (!empty($bill) && $bill['status'] !== 0) {
+            return $this->error('订单已支付');
+        }
+
+        // 如果没有订单 则需要新创建支付订单
+        if ($bill) {
+            $billId = $bill['id'];
+        } else {
+            $bill = [
+                'user_id'      => $this->userId,
+                'order_no'     => Common::createOrderNo('B'),
+                'total_amount' => $order['pay_amount'],
+                'pay_amount'   => $order['pay_amount'],
+                'createtime'   => time(),
+                'num'          => $order['num'],
+                'table_name'   => $this->tableName,
+                'table_id'     => $order['id'],
+                'shop_id'      => $order['hotel']['id'],
+                'shop_name'    => $order['hotel']['name'],
+                'shop_logo'    => $order['hotel']['image'],
+                'back_rate'    => $order['hotel']['back_rate'],
+                'args'         => json_encode([
+                    [
+                        'image'      => $order['room']['image'],// 图片
+                        'name'       => $order['room']['name'],// 规格名
+                        'num'        => $order['num'],// 购买数量
+                        // 酒店独有
+                        'days'       => $order['days'],
+                        'start_date' => $order['start_date'],
+                        'end_date'   => $order['end_date'],
+                    ]
+                ], JSON_UNESCAPED_UNICODE),
+            ];
+            if (!$billId = $billModel->insertGetId($bill)) {
+                return $this->error('支付订单创建失败');
+            }
+        }
+        return $this->success('支付订单创建成功', [
+            'bill_id' => $billId,
+        ]);
+    }
+
+    // 餐厅订单
+    private function hotel_canteen_order()
+    {
+        // 主表校验
+        $model = new HotelCanteenOrderModel();
+        $order = $model->getDetail(
+            params: ['order_no', $this->orderNo],
+            with  : [
+                'canteen', 'room'
+            ]
+        );
+        if (!$order) {
+            return $this->error('订单不存在或已取消');
+        }
+        if ($order['is_pay'] == 1) {
+            return $this->error('订单已支付');
+        }
+
+        $billModel = new BillModel();
+        $bill      = $billModel->getDetail(
+            params: ['table_id' => $order['id'], 'table_name' => $this->tableName],
+        );
+        if (!empty($bill) && $bill['status'] !== 0) {
+            return $this->error('订单已支付');
+        }
+
+        // 如果没有订单 则需要新创建支付订单
+        if ($bill) {
+            $billId = $bill['id'];
+        } else {
+            $bill = [
+                'user_id'      => $this->userId,
+                'order_no'     => Common::createOrderNo('B'),
+                'total_amount' => $order['pay_amount'],
+                'pay_amount'   => $order['pay_amount'],
+                'createtime'   => time(),
+                'num'          => 1,
+                'table_name'   => $this->tableName,
+                'table_id'     => $order['id'],
+                'shop_id'      => $order['canteen']['id'],
+                'shop_name'    => $order['canteen']['name'],
+                'shop_logo'    => $order['canteen']['image'],
+                'back_rate'    => $order['canteen']['back_rate'],
+                'args'         => json_encode([
+                    [
+                        'image'       => $order['room']['image'],// 图片
+                        'name'        => $order['room']['name'],// 规格名
+                        'num'         => 1,// 购买数量
+                        // 餐厅独有
+                        'get_to_time' => $order['get_to_time'],
+                    ]
+                ], JSON_UNESCAPED_UNICODE),
+            ];
+            if (!$billId = $billModel->insertGetId($bill)) {
+                return $this->error('支付订单创建失败');
+            }
+        }
+        return $this->success('支付订单创建成功', [
+            'bill_id' => $billId,
+        ]);
+    }
+
+    // 活动订单
+    private function university_event_apply()
+    {
+        // 主表校验
+        $model = new UniversityEventApplyModel();
+        $order = $model->getDetail(
+            params: ['order_no', $this->orderNo],
+            with  : [
+                'events'
+            ]
+        );
+        if (!$order) {
+            return $this->error('订单不存在或已取消');
+        }
+        if ($order['is_pay'] == 1) {
+            return $this->error('订单已支付');
+        }
+
+        $billModel = new BillModel();
+        $bill      = $billModel->getDetail(
+            params: ['table_id' => $order['id'], 'table_name' => $this->tableName],
+        );
+        if (!empty($bill) && $bill['status'] !== 0) {
+            return $this->error('订单已支付');
+        }
+
+        // 如果没有订单 则需要新创建支付订单
+        if ($bill) {
+            $billId = $bill['id'];
+        } else {
+            $bill = [
+                'user_id'      => $this->userId,
+                'order_no'     => Common::createOrderNo('B'),
+                'total_amount' => $order['pay_amount'],
+                'pay_amount'   => $order['pay_amount'],
+                'createtime'   => time(),
+                'num'          => $order['num'],
+                'table_name'   => $this->tableName,
+                'table_id'     => $order['id'],
+                'shop_id'      => $order['events']['id'],
+                'shop_name'    => $order['events']['name'],
+                'shop_logo'    => $order['events']['image'],
+                'back_rate'    => $order['events']['back_rate'],
+                'args'         => json_encode([
+                    [
+                        'image'      => $order['events']['image'],// 图片
+                        'name'       => $order['events']['name'],// 规格名
+                        'num'        => $order['num'],// 购买数量
+                        // 餐厅独有
+                        'start_time' => $order['events']['start_time'],
+                    ]
+                ], JSON_UNESCAPED_UNICODE),
+            ];
+            if (!$billId = $billModel->insertGetId($bill)) {
+                return $this->error('支付订单创建失败');
+            }
+        }
+        return $this->success('支付订单创建成功', [
+            'bill_id' => $billId,
+        ]);
+    }
+
+    // 线下订单
+    private function offline_shop_order()
+    {
+        // 主表校验
+        $model = new OfflineShopOrderModel();
+        $order = $model->getDetail(
+            params: ['order_no', $this->orderNo],
+            with  : [
+                'shop'
+            ]
+        );
+        if (!$order) {
+            return $this->error('订单不存在或已取消');
+        }
+        if ($order['is_pay'] == 1) {
+            return $this->error('订单已支付');
+        }
+
+        $billModel = new BillModel();
+        $bill      = $billModel->getDetail(
+            params: ['table_id' => $order['id'], 'table_name' => $this->tableName],
+        );
+        if (!empty($bill) && $bill['status'] !== 0) {
+            return $this->error('订单已支付');
+        }
+
+        // 如果没有订单 则需要新创建支付订单
+        if ($bill) {
+            $billId = $bill['id'];
+        } else {
+            $bill = [
+                'user_id'      => $this->userId,
+                'order_no'     => Common::createOrderNo('B'),
+                'total_amount' => $order['pay_amount'],
+                'pay_amount'   => $order['pay_amount'],
+                'createtime'   => time(),
+                'num'          => 1,
+                'table_name'   => $this->tableName,
+                'table_id'     => $order['id'],
+                'shop_id'      => $order['shop']['id'],
+                'shop_name'    => $order['shop']['name'],
+                'shop_logo'    => $order['shop']['image'],
+                'back_rate'    => $order['shop']['back_rate'],
+                'args'         => json_encode([
+                    [
+                        'image' => $order['shop']['image'],// 图片
+                        'name'  => $order['shop']['name'],// 规格名
+                        'num'   => 1,// 购买数量
+                    ]
+                ], JSON_UNESCAPED_UNICODE),
+            ];
+            if (!$billId = $billModel->insertGetId($bill)) {
+                return $this->error('支付订单创建失败');
+            }
+        }
+        return $this->success('支付订单创建成功', [
+            'bill_id' => $billId,
+        ]);
+    }
+}

+ 44 - 0
application/common/model/BillModel.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace app\common\model;
+
+use think\Db;
+use think\Model;
+
+/**
+ * 群组
+ */
+class BillModel extends BaseModel
+{
+    // 表名
+    protected $name = 'bill';
+    // 开启自动写入时间戳字段
+    protected $autoWriteTimestamp = false;
+    // 定义时间戳字段名
+    protected $createTime = false;
+    protected $updateTime = false;
+    protected $deleteTime = false;
+
+    public function searchOrderNoAttribute($query, $value, array $params)
+    {
+        if (empty($value)) {
+            return $query;
+        }
+        return $query->where('order_no', $value);
+    }
+
+    public function searchTableIdAttribute($query, $value, array $params)
+    {
+        if (empty($value)) {
+            return $query;
+        }
+        return $query->where('table_id', $value);
+    }
+    public function searchTableNameAttribute($query, $value, array $params)
+    {
+        if (empty($value)) {
+            return $query;
+        }
+        return $query->where('table_name', $value);
+    }
+}

+ 28 - 0
application/common/model/OfflineShopOrderModel.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace app\common\model;
+
+use think\Db;
+use think\Model;
+
+/**
+ * 群组
+ */
+class OfflineShopOrderModel extends BaseModel
+{
+    // 表名
+    protected $name = 'offline_shop_order';
+    // 开启自动写入时间戳字段
+    protected $autoWriteTimestamp = false;
+    // 定义时间戳字段名
+    protected $createTime = false;
+    protected $updateTime = false;
+    protected $deleteTime = false;
+
+
+    public function shop()
+    {
+        return $this->hasOne(OfflineShopModel::class, 'id', 'shop_id');
+    }
+
+}

+ 12 - 1
application/common/model/Wallet.php

@@ -14,9 +14,12 @@ class Wallet extends BaseModel
     const log_type = [
         1  => '系统调节',//money + -
         10  => '用户充值',//money +
-        20 => '老年大学活动报名',//money + -
         31 => '商城订单支付', //money -
         32 => '商城订单退款', //money +
+        40 => '酒店预定',//money + -
+        50 => '餐厅预定',//money + -
+        60 => '老年大学活动报名',//money + -
+        70 => '线下消费',//money + -
 
         //善豆
         101 => '签到', //bean +
@@ -30,6 +33,14 @@ class Wallet extends BaseModel
         'bean' => '善豆',
     ];
 
+    // Bill订单所属日志 type id
+    const BILL_LOG_TYPE = [
+        'hotel_order'            => 40,
+        'hotel_canteen_order'    => 50,
+        'university_event_apply' => 60,
+        'offline_shop_order'     => 70,
+    ];
+
     protected $message = '';
     protected $data    = [];