diff --git a/niucloud/app/ExceptionHandle.php b/niucloud/app/ExceptionHandle.php index a542d32e7..cc8408d93 100644 --- a/niucloud/app/ExceptionHandle.php +++ b/niucloud/app/ExceptionHandle.php @@ -121,7 +121,7 @@ class ExceptionHandle extends Handle } } - private function handleException(\Exception $e) { + private function handleException(Throwable $e) { $trace = array_map(function ($class){ return str_replace('\\', '/', $class); }, array_column($e->getTrace(), 'class')); @@ -132,6 +132,8 @@ class ExceptionHandle extends Handle } } - return fail("{$trace[0]}第{$e->getLine()}行出现异常,异常信息:" .$e->getMessage()); + $debug = env("APP_DEBUG", false); + + return fail("{$trace[0]}第{$e->getLine()}行出现异常,异常信息:" .$e->getMessage(), $debug ? $e->getTrace() : []); } } diff --git a/niucloud/app/adminapi/controller/channel/App.php b/niucloud/app/adminapi/controller/channel/App.php new file mode 100644 index 000000000..2215221fd --- /dev/null +++ b/niucloud/app/adminapi/controller/channel/App.php @@ -0,0 +1,162 @@ +getConfig()); + } + + /** + * 设置APP配置信息 + * @description 设置APP配置信息 + * @return Response + */ + public function set() + { + $data = $this->request->params([ + ['wechat_app_id', ""], + ['wechat_app_secret', ""], + ['android_app_key', ''], + ['application_id', ''], + ['uni_app_id', ''], + ['app_name', ''] + ]); + (new AppService())->setConfig($data); + return success('SET_SUCCESS'); + } + + public function versionList() { + $data = $this->request->params([ + ["platform",""], + ]); + return success((new AppService())->getVersionPage($data)); + } + + public function versionInfo($id) { + return success((new AppService())->getVersionInfo($id)); + } + + /** + * 添加app版本 + * @description 添加app版本 + * @return \think\Response + */ + public function add(){ + $data = $this->request->params([ + ["version_code",""], + ["version_name",""], + ["version_desc",""], + ["platform",""], + ["is_forced_upgrade",0], + ["package_path", ""], + ["package_type", ""], + ["package_type", ""], + ["build", []], + ["cert", []], + ["upgrade_type", ""], + ]); + $id = (new AppService())->addVersion($data); + return success('ADD_SUCCESS', ['id' => $id]); + } + + /** + * app版本管理编辑 + * @description 编辑app版本 + * @param $id app版本id + * @return \think\Response + */ + public function edit(int $id){ + $data = $this->request->params([ + ["version_code",""], + ["version_name",""], + ["version_desc",""], + ["platform",""], + ["is_forced_upgrade",0], + ["package_path", ""], + ["package_type", ""], + ["package_type", ""], + ["build", []], + ["cert", []], + ["upgrade_type", ""], + ]); + (new AppService())->editVersion($id, $data); + return success('EDIT_SUCCESS'); + } + + /** + * app版本管理删除 + * @description 删除app版本 + * @param $id app版本id + * @return \think\Response + */ + public function del(int $id){ + (new AppService())->delVersion($id); + return success('DELETE_SUCCESS'); + } + + public function appPlatform() { + return success(AppDict::getAppPlatform()); + } + + /** + * 获取app生成日志 + */ + public function buildLog(string $key) { + return success((new AppService())->getBuildLog($key)); + } + + /** + * 发布 + * @description 发布 + * @param $id app版本id + * @return \think\Response + */ + public function release(int $id) { + (new AppService())->release($id); + return success('RELEASE_SUCCESS'); + } + + public function generateSingCert() { + $data = $this->request->params([ + ['key_alias', ''], + ['key_password', ''], + ['store_password', ''], + ['limit', 30], + ['cn', ''], + ['o', ''], + ['ou', ''], + ['c', ''], + ['st', ''], + ['l', ''], + ]); + return success(data:(new AppService())->generateSingCert($data)); + } +} diff --git a/niucloud/app/adminapi/controller/sys/Config.php b/niucloud/app/adminapi/controller/sys/Config.php index e89b15a5e..398d3082e 100644 --- a/niucloud/app/adminapi/controller/sys/Config.php +++ b/niucloud/app/adminapi/controller/sys/Config.php @@ -137,6 +137,7 @@ class Config extends BaseAdminController { $data = $this->request->params([ [ 'key', '' ], + [ 'amap_key', ''], [ 'is_open', 0 ], // 是否开启定位 [ 'valid_time', 0 ] // 定位有效期/分钟,过期后将重新获取定位信息,0为不过期 ]); diff --git a/niucloud/app/adminapi/route/channel.php b/niucloud/app/adminapi/route/channel.php index 2b0660e5a..873f1e156 100644 --- a/niucloud/app/adminapi/route/channel.php +++ b/niucloud/app/adminapi/route/channel.php @@ -29,6 +29,29 @@ Route::group('channel', function () { //设置微信配置 Route::put('pc/config', 'channel.Pc/set'); + /***************************************************** app端 ****************************************************/ + Route::get('app/config', 'channel.App/get'); + //设置手机端配置 + Route::put('app/config', 'channel.App/set'); + // 获取app版本列表 + Route::get('app/version', 'channel.App/versionList'); + // 获取app版本详情 + Route::get('app/version/:id', 'channel.App/versionInfo'); + // 添加app版本 + Route::post('app/version', 'channel.App/add'); + // 编辑app版本 + Route::put('app/version/:id', 'channel.App/edit'); + // 删除app版本 + Route::delete('app/version/:id', 'channel.App/del'); + // 获取app平台 + Route::get('app/platfrom', 'channel.App/appPlatform'); + // 获取app生成日志 + Route::get('app/build/log/:key', 'channel.App/buildLog'); + // 发布 + Route::put('app/version/:id/release', 'channel.App/release'); + // 生成证书 + Route::post('app/generate_sing_cert', 'channel.App/generateSingCert'); + })->middleware([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/api/controller/channel/App.php b/niucloud/app/api/controller/channel/App.php new file mode 100644 index 000000000..dc5d1eece --- /dev/null +++ b/niucloud/app/api/controller/channel/App.php @@ -0,0 +1,73 @@ +request->params([ + [ 'code', '' ], + ]); + $wechat_app_service = new WechatAppService(); + return success($wechat_app_service->loginByCode($data[ 'code' ])); + } + + public function register() + { + $data = $this->request->params([ + [ 'register_type', '' ], + ]); + switch ($data['register_type']) { + case 'wechat': + return $this->wechatRegister(); + } + return fail("不支持的注册方式"); + } + + public function wechatRegister() { + $data = $this->request->params([ + [ 'openid', '' ], + [ 'unionid', '' ], + [ 'nickname', '' ], + [ 'avatar', '' ], + [ 'mobile_code', '' ], + [ 'mobile', '' ], + ]); + + //参数验证 + $this->validate($data, [ + 'mobile' => 'mobile' + ]); + + // 校验手机验证码(电脑端扫码) + ( new LoginService() )->checkMobileCode($data[ 'mobile' ]); + + $wechat_app_service = new WechatAppService(); + return success($wechat_app_service->register($data[ 'openid' ], $data[ 'mobile' ], $data[ 'nickname' ], $data[ 'avatar' ], $data[ 'avatar' ])); + } + + public function getNewVersion() + { + $data = $this->request->params([ + [ 'version_code', '' ], // 当前版本 + [ 'platform', '' ], // 请求平台 + ]); + $app_service = new AppService(); + return success(data:$app_service->getNewVersion($data)); + } +} diff --git a/niucloud/app/api/controller/sys/Config.php b/niucloud/app/api/controller/sys/Config.php index 9b4703e0c..1a15eca43 100644 --- a/niucloud/app/api/controller/sys/Config.php +++ b/niucloud/app/api/controller/sys/Config.php @@ -18,6 +18,7 @@ use app\service\api\member\MemberLevelService; use app\service\api\member\MemberService; use app\service\api\site\SiteService; use app\service\api\sys\ConfigService; +use app\service\core\sys\CoreSysConfigService; use core\base\BaseApiController; use think\Response; @@ -83,13 +84,17 @@ class Config extends BaseApiController [ 'openid', '' ] ]); + $config_service = new ConfigService(); + $res = []; $res[ 'tabbar_list' ] = ( new DiyConfigService() )->getBottomList(); - $res[ 'map_config' ] = ( new ConfigService() )->getMap(); + $res[ 'map_config' ] = $config_service->getMap(); $res[ 'site_info' ] = ( new SiteService() )->getSiteCache(); + $res[ 'site_info' ]['wap_url'] = $config_service->getSceneDomain()['wap_url']; $res[ 'member_level' ] = ( new MemberLevelService() )->getList(); $res[ 'login_config' ] = ( new MemberConfigService() )->getLoginConfig($data[ 'url' ]); $res[ 'theme_list' ] = ( new DiyService() )->getDiyTheme(); + $res[ 'app_config' ] = $config_service->getAppConfig(); $openid_field = match ( $this->request->getChannel() ) { 'wechat' => 'wx_openid', diff --git a/niucloud/app/api/controller/sys/Index.php b/niucloud/app/api/controller/sys/Index.php deleted file mode 100644 index 8bd027bc5..000000000 --- a/niucloud/app/api/controller/sys/Index.php +++ /dev/null @@ -1,28 +0,0 @@ -*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }

:)

ThinkPHP V' . App::version() . '
16载初心不改 - 你值得信赖的PHP框架

[ V6.0 版本由 亿速云 独家赞助发布 ]
'; - } - - public function hello($name = 'ThinkPHP6') - { - return 'hello,' . $name; - } -} diff --git a/niucloud/app/api/route/dispatch/BindDispatch.php b/niucloud/app/api/route/dispatch/BindDispatch.php index 3e138852a..61eb02baa 100644 --- a/niucloud/app/api/route/dispatch/BindDispatch.php +++ b/niucloud/app/api/route/dispatch/BindDispatch.php @@ -33,6 +33,10 @@ class BindDispatch extends Controller $controller = 'weapp.Weapp'; $action = 'register'; break; + case MemberLoginTypeDict::APP: + $controller = 'channel.App'; + $action = 'register'; + break; } @@ -43,4 +47,4 @@ class BindDispatch extends Controller ->setAction($this->actionName); } -} \ No newline at end of file +} diff --git a/niucloud/app/api/route/route.php b/niucloud/app/api/route/route.php index 379d4813d..8a48c72ca 100644 --- a/niucloud/app/api/route/route.php +++ b/niucloud/app/api/route/route.php @@ -68,6 +68,12 @@ Route::group(function () { // 通过外部交易号获取消息跳转路径 Route::get('weapp/getMsgJumpPath', 'weapp.Weapp/getMsgJumpPath'); + // app通过wx code登录 + Route::post('wxapp/login', 'channel.App/wechatLogin'); + + // 获取App新的版本 + Route::get('app/newversion', 'channel.App/getNewVersion'); + //登录 Route::get('login', 'login.Login/login'); //第三方绑定 @@ -148,6 +154,7 @@ Route::group(function () { Route::get('task/growth', 'sys.Task/growth'); // 获取积分任务 Route::get('task/point', 'sys.Task/point'); + })->middleware(ApiChannel::class) ->middleware(ApiCheckToken::class) ->middleware(ApiLog::class); diff --git a/niucloud/app/dict/channel/AppDict.php b/niucloud/app/dict/channel/AppDict.php new file mode 100644 index 000000000..78a4476b6 --- /dev/null +++ b/niucloud/app/dict/channel/AppDict.php @@ -0,0 +1,56 @@ + 'Android', +// self::IOS => 'ios' + ]; + } + + public static function getAppPlatformName($platform) { + $app_platform = self::getAppPlatform(); + return $app_platform[$platform] ?? ''; + } + + // ********** 版本状态 ************** + + const STATUS_UPLOAD_SUCCESS = 'upload_success'; + + const STATUS_CREATE_FAIL = 'create_fail'; + + const STATUS_PUBLISHED = 'published'; + + const STATUS_CREATING = 'creating'; + + public static function getStatus() { + return [ + self::STATUS_UPLOAD_SUCCESS => '上传成功', + self::STATUS_CREATE_FAIL => '创建失败', + self::STATUS_PUBLISHED => '已发布', + self::STATUS_CREATING => '创建中' + ]; + } + + public static function getStatusName($status) { + return self::getStatus()[$status] ?? ''; + } + +} diff --git a/niucloud/app/dict/common/CommonActiveDict.php b/niucloud/app/dict/common/CommonActiveDict.php index 497cca7cd..c9914dfe1 100644 --- a/niucloud/app/dict/common/CommonActiveDict.php +++ b/niucloud/app/dict/common/CommonActiveDict.php @@ -73,7 +73,7 @@ class CommonActiveDict 'bg_color' => '#FF1C77' ], ]; - return !empty($active) ? $data[$active] : $data; + return !empty($active) ? $data[$active] ?? [] : $data; } // 活动背景特效 diff --git a/niucloud/app/dict/member/MemberLoginTypeDict.php b/niucloud/app/dict/member/MemberLoginTypeDict.php index 2e0052a0d..d353c557d 100644 --- a/niucloud/app/dict/member/MemberLoginTypeDict.php +++ b/niucloud/app/dict/member/MemberLoginTypeDict.php @@ -30,6 +30,8 @@ class MemberLoginTypeDict // PC登录 public const PC = 'pc'; + public const APP = 'app'; + public static function getType($type = '') { $data = [ @@ -38,6 +40,7 @@ class MemberLoginTypeDict self::WECHAT => get_lang('dict_member.login_wechat'),//'微信公众号授权登录', self::WEAPP => get_lang('dict_member.login_weapp'),//'微信小程序授权登录', self::PC => get_lang('dict_member.login_pc'),//'微信小程序授权登录', + self::APP => get_lang('dict_member.login_app') ]; if (empty($type)) { return $data; diff --git a/niucloud/app/dict/member/MemberRegisterTypeDict.php b/niucloud/app/dict/member/MemberRegisterTypeDict.php index f24580d88..66cd6fb3e 100644 --- a/niucloud/app/dict/member/MemberRegisterTypeDict.php +++ b/niucloud/app/dict/member/MemberRegisterTypeDict.php @@ -30,6 +30,8 @@ class MemberRegisterTypeDict //手动添加 const MANUAL = 'manual'; + const APP = 'app'; + public static function getType($type = '') { $data = [ @@ -45,4 +47,4 @@ class MemberRegisterTypeDict return $data[$type] ?? ''; } -} \ No newline at end of file +} diff --git a/niucloud/app/dict/menu/admin.php b/niucloud/app/dict/menu/admin.php index 3dd711efd..a1d95c1b3 100644 --- a/niucloud/app/dict/menu/admin.php +++ b/niucloud/app/dict/menu/admin.php @@ -262,7 +262,7 @@ return [ 'methods' => 'get', 'sort' => '70', 'status' => '1', - 'is_show' => '0', + 'is_show' => '1', 'children' => [ [ 'menu_name' => '新增', diff --git a/niucloud/app/dict/menu/site.php b/niucloud/app/dict/menu/site.php index a44133684..53600d6c7 100644 --- a/niucloud/app/dict/menu/site.php +++ b/niucloud/app/dict/menu/site.php @@ -8,7 +8,7 @@ return [ 'menu_type' => '0', 'icon' => 'iconfont iconzhuangxiu3', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'diy/index', 'view_path' => '', 'methods' => '', 'sort' => '90', @@ -329,7 +329,7 @@ return [ 'menu_type' => '0', 'icon' => 'iconfont iconhuiyuan', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'member/member', 'view_path' => '', 'methods' => '', 'sort' => '89', @@ -652,7 +652,7 @@ return [ 'menu_type' => '0', 'icon' => 'iconfont iconjifen-xianxing', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'member/point', 'view_path' => '', 'methods' => '', 'sort' => '51', @@ -743,7 +743,7 @@ return [ 'menu_type' => '0', 'icon' => 'iconfont iconcaiwu1', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'finance/account', 'view_path' => '', 'methods' => '', 'sort' => '88', @@ -877,7 +877,7 @@ return [ 'menu_type' => '0', 'icon' => 'iconfont iconyingxiao2', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'app/marketing', 'view_path' => '', 'methods' => '', 'sort' => '87', @@ -908,7 +908,7 @@ return [ 'menu_type' => '0', 'icon' => '', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'marketing/verify/index', 'view_path' => '', 'methods' => 'get', 'sort' => '48', @@ -1025,7 +1025,7 @@ return [ 'menu_type' => '0', 'icon' => 'element FolderChecked', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'marketing/sign/config', 'view_path' => '', 'methods' => 'get', 'sort' => '30', @@ -1580,6 +1580,64 @@ return [ 'status' => '1', 'is_show' => '0', ], + [ + 'menu_name' => 'App端', + 'menu_key' => 'channel_app', + 'menu_short_name' => 'App端', + 'menu_type' => '1', + 'icon' => '', + 'api_url' => '', + 'router_path' => 'channel/app', + 'view_path' => 'channel/app/access', + 'methods' => '', + 'sort' => '50', + 'status' => '1', + 'is_show' => '1', + ], + [ + 'menu_name' => 'App端配置', + 'menu_key' => 'channel_app_config', + 'menu_short_name' => 'app端配置', + 'menu_type' => '1', + 'icon' => '', + 'api_url' => 'channel/app/config', + 'router_path' => 'channel/app/config', + 'view_path' => 'channel/app/config', + 'methods' => 'get', + 'sort' => '100', + 'status' => '1', + 'is_show' => '0', + 'children' => [ + [ + 'menu_name' => '设置app端配置', + 'menu_key' => 'set_channel_app_config', + 'menu_short_name' => '设置app端配置', + 'menu_type' => '2', + 'icon' => '', + 'api_url' => 'channel/app/config', + 'router_path' => '', + 'view_path' => '', + 'methods' => 'put', + 'sort' => '100', + 'status' => '1', + 'is_show' => '1', + ] + ] + ], + [ + 'menu_name' => 'APP版本管理', + 'menu_key' => 'app_version_list', + 'menu_short_name' => '版本管理', + 'menu_type' => '1', + 'icon' => '', + 'api_url' => 'channel/app/version', + 'router_path' => 'channel/app/version', + 'view_path' => 'channel/app/version', + 'methods' => 'get', + 'sort' => '100', + 'status' => '1', + 'is_show' => '0', + ] ], ], [ @@ -1793,7 +1851,7 @@ return [ 'menu_type' => '0', 'icon' => 'iconfont iconshezhi3', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'setting/system', 'view_path' => '', 'methods' => '', 'sort' => '83', @@ -1807,7 +1865,7 @@ return [ 'menu_type' => '0', 'icon' => 'element Basketball', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'setting/system', 'view_path' => '', 'methods' => '', 'sort' => '100', @@ -1883,7 +1941,7 @@ return [ 'menu_type' => '0', 'icon' => 'iconfont iconjiaoseyonghu', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'setting/member', 'view_path' => '', 'methods' => '', 'sort' => '71', @@ -1959,7 +2017,7 @@ return [ 'menu_type' => '1', 'icon' => 'element Wallet', 'api_url' => '', - 'router_path' => 'setting/pay', + 'router_path' => 'setting/pay/channel', 'view_path' => '', 'methods' => 'get', 'sort' => '60', @@ -2080,7 +2138,7 @@ return [ 'menu_type' => '1', 'icon' => 'element ChatLineSquare', 'api_url' => '', - 'router_path' => 'setting/notice', + 'router_path' => 'setting/notice/template', 'view_path' => '', 'methods' => '', 'sort' => '50', @@ -2168,7 +2226,7 @@ return [ 'menu_type' => '0', 'icon' => 'element Message', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'setting/sms/setting', 'view_path' => '', 'methods' => '', 'sort' => '40', @@ -2287,7 +2345,7 @@ return [ 'menu_type' => '0', 'icon' => 'element FolderChecked', 'api_url' => '', - 'router_path' => '', + 'router_path' => 'setting/agreement', 'view_path' => '', 'methods' => '', 'sort' => '20', diff --git a/niucloud/app/dict/sys/ConfigKeyDict.php b/niucloud/app/dict/sys/ConfigKeyDict.php index f824c0453..71a827f84 100644 --- a/niucloud/app/dict/sys/ConfigKeyDict.php +++ b/niucloud/app/dict/sys/ConfigKeyDict.php @@ -40,4 +40,6 @@ class ConfigKeyDict public const SMS = 'SMS';//短信配置 public const PINTUAN_ORDER_CONFIG = 'PINTUAN_ORDER_CONFIG';//拼团订单配置 + + public const APP = 'app'; } diff --git a/niucloud/app/dict/sys/FileDict.php b/niucloud/app/dict/sys/FileDict.php index 0c6b6832a..b50188141 100644 --- a/niucloud/app/dict/sys/FileDict.php +++ b/niucloud/app/dict/sys/FileDict.php @@ -35,6 +35,10 @@ class FileDict public const EXCEL = 'excel';//excel导入 + public const APP_PACKAGE = 'app_package';//应用包 + + public const ANDROID_CERT = 'android_cert';//android证书 + /** * 附件类型 * @return array @@ -76,6 +80,8 @@ class FileDict self::AUDIO,//视频上传 self::APPLET,//小程序包上传 self::EXCEL,//excel导入 + self::APP_PACKAGE,//应用包 + self::ANDROID_CERT,//android证书 ]; } @@ -91,4 +97,4 @@ class FileDict self::SMALL,//图片上传 ]; } -} \ No newline at end of file +} diff --git a/niucloud/app/install/controller/Index.php b/niucloud/app/install/controller/Index.php index b47cefe52..88bd8930d 100644 --- a/niucloud/app/install/controller/Index.php +++ b/niucloud/app/install/controller/Index.php @@ -56,6 +56,9 @@ class Index extends BaseInstall //sodium $sodium = extension_loaded('sodium'); $system_variables[] = [ "name" => "sodium", "need" => "开启", "status" => $sodium ]; + //imagick + $imagick = extension_loaded('imagick'); + $system_variables[] = [ "name" => "imagick", "need" => "开启", "status" => $imagick ]; $root_path = str_replace("\\", DIRECTORY_SEPARATOR, dirname(__FILE__, 4)); $root_path = str_replace("../", DIRECTORY_SEPARATOR, $root_path); @@ -88,7 +91,7 @@ class Index extends BaseInstall $this->assign("name", $name); $this->assign("verison", $verison); $this->assign("dirs_list", $dirs_list); - if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir) { + if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir && $imagick) { $continue = true; } else { $continue = false; diff --git a/niucloud/app/install/source/database.sql b/niucloud/app/install/source/database.sql index fea082e93..4d8b606bb 100644 --- a/niucloud/app/install/source/database.sql +++ b/niucloud/app/install/source/database.sql @@ -35,6 +35,27 @@ CREATE TABLE `addon_log` ( ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '插件日志表' ROW_FORMAT = Dynamic; +DROP TABLE IF EXISTS `app_version`; +CREATE TABLE `app_version` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `site_id` INT(11) NOT NULL DEFAULT 0 COMMENT '站点id', + `version_code` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '版本号', + `version_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '版本名称', + `version_desc` VARCHAR(1500) NOT NULL DEFAULT '' COMMENT '版本描述', + `platform` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'app平台 Android Ios', + `package_path` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '安装包路径', + `status` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '状态', + `is_forced_upgrade` INT(11) NOT NULL DEFAULT 0 COMMENT '是否需要强制升级', + `task_key` VARCHAR(255) NOT NULL DEFAULT '', + `fail_reason` VARCHAR(255) NOT NULL DEFAULT '', + `upgrade_type` VARCHAR(255) NOT NULL DEFAULT 'app' COMMENT 'app 整包更新 hot 热更新 market 应用市场更新', + `release_time` INT(11) NOT NULL DEFAULT 0 COMMENT '发布时间', + `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间', + `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间', + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'app版本管理' ROW_FORMAT = Dynamic; + + DROP TABLE IF EXISTS `applet_site_version`; CREATE TABLE `applet_site_version` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', diff --git a/niucloud/app/lang/zh-cn/api.php b/niucloud/app/lang/zh-cn/api.php index 2628668eb..20d22d6a3 100644 --- a/niucloud/app/lang/zh-cn/api.php +++ b/niucloud/app/lang/zh-cn/api.php @@ -24,6 +24,7 @@ return [ 'ADD_FAIL' => '添加失败', 'ADD_SUCCESS' => '添加成功', 'UPLOAD_FAIL' => '上传失败', + 'RELEASE_SUCCESS' => '发布成功', 'ATTACHMENT_DELETE_FAIL' => '附件删除失败', 'DATA_NOT_EXIST' => '数据不存在', 'DOWNLOAD_FAIL' => '下载失败', @@ -205,6 +206,7 @@ return [ //海报 'POSTER_NOT_EXIST' => '海报不存在', 'POSTER_IN_USE_NOT_ALLOW_MODIFY' => '海报使用中禁止修改状态', + 'POSTER_CREATE_ERROR' => '海报组件未配置完善,请联系管理员', //万能表单 'DIY_FORM_NOT_EXIST' => '表单不存在', diff --git a/niucloud/app/listener/qrcode/WechatQrcodeListener.php b/niucloud/app/listener/qrcode/WechatQrcodeListener.php index ce95d5771..796269739 100644 --- a/niucloud/app/listener/qrcode/WechatQrcodeListener.php +++ b/niucloud/app/listener/qrcode/WechatQrcodeListener.php @@ -12,7 +12,7 @@ class WechatQrcodeListener extends BaseNoticeTemplate public function handle(array $params) { - if ('wechat' == $params['channel'] || $params['channel'] == 'h5') { + if ('wechat' == $params['channel'] || $params['channel'] == 'h5' || $params['channel'] == 'app') { $page = $params['page']; $url = $params['url']; $data = $params['data']; @@ -44,4 +44,4 @@ class WechatQrcodeListener extends BaseNoticeTemplate } } -} \ No newline at end of file +} diff --git a/niucloud/app/listener/system/ShowAppListener.php b/niucloud/app/listener/system/ShowAppListener.php index ed4ffc36d..160488bc6 100644 --- a/niucloud/app/listener/system/ShowAppListener.php +++ b/niucloud/app/listener/system/ShowAppListener.php @@ -35,7 +35,7 @@ class ShowAppListener 'desc' => '管理核销员及核销记录', 'icon' => 'static/resource/images/marketing/verifier.png', 'key' => 'verify', - 'url' => '/marketing/verifier', + 'url' => '/marketing/verify/index', ], [ 'title' => '万能表单', diff --git a/niucloud/app/model/pay/Refund.php b/niucloud/app/model/pay/Refund.php index 2b4046e59..62a5c31a8 100644 --- a/niucloud/app/model/pay/Refund.php +++ b/niucloud/app/model/pay/Refund.php @@ -11,6 +11,7 @@ namespace app\model\pay; +use app\dict\common\CommonActiveDict; use app\dict\pay\PayDict; use app\dict\pay\RefundDict; use core\base\BaseModel; @@ -134,4 +135,12 @@ class Refund extends BaseModel $query->where('refund_no', 'like', "%$value%"); } } + + public function getTradeTypeNameAttr($value, $data) + { + if (empty($data['trade_type'])){ + return ''; + } + return CommonActiveDict::getActiveShort($data['trade_type'])['active_name'] ?? ""; + } } diff --git a/niucloud/app/model/sys/AppVersion.php b/niucloud/app/model/sys/AppVersion.php new file mode 100644 index 000000000..250a06d3f --- /dev/null +++ b/niucloud/app/model/sys/AppVersion.php @@ -0,0 +1,49 @@ + 'timestamp', + ]; + + /** + * 模型名称 + * @var string + */ + protected $name = 'app_version'; + + public function searchPlatformAttr(Query $query, $value, $data) + { + if ($value) { + $query->where('platform', $value); + } + } + + public function getPlatformNameAttr($value, $data) + { + return AppDict::getAppPlatformName($data['platform']); + } + + public function getStatusNameAttr($value, $data) + { + return AppDict::getStatusName($data['status']); + } +} diff --git a/niucloud/app/service/admin/channel/AppService.php b/niucloud/app/service/admin/channel/AppService.php new file mode 100644 index 000000000..5c30e00ab --- /dev/null +++ b/niucloud/app/service/admin/channel/AppService.php @@ -0,0 +1,188 @@ +model = new AppVersion(); + } + + /** + * 设置app信息 + * @param array $value + * @return bool + */ + public function setConfig(array $value) + { + return (new CoreAppService())->setConfig($this->site_id, $value); + } + + /** + * 获取app配置 + * @return mixed + */ + public function getConfig(){ + return (new CoreAppService())->getConfig($this->site_id); + } + + /** + * @param array $where + * @return array + * @throws \think\db\exception\DbException + */ + public function getVersionPage(array $where = []) + { + $order = 'id desc'; + $search_model = $this->model->where([ [ 'site_id' ,"=", $this->site_id ] ])->withSearch(["platform"], $where)->append(['platform_name', 'status_name'])->field("*")->order($order); + $list = $this->pageQuery($search_model); + return $list; + } + + /** + * @param $id + * @return AppVersion|array|mixed|\think\Model + */ + public function getVersionInfo($id) { + return $this->model->where([ [ 'site_id' ,"=", $this->site_id ], ['id', '=', $id] ])->findOrEmpty()->toArray(); + } + + /** + * 添加版本 + * @param array $data + * @return mixed + */ + public function addVersion(array $data) { + $not_release = $this->model->where([['site_id', '=', $this->site_id], ['release_time', '=', 0]])->findOrEmpty(); + if (!$not_release->isEmpty()) throw new CommonException("当前已存在未发布的版本"); + + $last_version = $this->model->where([['site_id', '=', $this->site_id]])->order('id desc')->findOrEmpty(); + if (!$last_version->isEmpty() && $data['version_code'] <= $last_version['version_code']) throw new CommonException("版本号必须高于上一版本设置的值"); + + $data['site_id'] = $this->site_id; + + $model = [ + 'site_id' => $this->site_id, + 'version_code' => $data['version_code'], + 'version_name' => $data['version_name'], + 'version_desc' => $data['version_desc'], + 'platform' => $data['platform'], + 'is_forced_upgrade' => $data['is_forced_upgrade'], + 'package_path' => $data['package_path'], + 'upgrade_type' => $data['upgrade_type'], + ]; + + if ($data['package_type'] == 'cloud') { + $task_key = (new CoreAppCloudService())->appCloudBuid($data); + $model['task_key'] = $task_key['key']; + $model['status'] = AppDict::STATUS_CREATING; + } else { + $model['status'] = AppDict::STATUS_UPLOAD_SUCCESS; + } + + $res = $this->model->create($model); + return $res->id; + } + + /** + * 编辑版本 + * @param int $id + * @param array $data + * @return true + */ + public function editVersion(int $id, array $data) + { + $last_version = $this->model->where([['site_id', '=', $this->site_id], ['id', '<>', $id]])->order('id desc')->findOrEmpty(); + if (!$last_version->isEmpty() && $data['version_code'] <= $last_version['version_code']) throw new CommonException("版本号必须高于上一版本设置的值"); + + $data['site_id'] = $this->site_id; + + $model = [ + 'version_code' => $data['version_code'], + 'version_name' => $data['version_name'], + 'version_desc' => $data['version_desc'], + 'platform' => $data['platform'], + 'is_forced_upgrade' => $data['is_forced_upgrade'], + 'package_path' => $data['package_path'], + 'upgrade_type' => $data['upgrade_type'], + ]; + + if ($data['package_type'] == 'cloud') { + $task_key = (new CoreAppCloudService())->appCloudBuid($data); + $model['task_key'] = $task_key['key']; + $model['status'] = AppDict::STATUS_CREATING; + } else { + $model['status'] = AppDict::STATUS_UPLOAD_SUCCESS; + } + $this->model->where([['id', '=', $id],['site_id', '=', $this->site_id]])->update($model); + return true; + } + + /** + * 删除app版本 + * @param int $id + * @return bool + */ + public function delVersion(int $id) + { + $model = $this->model->where([['id', '=', $id],['site_id', '=', $this->site_id]])->find(); + $res = $model->delete(); + return $res; + } + + public function getBuildLog(string $key) { + $result = (new CoreAppCloudService())->getAppCompileLog($key); + if ($result['status'] == 'fail') { + $this->model->update(['status' => AppDict::STATUS_CREATE_FAIL, 'fail_reason' => $result['fail_reason'], 'update_time' => time() ], ['task_key' => $key, 'site_id' => $this->site_id]); + } + if ($result['status'] == 'success') { + $this->model->update(['status' => AppDict::STATUS_UPLOAD_SUCCESS, 'package_path' => $result['file_path'], 'update_time' => time() ], ['task_key' => $key, 'site_id' => $this->site_id]); + } + return $result; + } + + /** + * 发布 + * @param string $key + * @return void + */ + public function release(int $id) { + $version = $this->model->where([['id', '=', $id],['site_id', '=', $this->site_id]])->findOrEmpty(); + if ($version->isEmpty()) throw new CommonException("版本不存在"); + if ($version['status'] != AppDict::STATUS_UPLOAD_SUCCESS) throw new CommonException("版本未上传成功"); + + $this->model->update(['release_time' => time(), 'status' => AppDict::STATUS_PUBLISHED], ['id' => $id]); + } + + public function generateSingCert($data) { + return (new CoreAppCloudService())->generateSingCert($data); + } +} diff --git a/niucloud/app/service/admin/notice/NiuSmsService.php b/niucloud/app/service/admin/notice/NiuSmsService.php index 12976cfbc..1e5662d43 100644 --- a/niucloud/app/service/admin/notice/NiuSmsService.php +++ b/niucloud/app/service/admin/notice/NiuSmsService.php @@ -33,7 +33,7 @@ class NiuSmsService extends BaseAdminService { parent::__construct(); $this->template_model = new NiuSmsTemplate(); - $this->niu_service = new CoreNiuSmsService(); + $this->niu_service = (new CoreNiuSmsService())->setSiteId($this->site_id); } public function enableNiuSms($enable) @@ -102,7 +102,11 @@ class NiuSmsService extends BaseAdminService */ public function registerAccount($data) { - $data['imgUrl'] = !empty($data['imgUrl']) ? request()->domain() . "/" . $data['imgUrl'] : ""; + if (!empty($data['imgUrl']) && strstr($data['imgUrl'], 'http') === false) { + $data['imgUrl'] = request()->domain() . "/" . $data['imgUrl']; + } else { + $data['imgUrl'] = $data['imgUrl'] ?? ''; + } $res = $this->niu_service->registerAccount($data); return $res; } @@ -116,7 +120,7 @@ class NiuSmsService extends BaseAdminService { $account_info = $this->niu_service->loginAccount($params); if ($account_info) { - (new CoreNiuSmsService())->setNiuLoginConfig($params,true); + (new CoreNiuSmsService())->setNiuLoginConfig($params, true); } return $account_info; } @@ -229,7 +233,11 @@ class NiuSmsService extends BaseAdminService */ public function signCreate($username, $params) { - $params['imgUrl'] = !empty($params['imgUrl']) ? request()->domain() . "/" . $params['imgUrl'] : ""; + if (!empty($params['imgUrl']) && strstr($params['imgUrl'], 'http') === false) { + $params['imgUrl'] = request()->domain() . '/' . $params['imgUrl']; + } else { + $params['imgUrl'] = $params['imgUrl'] ?? ''; + } $res = $this->niu_service->signCreate($username, $params); if (!empty($res['failList'])) { throw new AdminException($res['failList'][0]['msg']); @@ -391,9 +399,9 @@ class NiuSmsService extends BaseAdminService $audit_status = $report_info['audit_status'] ?? NoticeTypeDict::TEMPLATE_AUDIT_STATUS_NOT_REPORT; $error_status = ''; if (!empty($report_info) && $variable != $params_json) { - if (empty($params_json)){ + if (empty($params_json)) { $error_status = NoticeTypeDict::TEMPLATE_NEED_PULL; - }else{ + } else { $error_status = $audit_status == NoticeTypeDict::TEMPLATE_AUDIT_STATUS_PASS ? NoticeTypeDict::TEMPLATE_AUDIT_STATUS_NEED_AGAIN_REPORT : NoticeTypeDict::TEMPLATE_AUDIT_STATUS_NEED_EDIT; diff --git a/niucloud/app/service/admin/pay/RefundService.php b/niucloud/app/service/admin/pay/RefundService.php index 887a47f7d..667722914 100644 --- a/niucloud/app/service/admin/pay/RefundService.php +++ b/niucloud/app/service/admin/pay/RefundService.php @@ -35,7 +35,11 @@ class RefundService extends BaseAdminService */ public function getPage(array $where){ $field = 'id,refund_no,out_trade_no,type,channel,money,reason,status,create_time,refund_time,close_time,fail_reason,voucher,trade_type,trade_id,refund_type,main_type,main_id'; - $search_model = $this->model->where([ [ 'site_id', '=', $this->site_id ] ])->withSearch([ 'create_time', 'out_trade_no', 'refund_no', 'status' ], $where)->field($field)->append([ 'type_name', 'status_name' ])->order('create_time desc'); + $search_model = $this->model->where([ [ 'site_id', '=', $this->site_id ] ]) + ->withSearch([ 'create_time', 'out_trade_no', 'refund_no', 'status' ], $where) + ->field($field) + ->append([ 'type_name', 'status_name','trade_type_name' ]) + ->order('create_time desc'); return $this->pageQuery($search_model); } diff --git a/niucloud/app/service/admin/sys/ConfigService.php b/niucloud/app/service/admin/sys/ConfigService.php index 4c0b9243c..9c1660ec9 100644 --- a/niucloud/app/service/admin/sys/ConfigService.php +++ b/niucloud/app/service/admin/sys/ConfigService.php @@ -135,6 +135,7 @@ class ConfigService extends BaseAdminService { $data = [ 'key' => $value[ 'key' ], + 'amap_key' => $value['amap_key'], 'is_open' => $value[ 'is_open' ], // 是否开启定位 'valid_time' => $value[ 'valid_time' ] // 定位有效期/分钟,过期后将重新获取定位信息,0为不过期 ]; @@ -154,6 +155,7 @@ class ConfigService extends BaseAdminService $info = []; $info[ 'value' ] = [ 'key' => '', + 'amap_key' => '', 'is_open' => 1, // 是否开启定位 'valid_time' => 5 // 定位有效期/分钟,过期后将重新获取定位信息,0为不过期 ]; @@ -161,6 +163,8 @@ class ConfigService extends BaseAdminService $info[ 'value' ][ 'is_open' ] = $info[ 'value' ][ 'is_open' ] ?? 1; $info[ 'value' ][ 'valid_time' ] = $info[ 'value' ][ 'valid_time' ] ?? 5; + $info[ 'value' ][ 'amap_key' ] = $info[ 'value' ][ 'amap_key' ] ?? ''; + return $info[ 'value' ]; } diff --git a/niucloud/app/service/admin/upload/UploadService.php b/niucloud/app/service/admin/upload/UploadService.php index 14dcf907b..f8404019e 100644 --- a/niucloud/app/service/admin/upload/UploadService.php +++ b/niucloud/app/service/admin/upload/UploadService.php @@ -85,4 +85,4 @@ class UploadService extends BaseAdminService $core_upload_service = new CoreUploadService(); return $core_upload_service->document($file, $this->site_id, $type, $dir, StorageDict::LOCAL); } -} \ No newline at end of file +} diff --git a/niucloud/app/service/api/channel/AppService.php b/niucloud/app/service/api/channel/AppService.php new file mode 100644 index 000000000..a1bd26735 --- /dev/null +++ b/niucloud/app/service/api/channel/AppService.php @@ -0,0 +1,35 @@ +where([ + ['site_id', '=', $this->site_id], + ['platform', '=', $data['platform'] ], + ['version_code', '>', $data['version_code'] ], + ['status', '=', AppDict::STATUS_PUBLISHED], + ])->order("version_code desc")->findOrEmpty()->toArray(); + return empty($version) ? null : $version; + } +} diff --git a/niucloud/app/service/api/login/LoginService.php b/niucloud/app/service/api/login/LoginService.php index 005480fc3..818430925 100644 --- a/niucloud/app/service/api/login/LoginService.php +++ b/niucloud/app/service/api/login/LoginService.php @@ -119,6 +119,7 @@ class LoginService extends BaseApiService $openid_field = match ( $this->channel ) { 'wechat' => 'wx_openid', 'weapp' => 'weapp_openid', + 'app' => 'wxapp_openid', default => '' }; diff --git a/niucloud/app/service/api/sys/ConfigService.php b/niucloud/app/service/api/sys/ConfigService.php index 460295da2..66e868c45 100644 --- a/niucloud/app/service/api/sys/ConfigService.php +++ b/niucloud/app/service/api/sys/ConfigService.php @@ -11,7 +11,9 @@ namespace app\service\api\sys; +use app\service\core\channel\CoreAppService; use app\service\core\sys\CoreSysConfigService; +use app\service\core\weapp\CoreWeappConfigService; use core\base\BaseApiService; /** @@ -60,4 +62,11 @@ class ConfigService extends BaseApiService return (new CoreSysConfigService())->getMap($this->site_id); } + public function getAppConfig() { + $config = (new CoreAppService())->getConfig($this->site_id); + if (!empty($config) && isset($config['wechat_app_secret'])) unset($config['wechat_app_secret']); + $weapp_config = (new CoreWeappConfigService())->getWeappConfig($this->site_id); + $config['weapp_original'] = $weapp_config['weapp_original']; + return $config; + } } diff --git a/niucloud/app/service/api/wechat/WechatAppService.php b/niucloud/app/service/api/wechat/WechatAppService.php new file mode 100644 index 000000000..f8355927e --- /dev/null +++ b/niucloud/app/service/api/wechat/WechatAppService.php @@ -0,0 +1,203 @@ +site_id, $code); + if (empty($userinfo)) throw new ApiException('WECHAT_EMPOWER_NOT_EXIST'); + $token_response = $userinfo->getTokenResponse(); + if (empty($token_response)) throw new ApiException('WECHAT_EMPOWER_NOT_EXIST'); + $scope = $token_response[ 'scope' ]; + if ($scope == 'snsapi_base') {//静默授权 + $openid = $token_response[ 'openid' ] ?? ''; + } else { + $openid = $userinfo->getId();//对应微信的 openid + $nickname = $userinfo->getNickname();//对应微信的 nickname + $avatar = $userinfo->getAvatar();//对应微信的 头像地址 + } + $unionid = $userinfo->getRaw()[ 'unionid' ] ?? ''; + if (empty($openid)) throw new ApiException('WECHAT_EMPOWER_NOT_EXIST'); + $is_snapshotuser = $userinfo->getRaw()[ 'is_snapshotuser' ] ?? 0; + if ($is_snapshotuser == 1) throw new ApiException('WECHAT_SNAPSHOUTUSER'); + //todo 这儿还可能会获取用户昵称 头像 性别 ....用以更新会员信息 + return [ $avatar ?? '', $nickname ?? '', $openid, $unionid ]; + //todo 业务落地 + } + + /** + * 登录通过code + * @param string $code + * @return array|string[]|null + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function loginByCode(string $code) + { + [ $avatar, $nickname, $openid, $unionid ] = $this->userFromCode($code); + return $this->login($openid, $nickname, $avatar, $unionid); + } + + /** + * 公众号登录 + * @param string $openid + * @param string $nickname + * @param string $avatar + * @param string $unionid + * @return array|null + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function login(string $openid, string $nickname = '', string $avatar = '', string $unionid = '') + { + + $member_service = new MemberService(); + $member_info = $member_service->findMemberInfo([ 'wxapp_openid' => $openid, 'site_id' => $this->site_id ]); + if ($member_info->isEmpty() && !empty($unionid)) { + $member_info = $member_service->findMemberInfo([ 'wx_unionid' => $unionid, 'site_id' => $this->site_id ]); + if (!$member_info->isEmpty()) { + $member_info->wx_openid = $openid; + } + } + if ($member_info->isEmpty()) { + $config = ( new MemberConfigService() )->getLoginConfig(); + $is_auth_register = $config[ 'is_auth_register' ]; + $is_force_access_user_info = $config[ 'is_force_access_user_info' ]; + $is_bind_mobile = $config[ 'is_bind_mobile' ]; + + // 开启自动注册会员 + if ($is_auth_register) { + + // 开启强制获取会员信息并且开启强制绑定手机号,必须获取手机号才能进行注册,由于公众号无法主动获取,所以不能注册 + if ($is_force_access_user_info && $is_bind_mobile) { + return [ 'avatar' => $avatar, 'nickname' => $nickname, 'openid' => $openid, 'unionid' => $unionid ]; + } else if ($is_force_access_user_info) { + // 开启强制获取会员信息时,必须获取到昵称和头像才能进行注册 +// if (!empty($nickname) && !empty($avatar)) { + if (empty($nickname)){ + $nickname = unique_random(); + } + return $this->register($openid, '', $nickname, $avatar, $unionid); // 获取到昵称和头像,然后进行注册 +// } else { +// return [ 'avatar' => $avatar, 'nickname' => $nickname, 'openid' => $openid, 'unionid' => $unionid ]; +// } + } else if ($is_bind_mobile) { + // 开启强制绑定手机号,必须获取手机号才能进行注册,由于公众号无法主动获取,所以不能注册 + return [ 'openid' => $openid, 'unionid' => $unionid ]; + } else if (!$is_force_access_user_info && !$is_bind_mobile) { + // 关闭强制获取用户信息、并且关闭强制绑定手机号的情况下允许注册 + return $this->register($openid, '', $nickname, $avatar, $unionid); + } + + } else { + return [ 'openid' => $openid, 'unionid' => $unionid ]; // 将重要信息返回给前端保存 + } + } else { + // 可能会更新用户和粉丝表 + $login_service = new LoginService(); + // 若用户头像为空,那么从微信获取头像和昵称,然后进行更新 + if (empty($member_info->headimg)) { + if (!empty($avatar)) $member_info->headimg = $avatar; + if (!empty($nickname)) $member_info->nickname = $nickname; + } + return $login_service->login($member_info, MemberLoginTypeDict::WECHAT); + } + } + + /** + * 同步数据 + * @param string $code + * @return true + */ + public function sync(string $code) + { + [ $avatar, $nickname, $openid ] = $this->userFromCode($code); + //更新粉丝 + $core_wechat_fans_service = new CoreWechatFansService(); + //这儿或许可以异步 + $core_wechat_fans_service->edit($this->site_id, $openid, [ 'avatar' => $avatar, 'nickname' => $nickname ]); + $member_service = new MemberService(); + $member_info = $member_service->findMemberInfo([ 'wxapp_openid' => $openid, 'site_id' => $this->site_id ]); + if ($member_info->isEmpty()) throw new AuthException('MEMBER_NOT_EXIST');//账号不存在 + $member_service->editByFind($member_info, [ 'headimg' => $avatar, 'nickname' => $nickname ]); + return true; + } + + /** + * 注册 + * @param string $openid + * @param string $mobile + * @param string $nickname + * @param string $avatar + * @param string $wx_unionid + * @return array + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function register(string $openid, string $mobile = '', string $nickname = '', string $avatar = '', string $wx_unionid = '') + { + $member_service = new MemberService(); + $member_info = $member_service->findMemberInfo([ 'wxapp_openid' => $openid, 'site_id' => $this->site_id ]); + if (!$member_info->isEmpty()) throw new AuthException('MEMBER_IS_EXIST');//账号已存在, 不能在注册 + if (!empty($wx_unionid)) { + $member_info = $member_service->findMemberInfo([ 'wx_unionid' => $wx_unionid, 'site_id' => $this->site_id ]); + if (!$member_info->isEmpty()) throw new AuthException('MEMBER_IS_EXIST');//账号已存在, 不能在注册 + } + $register_service = new RegisterService(); + return $register_service->register($mobile, + [ + 'wxapp_openid' => $openid, + 'nickname' => $nickname, + 'headimg' => $avatar, + 'wx_unionid' => $wx_unionid + ], + MemberRegisterTypeDict::APP + ); + + } + +} diff --git a/niucloud/app/service/core/addon/WapTrait.php b/niucloud/app/service/core/addon/WapTrait.php index 6e2a8d16e..b89fd67c9 100644 --- a/niucloud/app/service/core/addon/WapTrait.php +++ b/niucloud/app/service/core/addon/WapTrait.php @@ -38,7 +38,7 @@ trait WapTrait $content .= " \n"; - $content .= " \n"; + $content .= " \n"; $content .= " \n"; $content .= " \n"; @@ -337,7 +337,6 @@ trait WapTrait { $manifest_json = str_replace('/', DIRECTORY_SEPARATOR, $compile_path . 'src/manifest.json'); $manifest_content = $this->jsonStringToArray(file_get_contents($manifest_json)); - ( new CoreAddonBaseService() )->writeArrayToJsonFile(array_merge2($manifest_content, $merge_data), $manifest_json); } @@ -348,8 +347,7 @@ trait WapTrait */ private function jsonStringToArray($string) { - $list = explode(PHP_EOL, $string); - + $list = explode("\n", $string); $json_array = []; foreach ($list as $index => $item) { if (strpos($item, '/*') === false) { diff --git a/niucloud/app/service/core/channel/CoreAppCloudService.php b/niucloud/app/service/core/channel/CoreAppCloudService.php new file mode 100644 index 000000000..6994be205 --- /dev/null +++ b/niucloud/app/service/core/channel/CoreAppCloudService.php @@ -0,0 +1,415 @@ +root_path = dirname(root_path()) . DIRECTORY_SEPARATOR; + $this->addon_path = root_path() . 'addon' . DIRECTORY_SEPARATOR; + } + + /** + * 上传APP + * @param $addon + */ + public function appCloudBuid(array $data) + { + $this->site_id = $data['site_id']; + + $action_token = ( new CoreModuleService() )->getActionToken('appbuild', [ 'data' => [ 'product_key' => BaseNiucloudClient::PRODUCT ] ]); + + $app_config = (new CoreAppService())->getConfig($this->site_id); + if (empty($app_config['app_name'])) throw new CommonException("请先配置应用名称"); + if (empty($app_config['uni_app_id'])) throw new CommonException("请先配置应用ID"); + if (empty($app_config['android_app_key'])) throw new CommonException("请先配置应用密钥"); + if (empty($app_config['application_id'])) throw new CommonException("请先配置应用包名"); + + $wap_url = (new CoreSysConfigService())->getSceneDomain($this->site_id)['wap_url']; + $map_config = ( new CoreConfigService() )->getConfigValue($this->site_id, 'MAPKEY'); + $build = [ + 'app_name' => $app_config['app_name'], + 'uni_app_id' => $app_config['uni_app_id'], + 'wechat_app_id' => $app_config['wechat_app_id'], + 'wechat_app_secret' => $app_config['wechat_app_secret'], + 'android_app_key' => $app_config['android_app_key'], + 'application_id' => $app_config['application_id'], + 'privacy_agreement' => $wap_url . '/app/pages/auth/agreement?key=privacy&=', + 'service_agreement' => $wap_url . '/app/pages/auth/agreement?key=service&=', + 'qq_map_key' => $map_config['key'] ?? '', + 'amap_key' => $map_config['amap_key'] ?? '', + 'version_name' => $data['version_name'], + 'version_code' => $data['version_code'], + 'cert' => $data['cert'] + ]; + + // 上传任务key + $task_key = time(); + // 此次上传任务临时目录 + $temp_dir = runtime_path() . 'build_app' . DIRECTORY_SEPARATOR . $task_key; + $package_dir = $temp_dir . DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR; + // uni + $uni_dir = $package_dir . 'uni-app'; + + dir_copy($this->root_path . 'uni-app', $uni_dir, exclude_dirs: [ 'node_modules', 'unpackage', 'dist' ]); + $this->handleUniapp($uni_dir); + // 替换env文件 + $this->weappEnvReplace($uni_dir . DIRECTORY_SEPARATOR . '.env.production'); + + // 拷贝证书文件 + if ($data['cert']['type'] == 'private') { + if (!file_exists($data['cert']['file'])) throw new CommonException('证书文件不存在'); + $cert_content = file_get_contents($data['cert']['file']); + file_put_contents($package_dir . 'cert.jks', $cert_content); + } + + // 拷贝icon文件 + file_copy($data['build']['icon'], $package_dir . 'drawable.zip'); + + + ( new CoreAddonBaseService() )->writeArrayToJsonFile($build, $package_dir . 'build.json'); + + // 处理 mainifest.json + $this->mergeManifestJson($uni_dir . DIRECTORY_SEPARATOR, [ + "name" => $app_config['app_name'], + "appid" => $app_config['uni_app_id'], + "versionName" => $data['version_name'], + "versionCode" => $data['version_code'], + ]); + + // 将临时目录下文件生成压缩包 + $zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'app.zip'; + ( new CoreAddonDevelopDownloadService('') )->compressToZip($package_dir, $zip_file); + + + $query = [ + 'authorize_code' => $this->auth_code, + 'timestamp' => $task_key, + 'token' => $action_token[ 'data' ][ 'token' ] ?? '' + ]; + $response = ( new CloudService(true, 'http://java.oss.niucloud.com/') )->httpPost('/cloud/appbuild?' . http_build_query($query), [ + 'multipart' => [ + [ + 'name' => 'file', + 'contents' => fopen($zip_file, 'r'), + 'filename' => 'app.zip' + ] + ], + ]); + + + // 删除临时文件 + del_target_dir($temp_dir, true); + + if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]); + + return [ 'key' => $query[ 'timestamp' ] ]; + } + + /** + * 处理uniapp 查询出站点没有的插件进行移除 + * @param string $dir + * @return void + */ + private function handleUniapp(string $dir) + { + $site_addon = (new CoreSiteService())->getAddonKeysBySiteId($this->site_id); + $local_addon = ( new Addon() )->where([ [ 'status', '=', AddonDict::ON ] ])->column('key'); + + // 移除uniapp中该站点没有的插件 + $diff_addon = array_filter(array_map(function ($key) use ($site_addon) { + if (!in_array($key, $site_addon)) return $key; + }, $local_addon)); + + $this->handlePageCode($dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $site_addon); + +// $this->handleTabbar($dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $site_addon); + + if (!empty($diff_addon)) { + foreach ($diff_addon as $addon) { + $this->addon = $addon; + + $addon_dir = $dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'addon' . DIRECTORY_SEPARATOR . $addon; + if (is_dir($addon_dir)) del_target_dir($addon_dir, true); + + // 编译 diy-group 自定义组件代码文件 + $this->compileDiyComponentsCode($dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $addon); + + // 编译 加载插件标题语言包 + $this->compileLocale($dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $addon); + + $manifest_json = root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR . 'manifest.json'; + if (file_exists($manifest_json)) { + $this->mergeManifestJson($dir . DIRECTORY_SEPARATOR, json_decode($manifest_json, true)); + } + } + } + } + + private function handlePageCode($compile_path, $addon_arr) + { + $pages = []; + foreach ($addon_arr as $addon) { + if (!file_exists($this->geAddonPackagePath($addon) . 'uni-app-pages.php')) continue; + $uniapp_pages = require $this->geAddonPackagePath($addon) . 'uni-app-pages.php'; + if (empty($uniapp_pages[ 'pages' ])) continue; + + $page_begin = strtoupper($addon) . '_PAGE_BEGIN'; + $page_end = strtoupper($addon) . '_PAGE_END'; + + // 对0.2.0之前的版本做处理 + $uniapp_pages[ 'pages' ] = preg_replace_callback('/(.*)(\\r\\n.*\/\/ PAGE_END.*)/s', function ($match) { + return $match[ 1 ] . ( substr($match[ 1 ], -1) == ',' ? '' : ',' ) . $match[ 2 ]; + }, $uniapp_pages[ 'pages' ]); + + $uniapp_pages[ 'pages' ] = str_replace('PAGE_BEGIN', $page_begin, $uniapp_pages[ 'pages' ]); + $uniapp_pages[ 'pages' ] = str_replace('PAGE_END', $page_end, $uniapp_pages[ 'pages' ]); + $uniapp_pages[ 'pages' ] = str_replace('{{addon_name}}', $addon, $uniapp_pages[ 'pages' ]); + + $pages[] = $uniapp_pages[ 'pages' ]; + } + + $content = @file_get_contents($compile_path . "pages.json"); + $content = preg_replace_callback('/(.*\/\/ \{\{ PAGE_BEGAIN \}\})(.*)(\/\/ \{\{ PAGE_END \}\}.*)/s', function ($match) use ($pages) { + return $match[ 1 ] . PHP_EOL . implode(PHP_EOL, $pages) . PHP_EOL . $match[ 3 ]; + }, $content); + + // 找到页面路由文件 pages.json,写入内容 + return file_put_contents($compile_path . "pages.json", $content); + } + + /** + * 处理底部导航【暂时停止调用,存在APP兼容性问题】 + * @param $compile_path + * @param $addon_arr + * @return void + */ + public function handleTabbar($compile_path, $addon_arr = []) + { + $bottomList = array_column(( new DiyConfigService() )->getBottomList(), null, 'key'); + $tabbarList = []; + if (empty($addon_arr)) { + foreach ($bottomList as $app_item) { + array_push($tabbarList, ...$app_item[ 'value' ][ 'list' ]); + } + } else { + foreach ($addon_arr as $addon) { + if (isset($bottomList[ $addon ])) { + array_push($tabbarList, ...$bottomList[ $addon ][ 'value' ][ 'list' ]); + } + } + } + + $tabbarList = array_map(function ($item) { + if (strpos($item[ 'link' ][ 'url' ], '?') !== false) { + $item[ 'link' ][ 'url' ] = explode('?', $item[ 'link' ][ 'url' ])[0]; + } + $link = array_filter(explode('/', $item[ 'link' ][ 'url' ])); + $item[ 'link' ] = $item[ 'link' ][ 'url' ]; + $item[ 'component' ] = implode('-', $link); + $item[ 'name' ] = lcfirst(implode('', array_map(function ($str) { + return ucfirst($str); + }, $link))); + return $item; + }, $tabbarList); + $tabbarList = array_column($tabbarList, null, 'name'); + + if (isset($tabbarList[ 'appPagesIndexIndex' ])) unset($tabbarList[ 'appPagesIndexIndex' ]); + if (isset($tabbarList[ 'appPagesMemberIndex' ])) unset($tabbarList[ 'appPagesMemberIndex' ]); + + // 处理vue文件 + $tpl = str_replace('/', DIRECTORY_SEPARATOR, public_path() . 'static/tpl/tabbar.tpl'); + $content = view($tpl, [ 'tabbarList' => $tabbarList ])->getContent(); + file_put_contents(str_replace('/', DIRECTORY_SEPARATOR, $compile_path . 'app/pages/index/tabbar.vue'), $content); + + // 处理tabbar.json + file_put_contents($compile_path . 'tabbar.json', json_encode(array_column($tabbarList, 'link'), JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); + } + + /** + * 小程序上传env文件处理 + * @param string $env_file + * @return void + */ + private function weappEnvReplace(string $env_file) + { + $env = file_get_contents($env_file); + $env = str_replace("VITE_APP_BASE_URL=''", "VITE_APP_BASE_URL='" . (string) url('/', [], '', true) . 'api/' . "'", $env); + $env = str_replace("VITE_IMG_DOMAIN=''", "VITE_IMG_DOMAIN='" . (string) url('/', [], '', true) . "'", $env); + $env = str_replace("VITE_SITE_ID = ''", "VITE_SITE_ID='" . $this->site_id . "'", $env); + file_put_contents($env_file, $env); + } + + /** + * 获取APP编译日志 + * @param string $timestamp + * @return void + */ + public function getAppCompileLog(string $timestamp) + { + $result = [ + 'status' => '', + 'build_log' => [], + 'file_path' => '', + 'fail_reason' => '' + ]; + + $query = [ + 'authorize_code' => $this->auth_code, + 'timestamp' => $timestamp + ]; + $build_log = ( new CloudService(true, 'http://java.oss.niucloud.com/') )->httpGet('cloud/get_appbuild_logs?' . http_build_query($query)); + $result['build_log'] = $build_log; + + if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) { + $last = end($build_log['data'][0]); + if ($last['code'] == 0) { + $result['status'] = 'fail'; + $result['fail_reason'] = $last['msg'] ?? ''; + return $result; + } + if ($last['percent'] == 100) { + $result = $this->buildSuccess($result, $timestamp); + } + } + + return $result; + } + + public function buildSuccess(array $result, string $task_key) + { + try { + $query = [ + 'authorize_code' => $this->auth_code, + 'timestamp' => $task_key + ]; + $chunk_size = 1 * 1024 * 1024; + $temp_dir = 'upload' . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . $task_key . DIRECTORY_SEPARATOR; + if (!is_dir($temp_dir)) mkdirs($temp_dir); + + $build_task = Cache::get($this->cache_key . $task_key) ?? []; + + if (!isset($build_task[ 'index' ])) { + $response = ( new CloudService(true, 'http://java.oss.niucloud.com/') )->request('HEAD', 'cloud/apk_download?' . http_build_query($query), [ + 'headers' => [ 'Range' => 'bytes=0-' ] + ]); + $length = $response->getHeader('Content-range'); + $length = (int) explode("/", $length[ 0 ])[ 1 ]; + $step = (int) ceil($length / $chunk_size); + $filename = $response->getHeader('filename')[0]; + + $build_task = array_merge($build_task, [ 'step' => $step, 'index' => 0, 'length' => $length, 'file_name' => $filename ]); + Cache::set($this->cache_key . $task_key, $build_task); + } else { + $file = $temp_dir . $build_task[ 'file_name' ]; + $file_resource = fopen($file, 'a'); + + if (( $build_task[ 'index' ] + 1 ) <= $build_task[ 'step' ]) { + $start = $build_task[ 'index' ] * $chunk_size; + $end = ( $build_task[ 'index' ] + 1 ) * $chunk_size; + $end = min($end, $build_task[ 'length' ]); + + $response = ( new CloudService(true, 'http://java.oss.niucloud.com/') )->request('GET', 'cloud/apk_download?' . http_build_query($query), [ + 'headers' => [ 'Range' => "bytes={$start}-{$end}" ] + ]); + fwrite($file_resource, $response->getBody()); + fclose($file_resource); + + $build_task[ 'index' ] += 1; + Cache::set($this->cache_key . $task_key, $build_task); + + $result['build_log'][] = [ 'code' => 1, 'action' => '安装包下载中,已下载' . round($build_task[ 'index' ] / $build_task[ 'step' ] * 100) . '%', 'percent' => '99' ]; + } else { + $result['build_log'][] = [ 'code' => 1, 'action' => '安装包下载中,已下载' . round($build_task[ 'index' ] / $build_task[ 'step' ] * 100) . '%', 'percent' => '100' ]; + $result['status'] = 'success'; + $result['file_path'] = $file; + Cache::set($this->cache_key . $task_key, null); + } + } + } catch (\Exception $e) { + $result['status'] = 'fail'; + $result['fail_reason'] = $e->getMessage().$e->getFile().$e->getLine(); + $result['build_log'][] = [ 'code' => 0, 'msg' => $e->getMessage(), 'action' => '', 'percent' => '100' ]; + } + return $result; + } + + /** + * 获取插件定义的package目录 + * @param string $addon + * @return string + */ + public function geAddonPackagePath(string $addon) + { + return $this->addon_path . $addon . DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR; + } + + public function generateSingCert(array $data) { + $dname = "CN={$data['cn']}, OU={$data['ou']}, O={$data['o']}, L={$data['l']}, ST={$data['st']}, C={$data['c']}"; + $query = [ + 'key_alias' => $data['key_alias'], + 'key_password' => $data['key_password'], + 'store_password' => $data['store_password'], + 'limit' => $data['limit'] * 365, + 'dname' => $dname + ]; + $response = ( new CloudService(true, 'http://java.oss.niucloud.com/') )->request('GET', 'cloud/getcert?' . http_build_query($query)); + $content_type = $response->getHeaders()['Content-Type'][0]; + if ($content_type == 'application/json') { + $content = json_decode($response->getBody()->getContents(), true); + if (isset($content[ 'code' ]) && $content[ 'code' ] == 0) throw new CommonException($content[ 'msg' ]); + } + $dir = 'upload' . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR; + if (!is_dir($dir)) mkdirs($dir); + + $file = $dir . $data['key_alias'] . '.zip'; + if (file_exists($file)) unlink($file); + + $file_resource = fopen($file, 'a'); + fwrite($file_resource, $response->getBody()); + fclose($file_resource); + return $file; + } +} diff --git a/niucloud/app/service/core/channel/CoreAppService.php b/niucloud/app/service/core/channel/CoreAppService.php new file mode 100644 index 000000000..e0b9a955c --- /dev/null +++ b/niucloud/app/service/core/channel/CoreAppService.php @@ -0,0 +1,60 @@ +model = new SysAttachment(); + } + + /** + * 获取app端配置 + * @return array|mixed + */ + public function getConfig(int $site_id) + { + $info = (new CoreConfigService())->getConfig($site_id, ConfigKeyDict::APP)['value'] ?? []; + if (empty($info)) { + $info = [ + 'wechat_app_id' => '', + 'wechat_app_secret' => '', + 'uni_app_id' => '', + 'app_name' => '', + 'android_app_key' => '', + 'application_id' => '' + ]; + } + return $info; + } + + public function setConfig(int $site_id, $data) + { + $info = (new CoreConfigService())->setConfig($site_id, ConfigKeyDict::APP, $data); + return $info; + } +} diff --git a/niucloud/app/service/core/channel/CoreH5Service.php b/niucloud/app/service/core/channel/CoreH5Service.php index 8a793a0a2..1dc5fe973 100644 --- a/niucloud/app/service/core/channel/CoreH5Service.php +++ b/niucloud/app/service/core/channel/CoreH5Service.php @@ -66,6 +66,17 @@ class CoreH5Service extends BaseCoreService ] ] ] + ], + "app-plus" => [ + "distribute" => [ + "sdkConfigs" => [ + "maps" => [ + "tencent" => [ + "key" => $map_key + ] + ] + ] + ] ] ]); } diff --git a/niucloud/app/service/core/niucloud/CoreModuleService.php b/niucloud/app/service/core/niucloud/CoreModuleService.php index 0ceabbaba..c0cad4a48 100644 --- a/niucloud/app/service/core/niucloud/CoreModuleService.php +++ b/niucloud/app/service/core/niucloud/CoreModuleService.php @@ -49,6 +49,7 @@ class CoreModuleService extends BaseNiucloudClient 'secret' => $this->secret, 'labels' => [ $label_id ], 'order_field' => 'sale_num desc, visit_num desc', + 'recommend_type'=>'PHP' ]; return $this->httpGet('store/saas/app', $params); } @@ -58,6 +59,7 @@ class CoreModuleService extends BaseNiucloudClient $params = [ 'code' => $this->code, 'secret' => $this->secret, + 'recommend_type'=>'PHP' ]; return $this->httpGet('promotion_adv', $params); } diff --git a/niucloud/app/service/core/notice/CoreNiuSmsService.php b/niucloud/app/service/core/notice/CoreNiuSmsService.php index 815ba405d..542987fb2 100644 --- a/niucloud/app/service/core/notice/CoreNiuSmsService.php +++ b/niucloud/app/service/core/notice/CoreNiuSmsService.php @@ -7,9 +7,11 @@ use app\dict\sys\SmsDict; use app\service\core\http\HttpHelper; use app\service\core\sys\CoreConfigService; use core\base\BaseAdminService; +use core\base\BaseCoreService; -class CoreNiuSmsService extends BaseAdminService +class CoreNiuSmsService extends BaseCoreService { + /*************************牛云短信处理****************************/ private const PACKAGE_LIST_URL = '/niusms/packages'; private const SEND_CODE_URL = '/niusms/send'; @@ -43,7 +45,7 @@ class CoreNiuSmsService extends BaseAdminService private const ORDER_STATUS_URL = '/niusms/order/status/%s/%s'; private $niushop_url_prefix = null; - + public $site_id = null; /** * @throws \Exception */ @@ -58,6 +60,11 @@ class CoreNiuSmsService extends BaseAdminService } } + public function setSiteId(string $site_id){ + $this->site_id = $site_id; + return $this; + } + /** * 设置账号缓存 * @param $params @@ -65,7 +72,7 @@ class CoreNiuSmsService extends BaseAdminService */ public function setNiuLoginConfig($params, $is_login = false) { - $config = $this->getNiuLoginConfig(true); + $config = $this->setSiteId($this->site_id)->getNiuLoginConfig(true); $config['default'] = $params['default'] ?? ($config['default'] ?? ""); $config[SmsDict::NIUSMS] = [ 'username' => $params['username'] ?? $config[SmsDict::NIUSMS]['username'] ?? "", @@ -151,7 +158,7 @@ class CoreNiuSmsService extends BaseAdminService { $url = $this->niushop_url_prefix . sprintf(self::ACCOUNT_INFO_URL, $username); $res = (new HttpHelper())->get($url); - $config = $this->getNiuLoginConfig(); + $config = $this->setSiteId($this->site_id)->getNiuLoginConfig(); if ($config['username'] == $res['username']) { $res['signature'] = $config['signature'] ?? ""; } diff --git a/niucloud/app/service/core/notice/NoticeService.php b/niucloud/app/service/core/notice/NoticeService.php index 63befa323..a07604aff 100644 --- a/niucloud/app/service/core/notice/NoticeService.php +++ b/niucloud/app/service/core/notice/NoticeService.php @@ -15,6 +15,7 @@ namespace app\service\core\notice; use app\job\notice\Notice; use app\model\sys\SysNotice; use core\base\BaseCoreService; +use core\exception\NoticeException; use think\facade\Log; @@ -50,7 +51,7 @@ class NoticeService extends BaseCoreService return Notice::dispatch(['site_id' => $site_id, 'key' => $key, 'data' => $data, 'template' => $template], is_async: $template['async']); } catch (\Exception $e) { - throw new \Exception($e->getMessage()); + throw new NoticeException($e->getMessage()); } } -} \ No newline at end of file +} diff --git a/niucloud/app/service/core/pay/CorePayChannelService.php b/niucloud/app/service/core/pay/CorePayChannelService.php index d9e11ac1d..901b24e6c 100644 --- a/niucloud/app/service/core/pay/CorePayChannelService.php +++ b/niucloud/app/service/core/pay/CorePayChannelService.php @@ -14,6 +14,7 @@ namespace app\service\core\pay; use app\dict\pay\PayDict; use app\model\pay\PayChannel; +use app\service\core\channel\CoreAppService; use app\service\core\weapp\CoreWeappConfigService; use app\service\core\wechat\CoreWechatConfigService; use core\base\BaseCoreService; @@ -124,10 +125,15 @@ class CorePayChannelService extends BaseCoreService //查询公众号配置 $core_weapp_config_service = new CoreWeappConfigService(); $mini_app_id = $core_weapp_config_service->getWeappConfig($site_id)[ 'app_id' ];//小程序appid + // 查询微信移动应用配置 + $core_app_service = new CoreAppService(); + $app_id = $core_app_service->getConfig($site_id)['wechat_app_id'] ?? ''; //App appid + //todo 查询微信小程序 appid . 应用appid..... return [ 'mp_app_id' => $mp_app_id, - 'mini_app_id' => $mini_app_id + 'mini_app_id' => $mini_app_id, + 'app_id' => $app_id //............ ]; } diff --git a/niucloud/app/service/core/wechat/CoreWechatAppService.php b/niucloud/app/service/core/wechat/CoreWechatAppService.php new file mode 100644 index 000000000..30981edf4 --- /dev/null +++ b/niucloud/app/service/core/wechat/CoreWechatAppService.php @@ -0,0 +1,81 @@ +getConfig($site_id); + + if (empty($app_config['wechat_app_id']) || empty($app_config['wechat_app_secret'])) throw new WechatException('WECHAT_NOT_EXIST');//公众号未配置 + + $config = array( + 'app_id' => $app_config['wechat_app_id'], + 'secret' => $app_config['wechat_app_secret'], + 'token' => "", + 'aes_key' => 'not_encrypt', + 'http' => [ + 'timeout' => 5.0, + 'retry' => true, // 使用默认重试配置 + ] + ); + return new Application($config); + } + + /** + * 微信实例接口调用 + * @param int $site_id + * @return \EasyWeChat\Kernel\HttpClient\AccessTokenAwareClient + * @throws InvalidArgumentException + */ + public static function appApiClient(int $site_id) + { + return self::app($site_id)->getClient(); + } + + /** + * 处理授权回调 + * @param int $site_id + * @param string $code + * @return UserInterface + */ + public static function userFromCode(int $site_id, string $code) + { + try { + $oauth = self::app($site_id)->getOauth(); + return $oauth->userFromCode($code); + } catch (\Exception $e) { + throw new CommonException($e->getCode() . ':' . $e->getMessage()); + } + } +} diff --git a/niucloud/app/upgrade/v115/upgrade.sql b/niucloud/app/upgrade/v115/upgrade.sql new file mode 100644 index 000000000..3ad3cc1d9 --- /dev/null +++ b/niucloud/app/upgrade/v115/upgrade.sql @@ -0,0 +1,21 @@ + +DROP TABLE IF EXISTS `app_version`; +CREATE TABLE `app_version` +( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `site_id` INT(11) NOT NULL DEFAULT 0 COMMENT '站点id', + `version_code` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '版本号', + `version_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '版本名称', + `version_desc` VARCHAR(1500) NOT NULL DEFAULT '' COMMENT '版本描述', + `platform` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'app平台 Android Ios', + `package_path` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '安装包路径', + `status` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '状态', + `is_forced_upgrade` INT(11) NOT NULL DEFAULT 0 COMMENT '是否需要强制升级', + `task_key` VARCHAR(255) NOT NULL DEFAULT '', + `fail_reason` VARCHAR(255) NOT NULL DEFAULT '', + `upgrade_type` VARCHAR(255) NOT NULL DEFAULT 'app' COMMENT 'app 整包更新 hot 热更新 market 应用市场更新', + `release_time` INT(11) NOT NULL DEFAULT 0 COMMENT '发布时间', + `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间', + `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '修改时间', + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'app版本管理' ROW_FORMAT = Dynamic; diff --git a/niucloud/config/upload.php b/niucloud/config/upload.php index a26034809..74b3155d1 100644 --- a/niucloud/config/upload.php +++ b/niucloud/config/upload.php @@ -73,6 +73,22 @@ $system = [ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ], 'size' => 10485760 + ], + 'app_package' => [ + 'ext' => ['apk', 'wgt'], + 'mime' => [ + 'application/vnd.android.package-archive', + 'application/vnd.wap.wgt' + ], + 'size' => 104857600 + ], + 'android_cert' => [ + 'ext' => ['jks'], + 'mime' => [ + 'application/octet-stream', + 'application/x-java-keystore' + ], + 'size' => 2097152 ] ], 'thumb' => [ diff --git a/niucloud/config/version.php b/niucloud/config/version.php index e7aab1f57..4819e2895 100644 --- a/niucloud/config/version.php +++ b/niucloud/config/version.php @@ -1,6 +1,6 @@ '1.1.4', - 'code' => '202508230001' + 'version' => '1.1.5', + 'code' => '202509120001' ]; diff --git a/niucloud/core/poster/Poster.php b/niucloud/core/poster/Poster.php index f8b45c46b..c1601c9d2 100644 --- a/niucloud/core/poster/Poster.php +++ b/niucloud/core/poster/Poster.php @@ -10,6 +10,7 @@ // +---------------------------------------------------------------------- namespace core\poster; +use core\exception\CommonException; use Kkokk\Poster\Facades\Poster as PosterInstance; class Poster extends BasePoster @@ -34,6 +35,9 @@ class Poster extends BasePoster */ public function createPoster(array $poster_data, string $dir, string $file_path) { + if (!extension_loaded('imagick')){ + throw new CommonException('海报组件未配置完善,请联系管理员');//POSTER_CREATE_ERROR + } $bg_type = $poster_data[ 'global' ][ 'bgType' ]; $instance = PosterInstance::extension('imagick')->config([ 'path' => realpath($dir) . DIRECTORY_SEPARATOR . $file_path,