#Suyghur преди 3 години
родител
ревизия
6e8721724c
променени са 3 файла, в които са добавени 737 реда и са изтрити 8 реда
  1. 730 1
      README.md
  2. 4 4
      demo/build.gradle
  3. 3 3
      demo/src/main/assets/qs_game/qs_cfg.properties

+ 730 - 1
README.md

@@ -1,2 +1,731 @@
-# QSGameSdkDemo
+# 修订记录
 
+|	日期 	|	版本	|	说明	|	 作者	|
+| :--: | :--: | :-- | :--: |
+|	2021-10-29	|	1.0.0	|	文档建立	| 麦锦培 |
+|	2021-11-10	|	1.0.1	|	1)SDK开放获取QS_GCP_ID能力<br>2)增加浮标切换账号回调	| 麦锦培 |
+
+
+# 1.接入准备
+
+## 服务端文档
+
+- [统一签名方式](http://yydocs.yyxxgame.com/web/#/p/b136c6888dff0b5961ffc595d1842034)
+- [登录校验接口](http://yydocs.yyxxgame.com/web/#/p/3bdc599ce28f6b1179c8958bfaed0725)
+
+## 客户端SDK接入Demo工程
+
+- [Git仓库地址](http://gogs.yyxxgame.com/Client/QSGameSdkDemo)
+
+## 引入SDK配置
+
+- 游戏资源文件名、布局名、布局id名等建议使用规范命名,避免和SDK资源冲突
+- Android Gradle Plugin Version : 4.1.3+
+- Gradle Version : 6.5+
+- 将SDK目录下的**`qingshi_gamesdk_2.0.0.aar`**引入到项目中
+- 拷贝SDK目录下**`assets/qs_game`**至项目中,并修改**`qs_cfg.properties`**文件的值
+
+```properties
+QS_PACKAGE_VERSION=出包时间,如20210101
+QS_CAMPAIGN_ID=我方提供的分别标识
+QS_APP_ID=我方提供的appid
+QS_APP_KEY=我方提供的appkey
+QS_OWN_DEBUG=false(true为测试模式,可以看到接口日志弹窗信息)
+QS_GCP_ID=非必要,按需填写,SDK不会根据这个值做任何逻辑
+```
+
+
+## 引入SDK
+
+- 在应用**`build.gradle`**中**`dependencies`**节点下添加SDK依赖,目前只提供远程依赖,需要离线aar包请联系我方技术
+> 在项目级**`build.gradle`**文件下的**`allprojects`**节点下添加仓库的url
+```groovy
+	allprojects {
+		repositories {
+			...
+			mavenCentral()
+			...
+		}
+	}
+```
+
+> 在应用级**`build.gradle`**文件下的**`allprojects`**节点下添加仓库的url
+```groovy
+	// 打点组件SDK
+	implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-analytics:2.0.0-alpah2'
+	// 支付组件SDK
+	implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-billing:2.0.0-alpah2'
+	// 登录组件SDK
+	implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-login:2.0.0-alpah3'
+	// 核心组件SDK
+	implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-core:2.0.0-alpah3'
+```
+
+
+## 配置游戏AndroidManifest.xml
+
+- 配置游戏AndroidManifest.xml的首个启动Activity为SDK的WelcomeActivity
+
+```xml
+	<activity
+		android:name="cn.qingshi.gamesdk.base.WelcomeActivity"
+		android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
+		android:launchMode="standard"
+		android:screenOrientation="游戏实际屏幕方向"
+		android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+		<intent-filter>
+			<action android:name="android.intent.action.MAIN" />
+			<category android:name="android.intent.category.LAUNCHER" />
+		</intent-filter>
+</activity>
+```
+
+- 修改AndroidManifest.xml中游戏Activity的**`intent-filter`**属性,假设DemoActivity为游戏的Activity,则需要修改**`action`**标签的**`adnroid:name`**为游戏的包名
+
+```xml
+	<activity
+	android:name="com.gamesdk.qingshi.DemoActivity"
+	android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
+	android:exported="true"
+	android:launchMode="singleTask"
+	android:screenOrientation="sensorLandscape">
+	<intent-filter>
+		<action android:name="游戏包名" />
+		<category android:name="android.intent.category.DEFAULT" />
+	</intent-filter>
+</activity>
+```
+
+
+## 混淆配置
+
+- SDK已经经过混淆,SDK内部个别方法使用到了反射,建议不做混淆,如必须开启混淆,请参考并添加以下混淆配置
+```pro
+-keep class cn.qingshi.gamesdk.**{*;}
+
+# support sdk
+-keep class cn.yyxx.support.**{*;}
+
+# msa sdk
+-keep class XI.**{*;}
+-keep class com.asus.**{*;}
+-keep class com.bun.**{*;}
+-keep class com.huawei.hms.ads.identifier.**{*;}
+-keep class com.samsung.android.deviceidservice.**{*;}
+-keep class com.netease.nis.sdkwrapper.** {*;}
+-keep class com.zui.**{*;}
+-keep class org.json.**{*;}
+
+# authsdk
+-keep class com.alibaba.**{*;}
+-keep class com.cmic.**{*;}
+-keep class com.mobile.**{*;}
+-keep class com.nirvana.**{*;}
+
+# mmkv
+-keep class com.tencent.mmkv.**{*;}
+
+# zap
+-keep class com.dolin.zap.**{*;}
+
+# v4-support
+-keep class android.support.**{*;}
+```
+
+
+# 2.接口说明
+
+> <font color=red size=5>**SDK的所有接口如无特殊说明,默认均为必接且请务必在游戏主线程调用**</font>
+
+## 1)同步Application中的生命周期
+
+需要在游戏的Application类的**attachBaseContext()**及**onCreate()**中实现SDK方法
+```java
+public class DemoApplication extends Application {
+
+	@Override
+	protected void attachBaseContext(Context base) {
+		super.attachBaseContext(base);
+		QSGameSdk.getInstance().attachBaseContext(this, base);
+	}
+
+	@Override
+	public void onCreate() {
+		super.onCreate();
+		QSGameSdk.getInstance().initApplication(this);
+	}
+}
+```
+
+
+## 2)同步游戏Activity中各个生命周期
+
+- 同步onStart
+
+```java
+	@Override
+	protected void onStart() {
+		super.onStart();
+		QSGameSdk.getInstance().onStart(this);
+	}
+```
+
+- 同步onResume
+
+```java
+	@Override
+	protected void onResume() {
+		super.onResume();
+		QSGameSdk.getInstance().onResume(this);
+	}
+```
+
+- 同步onRestart
+
+```java
+	@Override
+	protected void onRestart() {
+		super.onRestart();
+		QSGameSdk.getInstance().onReStart(this);
+	}
+```
+
+- 同步onPause
+
+```java
+	@Override
+	protected void onPause() {
+		super.onPause();
+		QSGameSdk.getInstance().onPause(this);
+	}
+```
+
+- 同步onStop
+
+```java
+	@Override
+	protected void onStop() {
+		super.onStop();
+		QSGameSdk.getInstance().onStop(this);
+	}
+```
+
+- 同步onDestroy
+
+```java
+	@Override
+	protected void onDestroy() {
+		super.onDestroy();
+		QSGameSdk.getInstance().onDestroy(this);
+	}
+```
+
+- 同步onActivityResult
+
+```java
+	@Override
+	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+		super.onActivityResult(requestCode, resultCode, data);
+		QSGameSdk.getInstance().onActivityResult(this, requestCode, requestCode, data);
+	}
+```
+
+- 同步onNewIntent
+
+```java
+	@Override
+	protected void onNewIntent(Intent intent) {
+		super.onNewIntent(intent);
+		QSGameSdk.getInstance().onNewIntent(this, intent);
+	}
+```
+
+
+## 3)SDK通用回调接口ICallback说明
+
+```java
+	public interface ICallback {
+		void onResult(int code, String result);
+	}
+```
+
+|	参数 	|	类型	|	说明	|
+| :--: | :--: | :--: |
+|	code	|	int	|	状态码(0成功,-1失败)	|
+|	result	|	string	|	返回信息	|
+
+
+## 4)SDK初始化
+
+- 在游戏的主Activity的onCreate中调用
+
+```java
+	/**
+	 * SDK初始化
+	 *
+	 * @param activity    Activity上下文
+	 * @param isLandscape 是否横屏
+	 * @param callback    SDK初始化回调
+	 */
+	public void initialize(final Activity activity, final Boolean isLandscape, ICallback callback)
+```
+
+- 示例
+
+```java
+	@Override
+	protected void onCreate(Bundle savedInstanceState){
+		QSGameSdk.getInstance().initialize(this, false, new ICallback() {
+			@Override
+			public void onResult(int code, String result) {
+				if (code == 0) {
+					//TODO SDK初始化成功
+				} else {
+					//TODO SDK初始化失败,result是失败的debug信息
+        		}
+			}
+        });
+	}
+```
+
+
+## 5)用户账号登录
+
+```java
+	/**
+	 * SDK用户登录
+	 *
+	 * @param activity Activity上下文
+	 * @param callback 登录回调对象
+	 */
+	public void login(Activity activity, ICallback callback)
+```
+
+**登录回调返回的result信息**
+
+|	参数 	|	类型	|	说明	|
+| :--: | :--: | :--: |
+|	open_id	|	string	|	SDK的用户ID	|
+|	game_token	|	string	|	签名token	|
+
+- 示例
+
+```java
+	QSGameSdk.getInstance().login(this, new ICallback(){
+		@Override
+		public void onResult(int code, String result) {
+			if (code == 0) {
+				//TODO 对SDK返回的用户信息进行验签
+				//result返回的是JSON字符串,可以得到open_id和game_token等信息
+				//签名规则详见服务端接入文档
+			} else {
+				//TODO 登录失败,result是返回的debug信息
+			}
+		}
+	});
+```
+
+
+## 6)用户账号登出
+
+> 用户在游戏中触发登出,游戏回到选服界面重新拉起登录
+
+```java
+	/**
+	 * SDK用户登出账号
+	 *
+	 * @param activity Activity上下文
+	 * @param callback 登出回调对象
+	 */
+	public void logout(Activity activity, ICallback callback)
+```
+
+- 示例
+
+```java
+	QSGameSdk.getInstance().logout(this, new ICallback() {
+		@Override
+		public void onResult(int code, String result) {
+			if (code == 0) {
+				//TODO 用户登出成功,登出成功后请返回游戏选服界面,然后调用SDK的登录接口拉起登录框
+			} else {
+				//TODO 用户登出失败,result是返回的debug信息
+			}
+		}
+    });
+```
+
+
+## 7)角色信息上报
+
+> 请务必根据当前角色的触发的事件进行上报
+
+角色信息实体对象QSRoleInfo,如无特别说明所有字段均不能为null或空串""
+
+|	参数 	|	类型	|	说明	|
+| :--: | :--: | :--: |
+|	openId	|	string	|	当前用户ID	|
+|	serverNo	|	string	|	当前角色所在的服务器ID	|
+|	serverName	|	string	|	当前角色所在的服务器名	|
+|	roleId	|	string	|	当前角色ID	|
+|	roleName	|	string	|	当前角色名	|
+|	roleLevel	|	string	|	当前角色等级	|
+|	roleGender	|	string	|	当前角色性别,如无默认传男	|
+|	balance	|	string	|	当前角色游戏币余额,若无传"0"	|
+|	power	|	string	|	当前角色战力,若无传"0"	|
+|	vipLevel	|	string	|	当前Vip角色等级,若无传"0"	|
+|	roleCTime	|	string	|	当前角色创建的时间戳(10位),角色一旦创建则是固定值	|
+|	roleLevelMTime	|	string	|	当前角色升级的时间戳(10位),如果是创角则传创角时间,如果是角色登录则传入上一次角色等级变化的时间	|
+|	ext	|	string	|	扩展参数,不需要则传入空字符串""	|
+
+
+> 角色创建
+
+```java
+	/**
+	 * SDK角色创建信息上报
+	 *
+	 * @param activity Activity上下文
+	 * @param roleInfo 角色信息实体
+	 */
+	public void roleCreate(Activity activity, QSRoleInfo roleInfo)
+```
+
+> 角色进入服务器(角色登录)
+
+```java
+	/**
+	 * SDK角色登录信息上报
+	 *
+	 * @param activity Activity上下文
+	 * @param roleInfo 角色信息实体
+	 */
+	public void roleLauncher(Activity activity, QSRoleInfo roleInfo)
+```
+
+> 角色升级
+
+```java
+	/**
+	 * SDK角色升级信息上报
+	 *
+	 * @param activity Activity上下文
+	 * @param roleInfo 角色信息实体
+	 */
+	public void roleUpgrade(Activity activity, QSRoleInfo roleInfo)
+```
+
+- 示例
+
+```java
+	QSRoleInfo gameRoleInfo = new QSRoleInfo();
+	// 用户ID
+	gameRoleInfo.setOpenId("用户ID");
+	// 服务器ID
+	gameRoleInfo.setServerNo("服务器ID");
+	// 服务器名
+	gameRoleInfo.setServerName("服务器名");
+	// 角色ID
+	gameRoleInfo.setRoleId("角色id");
+	// 角色名称
+	gameRoleInfo.setRoleName("角色名称");
+	// 角色等级
+	gameRoleInfo.setRoleLevel("角色等级");
+	// 角色性别,无该字段则传"男"
+	gameRoleInfo.setRoleGender("角色性别");
+	// 当前角色游戏币余额,无该字段则传"0"
+	gameRoleInfo.setBalance("当前角色游戏币余额");
+	// 当前角色战力,无该字段则传"0"
+	gameRoleInfo.setPower("当前角色战力");
+	// 用户VIP等级,无该字段则传"0"
+	gameRoleInfo.setVipLevel("用户VIP等级");
+	// 创角时间戳(角色一旦创角则是固定值)
+	gameRoleInfo.setRoleCTime("创角10位时间戳")
+	// 角色等级变化时间戳
+	gameRoleInfo.setroleLevelMTime("角色等级变化时间戳")
+	// 扩展字段
+	gameRoleInfo.setExt("扩展字段");
+
+	//角色创建
+	QSGameSdk.getInstance().roleCreate(this, gameRoleInfo);
+
+	//角色登录
+	QSGameSdk.getInstance().roleLauncher(this, gameRoleInfo;
+
+	//角色升级
+	QSGameSdk.getInstance().roleUpgrade(this, gameRoleInfo;
+```
+
+
+## 8)支付储值
+
+> 请务必保证调用角色信息上报中的角色登录上报后再调用
+> <font color=red size=5>**客户端SDK回调的只是支付流程的结果,实际支付结果将由服务端回调**</font>
+
+支付信息实体对象QSChargeInfo,如无特别说明所有字段均不能为null或空串""
+
+|	参数 	|	类型	|	说明	|
+| :--: | :--: | :--: |
+|	openId	|	string	|	当前用户ID	|
+|	serverNo	|	string	|	当前角色所在的服务器ID	|
+|	serverName	|	string	|	当前角色所在的服务器名	|
+|	roleId	|	string	|	当前角色ID	|
+|	roleName	|	string	|	当前角色名	|
+|	roleLevel	|	string	|	当前角色等级	|
+|	roleGender	|	string	|	当前角色性别,如无默认传男	|
+|	balance	|	string	|	当前角色游戏币余额,若无传"0"	|
+|	power	|	string	|	当前角色战力,若无传"0"	|
+|	vipLevel	|	string	|	当前Vip角色等级,若无传"0"	|
+|	cpOrderId	|	string	|	游戏订单号	|
+|	productName	|	string	|	商品名称	|
+|	amount	|	int	|	金额,单位分	|
+|	cpCallbackInfo	|	string	|	透传信息,该字段内容会原样在服务端接口返回	|
+
+```java
+	/**
+	 * SDK用户支付
+	 *
+	 * @param activity   Activity上下文
+	 * @param chargeInfo 支付信息实体对象
+	 * @param callback   支付回调对象
+	 */
+	public void charge(Activity activity, QSChargeInfo chargeInfo,ICallback callback)
+```
+
+- 示例
+
+```java
+	QSChargeInfo gameChargeInfo = new QSChargeInfo();
+	// 用户ID
+	gameChargeInfo.setOpenId("用户ID");
+	// 服务器ID
+	gameChargeInfo.setServerNo("服务器ID");
+	// 服务器名
+	gameChargeInfo.setServerName("服务器名");
+	// 角色ID
+	gameChargeInfo.setRoleId("角色id");
+	// 角色名称
+	gameChargeInfo.setRoleName("角色名称");
+	// 角色等级
+	gameChargeInfo.setRoleLevel("角色等级");
+	// 角色性别,无该字段则传"男"
+	gameChargeInfo.setRoleGender("角色性别");
+	// 当前角色游戏币余额,无该字段则传"0"
+	gameChargeInfo.setBalance("当前角色游戏币余额");
+	// 当前角色战力,无该字段则传"0"
+	gameChargeInfo.setPower("当前角色战力");
+	// 用户VIP等级,无该字段则传"0"
+	gameChargeInfo.setVipLevel("用户VIP等级");
+	// 游戏订单号
+	gameChargeInfo.setCpOrderId("游戏订单号");
+	// 商品名称
+	gameChargeInfo.setProductName("商品名称")
+	// 金额
+	gameChargeInfo.setAmount(0)
+	// 透传字段
+	gameChargeInfo.setCpCallbackInfo("透传字段");
+
+	//客户端SDK回调的只是支付流程的结果,实际支付结果将由服务端回调
+	QSGameSdk.getInstance().charge(this, gameChargeInfo , new ICallback() {
+		@Override
+			public void onResult(int code, String result) {
+				if (code == 0) {
+					//TODO 支付流程完成
+				} else {
+					//TODO 支付失败
+				}
+			}
+	});
+```
+
+
+## 10)设置SDK浮标用户账号登出回调
+
+> 建议在SDK初始化成功后设置,该回调会监听用户浮标切换账号的行为,处理逻辑跟logout接口保持一致即可
+
+```java
+	/**
+	 * 浮标退出回调
+	 *
+	 * @param activity Activity上下文
+	 * @param callback 浮标退出回调对象
+	 */
+	public void onFloatCenterLogout(Activity activity, ICallback callback)
+```
+
+- 示例
+
+```java
+	QSGameSdk.getInstance().onFloatCenterLogout(this, new ICallback() {
+		@Override
+		public void onResult(int code, String result) {
+			if (code == 0) {
+				//TODO 用户浮标登出成功,登出成功后请返回游戏选服界面,然后调用SDK的登录接口拉起登录框
+			} else {
+				//TODO 用户浮标登出失败,result是返回的debug信息
+			}
+		}
+    });
+```
+
+
+## 11)显示SDK退出框(选接)
+
+> 用户(玩家)按下返回键时调用,接入方需要实现Activity的onKeyDown,并判断keyCode为KeyEvent.KEYCODE_BACK时调用该接口
+
+```java
+	/**
+	 * 显示退出框
+	 *
+	 * @param activity Activity上下文
+	 * @param callback 退出回调对象
+	 */
+	public void openExitView(Activity activity, ICallback callback)
+```
+
+- 示例
+
+```java
+	//重写Activity的onKeyDown并判断KeyDown事件
+	@Override
+	public boolean onKeyDown(int keyCode, KeyEvent event) {
+		if (keyCode == KeyEvent.KEYCODE_BACK) {
+			QSGameSdk.getInstance().openExitView(this, new ICallback() {
+				@Override
+				public void onResult(int code, String result) {
+					if (code == 0) {
+						// 结束当前Activity
+						// 如果要杀进程需要在onDestroy中处理,不然会不执行SDK的onDestroy方法
+						finish();
+					}
+				}
+			});
+			return true;
+		}
+		return super.onKeyDown(keyCode, event);
+	}
+
+	@Override
+	protected void onDestroy() {
+		super.onDestroy();
+		QSGameSdk.getInstance().onDestroy(this);
+		// 结束当前应用进程
+		System.exit(0);
+	}
+```
+
+## 12)获取SDK当前用户ID(选接)
+
+```java
+	/**
+	 * 获取当前SDK用户ID
+	 *
+	 * @return
+	 */
+	public String getCurrentOpenId()
+```
+
+- 示例
+
+```java
+	QSGameSdk.getInstance().getCurrentOpenId();
+```
+
+
+## 13)获取SDK当前版本(选接)
+
+```java
+	/**
+	 * 获取当前SDK版本
+	 *
+	 * @return
+	 */
+	public String getCurrentSdkVersion()
+```
+
+- 示例
+
+```java
+	QSGameSdk.getInstance().getCurrentSdkVersion();
+```
+
+
+## 14)权限请求(选接)
+
+> 若游戏需要动态请求特殊或危险权限,可以选择使用SDK的权限请求接口,该功能已经适配Android 12的行为变更
+> SDK内部已经申请了SD卡存储权限及获取设备信息权限
+
+```java
+	/**
+	 * 权限请求
+	 *
+	 * @param activity    Activity上下文
+	 * @param permissions 权限列表
+	 * @param callback    权限请求回调对象
+	 */
+	public void requestPermission(Activity activity, List<String> permissions, ICallback callback)
+
+```
+
+- 示例
+
+```java
+	List<String> permissions = new ArrayList<String>() {{
+		// 相机摄像头
+		add(Permission.CAMERA);
+		// 音频麦克风
+		add(Permission.RECORD_AUDIO);
+	}};
+	QSGameSdk.getInstance().requestPermission(activity, permissions, new ICallback() {
+		@Override
+		public void onResult(int code, String result) {
+			if (code == 0) {
+				//TODO 授权成功,result是成功授权的权限json字符串
+			} else {
+				//TODO 授权是白,result是失败授权的权限json字符串
+			}
+		}
+	});
+```
+
+
+## 15)日志接口(选接)
+
+> 若游戏有需要持久化java、kotlin和C++(联系我方技术获取头文件)层的日志,可以使用SDK的日志接口。SDK的日志框架底层使用C++进行开发,使用了Linux系统的mmap内存拷贝技术
+> SDK会默认缓存3天的日志,过期则自动删除
+> 缓存的文件使用Facebook开源的压缩算法zlib进行压缩
+> 缓存路径为**手机内部存储目录/Android/data/包名/files/dolin/zap**,即应用的私有目录
+> 更多使用方法请联系我方技术
+
+- 示例
+
+```java
+	// debug日志
+	Logger.d(TAG,msg);
+	// info日志
+	Logger.i(TAG,msg);
+	// error日志
+	Logger.e(TAG,msg);
+```
+
+
+## 16)获取SDK配置文件QS_GCP_ID(选接)
+
+> 为了方便接入方需要,这个接口可以获取SDK配置文件中的QS_GCP_ID接入方填写的值,SDK不会根据这个值做任何逻辑
+
+```java
+	/**
+	 * 获取SDK配置文件QS_GCP_ID
+	 *
+	 * @param context    Context上下文
+	 */
+	public static void getQsGcpId(Context context)
+
+```
+
+- 示例
+
+```java
+	// debug日志
+	ParamsUtils.getQsGcpId(TAG,msg);
+```

+ 4 - 4
demo/build.gradle

@@ -73,8 +73,8 @@ android {
 }
 
 dependencies {
-    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-core:2.0.0-alpah1'
-    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-analytics:2.0.0-alpah1'
-    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-billing:2.0.0-alpah1'
-    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-login:2.0.0-alpah2'
+    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-core:2.0.0-alpah3'
+    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-analytics:2.0.0-alpah2'
+    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-billing:2.0.0-alpah2'
+    implementation 'io.github.yyxxgame.sdk:qingshi-gamesdk-login:2.0.0-alpah3'
 }

+ 3 - 3
demo/src/main/assets/qs_game/qs_cfg.properties

@@ -1,11 +1,11 @@
 #出包版本
 QS_PACKAGE_VERSION=20201010
 #分包标识
-QS_CAMPAIGN_ID=9y12un3y
+QS_CAMPAIGN_ID=9eb26gw1
 #应用ID
-QS_APP_ID=21
+QS_APP_ID=1407
 #应用秘钥
-QS_APP_KEY=efe5a67ad0c9bdead320a19ce76cc569
+QS_APP_KEY=45a71ad438f29579fa4035b734a6a4b3
 #debug模式(cp出正式包请关闭)
 QS_OWN_DEBUG=true