Zory 1 周之前
父节点
当前提交
427401c3b2

+ 207 - 0
app/controller/admin/PrintCloud.php

@@ -0,0 +1,207 @@
+<?php
+
+namespace app\controller\admin;
+
+use app\extra\basic\Base;
+use app\extra\service\saas\PrintService;
+use app\middleware\AuthMiddleware;
+use app\model\saas\SaasPrint;
+use app\validate\saas\PrintValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+use Webman\Annotation\Middleware;
+use Webman\RedisQueue\Redis;
+
+
+#[Controller(prefix: "/api/print"),Middleware(AuthMiddleware::class)]
+class PrintCloud extends Base
+{
+
+
+    #[Inject]
+    protected PrintService $service;
+
+    #[Inject]
+    protected PrintValidate $validate;
+
+    #[Inject]
+    protected SaasPrint $model;
+
+    #[Route(path: "list",methods: "get")]
+    public function getStoreList(Request $request): Response
+    {
+        try {
+            $param = $request->get();
+            $list = $this->service->getDataList($param);
+            return successTrans("success.data",pageFormat($list),200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 查询打印机状态
+     * @return Response
+     */
+    #[Route(path: "refresh",methods: "post")]
+    public function refreshState(): Response
+    {
+        try {
+            Redis::send("print-state",[]);
+            return successTrans("success.print-state");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 打印测试
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "test",methods: "post")]
+    public function testPrint(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "sn.require"    => trans("empty.require")
+            ],"post");
+            if (!is_array($param)) return error($param);
+            $print = $this->model->where("sn",$param["sn"])->findOrEmpty();
+            if ($print->isEmpty()) return errorTrans("empty.data");
+            $resp = (new \app\extra\tools\PrintService())->config(['appid' => sConf('dy.ex_appid'),'secret' => sConf('dy.ex_secret')])->printTemplate(sConf('dy.ex_print'),$param['sn'],[
+                [
+                    "express"   => [
+                        [
+                            "j_mobile" => "180****9980",
+                            "j_address" =>"安徽省阜阳市颍州区xxx镇xxx村xxx",
+                            "express_num" => "SF3270714680386",
+                            "name" => "测试的商品标题名称测试的商品标题名称测试的商品标题名称测试的商品标题名称测试的商品标题名称",
+                            "time" => getDateFull(),
+                            "type" => "特快",
+                            "s_name" => "王*二",
+                            "s_address" => "安徽省阜阳市颍州区xxx镇xxx村xxx",
+                            "s_mobile" => "******00982",
+                            "j_name" => "王麻子",
+                            "express_type" => "饰品",
+                            "order" => "1033999288123123"
+                        ]
+                    ]
+                ]
+            ]);
+            if (!$resp['status']) return error($resp['message']);
+            return successTrans("success.print");
+        } 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 (!$this->validate->check($param)) return error($this->validate->getError());
+            if (!isset($param['id'])) {
+                $resp = (new \app\extra\tools\PrintService())->config(['appid' => sConf('dy.ex_appid'),'secret' => sConf('dy.ex_secret')])->bindDevice($param['sn'],$param['name']);
+                if (!$resp['status']) return error($resp['message']);
+            }
+            $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: "edit",methods: "post")]
+    public function edit(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            if (!$this->validate->scene('edit')->check($request->post())) 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());
+        }
+    }
+
+}

+ 11 - 5
app/controller/admin/Store.php

@@ -58,15 +58,21 @@ class Store extends Base
         try {
             $param = $this->_valid([
                 "id.require"    => trans("empty.require"),
+                "type.default"  => 1, // 1 设置path 2 关闭二维码
             ],"post");
             if (!is_array($param)) return error($param);
             $store = $this->model->where("id",$param['id'])->findOrEmpty();
             if ($store->isEmpty()) return errorTrans("empty.data");
-            // 设置path
-            $resp = (new Client)->config($this->getDyConfig())->token()->setMiniPath($store['store_id']);
-            if ($resp['err_no'] <> 0) return error($resp['err_msg']);
-            $resp = (new Account)->config($this->getDyConfig())->token()->setWhiteSetting($store['store_id'],1,true);
-            if ($resp['err_no'] <> 0) return error($resp['err_msg']);
+            if ($param['type'] == 1) {
+                // 设置path
+                $resp = (new Client)->config($this->getDyConfig())->token()->setMiniPath($store['store_id']);
+                if ($resp['err_no'] <> 0) return error($resp['err_msg']);
+                $resp = (new Account)->config($this->getDyConfig())->token()->setWhiteSetting($store['store_id'],1,true);
+                if ($resp['err_no'] <> 0) return error($resp['err_msg']);
+            } else {
+                $resp = (new Client)->config($this->getDyConfig())->token()->setBtnText($store['store_id']);
+                if ($resp['err_no'] <> 0) return error($resp['err_msg']);
+            }
             return successTrans("success.data");
         } catch (\Throwable $throwable) {
             return error($throwable->getMessage());

+ 2 - 2
app/controller/mini/Test.php

@@ -23,9 +23,9 @@ class Test extends Base
 //            $resp = (new \app\extra\douyin\Order())->config($this->getDyConfig())->token()->getOrderDetail(["1090054060293461518"]);
 //            $resp = (new \app\extra\douyin\Order())->config($this->getDyConfig())->token()->orderLock(1,"1090054060293461518","7578130844109078591","76IQA12W5EQ8NKELH8");
 //            $resp = (new \app\extra\douyin\Account())->config($this->getDyConfig())->token()->setWhiteSetting("7513378475235919883",1,true);
-//            $resp = (new Client)->config($this->getDyConfig())->token()->setMiniPath("7513378475235919883");
+            $resp = (new Client)->config($this->getDyConfig())->token()->setBtnText('7513378475235919883');
 //            $resp = (new Client)->config($this->getDyConfig())->token()->queryOrder("7513378475235919883","_000SDaHqDYY9GGnyrpYfp4vIPHD8qs32XCx");
-//            print_r($resp);
+            print_r($resp);
             return success("ok");
         } catch (\Throwable $throwable) {
             return error($throwable->getMessage());

+ 29 - 0
app/extra/douyin/Client.php

@@ -56,4 +56,33 @@ class Client extends Base
         return Http::asJson()->withHeaders($this->header)->post($this->gateway."api/trade/v2/fulfillment/query_user_certificates/", $param)->array();
     }
 
+    /**
+     * 查询商家配置文案
+     * @return array
+     */
+    public function getBtnText(): array
+    {
+        return Http::asJson()->withHeaders($this->header)->post($this->gateway."api/apps/trade/v2/toolkit/query_text/", ["text_type" => 0])->array();
+    }
+
+
+    /**
+     * 设置商家配置文案
+     * @param string $account
+     * @return array
+     */
+    public function setBtnText(string $account = ""): array
+    {
+        $param = [
+            "account_id"        => $account,
+            "bind_biz_type"     => 0,
+            "delivery_app_info" => [
+                "button_text_id" => "te7252216917182660619",
+                "display_mode" => 2,
+                "guidance_text_id"=>"te7249212519187791884"
+            ]
+        ];
+        return Http::asJson()->withHeaders($this->header)->post($this->gateway."api/apps/trade/v2/toolkit/update_merchant_conf/", $param)->array();
+    }
+
 }

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

@@ -0,0 +1,41 @@
+<?php
+
+namespace app\extra\service\saas;
+
+use app\extra\basic\Service;
+use app\model\saas\SaasPrint;
+
+class PrintService extends Service
+{
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getDataList(array $param = [])
+    {
+        $this->mode = new SaasPrint();
+        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['name']) && $filter[] = ["name", 'like', "%{$param['name']}%"];
+        !empty($param['sn']) && $filter[] = ["sn", 'like', "%{$param['sn']}%"];
+        return $filter;
+    }
+
+}

+ 133 - 0
app/extra/tools/PrintService.php

@@ -0,0 +1,133 @@
+<?php
+
+namespace app\extra\tools;
+
+use yzh52521\EasyHttp\Http;
+
+class PrintService
+{
+
+    /**
+     * 配置信息
+     * @var array
+     */
+    protected array $config = [];
+
+    /**
+     * 网关
+     * @var string
+     */
+    protected string $gateway = "https://cloud.kuaimai.com/";
+
+
+    /**
+     * 发起打印
+     * @param int $templateId
+     * @param string $sn
+     * @param array $data
+     * @param int $num
+     * [{"express":[{"j_mobile":"180****9980","j_address":"安徽省阜阳市颍州区xxx镇xxx村xxx","express_num":"SF3270714680386","name":"飞天茅台53度500ml","time":"2025-12-04 12:18:09","type":"特快","s_name":"王*二","s_address":"安徽省阜阳市颍州区xxx镇xxx村xxx","s_mobile":"******00982","j_name":"王麻子","express_type":"饰品","order":"1033999288123123"}]}]
+     * @return array
+     */
+    public function printTemplate(int $templateId,string $sn = "",array $data = [],int $num = 1): array
+    {
+        $param = [
+            "appId"         => $this->config['appid'],
+            "sn"            => $sn,
+            "templateId"    => $templateId,
+            "printTimes"    => $num,
+            "renderDataArray" => json_encode($data),
+            "timestamp"     => getDateFull()
+        ];
+        $param['sign'] = $this->getPaySign($param);
+        return Http::asJson()->post($this->gateway."api/cloud/print/tsplTemplatePrint", $param)->array();
+    }
+
+    /**
+     * 打印机状态查询下
+     * @param array $data 最多100台
+     * @return array
+     */
+    public function deviceState(array $data = []): array
+    {
+        $param = [
+            "appId"         => $this->config['appid'],
+            "snsStr"        => json_encode($data),
+            "timestamp"     => getDateFull()
+        ];
+        $param['sign'] = $this->getPaySign($param);
+        return Http::asJson()->post($this->gateway."api/cloud/device/batchStatus", $param)->array();
+    }
+
+    /**
+     * 绑定设备
+     * @param string $sn
+     * @param string $name
+     * @return array status true为成功,false为失败 message
+     */
+    public function bindDevice(string $sn = "",string $name = ""): array
+    {
+        $param = [
+            "appId"     => $this->config['appid'],
+            "sn"        => $sn,
+            "noteName"  => $name,
+            "timestamp" => getDateFull()
+        ];
+        $param['sign'] = $this->getPaySign($param);
+        return Http::asJson()->post($this->gateway."api/cloud/device/bindDevice", $param)->array();
+    }
+
+    /**
+     * 解绑设备
+     * @param string $sn
+     * @param string $deviceKey
+     * @return array status true为成功,false为失败 message
+     */
+    public function unbindDevice(string $sn = "",string $deviceKey = ""): array
+    {
+        $param = [
+            "appId"     => $this->config['appid'],
+            "sn"        => $sn,
+            "deviceKey" => $deviceKey,
+            "timestamp" => getDateFull()
+        ];
+        $param['sign'] = $this->getPaySign($param);
+        return Http::asJson()->post($this->gateway."api/cloud/device/unbindDevice", $param)->array();
+    }
+
+
+
+    /**
+     * @param array $data
+     * @return $this
+     */
+    public function config(array $data = [])
+    {
+        $this->config = $data;
+        return $this;
+    }
+
+
+    /**
+     * 生成签名
+     * @param array $data 参与签名的数据
+     * @param string $signType 参与签名的类型
+     * @param string $buff 参与签名字符串前缀
+     * @return string
+     */
+    public function getPaySign(array $data, string $signType = 'MD5', string $buff = ''): string
+    {
+        ksort($data);
+        if (isset($data['sign'])) unset($data['sign']);
+        foreach ($data as $k => $v) {
+            if ('' === $v || null === $v) continue;
+            $buff .= "{$k}{$v}";
+        }
+        $buff .= $this->config['secret'];
+        if (strtoupper($signType) === 'MD5') {
+            return md5($this->config['secret'].$buff);
+        }
+        return strtoupper(hash_hmac('SHA256', $buff, $this->config['secret']));
+    }
+
+}

+ 61 - 0
app/model/saas/SaasPrint.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace app\model\saas;
+
+use app\extra\basic\Model;
+use think\model\relation\HasOne;
+
+
+/**
+ * @property integer $id (主键)
+ * @property string $sn 序列号
+ * @property integer $agent_id 
+ * @property integer $store_id 
+ * @property string $device_key 
+ * @property string $name 打印机名称
+ * @property mixed $create_at
+ */
+class SaasPrint 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_print";
+    
+    /**
+     * 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 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");
+    }
+
+}

+ 36 - 0
app/queue/redis/PrintState.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace app\queue\redis;
+
+use app\extra\tools\PrintService;
+use app\model\saas\SaasPrint;
+use Webman\RedisQueue\Consumer;
+
+class PrintState implements Consumer
+{
+
+    public $queue = "print-state";
+
+    public $connection = "default";
+
+    public function consume($data): bool
+    {
+        echo getDateFull()."===批量查询打印件状态\n";
+        $print = (new SaasPrint)->select();
+        $sn = [];
+        if ($print->isEmpty()) return true;
+        foreach ($print as $key => $value) {
+            $sn[$key] = $value['sn'];
+        }
+        $resp = (new PrintService)->config(['appid' => sConf('dy.ex_appid'),'secret' => sConf('dy.ex_secret')])->deviceState($sn);
+        if (!$resp['status']) return true;
+        if (empty($resp['data'])) return true;
+        foreach ($resp['data'] as $key => $val) {
+            echo getDateFull()."===更新序列号=={$val['sn']}=={$val['status']}=={$val['deviceStatus']}\n";
+            $state = (new SaasPrint)->where("sn",$val['sn'])->update(["online" => $val['status'],"device_state" => $val['deviceStatus']]);
+            echo "更新状态==={$state}\n";
+        }
+        return true;
+    }
+
+}

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

@@ -0,0 +1,28 @@
+<?php
+
+namespace app\validate\saas;
+
+use think\Validate;
+
+class PrintValidate extends Validate
+{
+
+
+    protected $rule = [
+        "name"          => "require",
+        "sn"            => "require",
+        "device_key"    => "require"
+    ];
+
+
+    protected $message = [
+        "name.require"      => "请输入打印机名称",
+        "sn.require"        => "请输入打印机序列号",
+        "device_key.require"=> "请输入设备密钥"
+    ];
+
+    protected $scene = [
+        "edit" => ['sn']
+    ];
+
+}

+ 3 - 1
resource/translations/zh_CN/messages.php

@@ -35,6 +35,8 @@ return [
     "success"   => [
         "data"  => "操作成功",
         "sms"   => "验证码已成功发送至%mobile%,请注意查收",
-        "login" => "登录成功"
+        "login" => "登录成功",
+        "print" => "已成功发起打印测试,请留意打印机是否正常工作",
+        "print-state" => "已成功发起状态查询任务,请等待1-3分钟再刷新数据"
     ],
 ];