Selaa lähdekoodia

Merge branch 'master' of http://39.98.194.76:3000/txct/wanyue_app

yxjapp 7 kuukautta sitten
vanhempi
säilyke
84ccd9174a

+ 4 - 3
app/admin/controller/finance/WriteOffController.php

@@ -73,12 +73,14 @@ class WriteOffController
         $recordStart = ($page - 1) * 20;
         $sql = "select 
                 g.goods_name,g.goods_sales_price,g.join_goods_category_id,gs.goods_sku_specs_json,wu.user_name as wu_username, su.user_name as su_username,du.data_used_addtimes,
-                JSON_EXTRACT(du.join_data_used_object_json,'$.charge.charge_premises') as write_off_premises, su.join_user_dept_id as premises_id,du.data_used_count as nbr 
+                JSON_EXTRACT(du.join_data_used_object_json,'$.charge.charge_premises') as write_off_premises, su.join_user_dept_id as premises_id,du.data_used_count as nbr, 
+                ssd.dept_id as ssd_dept_id, ssd.dept_name as ssd_dept_name 
             from app_data_used_{$month} as du 
-                left join app_goods as g on JSON_EXTRACT(du.join_data_used_object_json,'$.goods_id') = g.goods_id 
+                left join app_goods as g on REPLACE(JSON_EXTRACT(du.join_data_used_object_json,'$.goods_id'),'\"','') = CAST(g.goods_id AS CHAR)
                 left join app_goods_sku as gs on JSON_EXTRACT(du.join_data_used_object_json,'$.goods_sku_id') = gs.goods_sku_id 
                 left join app_sys_user as wu on du.join_data_used_user_id = wu.user_id 
                 left join app_sys_user as su on JSON_EXTRACT(du.join_data_used_object_json,'$.salesman_id') = su.user_id 
+                left join app_sys_dept as ssd on JSON_EXTRACT(du.join_data_used_object_json,'$.salesman_premises_id') = ssd.dept_id 
                 {$where} 
             order by du.data_used_addtimes desc 
             limit " . $recordStart . ',' . $pageSize;
@@ -179,7 +181,6 @@ class WriteOffController
                 left join app_goods as g on JSON_EXTRACT(du.join_data_used_object_json,'$.goods_id') = g.goods_id 
                 {$where}
             group by data_used_classify";
-            dump($sql);
         $rows = Db::select($sql);
         $rows = json_decode(json_encode($rows),true);
         

+ 131 - 1
app/admin/controller/member/QuotaController.php

@@ -19,6 +19,7 @@ use support\exception\BusinessException;
 use support\Request;
 use support\Response;
 use support\view\Raw;
+use Tinywan\Jwt\JwtToken;
 
 class QuotaController extends Curd
 {
@@ -323,8 +324,110 @@ class QuotaController extends Curd
         }
     }
 
-    public static function doWriteOff($params){
+    /**
+     * @Desc 额度核销-批量
+     * @Author Gorden
+     * @Date 2024/6/4 8:32
+     *
+     * @param Request $request
+     * @return Response
+     */
+    public function writeOffBatch(Request $request)
+    {
+        $params = $request->post();
+        $memberId = $params['member_id'] ?? '';
+        $times = $params['times'] ?? '';
+        $code = $params['sms_code'] ?? '';
+
+        if (!$memberId || !$code) {
+            return json_fail("参数异常");
+        }
+
+        // 验证码核验
+        $member = Member::find($memberId);
+        $mobile = $member->member_mobile;
+        $key = "SMS:CODE:WRITE_OFF:" . $mobile;
+        $redisCode = Redis::get($key);
+        if ($redisCode != $code) {
+            return json_fail("验证码错误,请重新输入");
+        }
+        
+        if (!$times) {
+            $params['times'] = date('Y-m-d H:i:s');
+        } else {
+            $params['times'] = date('Y-m-d H:i:s', strtotime($times));
+        }
+
+        Db::beginTransaction();
+        try {
+            foreach($params['quotaList'] as $quota){
+                if (!isset($quota['nbr']) || intval($quota['nbr']) == 0){
+                    continue;
+                }
+                $nbr = intval($quota['nbr']);
+                
+                $quotas = MemberQuota::where('join_quota_member_id', $memberId)
+                ->where('join_member_rule_added_component_id', $quota['rule_added_component_id'])
+                ->where('member_quota_status', 'PENDING')
+                ->limit($nbr)
+                ->get()
+                ->toArray();
+                
+                if ($quotas[0]['member_quota_nbr'] != '-99.00' && count($quotas) < intval($nbr)) {
+                    return json_fail("可核销数量不足");
+                }
+                // 生成核销数据
+                $param = [
+                    'component_id'=>$quota['rule_added_component_id'],
+                    'member_id'=>$memberId,
+                    'write_off_member_id'=>$params['write_off_member_id'],
+                    'dept_premises_id'=>$params['dept_premises_id'] ?? '',
+                    'times'=>$params['times'],
+                    'remark'=>$params['remark'] ?? ''
+                ];
+                $writeOffData = AddedService::generateWriteOffData($param);
+                if($quotas[0]['member_quota_nbr'] != '-99.00'){
+                    foreach ($quotas as $quota) {
+                        $writeOffData['member_quota_id'] = $quota['member_quota_id'];
         
+                        MemberQuota::where('member_quota_id', $quota['member_quota_id'])->update([
+                            'member_quota_status' => 'USED',
+                            'member_quota_used_json' => json_encode($writeOffData)
+                        ]);
+                    }
+                }else{
+                    $quota = $quotas[0];
+                    for($i=0;$i<$nbr;$i++){
+                        $quota['member_quota_id'] = 'MQ'.date('YmdHis').random_string(6,'up');
+                        $quota['member_quota_status'] = 'USED';
+                        $quota['member_quota_used_json'] = json_encode($writeOffData);
+                        $quota['member_quota_addtimes'] = strtotime($quota['member_quota_addtimes']);
+                        $quota['member_quota_nbr'] = 1;
+                        MemberQuota::insert($quota);
+                    }
+                }   
+            }
+
+            _syslog("核销","核销成功");
+
+            //  清除验证码
+            // Redis::del($key);
+
+            Db::commit();
+
+            return json_success("核销成功");
+        } catch (\Exception $e) {
+            Db::rollBack();
+
+            dump($e->getMessage());
+            _syslog("核销","核销失败");
+
+            return json_fail("核销失败");
+        }
+    }
+
+    public static function doWriteOff($params)
+    {    
         $quotas = MemberQuota::where('join_quota_member_id', $params['member_id'])
             ->where('join_member_rule_added_component_id', $params['component_id'])
             ->where('member_quota_status', 'PENDING')
@@ -364,4 +467,31 @@ class QuotaController extends Curd
 
     }
 
+    /**
+     * 会员账户,批量核销选择的权益
+     */
+    public function chooseList(Request $request)
+    {
+        $memberId = $request->get('member_id', '');
+        $componentIds = $request->get('component_ids', []);
+
+        if(empty($componentIds) || !$memberId){
+            return json_fail("参数异常");
+        }
+
+        $components = RuleAddedComponent::whereIn('rule_added_component_id',$componentIds)
+            ->select('rule_added_component_name','rule_added_component_id')
+            ->get();
+        foreach ($components as &$component){
+            $component->unused = MemberQuota::where('join_quota_member_id',$memberId)
+                ->where('join_member_rule_added_component_id',$component->rule_added_component_id)
+                ->where('member_quota_status','PENDING')
+                ->count();
+        }
+
+        $member = Member::where('member_id',$memberId)->select('member_id','member_mobile')->first();
+
+        return json_success('',['member'=>$member,'quotas'=>$components]);
+    }
+
 }

+ 80 - 53
app/admin/controller/order/WholeController.php

@@ -36,6 +36,7 @@ use support\exception\BusinessException;
 use support\Redis;
 use support\Request;
 use support\Response;
+use Webman\Event\Event;
 use Yansongda\Pay\Pay;
 use function Qiniu\Http\Middleware\compose;
 
@@ -69,7 +70,7 @@ class WholeController extends Curd
 
         if (!empty($where['order_status_system']) && in_array($where['order_status_system'], ['PENDING', 'WAITING', 'SENDING', 'RECVING', 'SIGNED', 'CONFIRM'])) {
             $where['order_is_complete'] = 'N';
-            $where['order_category'] = isset($where['order_category']) ? $where['order_category'] : 'NORMAL';
+            $where['order_category'] = isset($where['order_category']) ? $where['order_category'] : ['in','SYSTEM,NORMAL'];
         }
 
         if (!empty($where['order_status_system']) && $where['order_status_system'] == 'RETURN') {
@@ -237,11 +238,16 @@ class WholeController extends Curd
                     $configJson = !empty($component['goods_component_json']) ? json_decode($component['goods_component_json'], true) : [];
                     if (!empty($component['goods'])) {
                         $supplierName = Supplier::where('supplier_id', $component['goods']['join_goods_supplier_id'])->value('supplier_name');
+                        $benefit = MemberBenefit::where('join_benefit_member_id',$item['join_sheet_member_id'])
+                            ->where('join_benefit_goods_id',$component['goods']['goods_id'])
+                            ->where('join_benefit_order_id',$orderId)
+                            ->first();
                         $goodsArr[] = [
                             'goods_name' => $component['goods']['goods_name'],
                             'goods_cover' => getenv('STORAGE_DOMAIN') . $component['goods']['goods_cover'],
                             'supplier_name' => $supplierName,
                             'nbr' => $configJson['nbr'] ?? 0,
+                            'used' => !empty($benefit->member_benefit_used_count) ? intval($benefit->member_benefit_used_count) : ''
                         ];
                     }
                 }
@@ -266,39 +272,41 @@ class WholeController extends Curd
                 }
 
             }
-            if ($item['goods']['goods_classify'] == 'SERVICE') {
-                $benifit = MemberBenefit::where('join_benefit_member_id', $item['join_sheet_member_id'])
+            if (in_array($item['goods']['goods_classify'],['SERVICE','CHNMED','CHNNCD','PACKAGE'])) {
+                $benifits = MemberBenefit::where('join_benefit_member_id', $item['join_sheet_member_id'])
                     ->where('join_benefit_order_id', $orderId)
-                    ->first();
-                if (!empty($benifit)) {
-                    $item['benefit'] = [
-                        'total' => intval($benifit->member_benefit_limit_count),
-                        'used' => intval($benifit->member_benefit_used_count),
-                        'cut' => $benifit->member_benefit_limit_count - $benifit->member_benefit_used_count,
-                    ];
-                    $appontments = Appointment::where('join_appointment_member_benefit_id', $benifit->member_benefit_id)
-                        ->where('appointment_status', 'DONE')
-                        ->select('appointment_id', 'appointment_done_datetime', 'appointment_done_json')
-                        ->get()
-                        ->toArray();
+                    ->get();
+                if (!empty($benifits)) {
                     $item['appontment'] = [];
-                    foreach ($appontments as $appontment) {
-                        $doneJson = [];
-                        $username = '';
-                        if (!empty($appontment['appointment_done_json'])) {
-                            $doneJson = json_decode($appontment['appointment_done_json'], true);
-                            if (isset($doneJson['charge'])) {
-                                $username = SysUser::where('user_id', $doneJson['charge']['charge_user_id'])->value('user_name');
+                    foreach($benifits as $benifit){
+                        $item['benefit'] = [
+                            'total' => intval($benifit->member_benefit_limit_count),
+                            'used' => intval($benifit->member_benefit_used_count),
+                            'cut' => $benifit->member_benefit_limit_count - $benifit->member_benefit_used_count,
+                        ];
+                        $appontments = Appointment::where('join_appointment_member_benefit_id', $benifit->member_benefit_id)
+                            ->where('appointment_status', 'DONE')
+                            ->select('appointment_id', 'appointment_done_datetime', 'appointment_done_json')
+                            ->get()
+                            ->toArray();
+                        foreach ($appontments as $appontment) {
+                            $doneJson = [];
+                            $username = '';
+                            if (!empty($appontment['appointment_done_json'])) {
+                                $doneJson = json_decode($appontment['appointment_done_json'], true);
+                                if (isset($doneJson['charge'])) {
+                                    $username = SysUser::where('user_id', $doneJson['charge']['charge_user_id'])->value('user_name');
+                                }
                             }
+                            $item['appontment'][] = [
+                                'member' => ($item['cert'] ? $item['cert']['member_cert_name'] . '-' : '') . ($item['member'] ? $item['member']['member_mobile'] : ''),
+                                'goods_name' => $item['goods']['goods_name'].'-'.$benifit->member_benefit_name,
+                                'premisses' => isset($doneJson['charge']) ? $doneJson['charge']['charge_premises'] : '',
+                                'username' => $username,
+                                'nbr' => 1,
+                                'done_time' => $appontment['appointment_done_datetime']
+                            ];
                         }
-                        $item['appontment'][] = [
-                            'member' => ($item['cert'] ? $item['cert']['member_cert_name'] . '-' : '') . ($item['member'] ? $item['member']['member_mobile'] : ''),
-                            'goods_name' => $item['goods']['goods_name'],
-                            'premisses' => isset($doneJson['charge']) ? $doneJson['charge']['charge_premises'] : '',
-                            'username' => $username,
-                            'nbr' => 1,
-                            'done_time' => $appontment['appointment_done_datetime']
-                        ];
                     }
                 }
             }
@@ -595,7 +603,7 @@ class WholeController extends Curd
                 $this->saveExpress($params);
             }
             // 买的单个服务
-            if ($goods['goods_classify'] == 'SERVICE') {
+            if (in_array($goods['goods_classify'],['SERVICE','CHNMED','CHNNCD'])) {
                 // 预约表
                 for ($i = 0; $i < intval($params['order_sheet_num']); $i++) {
                     $params['appointmentId'] = 'AP' . date('YmdHis') . random_string(6, 'up');
@@ -603,7 +611,7 @@ class WholeController extends Curd
                     $this->insertAppointment($params, $writeOffDate);
                 }
                 $goods['skuId'] = $params['join_sheet_goods_sku_id'];
-                $goods['category'] = 'SERVICE';
+                $goods['category'] = $goods['goods_classify'];
                 // 权益表
                 $this->insertMemberBenefit($params, $goods);
             } elseif ($goods['goods_classify'] == 'PACKAGE') {  // 一个套餐买多个
@@ -851,12 +859,16 @@ class WholeController extends Curd
         }
     }
 
+    /**
+     * @Desc 发货
+     * @Author Gorden
+     * @Date 2024/7/16 8:43
+     *
+     * @param Request $request
+     * @return Response
+     */
     public function delivery(Request $request)
     {
-        if (!Order::where('order_id', $request->post('order_id'))->where('order_status_system', 'SENDING')->exists()) {
-            return json_fail('订单状态异常');
-        }
-
         // 验证
         $validate = new OrderExpressValidate();
         if (!$validate->scene('delivery')->check($request->post())) {
@@ -879,14 +891,15 @@ class WholeController extends Curd
                 $params['order_express_addtimes'] = strtotime($params['order_express_addtimes']);
 
                 $orderData = [
+                    'order_is_complete' => 'Y',
                     'order_status_system' => 'CONFIRM',
-                    'order_status_storage' => 'EXPRESSING'
+                    'order_status_storage' => 'DONE'
                 ];
 
                 // 7天后自动完成
-                $redis = Redis::connection();
-                $key = Order::AUTOMATIC_COMPLETE_PREFIX . date('Ymd', strtotime("+7 days"));
-                $redis->sadd($key, $params['order_id']);
+//                $redis = Redis::connection();
+//                $key = Order::AUTOMATIC_COMPLETE_PREFIX . date('Ymd', strtotime("+7 days"));
+//                $redis->sadd($key, $params['order_id']);
 
 //                $model = new OrderExpress();
                 $model = OrderExpress::where('join_express_order_id', $params['order_id'])->first();
@@ -899,9 +912,9 @@ class WholeController extends Curd
                     'order_status_storage' => 'EXPRESSING'
                 ];
 
-                // 15天后自动确认收货
+                // 15天后自动完成订单
                 $redis = Redis::connection();
-                $key = Order::AUTOMATIC_RECEIPT_PREFIX . date('Ymd', strtotime("+15 days"));
+                $key = Order::AUTOMATIC_COMPLETE_PREFIX . date('Ymd', strtotime("+15 days"));
                 $redis->sadd($key, $params['order_id']);
 
                 $model = OrderExpress::where('join_express_order_id', $params['order_id'])->first();
@@ -952,6 +965,9 @@ class WholeController extends Curd
             $model->order_express_addtimes = $params['order_express_addtimes'] ?? time();
             $model->save();
 
+            // 事件通知
+            Event::dispatch('client_message.delivery',$params);
+
             Db::commit();
 
             _syslog("订单","发货成功");
@@ -1108,6 +1124,10 @@ class WholeController extends Curd
         if (!$memberId || empty($benefitList)) {
             return json_fail('参数异常');
         }
+        if (empty($code)){
+            return json_fail('请输入验证码');
+        }
+
         $benefitIds = [];
         foreach($benefitList as $benefit){
             if(isset($benefit['nbr']) && intval($benefit['nbr']) > 0){
@@ -1118,14 +1138,14 @@ class WholeController extends Curd
             return json_fail("请填写有效的核销数量");
         }
 
-        // $member = Member::find($memberId);
-        // $mobile = $member->member_mobile;
-        // $key = "SMS:CODE:QUOTA:" . $mobile;
-        // $redisCode = Redis::get($key);
-        // if ($redisCode != $code) {
-        //     return json_fail("验证码错误,请重新输入");
-        // }
-        // Redis::del($key);
+        $member = Member::find($memberId);
+        $mobile = $member->member_mobile;
+        $key = "SMS:CODE:WRITE_OFF:" . $mobile;
+        $redisCode = Redis::get($key);
+        if ($redisCode != $code) {
+            return json_fail("验证码错误,请重新输入");
+        }
+        Redis::del($key);
 
         $benefits = MemberBenefit::whereIn('member_benefit_id', $benefitIds)
             ->where('join_benefit_member_id', $memberId)
@@ -1170,9 +1190,9 @@ class WholeController extends Curd
                         // 更新benefit 表
                         MemberBenefit::where('member_benefit_id',$benefit['member_benefit_id'])->update(['member_benefit_used_count'=>$usedCount]);
                         // 更新Appointment 表
-                        $appointments = Appointment::where('join_appointment_member_benefit_id', $benefit['join_benefit_order_id'])
+                        $appointments = Appointment::where('join_appointment_member_benefit_id', $benefit['member_benefit_id'])
                             ->where('appointment_status', 'INIT')
-                            ->limit($list['nbr'])
+                            ->limit(intval($list['nbr']))
                             ->get();
                         foreach ($appointments as $appointment) {
                             Appointment::where('appointment_id', $appointment->appointment_id)->update([
@@ -1477,6 +1497,9 @@ class WholeController extends Curd
 
             Db::commit();
 
+            // 事件通知
+            Event::dispatch('client_message.refund',$order->join_order_member_id);
+
             _syslog("退款", "发起退款", json_decode($res), $data);
             return json_success("退款成功");
         } catch (PayException $e) {
@@ -1493,6 +1516,10 @@ class WholeController extends Curd
             dump($e->getTrace());
 
             _syslog("退款", "发起退款", $e->getMessage(), $data);
+
+            if (strpos($e->getMessage(),'余额不足') !== false){
+                return json_fail("基本账户余额不足,请充值后重新发起");
+            }
             return json_fail("数据更新失败");
         }
     }
@@ -1572,7 +1599,7 @@ class WholeController extends Curd
             ])
             ->select('order_id','join_order_member_id','order_is_complete','order_status_system')
             ->where("order_is_complete",'N')
-            ->where("order_category",'NORMAL')
+            ->whereIn("order_category",['NORMAL','SYSTEM'])
             ->orderBy('order_addtimes','DESC')
             ->get()
             ->toArray();

+ 63 - 0
app/admin/service/client/MessageService.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace app\admin\service\client;
+
+use app\model\ClientMessage;
+use app\model\SysUser;
+use support\Db;
+
+class MessageService
+{
+    public static function unreadChatMessage()
+    {
+        $times = [
+            strtotime("-40 minutes"),
+            strtotime("-30 minutes"),
+        ];
+        $chats = Db::table('chat_message')
+            ->selectRaw('join_message_recv_id,join_message_send_id,GROUP_CONCAT(chat_message_id) as chat_message_ids,MIN(chat_message_id) as min_chat_message_id')
+            ->where('chat_message_status', 'PENDING')
+            ->whereBetween('chat_message_addtimes',$times)
+            ->groupBy('join_message_send_id', 'join_message_recv_id')
+            ->get();
+
+        foreach ($chats as $chat) {
+            // 接收者是后台人员
+            if (substr($chat->join_message_recv_id, 0, 2) == 'UR') {
+                continue;
+            }
+            if (ClientMessage::where('join_client_message_recv_member_id', $chat->join_message_recv_id)
+                ->where('client_message_classify','CHAT')
+                ->whereJsonContains("client_message_extend_json->message_id",strval($chat->min_chat_message_id))
+                ->exists()) {
+                continue;
+            }
+            // 是客服还是医生
+            $user = SysUser::select('join_user_role_id', 'user_id')
+                ->where('user_id',$chat->join_message_send_id)
+                ->first();
+            if ($user && $user->join_user_role_id == 30){
+                $role = '医生';
+            }elseif ($user && $user->join_user_role_id == 27){
+                $role = '小悦客服';
+            }else{
+                continue;
+            }
+            $messageIds = explode(',',$chat->chat_message_ids);
+            $insertData = [
+                'client_message_classify'=>'CHAT',
+                'join_client_message_send'=>'SYSTEM',
+                'join_client_message_recv_member_id'=>$chat->join_message_recv_id,
+                'client_message_sendtime'=>date('Y-m-d H:i:s'),
+                'client_message_status'=>'PENDING',
+                'client_message_category'=>'NORMAL',
+                'client_message_header_json'=>json_encode(['title'=>'未读消息']),
+                'client_message_body_json'=>json_encode(['content'=>"您有来自".$role."的消息,请及时查收。"]),
+                'client_message_extend_json'=>json_encode(['message_id'=>$messageIds]),
+                'client_message_addtimes'=>time()
+            ];
+            ClientMessage::insert($insertData);
+        }
+
+    }
+}

+ 43 - 5
app/admin/service/order/OrderService.php

@@ -30,15 +30,16 @@ class OrderService
                 // 订单主表
                 Order::where('order_id', $order->order_id)->update([
                     'order_is_complete' => 'Y',
-                    'order_status_system' => 'CONFIRM'
+                    'order_status_system' => 'CONFIRM',
+                    'order_status_storage'=> 'DONE'
                 ]);
                 // 订单详情表
-                OrderSheet::where('join_sheet_order_id', $order->order_id)->update(['order_sheet_status' => 'CONFIRM']);
+                OrderSheet::where('join_sheet_order_id', $order->order_id)->update(['order_sheet_status' => 'DONE']);
 
                 // 7天后自动完成 order_is_complete=Y
-                $redis = Redis::connection();
-                $key = Order::AUTOMATIC_COMPLETE_PREFIX . date('Ymd', strtotime("+7 days"));
-                $redis->sadd($key, $order->order_id);
+//                $redis = Redis::connection();
+//                $key = Order::AUTOMATIC_COMPLETE_PREFIX . date('Ymd', strtotime("+7 days"));
+//                $redis->sadd($key, $order->order_id);
             }
             Db::commit();
         } catch (\Exception $e) {
@@ -46,6 +47,43 @@ class OrderService
         }
     }
 
+    /**
+     * @Desc 自动完成订单
+     * @Author Gorden
+     * @Date 2024/7/16 9:37
+     *
+     * @return void
+     */
+    public static function AutomaticComplete()
+    {
+        Db::beginTransaction();
+        try {
+
+            $redis = Redis::connection();
+            $key = Order::AUTOMATIC_COMPLETE_PREFIX . date('Ymd');
+            $orderIds = $redis->smembers($key);
+
+            foreach ($orderIds as $orderId){
+                $order = Order::where('order_id',$orderId)
+                    ->select('order_is_complete','order_category','order_status_system')
+                    ->first();
+                if ($order && $order->order_is_complete != 'Y' && $order->order_category != 'RETURN' && in_array($order->order_status_system,['RECVING','SIGNED','CONFIRM'])){
+                    // 更新主表
+                    Order::where('order_id',$orderId)->update(['order_is_complete'=>'Y','order_status_system'=>'CONFIRM','order_status_storage'=>'DONE']);
+                    // sheet表
+                    OrderSheet::where('join_sheet_order_id',$orderId)->update(['order_sheet_status'=>'DONE']);
+                }
+            }
+
+            $redis->del($key);
+
+            Db::commit();
+        } catch (\Exception $e) {
+            dump($e->getMessage());
+            Db::rollBack();
+        }
+    }
+
     public static function checkPayingOrder()
     {
         try {

+ 18 - 8
app/api/controller/pay/AlipayController.php

@@ -5,6 +5,7 @@ namespace app\api\controller\pay;
 use app\api\controller\Log;
 use app\model\Order;
 use app\model\PayDetail;
+use Payment\Common\PayException;
 use support\Db;
 use support\Request;
 use Yansongda\Pay\Exceptions\BusinessException;
@@ -15,12 +16,15 @@ class AlipayController
     public function index(Request $request)
     {
         $params = $request->all();
-        if (!isset($params['order_id'])){
+        if (!isset($params['order_id'])) {
             return json_fail('参数异常');
         }
+        if (!isset($params['platform'])) {
+            return json_fail('缺少平台参数');
+        }
         $orderId = $params['order_id'];
-        $payDetail = PayDetail::where('join_pay_order_id',$orderId)->where('pay_status','WAITING')->first();
-        if (!$payDetail){
+        $payDetail = PayDetail::where('join_pay_order_id', $orderId)->where('pay_status', 'WAITING')->first();
+        if (!$payDetail) {
             return json_fail('订单异常');
         }
         $payData = [
@@ -34,18 +38,24 @@ class AlipayController
 
             $payDetail->pay_prepayid = 'ALIPAY';
             $payDetail->save();
-
-            $result = Pay::alipay(config('payment.alipay'))->app($payData)->getContent();
+            if ($params['platform'] == 'android') { // APP支付
+                $result = Pay::alipay(config('payment.alipay'))->app($payData)->getContent();
+            } elseif ($params['platform'] == 'WeChat') {    // 网页支付
+                $result = Pay::alipay(config('payment.alipay'))->wap($payData)->getContent();
+            } else {
+                Db::rollBack();
+                return json_fail("平台参数无效");
+            }
 
             Db::commit();
 
-            return json_success('',$result);
-        } catch (BusinessException $e) {
+            return json_success('', $result);
+        } catch (PayException $e) {
             Db::rollBack();
             return json_fail($e->getMessage());
         } catch (\Exception $e) {
             Db::rollBack();
-            return json_fail('下单失败');
+            return json_fail('下单失败' . $e->getMessage());
         }
 
 

+ 28 - 4
app/api/controller/pay/WxpayController.php

@@ -4,6 +4,7 @@ namespace app\api\controller\pay;
 
 use app\model\Order;
 use app\model\PayDetail;
+use Payment\Common\PayException;
 use support\Db;
 use support\Request;
 use Yansongda\Pay\Exceptions\BusinessException;
@@ -18,6 +19,9 @@ class WxpayController
         if (!isset($params['order_id'])) {
             return json_fail('参数异常');
         }
+        if (!isset($params['platform'])){
+            return json_fail('缺少平台参数');
+        }
         $orderId = $params['order_id'];
         $payDetail = PayDetail::where('join_pay_order_id',$orderId)->where('pay_status','WAITING')->first();
         if (!$payDetail) {
@@ -34,16 +38,36 @@ class WxpayController
             $payDetail->pay_prepayid = 'WXPAY';
             $payDetail->save();
 
-            $alipay = Pay::wechat(config('payment.wxpay'))->app($payData)->getContent();
+            if ($params['platform'] == 'android'){  // APP
+                $wxpay = Pay::wechat(config('payment.wxpay'))->app($payData)->getContent();
+            }elseif ($params['platform'] == 'WeChat'){  // 公众号
+                if (empty($params['openid'])){
+                    Db::rollBack();
+                    return json_fail("缺少OpenID 参数");
+                }
+                $payData['openid'] = $params['openid'];
+                $config = config('payment.wxpay');
+                $wxpay = Pay::wechat($config)->mp($payData);
+            }elseif ($params['platform'] == 'mp-weixin'){   // 小程序
+                if (empty($params['openid'])){
+                    Db::rollBack();
+                    return json_fail("缺少OpenID 参数");
+                }
+                $payData['openid'] = $params['openid'];
+                $wxpay = Pay::wechat(config('payment.wxpay'))->miniapp($payData);
+            }else{
+                throw new PayException("平台参数无效");
+            }
 
             Db::commit();
-            return json_success('', json_decode($alipay, true));
-        } catch (BusinessException $e) {
+            return json_success('', json_decode($wxpay, true));
+        } catch (\support\exception\BusinessException $e) {
             Db::rollBack();
             return json_fail($e->getMessage());
         } catch (\Exception $e) {
             Db::rollBack();
-            return json_fail('下单失败');
+            dump($e->getMessage());
+            return json_fail('下单失败:'.$e->getMessage());
         }
 
 

+ 78 - 0
app/event/ClientMessageEvent.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace app\event;
+
+use app\model\ClientMessage;
+use app\model\Order;
+use app\model\OrderSheet;
+
+class ClientMessageEvent
+{
+    /**
+     * @Desc 发货通知
+     * @Author Gorden
+     * @Date 2024/7/16 10:28
+     *
+     * @param $params
+     * @return void
+     */
+    public function delivery($params)
+    {
+        try {
+            $order = Order::where('order_id', $params['order_id'])
+                ->select('join_order_member_id')
+                ->first();
+            $clientMessage = new ClientMessage();
+            $clientMessage->client_message_classify = 'ORDER';
+            $clientMessage->join_client_message_send = 'SYSTEM';
+            $clientMessage->join_client_message_recv_member_id = $order->join_order_member_id;
+            $clientMessage->client_message_sendtime = date('Y-m-d H:i:s');
+            $clientMessage->client_message_status = 'PENDING';
+            $clientMessage->client_message_category = 'NORMAL';
+            $clientMessage->client_message_header_json = json_encode(['title' => '订单消息']);
+            $clientMessage->client_message_addtimes = time();
+
+            $sheet = OrderSheet::with([
+                'goods' => function ($query) {
+                    $query->select('goods_id', 'goods_name');
+                }
+            ])->where('join_sheet_order_id', $params['order_id'])
+                ->select('order_sheet_id', 'join_sheet_goods_id', 'join_sheet_order_id', 'order_sheet_num')
+                ->first();
+
+
+            if ($params['express_type'] == '自提') {
+                $clientMessage->client_message_body_json = json_encode([
+                    'content' => '提货通知:您于' . date('Y年m月d日') . '在' . $params['order_express_premises'] . '提取了您购买的商品【' . $sheet->goods->goods_name . '】,数量:【' . intval($sheet->order_sheet_num) . '】。'
+                ]);
+            } else {
+                $clientMessage->client_message_body_json = json_encode([
+                    'content' => '发货通知:您购买的商品【' . $sheet->goods->goods_name . '】,数量:【' . intval($sheet->order_sheet_num) . '】已发货,物流公司:' . $params['order_express_company'] . ',物流单号:' . $params['order_express_code'] . ',请注意查收。'
+                ]);
+            }
+
+            $clientMessage->save();
+        } catch (\Exception $e) {
+        }
+    }
+
+
+    public function refund($memberId)
+    {
+        try {
+            $clientMessage = new ClientMessage();
+            $clientMessage->client_message_classify = 'ORDER';
+            $clientMessage->join_client_message_send = 'SYSTEM';
+            $clientMessage->join_client_message_recv_member_id = $memberId;
+            $clientMessage->client_message_sendtime = date('Y-m-d H:i:s');
+            $clientMessage->client_message_status = 'PENDING';
+            $clientMessage->client_message_category = 'NORMAL';
+            $clientMessage->client_message_header_json = json_encode(['title' => '订单消息']);
+            $clientMessage->client_message_body_json = json_encode(['content' => '退款通知:您申请的退款已原路返回,请注意查收。']);
+            $clientMessage->client_message_addtimes = time();
+            $clientMessage->save();
+
+        } catch (\Exception $e) {
+        }
+    }
+}

+ 2 - 1
composer.json

@@ -43,7 +43,8 @@
     "ldy/payment": "^3.6",
     "intervention/image": "^2.7",
     "webman/console": "^1.3",
-    "yansongda/pay": "v2.10"
+    "yansongda/pay": "v2.10",
+    "webman/event": "^1.0"
   },
   "suggest": {
     "ext-event": "For better performance. "

+ 10 - 0
config/event.php

@@ -0,0 +1,10 @@
+<?php
+
+return [
+    'client_message.delivery' => [
+        [\app\event\ClientMessageEvent::class, 'delivery']
+    ],
+    'client_message.refund' => [
+        [\app\event\ClientMessageEvent::class, 'refund']
+    ],
+];

+ 5 - 3
config/payment.php

@@ -15,8 +15,8 @@ return [
     ],
     'alipay' => [
         'app_id' => '2021004155613207',
-        'notify_url' => getenv('NOTIFY_DOMAIN').'/api.pay.notify.php',
-        'return_url' => getenv('NOTIFY_DOMAIN').'/api.pay.notify.php',
+        'notify_url' => getenv('NOTIFY_DOMAIN') . '/api.pay.notify.php',
+        'return_url' => getenv('NOTIFY_DOMAIN') . '/api.pay.notify.php',
         'ali_public_key' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2NY/qJXPHCcbYdeRMHjK5uZK7nL9Uhpyq+itpl/lqQSmuQ8Kz6zHsQOEPeAr5b4CBU/7mr/UhUKrsCiIsjqFOkLS/htrksdPEbzDSTC55kpYnt3RHCa/wuLu2rJ/44gatEklS7s+fgX4AYvN5LjjF5iaei/ec8naTlGM5odVL/smXjagFFiM3oAsHitPuVyBOmT5oSyxACy6J/b5bnvykI+1BD5ZOisT4A1n98yyG1utWJdPzQhCWUAN/gFuud7PsAXONbt/HSw940rxQCF64tg2q2oICFgdtxpLZk08GTzsz957Y02nskovTXVLwVPzvYvdzNCT2Htl3vZmacvIqQIDAQAB',
         // 加密方式: **RSA2**
         'private_key' => 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaUCndAhC4NUmpA/kL7fcs7o/kP044ZezMKUc0f/kh6n78D7TS+EtpJz2LODFXxdNamodyyz+AZh+aM22kPAXRFLWmjont1ODx3pQm2po0YIQxRz+v/4mj7OuZJ6gVF3Bvlr60g8LbFvnyqtG4vjBim/NIDCv0M294o7fRElPdxdf3yxgyzqBaFc7PmMEYVSVhBnlYHU3Hwczf2ylbv9A0g1fTLhaqqnSt5aJ4xETVoqtX0Vvh6GsnecObrgodZ9HD+Dcx70W+qQ/Td2R89PiHKR4d9ZNRu6H6J9OMYxxUvEGcFfvi+c3OT3PCf2X5RS4SD/VFsxwQXmmkye38qiDrAgMBAAECggEAE3EgJSE6fAryseG3QgKETtvrsyUqtL5avEpDF2E8QUKrJxTPgnkX/zKbdWvqA5YAD/1CLXtgD8xOFP5/xN5vGS2TyV1SEW3tvWt+nPqTzR+P6CmC46i9bbLO6Cfv7GBcoSKL+nBTX4kgiqts6urDa9kcKKqn6weD9t4hrayydlFhiXGT+zUtnkZobJIWmzG+ZLjusn/wp4vyQyXQGnjyiEmzCHab/n8hLfPR9d/3mfG/rj/mIJ9630H+mstMTGoZxDKobeC+k5HQpICyY9bbmug7IgZtqHCO0xou8tpinMRmk/wRD/Bg4XIDdAYgGucb0rpRvbI9KxgGpzpGFXFkuQKBgQDdY/eMdrwnH13XQT4l+ZrjEi7fkCTFvmfafJy1G55feFK9k+YmX7UXtcbw/bc59CqjIL/bpkYy1t+0SrB0eywGvMFBD3G3EZQnQmFmHW7bAba3pTcEoVlyhm9Oz9igvbpI1fZmaeqE+9DOVlWwtcLjhpBh/wuHP5KgyfWKBqwrBQKBgQCyb8PgKklTNFS7iHKBKTIx/ES4xZBSej/Q/lLY0ZGc2LTTGn2HxmmbcJIH5fR4+opOGSGsXc/vfp2pGk1yq42rRVVjUG7Y68J2VpIjELQ8SNbSK+4YqS8VI+Kez0m7ZDEWTwxMRbQTiCaBRUwGhjkReLyLrfXmz5Syxaf7rBg/LwKBgQDE4eQCDI2jFSf1B9ZnGyT9DuyUcLHjEUN2cB9EiH09VdnvMhoYwkBgB44WPuu1JEjOrY8xnRsMlz52LX3i+K7chvwuCbgNIBrrFwNbNo2hQlLl2o2lFoBfcuKF6h0yRcfmgjEQPt0Kyo6VEP4/mkTo5oB8Rb5Q1t5lE3XC+9AcqQKBgEJDENkguuQEDecqL2NZegNn69k1vHd0YFhq6TcM8+br7pJqRu1xt+v6LLB0K4n1eACygnewyrPkMAYI93O60zwj3iaoStGRE0DAuzn8TQIKBoQ7vgo4YXyXO+O/lGDbPwNKzYVRaSLLr4jXw/i0RWMAk/vG2QciVNTiY5Qo/0QPAoGANqq2RacHmcevwp3S3iXfHGxb8kfG90aGDtTr9AY965IGmy4ckKEZJ5+XkhH8Yi+YYWyIkTpgsSQUCDoBSvQ7FBSFnYn5CcX8MIpsx833DpGEK4PMeje0q/rbQ4P1/gOgvgICGWJsOYkzooFhX+TVGXCXE4EE3E471GadQOhy3EQ=',
@@ -35,9 +35,11 @@ return [
     ],
     'wxpay' => [
         'appid' => 'wx089c26eaf96c3d51', // APP APPID
+        'app_id'=>'wxc6274da7198e3eb4',
+        'miniapp_id' => 'wxc4a09d3062d60a94',
         'mch_id' => '1680393367',
         'key' => 'c451cedbab8058e3502a35c6dacf0919',
-        'notify_url' => getenv('NOTIFY_DOMAIN').'/api.pay.notify.php',
+        'notify_url' => getenv('NOTIFY_DOMAIN') . '/api.pay.notify.php',
         'cert_client' => config_path('cert/wxpay/apiclient_cert.pem'), // optional,退款等情况时用到
         'cert_key' => config_path('cert/wxpay/apiclient_key.pem'),// optional,退款等情况时用到
         'log' => [ // optional

+ 4 - 0
config/plugin/webman/event/app.php

@@ -0,0 +1,4 @@
+<?php
+return [
+    'enable' => true,
+];

+ 17 - 0
config/plugin/webman/event/bootstrap.php

@@ -0,0 +1,17 @@
+<?php
+/**
+ * This file is part of webman.
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the MIT-LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @author    walkor<walkor@workerman.net>
+ * @copyright walkor<walkor@workerman.net>
+ * @link      http://www.workerman.net/
+ * @license   http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+
+return [
+    Webman\Event\BootStrap::class,
+];

+ 7 - 0
config/plugin/webman/event/command.php

@@ -0,0 +1,7 @@
+<?php
+
+use Webman\Event\EventListCommand;
+
+return [
+    EventListCommand::class
+];

+ 7 - 1
process/Task.php

@@ -3,6 +3,7 @@
 namespace process;
 
 use app\admin\controller\notify\RechargeController;
+use app\admin\service\client\MessageService;
 use app\admin\service\goods\GoodsService;
 use app\admin\service\order\OrderService;
 use Workerman\Crontab\Crontab;
@@ -21,12 +22,17 @@ class Task
 //            GoodsService::checkOffListing();
             // 未支付30分钟取消
             OrderService::checkPayingOrder();
+
+            // 会员消息 30分钟未读,发送站内信
+            MessageService::unreadChatMessage();
         });
 
-        // 每天的8点执行,注意这里省略了秒位
+        // 每天的2点执行,注意这里省略了秒位
         new Crontab('0 2 * * *', function () {
             // 签收后7天自动确认收货(已完成)
             OrderService::AutomaticReceipt();
+            // 发货后15天自动完成
+            OrderService::AutomaticComplete();
         });
     }
 }

+ 3 - 0
route/admin.php

@@ -722,6 +722,9 @@ Route::group('/admin', function () {
             Route::post('/update', [\app\admin\controller\member\QuotaController::class, 'update']);
             Route::post('/writeOff', [\app\admin\controller\member\QuotaController::class, 'writeOff']);
             Route::delete('/delete', [\app\admin\controller\member\QuotaController::class, 'delete']);
+            Route::get('/chooseList', [\app\admin\controller\member\QuotaController::class, 'chooseList']);
+
+            Route::post('/writeOffBatch', [\app\admin\controller\member\QuotaController::class, 'writeOffBatch']);
         });
     });
     /* 营销管理 */