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,