From 9ee99202bbb02c4cf73f13429ac3ee93aec92859 Mon Sep 17 00:00:00 2001
From: 15090180611 <215509543@qq.com>
Date: Mon, 4 Nov 2024 18:06:27 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 application/admin/library/Wechat.php          |  48 +++++++
 .../admin/library/services/LoginService.php   | 129 ++++++++++++++++++
 application/api/controller/User.php           |  77 +++++++++++
 3 files changed, 254 insertions(+)
 create mode 100644 application/admin/library/Wechat.php
 create mode 100644 application/admin/library/services/LoginService.php

diff --git a/application/admin/library/Wechat.php b/application/admin/library/Wechat.php
new file mode 100644
index 0000000..52e5872
--- /dev/null
+++ b/application/admin/library/Wechat.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace app\admin\library;
+
+use think\Config;
+
+class Wechat
+{
+
+
+    /**
+     * 获取小程序配置
+     * @param int $brand_id 品牌商id
+     * @return array
+     */
+    public function getMiniConfig(){
+
+        $addonConfig = get_addon_config('epay');
+        $config =  $addonConfig['wechat'];
+
+            $miniConfig = [
+                'appid'          => config("site.wx_miniapp_id") ?? '',
+                'appsecret'      => config("site.wx_miniapp_secret") ?? '',
+                'encodingaeskey' => '',
+                // 配置商户支付参数
+                'mch_id'         => $config['mch_id'] ?? '',
+                'mch_key'        => $config['key'] ?? '',
+                'mch_key_v3'        => $config['key_v3'] ?? '',
+                // 配置商户支付双向证书目录 (p12 | key,cert 二选一,两者都配置时p12优先)
+
+                'ssl_key'       => '',
+                'ssl_cer'       => '',
+                // 配置缓存目录,需要拥有写权限
+                'cache_path'     => RUNTIME_PATH.'wechat',
+            ];
+
+
+        if (isset($config['cert_client']) && substr($config['cert_client'], 0, 8) == '/addons/') {
+            $miniConfig['ssl_cer'] = ROOT_PATH . str_replace('/', DS, substr($config['cert_client'], 1));
+        }
+        if (isset($config['cert_key']) && substr($config['cert_key'], 0, 8) == '/addons/') {
+            $miniConfig['ssl_key'] = ROOT_PATH . str_replace('/', DS, substr($config['cert_key'], 1));
+        }
+
+            return $miniConfig;
+    }
+
+}
\ No newline at end of file
diff --git a/application/admin/library/services/LoginService.php b/application/admin/library/services/LoginService.php
new file mode 100644
index 0000000..7fb080b
--- /dev/null
+++ b/application/admin/library/services/LoginService.php
@@ -0,0 +1,129 @@
+<?php
+
+
+namespace app\admin\library\services;
+
+
+
+use addons\xilufitness\services\BaseService;
+use fast\Random;
+use think\Log;
+use WeMini\Crypt;
+use function EasyWeChat\Kernel\Support\get_client_ip;
+
+/**
+ * 登录注册服务模块
+ * Class LoginService
+ * @package addons\services\login
+ */
+class LoginService extends BaseService
+{
+
+    /**
+     * 获取小程序openid
+     * @param string $code 登录时的code
+     * @return array
+     */
+    public function getOpenid(string $code): array {
+       return Crypt::instance($this->data['mini_config'])->session($code);
+    }
+
+    /**
+     * 加密信息解密
+     * @param string $iv
+     * @param string $encrypted_data
+     * @param string $session_key
+     * return bool|array
+     */
+    public function decodeData(string $iv, string $encrypted_data, string $session_key) {
+        return Crypt::instance($this->data['mini_config'])->decode($iv,$encrypted_data,$session_key);
+    }
+
+    /**
+     * 用户注册登录
+     * @param string $mobile 手机号
+     * @param string $openid 小程序openid
+     * @param int $brand_id 品牌id
+     * @param int $rec_user_id 推荐人id
+     */
+    public function userRegisterLogin(string $mobile, string $openid, int $brand_id = 0, int $rec_user_id): array {
+        $nickname = Random::build('alnum',4).rand(0,100);
+        $password = Random::numeric(6);
+        $loginip = get_client_ip();
+        $userAccountModel = new \addons\xilufitness\model\User; //附加用户表
+        $userModel = new \app\common\model\User; //主用户表
+        $user = $userModel::getByMobile($mobile);
+        $userAccount = $userAccountModel->where(['brand_id' => $brand_id, 'mobile' => $mobile])->find();
+        //登录成功事件字段信息
+        $loginSusscess = [
+            'openid' => $openid,
+            'brand_id' => $brand_id
+        ];
+        if($user){
+            if($userAccount){
+                $userAccount->allowField(true)->save(['loginip' => $loginip]);
+                $this->auth->direct($userAccount->user_id);
+                $loginSusscess['user_id'] = xilufitness_get_id_value($userAccount->id);
+                \think\Hook::listen('xilufitness_user_login_success',$loginSusscess);
+                $this->saveUserShare(xilufitness_get_id_value($userAccount->id),$rec_user_id,$this->brand_id);
+                return ['token' => $this->auth->getToken()];
+            } else {
+                $userAccountModel->allowField(true)->save([
+                    'nickname' => $nickname,
+                    'brand_id' => $brand_id,
+                    'user_id'  => $user->id ?? 0,
+                    'mobile'   => $mobile,
+                    'loginip'  => $loginip
+                ]);
+                $this->auth->direct($user->id);
+                $loginSusscess['user_id'] = xilufitness_get_id_value($userAccountModel->id);
+                \think\Hook::listen('xilufitness_user_login_success',$loginSusscess);
+                $this->saveUserShare(xilufitness_get_id_value($userAccountModel->id),$rec_user_id,$this->brand_id);
+                return ['token' => $this->auth->getToken()];
+            }
+        } else {
+            Log::log("注册");
+            $result = $this->auth->register($nickname,$password,'',$mobile);
+            if($result){
+                $userInfo = $this->auth->getUser();
+                if($userAccount){
+                    $userAccount->allowField(true)->save(['loginip' => $loginip]);
+                    $loginSusscess['user_id'] = xilufitness_get_id_value($userAccount->id);
+                    \think\Hook::listen('xilufitness_user_login_success',$loginSusscess);
+                    $this->saveUserShare(xilufitness_get_id_value($userAccount->id),$rec_user_id,$this->brand_id);
+                    return ['token' => $this->auth->getToken()];
+                } else {
+                    $userAccountModel->allowField(true)->save([
+                        'nickname' => $nickname,
+                        'brand_id' => $brand_id,
+                        'user_id'  => $userInfo['id'] ?? 0,
+                        'mobile'   => $mobile,
+                        'loginip'  => $loginip
+                    ]);
+                    $loginSusscess['user_id'] = xilufitness_get_id_value($userAccountModel->id);
+                    \think\Hook::listen('xilufitness_user_login_success',$loginSusscess);
+                    $this->saveUserShare(xilufitness_get_id_value($userAccountModel->id),$rec_user_id,$this->brand_id);
+                    return ['token' => $this->auth->getToken()];
+                }
+            } else {
+                $this->resultError(__('Registration login failed'));
+                return [];
+            }
+        }
+    }
+
+    /**
+     * 邀请有礼 推荐用户
+     * @param int $user_id 用户id
+     * @param int $rec_user_id  推荐人id
+     * @param int $brand_id 所属品牌商
+     * @return bool
+     */
+    private function saveUserShare(int $user_id, int $rec_user_id, int $brand_id){
+        $params['user_id'] = $user_id;
+        $params['rec_user_id'] = $rec_user_id;
+        $params['brand_id'] = $brand_id;
+        return \think\Hook::listen('xilufitness_user_share',$params);
+    }
+
+}
\ No newline at end of file
diff --git a/application/api/controller/User.php b/application/api/controller/User.php
index d269016..a46a8fb 100644
--- a/application/api/controller/User.php
+++ b/application/api/controller/User.php
@@ -2,12 +2,14 @@
 
 namespace app\api\controller;
 
+use addons\xilufitness\services\login\LoginService;
 use app\common\controller\Api;
 use app\common\library\Ems;
 use app\common\library\Sms;
 use fast\Random;
 use think\Config;
 use think\Validate;
+use app\admin\library\Wechat;
 
 /**
  * 会员接口
@@ -17,6 +19,81 @@ class User extends Api
     protected $noNeedLogin = ['login', 'mobilelogin', 'register', 'resetpwd', 'changeemail', 'changemobile', 'third'];
     protected $noNeedRight = '*';
 
+    protected $miniConfig;
+
+    public function _initialize()
+    {
+        $this->miniConfig = (new Wechat)->getMiniConfig();
+        parent::_initialize();
+    }
+
+
+
+
+    /**
+     * @ApiTitle(获取小程序openid信息)
+     * @ApiSummary(根据前端code换取openid信息)
+     * @ApiRoute(/getOpenid)
+     * @ApiMethod(GET)
+     * @ApiParams(name="code",type="string",required=true,description="前端code值")
+     * @ApiHeaders(name = "brand-key", type = "string",require = true, description = "应用key")
+     * @ApiHeaders(name = "token", type = "string", require = true, description = "Token")
+     * @ApiReturnParams(name="code", type="integer",required=true, sample="0")
+     * @ApiReturnParams(name="msg", type="string",required=true, sample="获取成功")
+     * @ApiReturnParams(name="data", type="bject",required=true, description= "扩展数据")
+     * @ApiReturn({
+    "code" => 1,
+    "msg" => "获取成功",
+    "data" => {}
+     *})
+     */
+
+    public function getOpenid(){
+        $code = $this->request->param('code/s');
+
+
+
+        try {
+            $result = LoginService::getInstance(['mini_config' => $this->miniConfig])->getOpenid($code);
+        } catch (\WeChat\Exceptions\LocalCacheException $e){
+            $this->error($e->getMessage());
+        } catch (\Exception $e){
+            $this->error($e->getMessage());
+        }
+        $this->success('',$result);
+    }
+
+    /**
+     * @ApiTitle(加密信息解密)
+     * @ApiSummary(解密微信信息)
+     * @ApiRoute(/decodeData)
+     * @ApiMethod(POST)
+     * @ApiParams(name = "iv", type = "string",required=true)
+     * @ApiParams(name = "encryptedData", type = "string",required=true)
+     * @ApiParams(name = "sessionKey", type = "string",required=true)
+     * @ApiHeaders(name = "brand-key", type = "string",require = true, description = "应用key")
+     * @ApiHeaders(name = "token", type = "string", require = true, description = "Token")
+     * @ApiReturn({
+    "code" => 1,
+    "msg" => "获取成功",
+    "data" => {}
+     *})
+     */
+    public function decodeData() {
+        $iv             = $this->request->param('iv/s');
+        $encryptedData  = $this->request->param('encryptedData/s');
+        $sessionKey     = $this->request->param('sessionKey/s');
+        if(empty($iv) || empty($encryptedData) || empty($sessionKey)){
+            $this->error(__('Params error'));
+        }
+        $result = LoginService::getInstance(['mini_config' => $this->miniConfig])->decodeData($iv,$sessionKey,$encryptedData);
+        $this->success('',$result);
+    }
+
+
+
+
+
     public function _initialize()
     {
         parent::_initialize();