Zory 1 miesiąc temu
rodzic
commit
7ba4f8fcd9

+ 86 - 0
app/controller/api/Auth.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace app\controller\api;
+
+use app\extra\basic\Base;
+use app\extra\dyLife\Crypt;
+use app\extra\tools\CodeExtend;
+use app\middleware\AuthMiddleware;
+use app\model\saas\SaasUserOpen;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Attributes\Route\Controller;
+use LinFly\Annotation\Attributes\Route\GetMapping;
+use LinFly\Annotation\Attributes\Route\Middleware;
+use LinFly\Annotation\Attributes\Route\PostMapping;
+use support\Request;
+use Shopwwi\WebmanAuth\Facade\Auth as AuthFacade;
+use support\Response;
+
+
+#[Controller("/dy/auth"),Middleware(AuthMiddleware::class)]
+class Auth extends Base
+{
+
+    protected array $noNeedLogin = ["log2mobile"];
+
+    #[Inject]
+    protected SaasUserOpen $model;
+
+    #[PostMapping("mobile")]
+    public function log2mobile(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            $sessionKey = (new Crypt)->config($this->getDyConfig())->getSessionKey($param['login']);
+            if (empty($sessionKey)) return error("授权登录失败");
+            $mobile = [];
+            if (!empty($param['code'])) {
+                $mobileStr = (new Crypt)->config($this->getDyConfig())->token()->getMobile($param['code']);
+                if (!empty($mobileStr)) {
+                    $mobile = $this->decrypt2code(sConf('wechat.min_private_key'), $mobileStr);
+                }
+            }
+            $userInfo = [
+                "openid"    => $sessionKey['openid'],
+                "nickname"  => "DY-".strtoupper(CodeExtend::random(5,3)),
+                "create_ip" => $request->getRealIp()
+            ];
+            $map = ["openid" => $sessionKey['openid']];
+            if (!empty($mobile['purePhoneNumber'])) {
+                $userInfo['mobile'] = $mobile['purePhoneNumber'];
+            }
+            $user = $this->model->where($map)->findOrEmpty();
+            if ($user->isEmpty()) {
+                $user->insertGetId($userInfo);
+            }
+            $userAuth = get_object_vars(AuthFacade::guard("user")->login(['openid' => $sessionKey['openid']]));
+            return success("ok",$userAuth);
+        } catch (\Throwable $th) {
+            return error($th->getMessage());
+        }
+    }
+
+    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 [];
+        }
+        return json_decode($plaintext,true);
+    }
+
+
+    protected function decrypt($encrypted_data, $session_key, $iv) {
+        $data = base64_decode($encrypted_data);
+        $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;
+    }
+}

+ 43 - 0
app/controller/api/Goods.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace app\controller\api;
+
+use app\extra\basic\Base;
+use app\middleware\AuthMiddleware;
+use app\model\saas\SaasGoods;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Attributes\Route\Controller;
+use LinFly\Annotation\Attributes\Route\GetMapping;
+use LinFly\Annotation\Attributes\Route\Middleware;
+use support\Request;
+use support\Response;
+
+
+#[Controller("/dy/goods"),Middleware(AuthMiddleware::class)]
+class Goods extends Base
+{
+
+    #[Inject]
+    protected SaasGoods $model;
+
+
+    #[GetMapping("data")]
+    public function getGoodsData(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "goods.require" => trans("empty.require"),
+                "spm.require"   => trans("empty.require"),
+            ],$request->method());
+            if (!is_array($param)) return error($param);
+            $data = $this->model->where("id",$param['spm'])->with(['poi' => function ($query) {
+                $query->field("poi_id,poi_name,poi_address,longitude,latitude");
+            }])->findOrEmpty();
+            if ($data->isEmpty()) return errorTrans("empty.data");
+            return $this->encode("success",$data->toArray());
+        } catch (\Throwable $th) {
+            return error($th->getMessage());
+        }
+    }
+
+}

+ 26 - 7
app/controller/api/Home.php

@@ -5,6 +5,8 @@ namespace app\controller\api;
 use app\extra\basic\Base;
 use app\extra\dyLife\data\BaseData;
 use app\middleware\AuthMiddleware;
+use app\model\saas\SaasGoods;
+use app\model\saas\SaasStore;
 use LinFly\Annotation\Attributes\Route\Controller;
 use LinFly\Annotation\Attributes\Route\GetMapping;
 use LinFly\Annotation\Attributes\Route\Middleware;
@@ -20,21 +22,38 @@ class Home extends Base
     /**
      * @var array|string[]
      */
-    protected array $noNeedLogin = ["getHomeData"];
+    protected array $noNeedLogin = ["getHomeData","getLicense"];
 
     #[GetMapping("data")]
     public function getHomeData(Request $request): Response
     {
         try {
-            $resp = (new BaseData)->config([
-                "appid"     => sConf("wechat.appid"),
-                "secret"    => sConf("wechat.secret"),
-                "account"   => sConf("wechat.shop_id"),
-            ])->token()->getStoreCategoryTemplate(6005001);
-            return $this->success("ok",$resp);
+            $param = $this->_valid([
+                "store.require" => trans("empty.require")
+            ],$request->method());
+            if (!is_array($param)) return error($param);
+            $banner = [
+                [
+                    "cover" => "https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/dc7fd761c2e2af9c340f20677f8f115d942f0bde.png"
+                ]
+            ];
+            $store = (new SaasStore)->where("poi_id",$param['store'])->field("poi_name,start_at,end_at,longitude,latitude,service_mobile")->findOrEmpty();
+            $goods = (new SaasGoods)->where("poi_id",$param['store'])->field("product_id,product_name,image_list,category,price,line_price,sale_stock,id")->select()->toArray();
+            return success("ok",compact('banner','store','goods'));
         } catch (\Throwable $th) {
             return error($th->getMessage());
         }
     }
 
+
+    #[GetMapping("license")]
+    public function getLicense(): Response
+    {
+        try {
+            return success("ok",['img' => sConf("service.license")]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
 }

+ 77 - 0
app/controller/merchant/User.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace app\controller\merchant;
+
+use app\extra\basic\Base;
+use app\extra\tools\CodeExtend;
+use app\middleware\AuthMiddleware;
+use app\model\system\SystemUser;
+use app\service\system\UserService;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Attributes\Route\Controller;
+use LinFly\Annotation\Attributes\Route\GetMapping;
+use LinFly\Annotation\Attributes\Route\Middleware;
+use LinFly\Annotation\Attributes\Route\PostMapping;
+use support\Request;
+use support\Response;
+
+
+#[Controller("/api/merchant/user"),Middleware(AuthMiddleware::class)]
+class User extends Base
+{
+    #[Inject]
+    protected UserService $service;
+
+    #[Inject]
+    protected SystemUser $model;
+
+
+    #[GetMapping('list')]
+    public function getDataList(Request $request): Response
+    {
+        try {
+            $param = $request->all();
+            $param['type'] = 3;
+            $param['store_id'] = $request->user['store_id'];
+            $data = $this->service->setModel()->getList($param,"account");
+            return successTrans(100010,pageFormat($data),200);
+        } catch (\Throwable $th) {
+            return error($th->getMessage());
+        }
+    }
+    /**
+     * 账户列表
+     * @param Request $request
+     * @return Response
+     */
+    #[PostMapping("save")]
+    public function setUserData(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            if(!isset($param['id'])) // 新增
+            {
+                $param['salt'] = CodeExtend::random(6,3);
+                $param['password'] = md5($param['password'].$param['salt']);
+                $param['create_ip'] = $request->getRealIp();
+                $param['store_id'] = $request->user['store_id'];
+                $user = $this->model->where("username",$param['username'])->findOrEmpty();
+                if (!$user->isEmpty()) return errorTrans(20011);
+            }
+            if (isset($param['app_id'])) {
+                $param['app_id'] = json_encode($param['app_id']);
+            }
+            if(isset($param['role_path']) && is_array($param['role_path'])){
+                $parent = $param['role_path'];
+                $param['role_path'] = implode(",",$parent);
+                $param['role_id'] = $parent[count($parent) - 1];
+            }
+            $state = $this->model->setAutoData($param);
+            if (!$state) return errorTrans(100011);
+            return successTrans(100010);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 14 - 13
app/extra/basic/Base.php

@@ -26,7 +26,7 @@ class Base
 
     protected function getDyConfig(): array
     {
-        return ["appid" => sConf('dy.appid'),'secret' => sConf('dy.secret')];
+        return ["appid" => sConf('wechat.mini_appid'),'secret' => sConf('wechat.mini_secret')];
     }
 
     /**
@@ -124,38 +124,39 @@ class Base
 
     /**
      * @param int $status
-     * @param string $message
-     * @param array|Arrayable|null $data
+     * @param string $msg
+     * @param null $data
+     * @return Response
      */
-    public function make(int $status, string $message, $data = null)
+    public function make(int $status, string $msg, $data = null)
     {
-        $content = compact('status', 'message');
+        $content = compact('status', 'msg');
         if (!is_null($data))
             $content['data'] = $this->parseData($data);
         return json($content);
     }
 
-    public function encode($message = self::DEFAULT_SUCCESS_MESSAGE, $data = null)
+    public function encode($msg = self::DEFAULT_SUCCESS_MESSAGE, $data = null)
     {
-        $message = $this->parseData($message);
-        if (is_array($message)) {
-            $data = $message;
-            $message = self::DEFAULT_SUCCESS_MESSAGE;
+        $msg = $this->parseData($msg);
+        if (is_array($msg)) {
+            $data = $msg;
+            $msg = self::DEFAULT_SUCCESS_MESSAGE;
         } else {
             $data = $this->parseData($data);
         }
         $status = self::DEFAULT_SUCCESS_CODE;
         $encode = true;
-        $content = compact('status','encode', 'message');
+        $content = compact('status','encode', 'msg');
         if (is_null($data) || env('APP_DEBUG', false))
-            return $this->success($message, $data['data'] ?? $data);
+            return $this->success($msg, $data['data'] ?? $data);
         if (!is_array($data) || !isset($data['data'])) {
             $res['data'] = $data;
         } else {
             $res = $data;
         }
         $res['status'] = $status;
-        $res['message'] = $message;
+        $res['msg'] = $msg;
         $content['data'] =  base64_encode(gzdeflate(json_encode($res,JSON_UNESCAPED_UNICODE),9));
         return json($content);
     }

+ 66 - 0
app/extra/dyLife/Crypt.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace app\extra\dyLife;
+
+use yzh52521\EasyHttp\Http;
+
+class Crypt extends BasicLife
+{
+
+    /**
+     * 获取小程序登录sessionKey
+     * @param string $code
+     * @return array
+     */
+    public function getSessionKey(string $code = ""): array
+    {
+        $url = "https://developer.toutiao.com/api/apps/v2/jscode2session";
+        $param = [
+            "appid"     => $this->config['appid'],
+            "secret"    => $this->config['secret'],
+            "code"      => $code
+        ];
+        $resp = Http::asJson()->post($url,$param)->array();
+        if ($resp['err_no'] == 0) {
+            return $resp['data'];
+        }
+        return [];
+    }
+
+    /**
+     * 查询标签组信息 - 用于支付
+     * @param int $goods_type
+     * @return array
+     */
+    public function getTagGroupId(int $goods_type): array
+    {
+        $url = $this->gateway."api/trade_basic/v1/developer/tag_query/";
+        $param = [
+            "goods_type"      => $goods_type
+        ];
+        $resp = Http::asJson()->withHeaders($this->header)->post($url,$param)->array();
+        if ($resp['err_no'] == 0) {
+            return $resp['data'];
+        }
+        return [];
+    }
+
+    /**
+     * 小程序获取手机号码
+     * @param string $code
+     * @return string
+     */
+    public function getMobile(string $code = ""):string
+    {
+        $url = $this->gateway."api/apps/v1/get_phonenumber_info/";
+        $param = [
+            "code"      => $code
+        ];
+        $resp = Http::asJson()->withHeaders($this->header)->post($url,$param)->array();
+        if ($resp['err_no'] == 0) {
+            return $resp['data'];
+        }
+        return "";
+    }
+
+}

+ 6 - 0
app/model/saas/SaasGoods.php

@@ -4,6 +4,7 @@ namespace app\model\saas;
 
 use app\extra\basic\Model;
 use think\model\relation\HasMany;
+use think\model\relation\HasOne;
 
 
 /**
@@ -93,4 +94,9 @@ class SaasGoods extends Model
         return $this->hasMany(SaasGoodsSku::class, 'product_id', 'product_id');
     }
 
+    public function poi(): HasOne
+    {
+        return $this->hasOne(SaasStore::class, 'poi_id', 'poi_id');
+    }
+
 }

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

@@ -0,0 +1,47 @@
+<?php
+
+namespace app\model\saas;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property mixed $openid 
+ * @property string $nickname 
+ * @property mixed $mobile 
+ * @property integer $status 状态
+ * @property mixed $create_at
+ */
+class SaasUserOpen 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_user_open";
+    
+    /**
+     * 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;
+
+
+}

+ 3 - 3
config/plugin/shopwwi/auth/app.php

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