zory 2 weeks ago
parent
commit
c9d5e042f4

+ 27 - 10
app/controller/mini/Auth.php

@@ -5,17 +5,32 @@ namespace app\controller\mini;
 use app\extra\basic\Base;
 use app\extra\douyin\Crypt;
 use app\extra\tools\CodeExtend;
+use app\model\saas\SaasMember;
+use app\model\saas\SaasOrderLife;
 use LinFly\Annotation\Route\Controller;
 use LinFly\Annotation\Route\Route;
 use support\Request;
 use support\Response;
-
+use Shopwwi\WebmanAuth\Auth as AuthMode;
 
 #[Controller(prefix: "/api/dy/home")]
 class Auth extends Base
 {
 
 
+    #[Route(path: "license",methods: "post")]
+    public function getLicense(): Response
+    {
+        try {
+            return success("ok",[
+                "img" => "https://hx-mini.jsshuita.com.cn/license.jpg"
+            ]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
     /**
      * @param Request $request
      * @return Response
@@ -31,14 +46,20 @@ class Auth extends Base
             if (!isset($sessionKey['openid'])) return error("获取数据失败");
             $openId = $sessionKey['openid'];
             $userIn = [
-                'openid'    => $openId,
+                'open_id'   => $openId,
                 "create_ip" => $request->getRealIp(),
                 "nickname"  => "用户_".strtoupper(CodeExtend::random(3,5)),
                 "avatar"    => "https://img.inmei.cc/logo.png"
             ];
-            print_r($sessionKey);
-            print_r($userIn);
-            return error("err");
+            $user = (new SaasMember)->where("open_id",$openId)->findOrEmpty();
+            $userIn['id'] = $user['id'];
+            if ($user->isEmpty()) {
+                $userIn['id'] = $user->insertGetId($userIn);
+            }
+            return successTrans("success.data",[
+                "user"      => get_object_vars((new AuthMode)->guard("member")->login($userIn)),
+                "coupon"    => (new SaasOrderLife)->where("open_id",$openId)->where("status",1)->select()
+            ]);
         } catch (\Throwable $throwable) {
             return error($throwable->getMessage());
         }
@@ -48,10 +69,8 @@ class Auth extends Base
     protected function decrypt2code($private_key, $ciphertext_str) {
         // 解码 base64 密文
         $ciphertext = base64_decode($ciphertext_str);
-
         // 使用私钥解密
         openssl_private_decrypt($ciphertext, $plaintext, $private_key, OPENSSL_PKCS1_PADDING);
-
         if ($plaintext === false) {
             return [];
         }
@@ -64,9 +83,7 @@ class Auth extends Base
         $key = base64_decode($session_key);
         $iv_decoded = base64_decode($iv);
         // 使用 AES-256-CBC 模式解密
-        $decrypted = openssl_decrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv_decoded);
-
-        return $decrypted;
+        return openssl_decrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv_decoded);
     }
 
 

+ 47 - 0
app/controller/mini/Confirm.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace app\controller\mini;
+
+use app\extra\basic\Base;
+use app\extra\douyin\Crypt;
+use app\extra\tools\CodeExtend;
+use app\middleware\DyMiddleware;
+use app\model\saas\SaasMember;
+use app\model\saas\SaasOrderLife;
+use app\model\saas\SaasStore;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use Shopwwi\WebmanAuth\Auth as AuthMode;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/api/dy/confirm"),Middleware(DyMiddleware::class)]
+class Confirm extends Base
+{
+
+    #[Route(path: "detail",methods: "post")]
+    public function getLifeOrder(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "order.require" => "请求参数错误"
+            ],'post');
+            if (!is_array($param)) return error($param);
+            $order = (new SaasOrderLife)->where("order_id",$param['order'])->where("open_id",$request->user['open_id'])->findOrEmpty();
+            if ($order->isEmpty()) return error("订单尚未同步");
+            $store = (new SaasStore)->where("store_id",$order['store_id'])->where("agent_id",$order['agent_id'])->field("service_mobile,service_type,service_at_start,service_at_end")->findOrEmpty();
+            $time = [];
+            for ($i = 0;$i <= 15;$i ++)
+            {
+                $time[$i]['day'] = date("m月d日",strtotime("+{$i} day"));
+                $time[$i]['children'] = getHourlyTimeSlots();
+            }
+            return successTrans("success.data",compact("order","store",'time'));
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 52 - 0
app/controller/mini/Notify.php

@@ -3,6 +3,8 @@
 namespace app\controller\mini;
 
 use app\extra\basic\Base;
+use app\model\saas\SaasGoods;
+use app\model\saas\SaasOrderLife;
 use LinFly\Annotation\Route\Controller;
 use LinFly\Annotation\Route\Route;
 use support\Request;
@@ -13,6 +15,29 @@ use support\Response;
 class Notify extends Base
 {
 
+
+
+    /**
+     * 核销工具解决方案-spi
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "pay",methods: "post")]
+    public function getPayStatue(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            echo getDateFull()."==支付结果回调==\n";
+            print_r($param);
+            return json([
+                "err_no"    => 0,
+                "err_tips"  => "success"
+            ]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
     /**
      * 核销工具解决方案-spi
      * @param Request $request
@@ -48,6 +73,33 @@ class Notify extends Base
             switch ($param['type'])
             {
                 case "pre_create_order": // 预下单回调
+                    $orderData = json_decode($param['msg']);
+                    $orderGoods = (new SaasGoods)->where("out_id",$orderData['goods'][0]['goods_id'])->findOrEmpty();
+                    if ($orderGoods->isEmpty()) return json([
+                        "err_no"    => 0,
+                        "err_tips"  => "success"
+                    ]);
+                    (new SaasOrderLife)->insertGetId([
+                        "open_id"   => $orderData['open_id'],
+                        "agent_id"  => $orderGoods['agent_id'],
+                        "store_id"  => $orderGoods['agent_id'],
+                        "order_id"  => $orderData['order_id'],
+                        "product_name"  => $orderData['goods'][0]['title'],
+                        "product_img"   => $orderData['goods'][0]['img_url'],
+                        "out_id"    => $orderData['goods'][0]['goods_id'],
+                        "order_amount"  => $orderData['goods'][0]['price'],
+                        "pay_amount"    => $orderData['goods'][0]['price'],
+                        "count"         => $orderData['goods'][0]['quantity'],
+                        "status"        => 0
+                    ]);
+                    return json([
+                        "out_order_no"  => $orderData['order_id'],
+                        "order_entry_schema"    => [
+                            "path"      => "page/order/detail",
+                            "params"    => ['order' => $orderData['order_id']]
+                        ],
+                        "pay_notify_url"    => "https://hx-mini-api.jsshuita.com.cn/notify/pay"
+                    ]);
                     break;
                 case "pre_create_refund": // 退款审核回调
                     break;

+ 126 - 0
app/controller/mini/Order.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace app\controller\mini;
+
+use app\extra\basic\Base;
+use app\extra\douyin\Crypt;
+use app\extra\service\saas\OrderService;
+use app\extra\tools\CodeExtend;
+use app\middleware\DyMiddleware;
+use app\model\saas\SaasMember;
+use app\model\saas\SaasOrderLife;
+use app\model\saas\SaasStore;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use Shopwwi\WebmanAuth\Auth as AuthMode;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/api/dy/order"),Middleware(DyMiddleware::class)]
+class Order extends Base
+{
+
+    protected array $noNeedLogin = ["getLifeOrder"];
+
+
+    /**
+     * 来客订单详情
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "life",methods: "post")]
+    public function getLifeOrder(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "order.require" => "请求参数错误",
+                "code.require"  => "请求参数错误"
+            ],'post');
+            if (!is_array($param)) return error($param);
+            $config = sConf("dy.");
+            $sessionKey = (new Crypt)->config(['appid' => $config['appid'],'secret' => $config['secret']])->getSessionKey($param['code']);
+            if (empty($sessionKey)) return error("授权登录失败");
+            if (!isset($sessionKey['openid'])) return error("获取数据失败");
+            $openId = $sessionKey['openid'];
+            $userIn = [
+                'open_id'   => $openId,
+                "create_ip" => $request->getRealIp(),
+                "nickname"  => "用户_".strtoupper(CodeExtend::random(3,5)),
+                "avatar"    => "https://img.inmei.cc/logo.png"
+            ];
+            $user = (new SaasMember)->where("open_id",$openId)->findOrEmpty();
+            $userIn['id'] = $user['id'];
+            if ($user->isEmpty()) {
+                $userIn['id'] = $user->insertGetId($userIn);
+            }
+            $order = (new SaasOrderLife)->where("order_id",$param['order'])->where("open_id",$openId)->findOrEmpty();
+            if ($order->isEmpty()) return error("订单尚未同步");
+            return successTrans("success.data",[
+                "user"      => get_object_vars((new AuthMode)->guard("member")->login($userIn)),
+                "order"     => $order
+            ]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 获取门店
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "store",methods: "post")]
+    public function getLocationStore(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "order.require"     => "请求参数错误",
+                "location.require"  => "请求参数错误"
+            ],'post');
+            if (!is_array($param)) return error($param);
+            $order = (new SaasOrderLife)->where("order_id",$param['order'])->where("open_id",$request->user['open_id'])->findOrEmpty();
+            if ($order->isEmpty()) return error("订单尚未同步");
+            $location = explode(",",$param['location']);
+            $resp = store_region($location[1],$location[0],2,"store_id={$order['store_id']} and agent_id={$order['agent_id']}");
+            foreach ($resp as $key=>$val) {
+                $resp[$key] = $val;
+                $resp[$key]['juli'] = format_money($val['juli']/1000);
+            }
+            $store = (new SaasStore)->where("store_id",$order['store_id'])->where("agent_id",$order['agent_id'])->findOrEmpty();
+            return success("ok",[
+                "data"  => $resp,
+                "store" => $store->toArray()
+            ]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 订单列表
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "data",methods: "get")]
+    public function getOrderList(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "page.default"  => 1,
+                "size.default"  => 10,
+                "status.default"  => 0
+            ]);
+            if (!is_array($param)) return error($param);
+            $param['open_id']  = $request->user['open_id'];
+            $list = (new OrderService)->getDataListMini($param);
+            return successTrans(100010,pageFormat($list));
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 39 - 0
app/controller/mini/User.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace app\controller\mini;
+
+use app\extra\basic\Base;
+use app\middleware\DyMiddleware;
+use app\model\saas\SaasMember;
+use app\model\saas\SaasOrderLife;
+use app\model\saas\SaasStore;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/api/dy/user"),Middleware(DyMiddleware::class)]
+class User extends Base
+{
+
+
+    /**
+     * 获取门店
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "info",methods: "get")]
+    public function getUserInfo(Request $request): Response
+    {
+        try {
+            $user = (new SaasMember)->where("open_id",$request->user['open_id'])->field('nickname,avatar')->findOrEmpty();
+            if ($user->isEmpty()) return error("数据不存在");
+            return success("ok",$user->toArray());
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 34 - 0
app/extra/service/saas/OrderService.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace app\extra\service\saas;
+
+use app\extra\basic\Service;
+use app\model\saas\SaasOrder;
+
+class OrderService extends Service
+{
+
+
+    public function getDataListMini(array $param = [])
+    {
+        $this->mode = new SaasOrder();
+        return $this->searchVal($param,$this->searchFilter($param))->with(['goods' => function($query){
+            $query->field("product_name,product_id,image_list,actual_amount_once");
+        }])->paginate([
+            "list_rows" => $param['size'],
+            "page"      => $param['page']
+        ]);
+    }
+
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['agent']) && $filter[] = ["agent_id", '=', $param['shop']];
+        !empty($param['open_id']) && $filter[] = ["open_id", '=', $param['open_id']];
+        !empty($param['status']) && $filter[] = ["status", '=', ($param['status']-1)];
+        !empty($param['order']) && $filter[] = ["order_sn", 'like', "%{$param['order']}%"];
+        return $filter;
+    }
+
+}

+ 41 - 0
app/functions.php

@@ -403,4 +403,45 @@ if (!function_exists('sOplog')) {
     {
         return SystemService::setOplog($action, $content,$userName);
     }
+}
+
+
+
+if(!function_exists('store_region')){
+    /**
+     * 返回附近司机数据
+     * @param $latitude
+     * @param $longitude
+     * @param $type 1 返回查询影响记录数;2 返回数据数组
+     */
+    function store_region($latitude,$longitude,$type = 1,$where = 'status = 1',$field="*"){
+        $sql = "select ".$field." from(
+SELECT id,poi_id,poi_name,status,poi_address,longitude,latitude,
+ROUND(6378.138*2*ASIN(SQRT(POW(SIN(({$latitude}*PI()/180-latitude*PI()/180)/2),2)+COS({$latitude}*PI()/180)*COS(latitude*PI()/180)*POW(SIN(({$longitude}*PI()/180-longitude*PI()/180)/2),2)))*1000) AS juli
+FROM saas_store_shop where ".$where.") as tmp_table_name order by juli asc";
+        if($type == 1){
+            return \think\facade\Db::execute($sql);
+        }
+        return \think\facade\Db::query($sql);
+    }
+}
+
+if(!function_exists('getHourlyTimeSlots')){
+    function getHourlyTimeSlots($startHour = 9, $endHour = 22, $format = 'H:i'): array
+    {
+        $slots = [];
+
+        for ($hour = $startHour; $hour < $endHour; $hour++) {
+            $startTime = sprintf('%02d:00', $hour);
+            $endTime = sprintf('%02d:00', $hour + 1);
+
+            $slots[] = [
+                'start' => $startTime,
+                'end' => $endTime,
+                'display' => $startTime . ' - ' . $endTime
+            ];
+        }
+
+        return $slots;
+    }
 }

+ 3 - 3
app/middleware/DyMiddleware.php

@@ -17,12 +17,12 @@ class DyMiddleware implements MiddlewareInterface
             $controller = new \ReflectionClass($request->controller);
             $noNeedLogin = $controller->getDefaultProperties()['noNeedLogin']??[];
             if (empty($noNeedLogin) || !in_array($request->action, $noNeedLogin)) {
-                $type = $request->header('api-type','');
+                $type = $request->header('platform','');
                 if (empty($type)) return json(['code'=> 0,'msg'=> trans("error.param")]);
                 $token =  $request->header("Authorization","");
                 if (empty($token)) return json(['code'=> 0,'msg'=> trans("error.request")]);
-                (new JWT)->guard("admin")->verify();
-                $user = (new Auth)->guard("admin")->user();
+                (new JWT)->guard("member")->verify();
+                $user = (new Auth)->guard("member")->user();
                 if (empty($user)) return json(['code'=>401,'msg'=> trans("error.login")]);
                 $request->user = $user->toArray();
             }

+ 47 - 0
app/model/saas/SaasMember.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace app\model\saas;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property string $open_id 
+ * @property string $nickname 
+ * @property string $avatar 
+ * @property string $create_ip 
+ * @property mixed $create_at
+ */
+class SaasMember extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "saas_member";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 59 - 0
app/model/saas/SaasOrder.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace app\model\saas;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property integer $uuid 
+ * @property integer $agent_id 代理id
+ * @property integer $store_id 店铺id
+ * @property string $order_id 
+ * @property integer $product_id 商品ID
+ * @property string $product_name 
+ * @property string $username 
+ * @property string $code 
+ * @property string $mobile 
+ * @property string $region 
+ * @property string $address 
+ * @property integer $status 
+ * @property string $express_id 顺丰订单id
+ * @property integer $is_send 1已发送
+ * @property integer $is_auto 1自动呼叫快递
+ * @property string $remark 
+ * @property mixed $create_at
+ */
+class SaasOrder extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "saas_order";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 72 - 0
app/model/saas/SaasOrderLife.php

@@ -0,0 +1,72 @@
+<?php
+
+namespace app\model\saas;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property string $open_id 
+ * @property integer $agent_id 代理id
+ * @property integer $store_id 店铺id
+ * @property string $order_id 
+ * @property string $product_name 
+ * @property integer $out_id 来客商品ID
+ * @property integer $order_amount 订单金额
+ * @property integer $pay_amount 实际支付金额
+ * @property mixed $pay_at 支付时间
+ * @property mixed $refund_at 退款时间
+ * @property mixed $refund_apply_at 退款申请时间
+ * @property integer $intention_poi_id 下单门店
+ * @property string $mobile 
+ * @property integer $count 
+ * @property integer $status 
+ * @property integer $is_send 1已发送过短信
+ * @property string $remark 
+ * @property mixed $create_at
+ */
+class SaasOrderLife extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "saas_order_life";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+    public function getOrderAmountAttr($data): string
+    {
+        if ($data == 0) return 0;
+        return format_money($data/100);
+    }
+
+    public function getPayAmountAttr($data): string
+    {
+        if ($data == 0) return 0;
+        return format_money($data/100);
+    }
+
+}

+ 7 - 1
config/plugin/shopwwi/auth/app.php

@@ -7,8 +7,14 @@
          'admin' => [
              'key' => 'id',
              'field' => ['id','username'], //设置允许写入扩展中的字段
-             'num' => 0, //-1为不限制终端数量 0为只支持一个终端在线 大于0为同一账号同终端支持数量 建议设置为1 则同一账号同终端在线1个
+             'num' => 2, //-1为不限制终端数量 0为只支持一个终端在线 大于0为同一账号同终端支持数量 建议设置为1 则同一账号同终端在线1个
              'model'=> [\app\model\system\SystemUser::class,'thinkphp'] // 当为数组时 [app\model\Test::class,'thinkphp'] 来说明模型归属
+         ],
+         'member' => [
+             'key' => 'id',
+             'field' => ['id','open_id'], //设置允许写入扩展中的字段
+             'num' => 0, //-1为不限制终端数量 0为只支持一个终端在线 大于0为同一账号同终端支持数量 建议设置为1 则同一账号同终端在线1个
+             'model'=> [\app\model\saas\SaasMember::class,'thinkphp'] // 当为数组时 [app\model\Test::class,'thinkphp'] 来说明模型归属
          ]
      ],
      'jwt' => [