zory 2 weken geleden
bovenliggende
commit
433da20031

+ 130 - 0
app/controller/admin/Goods.php

@@ -0,0 +1,130 @@
+<?php
+
+namespace app\controller\admin;
+
+use app\extra\basic\Base;
+use app\extra\service\saas\GoodsService;
+use app\middleware\AuthMiddleware;
+use app\model\saas\SaasGoods;
+use app\model\saas\SaasStore;
+use app\validate\saas\GoodsValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+use Webman\Annotation\Middleware;
+
+#[Controller(prefix: "/api/goods"),Middleware(AuthMiddleware::class)]
+class Goods extends Base
+{
+
+    #[Inject]
+    protected GoodsService $service;
+
+    #[Inject]
+    protected GoodsValidate $validate;
+
+    #[Inject]
+    protected SaasGoods $model;
+
+    #[Route(path: "list",methods: "get")]
+    public function getStoreList(Request $request): Response
+    {
+        try {
+            $param = $request->get();
+            $list = $this->service->getList($param);
+            return successTrans("success.data",pageFormat($list),200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 新增/编辑代理
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "save",methods: "post")]
+    public function save(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            if (empty($param['store_id'])) return errorTrans("empty.require");
+            $store = (new SaasStore)->where("store_id",$param['store_id'])->findOrEmpty();
+            if ($store->isEmpty()) return errorTrans("empty.data");
+            if (empty($store['agent_id'])) return errorTrans("empty.data");
+            $param['agent_id'] = $store['agent_id'];
+            if (!empty($param['product_price'])) $param['product_price'] = $param['product_price']*100;
+            if (!empty($param['product_origin'])) $param['product_origin'] = $param['product_origin']*100;
+            if (!$this->validate->check($param)) return error($this->validate->getError());
+            $state = $this->model->setAutoData($param);
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            echo $throwable->getMessage()."\n";
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "batch",methods: "post")]
+    public function setBatchData(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"        => trans("empty.require"),
+                "value.require"     => trans("empty.require"),
+                "field.require"     => trans("empty.require"),
+                "type.require"      => trans("empty.require"),
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->save([$param['field'] => $param['value']]);
+            } else {
+                $state = $this->model->where("id",$param['id'])->save([$param['field'] => $param['value']]);
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 删除
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "del",methods: "post")]
+    public function delUser(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"    => trans("empty.require"),
+                "type.default"  => "one",
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->delete();
+            } else {
+                $data = $this->model->where("id",$param['id'])->findOrEmpty();
+                if ($data->isEmpty()) return errorTrans("empty.data");
+                // 删除其他相关数据
+                $state = $data->delete();
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 133 - 0
app/controller/admin/Shop.php

@@ -0,0 +1,133 @@
+<?php
+
+namespace app\controller\admin;
+
+use app\extra\basic\Base;
+use app\extra\service\saas\ShopService;
+use app\extra\tools\CodeExtend;
+use app\middleware\AuthMiddleware;
+use app\model\saas\SaasAgent;
+use app\model\saas\SaasStore;
+use app\model\saas\SaasStoreShop;
+use app\model\system\SystemUser;
+use app\validate\saas\ShopValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+use Webman\Annotation\Middleware;
+
+
+#[Controller(prefix: "/api/shop"),Middleware(AuthMiddleware::class)]
+class Shop extends Base
+{
+
+    #[Inject]
+    protected ShopValidate $validate;
+
+    #[Inject]
+    protected ShopService $service;
+
+    #[Inject]
+    protected SaasStoreShop $model;
+
+    #[Route(path: "list",methods: "get")]
+    public function getStoreList(Request $request): Response
+    {
+        try {
+            $param = $request->get();
+            $list = $this->service->getList($param);
+            return successTrans("success.data",pageFormat($list),200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 新增/编辑代理
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "save",methods: "post")]
+    public function save(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            if (empty($param['store_id'])) return errorTrans("empty.require");
+            $store = (new SaasStore)->where("store_id",$param['store_id'])->findOrEmpty();
+            if ($store->isEmpty()) return errorTrans("empty.data");
+            if (empty($store['agent_id'])) return errorTrans("empty.data");
+            $param['agent_id'] = $store['agent_id'];
+            if (!$this->validate->check($param)) return error($this->validate->getError());
+            $state = $this->model->setAutoData($param);
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            echo $throwable->getMessage()."\n";
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "batch",methods: "post")]
+    public function setBatchData(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"        => trans("empty.require"),
+                "value.require"     => trans("empty.require"),
+                "field.require"     => trans("empty.require"),
+                "type.require"      => trans("empty.require"),
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->save([$param['field'] => $param['value']]);
+            } else {
+                $state = $this->model->where("id",$param['id'])->save([$param['field'] => $param['value']]);
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 删除
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "del",methods: "post")]
+    public function delUser(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"    => trans("empty.require"),
+                "type.default"  => "one",
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->delete();
+            } else {
+                $data = $this->model->where("id",$param['id'])->findOrEmpty();
+                if ($data->isEmpty()) return errorTrans("empty.data");
+                // 删除其他相关数据
+                $state = $data->delete();
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+}

+ 7 - 5
app/controller/common/Login.php

@@ -91,7 +91,7 @@ class Login extends Base
             $typeUser = $this->getTypeUser($user['agent_id']);
             if (empty($typeUser)) return [0,trans("empty.agent"),[]];
             if ($typeUser['status'] <> 1) return [0,trans("error.agent"),[]];
-            if (time() > strtotime($typeUser['vip_at'])) return [0,trans("error.agent-out"),[]];
+            if (time() > strtotime($typeUser['vip_end'])) return [0,trans("error.agent-out"),[]];
         }
         if ($type == 2) {
             if (md5($param['password'].$user['salt']) <> $user['password']) return [0,trans("error.passwd"),[]];
@@ -123,16 +123,18 @@ class Login extends Base
             $userData = (new Auth)->guard("admin")->user()->toArray();
             if (isset($userData['password'])) unset($userData['password']);
             $agent = (new SaasAgent)->where("agent_id",$userData['agent_id'])->findOrEmpty();
-            if (empty($agent['vip_at']))
+            if (empty($agent['vip_end']))
             {
-                $userData['vip_at'] = 0;
+                $userData['vip_end'] = 0;
             } else {
-                $userData['vip_at'] = strtotime($agent['vip_at']);
+                $userData['vip_end'] = strtotime($agent['vip_end']);
             }
             return successTrans("success.data",[
                 "username"  => $userData['username'],
                 "truename"  => $userData['truename'],
-                "vip_at"    => $userData['vip_at'],
+                "vip_at"    => $userData['vip_end'],
+                "agent_id"  => $userData['agent_id'],
+                "store_id"  => $userData['store_id'],
                 "super"     => $userData['is_super'],
                 "type"      => $userData['type']
             ]);

+ 134 - 0
app/controller/merchant/Goods.php

@@ -0,0 +1,134 @@
+<?php
+
+namespace app\controller\merchant;
+
+use app\extra\basic\Base;
+use app\extra\service\saas\GoodsService;
+use app\middleware\AuthMiddleware;
+use app\model\saas\SaasGoods;
+use app\model\saas\SaasStore;
+use app\validate\saas\GoodsValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+use Webman\Annotation\Middleware;
+
+
+#[Controller(prefix: "/api/merchant/goods"),Middleware(AuthMiddleware::class)]
+class Goods extends Base
+{
+
+
+
+    #[Inject]
+    protected GoodsService $service;
+
+    #[Inject]
+    protected GoodsValidate $validate;
+
+    #[Inject]
+    protected SaasGoods $model;
+
+    #[Route(path: "list",methods: "get")]
+    public function getStoreList(Request $request): Response
+    {
+        try {
+            $param = $request->get();
+            $param['agent'] = $request->user['agent_id'];
+            $list = $this->service->getList($param);
+            return successTrans("success.data",pageFormat($list),200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 新增/编辑代理
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "save",methods: "post")]
+    public function save(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            if (empty($param['store_id'])) return errorTrans("empty.require");
+            $store = (new SaasStore)->where("store_id",$param['store_id'])->findOrEmpty();
+            if ($store->isEmpty()) return errorTrans("empty.data");
+            if (empty($store['agent_id'])) return errorTrans("empty.data");
+            $param['agent_id'] = $store['agent_id'];
+            if (!empty($param['product_price'])) $param['product_price'] = $param['product_price']*100;
+            if (!empty($param['product_origin'])) $param['product_origin'] = $param['product_origin']*100;
+            if (!$this->validate->check($param)) return error($this->validate->getError());
+            $state = $this->model->setAutoData($param);
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            echo $throwable->getMessage()."\n";
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "batch",methods: "post")]
+    public function setBatchData(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"        => trans("empty.require"),
+                "value.require"     => trans("empty.require"),
+                "field.require"     => trans("empty.require"),
+                "type.require"      => trans("empty.require"),
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->save([$param['field'] => $param['value']]);
+            } else {
+                $state = $this->model->where("id",$param['id'])->save([$param['field'] => $param['value']]);
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 删除
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "del",methods: "post")]
+    public function delUser(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"    => trans("empty.require"),
+                "type.default"  => "one",
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->delete();
+            } else {
+                $data = $this->model->where("id",$param['id'])->findOrEmpty();
+                if ($data->isEmpty()) return errorTrans("empty.data");
+                // 删除其他相关数据
+                $state = $data->delete();
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 73 - 0
app/controller/mini/Auth.php

@@ -0,0 +1,73 @@
+<?php
+
+namespace app\controller\mini;
+
+use app\extra\basic\Base;
+use app\extra\douyin\Crypt;
+use app\extra\tools\CodeExtend;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/api/dy/home")]
+class Auth extends Base
+{
+
+
+    /**
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "login",methods: "post")]
+    public function setLogin(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            $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 = [
+                'openid'    => $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");
+        } catch (\Throwable $throwable) {
+            return error($throwable->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;
+    }
+
+
+}

+ 130 - 0
app/controller/store/Goods.php

@@ -0,0 +1,130 @@
+<?php
+
+namespace app\controller\store;
+
+use app\extra\basic\Base;
+use app\extra\service\saas\GoodsService;
+use app\middleware\AuthMiddleware;
+use app\model\saas\SaasGoods;
+use app\model\saas\SaasStore;
+use app\validate\saas\GoodsValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+use Webman\Annotation\Middleware;
+
+
+#[Controller(prefix: "/api/store/goods"),Middleware(AuthMiddleware::class)]
+class Goods extends Base
+{
+
+
+    #[Inject]
+    protected GoodsService $service;
+
+    #[Inject]
+    protected GoodsValidate $validate;
+
+    #[Inject]
+    protected SaasGoods $model;
+
+    #[Route(path: "list",methods: "get")]
+    public function getStoreList(Request $request): Response
+    {
+        try {
+            $param = $request->get();
+            $param['store'] = $request->user['store_id'];
+            $list = $this->service->getList($param);
+            return successTrans("success.data",pageFormat($list),200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 新增/编辑代理
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "save",methods: "post")]
+    public function save(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            $param['store_id'] = $request->user['store_id'];
+            $param['agent_id'] = $request->user['agent_id'];
+            if (!empty($param['product_price'])) $param['product_price'] = $param['product_price']*100;
+            if (!empty($param['product_origin'])) $param['product_origin'] = $param['product_origin']*100;
+            if (!$this->validate->check($param)) return error($this->validate->getError());
+            $state = $this->model->setAutoData($param);
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            echo $throwable->getMessage()."\n";
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "batch",methods: "post")]
+    public function setBatchData(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"        => trans("empty.require"),
+                "value.require"     => trans("empty.require"),
+                "field.require"     => trans("empty.require"),
+                "type.require"      => trans("empty.require"),
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->save([$param['field'] => $param['value']]);
+            } else {
+                $state = $this->model->where("id",$param['id'])->save([$param['field'] => $param['value']]);
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 删除
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "del",methods: "post")]
+    public function delUser(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "id.require"    => trans("empty.require"),
+                "type.default"  => "one",
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if ($param['type'] == "batch") {
+                $state = $this->model->where("id","in",$param['id'])->delete();
+            } else {
+                $data = $this->model->where("id",$param['id'])->findOrEmpty();
+                if ($data->isEmpty()) return errorTrans("empty.data");
+                // 删除其他相关数据
+                $state = $data->delete();
+            }
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 32 - 0
app/extra/douyin/AccessToken.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace app\extra\douyin;
+
+use yzh52521\EasyHttp\Http;
+
+class AccessToken extends Base
+{
+
+    /**
+     * 获取AccessToken
+     * https://developer.open-douyin.com/docs/resource/zh-CN/mini-app/develop/server/basic-abilities/interface-request-credential/non-user-authorization/get-client_token
+     * @param string $grantType
+     * @return array
+     */
+    public function getAccessTokenLine(string $grantType = 'client_credential'): array
+    {
+        $data = [
+            "client_key"        => $this->config['appid'],
+            "client_secret"     => $this->config['secret'],
+            "grant_type"        => $grantType
+        ];
+        $url = $this->gateway."oauth/client_token/";
+        $result = Http::asJson()->post($url,$data)->array();
+        if(!empty($result['data']))
+        {
+            return $result['data'];
+        }
+        return [];
+    }
+
+}

+ 89 - 0
app/extra/douyin/Base.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace app\extra\douyin;
+
+use support\think\Cache;
+
+class Base
+{
+    /**
+     * API地址
+     * @var string
+     */
+    protected string $gateway = "https://open.douyin.com/";
+
+    /**
+     * 配置信息
+     * @var array
+     */
+    protected array $config = [];
+
+    /**
+     * @var string
+     */
+    private string $access_token;
+
+    /**
+     * 默认header
+     * @var string[]
+     */
+    protected array $header = [
+        "content-type"  => "application/json"
+    ];
+
+    /**
+     * AccessToken前缀
+     * @var string
+     */
+    protected string $tokenPrefix = "dy_[appid]_access_token";
+
+    public function token(): static
+    {
+        $this->header = [
+            "access-token" => $this->getAccessToken()
+        ];
+        return $this;
+    }
+
+    /**
+     * 设置配置信息
+     * @param array $config
+     * @return $this
+     */
+    public function config(array $config = []): static
+    {
+        $this->config = $config;
+        return $this;
+    }
+
+
+    public function getAccessToken()
+    {
+        $accessToken = Cache::get($this->getTokenPrefix());
+        if (!empty($accessToken)) return $accessToken;
+        $result = (new AccessToken)->config($this->config)->getAccessTokenLine();
+        if (empty($result)) return "获取Token失败\n";
+        Cache::set($this->getTokenPrefix(),$result['access_token'],$result['expires_in']);
+        return $result['access_token'];
+    }
+
+    /**
+     * 注册当前请求接口
+     * @param string $url 接口地址
+     * @return string
+     */
+    protected function registerApi(string &$url): string
+    {
+        if (empty($this->access_token)) $this->access_token = $this->getAccessToken();
+        return $url = str_replace('ACCESS_TOKEN', urlencode($this->access_token), $url);
+    }
+
+    /**
+     * @return string
+     */
+    protected function getTokenPrefix(): string
+    {
+        return str_replace("[appid]",$this->config['appid'],$this->tokenPrefix);
+    }
+
+}

+ 59 - 0
app/extra/douyin/Crypt.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace app\extra\douyin;
+
+use yzh52521\EasyHttp\Http;
+
+class Crypt extends Base
+{
+    public function getSessionKey(string $code = "")
+    {
+        $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
+     */
+    public function getTagGroupId(int $goods_type)
+    {
+        $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 "";
+    }
+
+}

+ 83 - 0
app/extra/douyin/SignUtil.php

@@ -0,0 +1,83 @@
+<?php
+
+namespace app\extra\douyin;
+
+class SignUtil
+{
+    /*
+     * appid/client_key对应的client_secret TODO 这里换成服务商的appsecret
+     */
+    private static $secret = "12345678901234566543210987654321";
+    private static $key;
+    private static $iv;
+
+    public static function init($secret) {
+        self::$secret = $secret;
+        self::$key = self::parseSecret(self::$secret);
+        self::$iv = substr(self::$key, 16);
+    }
+
+    /**
+     *  AES解密
+     * @param string $data base64后的密文
+     * @return string 明文
+     */
+    public static function decryptAES($data) {
+        try {
+            $encrypted = self::decode($data); // 先用base64解密
+            $decrypted = openssl_decrypt(
+                $encrypted,
+                'AES-256-CBC',
+                self::$key,
+                OPENSSL_RAW_DATA,
+                self::$iv
+            );
+            return $decrypted;
+        } catch (\Exception $e) {
+            error_log($e->getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * base64编码
+     */
+    public static function encode($data) {
+        return base64_encode($data);
+    }
+
+    /**
+     * base64解码
+     */
+    public static function decode($data) {
+        return base64_decode($data);
+    }
+
+    private static function parseSecret($secret) {
+        $secret = self::fillSecret($secret);
+        $secret = self::cutSecret($secret);
+        return $secret;
+    }
+
+    private static function cutSecret($secret) {
+        if (strlen($secret) <= 32) {
+            return $secret;
+        }
+        $rightCnt = (int)((strlen($secret) - 32) / 2);
+        $leftCnt = strlen($secret) - 32 - $rightCnt;
+        return substr($secret, $leftCnt, 32);
+    }
+
+    private static function fillSecret($secret) {
+        if (strlen($secret) >= 32) {
+            return $secret;
+        }
+        $rightCnt = (int)((32 - strlen($secret)) / 2);
+        $leftCnt = 32 - strlen($secret) - $rightCnt;
+        $sb = str_repeat('#', $leftCnt);
+        $sb .= $secret;
+        $sb .= str_repeat('#', $rightCnt);
+        return $sb;
+    }
+
+}

+ 4 - 1
app/extra/service/saas/AgentService.php

@@ -4,6 +4,7 @@ namespace app\extra\service\saas;
 
 use app\extra\basic\Service;
 use app\model\saas\SaasAgent;
+use app\model\saas\SaasStore;
 
 class AgentService extends Service
 {
@@ -15,7 +16,9 @@ class AgentService extends Service
     public function getList(array $param = [])
     {
         $this->mode = new SaasAgent();
-        return $this->searchVal($param,$this->searchFilter($param))->paginate([
+        return $this->searchVal($param,$this->searchFilter($param))->append(['store'])->withAttr(['store' => function($data,$resp){
+            return (new SaasStore)->where("agent_id",$resp['agent_id'])->count();
+        }])->paginate([
             "list_rows" => $param['pageSize'],
             "page"      => $param['page']
         ]);

+ 40 - 0
app/extra/service/saas/GoodsService.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace app\extra\service\saas;
+
+use app\extra\basic\Service;
+use app\model\saas\SaasGoods;
+
+class GoodsService extends Service
+{
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [])
+    {
+        $this->mode = new SaasGoods();
+        return $this->searchVal($param,$this->searchFilter($param))->with(['agent' => function($query){
+            $query->field("agent_id,name");
+        },"store" => function($query){
+            $query->field("store_id,store_name");
+        }])->paginate([
+            "list_rows" => $param['pageSize'],
+            "page"      => $param['page']
+        ]);
+    }
+
+
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['agent']) && $filter[] = ["agent_id", '=', $param['agent']];
+        !empty($param['store']) && $filter[] = ["store_id", '=', $param['store']];
+        !empty($param['status']) && $filter[] = ["status", '=', ($param['status']-1)];
+        !empty($param['type']) && $filter[] = ["store_type", '=', $param['type']];
+        !empty($param['name']) && $filter[] = ["product_name", 'like', "%{$param['name']}%"];
+        return $filter;
+    }
+
+}

+ 41 - 0
app/extra/service/saas/ShopService.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace app\extra\service\saas;
+
+use app\extra\basic\Service;
+use app\model\saas\SaasStoreShop;
+
+class ShopService extends Service
+{
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [])
+    {
+        $this->mode = new SaasStoreShop();
+        return $this->searchVal($param,$this->searchFilter($param))->with(['agent' => function($query){
+            $query->field("agent_id,name");
+        },"store" => function($query){
+            $query->field("store_id,store_name");
+        }])->paginate([
+            "list_rows" => $param['pageSize'],
+            "page"      => $param['page']
+        ]);
+    }
+
+
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['agent']) && $filter[] = ["agent_id", '=', $param['agent']];
+        !empty($param['store']) && $filter[] = ["store_id", '=', $param['store']];
+        !empty($param['status']) && $filter[] = ["status", '=', ($param['status']-1)];
+        !empty($param['type']) && $filter[] = ["store_type", '=', $param['type']];
+        !empty($param['name']) && $filter[] = ["name", 'like', "%{$param['name']}%"];
+        return $filter;
+    }
+
+}

+ 44 - 0
app/middleware/DyMiddleware.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace app\middleware;
+
+use Shopwwi\WebmanAuth\Auth;
+use Shopwwi\WebmanAuth\JWT;
+use Webman\Http\Request;
+use Webman\Http\Response;
+use Webman\MiddlewareInterface;
+
+class DyMiddleware implements MiddlewareInterface
+{
+
+    public function process(Request $request, callable $handler): Response
+    {
+        try {
+            $controller = new \ReflectionClass($request->controller);
+            $noNeedLogin = $controller->getDefaultProperties()['noNeedLogin']??[];
+            if (empty($noNeedLogin) || !in_array($request->action, $noNeedLogin)) {
+                $type = $request->header('api-type','');
+                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();
+                if (empty($user)) return json(['code'=>401,'msg'=> trans("error.login")]);
+                $request->user = $user->toArray();
+            }
+        } catch (\ReflectionException $exception) {
+            return json(['code'=> 500,'msg'=> $exception->getMessage()]);
+        }
+        $response = $request->method() == 'OPTIONS' ? response('',204) : $handler($request);
+        // 给响应添加跨域相关的http头
+        $response->withHeaders([
+            'Access-Control-Allow-Credentials' => 'true',
+            'Access-Control-Allow-Origin' => $request->header('origin', '*'),
+            'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
+            'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
+        ]);
+        return $response;
+    }
+
+
+}

+ 34 - 11
app/model/saas/SaasGoods.php

@@ -3,20 +3,21 @@
 namespace app\model\saas;
 
 use app\extra\basic\Model;
+use think\model\relation\HasOne;
 
 
 /**
- * @property integer $id (主键)
- * @property integer $store_id 来客账户id
- * @property integer $agent_id 代理id
- * @property integer $product_id 
- * @property string $product_name 
- * @property string $express_name 面单打印名称
- * @property string $product_img 
- * @property integer $product_price 
- * @property integer $product_orgin 划线价
- * @property integer $out_id 来客商品ID
- * @property integer $status 
+ * @property integer $id (主键)
+ * @property integer $store_id 来客账户id
+ * @property integer $agent_id 代理id
+ * @property integer $product_id 
+ * @property string $product_name 
+ * @property string $express_name 面单打印名称
+ * @property string $product_img 
+ * @property integer $product_price 
+ * @property integer $product_orgin 划线价
+ * @property integer $out_id 来客商品ID
+ * @property integer $status 
  * @property mixed $create_at
  */
 class SaasGoods extends Model
@@ -49,5 +50,27 @@ class SaasGoods extends Model
      */
     public bool $timestamps = false;
 
+    public function getProductPriceAttr($data): string
+    {
+        if ($data == 0) return 0;
+        return format_money($data/100);
+    }
 
+    public function getProductOriginAttr($data): string
+    {
+        if ($data == 0) return 0;
+        return format_money($data/100);
+    }
+
+
+    public function agent(): HasOne
+    {
+        return $this->hasOne("app\model\saas\SaasAgent","agent_id","agent_id");
+    }
+
+
+    public function store(): HasOne
+    {
+        return $this->hasOne("app\model\saas\SaasStore","store_id","store_id");
+    }
 }

+ 20 - 8
app/model/saas/SaasStoreShop.php

@@ -3,17 +3,18 @@
 namespace app\model\saas;
 
 use app\extra\basic\Model;
+use think\model\relation\HasOne;
 
 
 /**
- * @property integer $id (主键)
- * @property integer $user_id 
- * @property integer $account_id 来客id
- * @property integer $poi_id 
- * @property string $poi_name 
- * @property string $poi_address 
- * @property integer $is_default 
- * @property integer $status 
+ * @property integer $id (主键)
+ * @property integer $user_id 
+ * @property integer $account_id 来客id
+ * @property integer $poi_id 
+ * @property string $poi_name 
+ * @property string $poi_address 
+ * @property integer $is_default 
+ * @property integer $status 
  * @property mixed $create_at
  */
 class SaasStoreShop extends Model
@@ -47,4 +48,15 @@ class SaasStoreShop extends Model
     public bool $timestamps = false;
 
 
+    public function agent(): HasOne
+    {
+        return $this->hasOne("app\model\saas\SaasAgent","agent_id","agent_id");
+    }
+
+
+    public function store(): HasOne
+    {
+        return $this->hasOne("app\model\saas\SaasStore","store_id","store_id");
+    }
+
 }

+ 28 - 0
app/validate/saas/GoodsValidate.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace app\validate\saas;
+
+use think\Validate;
+
+class GoodsValidate extends Validate
+{
+
+
+    protected $rule = [
+        "agent_id"      => "require",
+        "store_id"      => "require",
+        "product_name"  => "require",
+        "out_id"        => "require",
+        "product_price" => "require"
+    ];
+
+
+    protected $message = [
+        "agent_id.require"      => "请现在代理",
+        "store_id.require"      => "请输入来客ID",
+        "product_name.require"  => "请输入商品名称",
+        "out_id.require"        => "请输入来客商品ID",
+        "product_price.require" => "请输入金额"
+    ];
+
+}

+ 30 - 0
app/validate/saas/ShopValidate.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace app\validate\saas;
+
+use think\Validate;
+
+class ShopValidate extends Validate
+{
+
+
+    protected $rule = [
+        "agent_id"      => "require",
+        "store_id"      => "require",
+        "poi_id"        => "require",
+        "poi_name"      => "require",
+        "poi_location"  => "require",
+        "poi_address"   => "require",
+    ];
+
+
+    protected $message = [
+        "agent_id.require"      => "请现在代理",
+        "store_id.require"      => "请输入来客ID",
+        "poi_id.require"        => "请输入门店POI",
+        "poi_name.require"      => "请输入门店名称",
+        "poi_location.require"  => "请输入门店经纬度",
+        "poi_address.require"   => "请输入门店地址",
+    ];
+
+}