提交 071017cf 作者: 王进

微信SDK改版

v3.0
上级 73716806
/** /**
* 鲸鱼游戏微信小游戏接入库 * 鲸鱼游戏微信小游戏接入库
* @author 推广技术部 * @author 推广技术部
* @time: 2020-11-06 * @time: 2020-11-20
* 更新内容:1.增加SDK版本号控制台输出
*/ */
class WechatSDK { class WechatSDK {
private sdkVersion: string = '2.5.9' private sdkVersion: string = '3.0.0'
public constructor() { private onlineTime: number = 0; // 在线时长(单位:分钟)
private actId: string = '' // 动态消息活动id
private clickCounter = 0 // 当前用户点击次数
private GameRecorder: any = null // 录屏对象
private recorderBtn: any = null // 对局回放分享按钮对象
constructor() {
console.log('当前加载SDK版本号为:', this.sdkVersion); console.log('当前加载SDK版本号为:', this.sdkVersion);
this.sdkInit(); this.sdkInit();
this.timerInit(); this.timerInit();
} }
private onlineTime: number = 0; // 在线时长(单位:分钟)
private timerInit() { // 用户在线时间 private timerInit() { // 用户在线时间
const _selt = this;
let loginTime = new Date().getTime(); // 登录时间 let loginTime = new Date().getTime(); // 登录时间
let offTime = (wx as any).getStorageSync('offlineTime'); // 离线前记录的时间点 let offTime = (wx as any).getStorageSync('offlineTime'); // 离线前记录的时间点
let offlineTime = offTime ? ((loginTime - offTime) / (1000 * 60)).toFixed(2) : 0; // 离线时长(分钟) let offlineTime = offTime ? ((loginTime - offTime) / (1000 * 60)).toFixed(2) : 0; // 离线时长(分钟)
if (offlineTime > 299) { if (offlineTime > 299) this.onlineTime = 0;
_selt.onlineTime = 0; else this.onlineTime = (wx as any).getStorageSync('onlineMinute') || 0;
} else { setInterval(() => { // 每分钟记录一次
_selt.onlineTime = (wx as any).getStorageSync('onlineMinute') || 0; this.onlineTime++;
}
setInterval(function () { // 每分钟记录一次
_selt.onlineTime++;
let curTime = new Date().getTime(); let curTime = new Date().getTime();
(wx as any).setStorageSync("onlineMinute", _selt.onlineTime); (wx as any).setStorageSync("onlineMinute", this.onlineTime);
(wx as any).setStorageSync("offlineTime", curTime); (wx as any).setStorageSync("offlineTime", curTime);
}, 60000); }, 60000);
} }
private actId = '' // 动态消息活动id private sdkInit = async () => {
private async sdkInit() { this.LaunchOptions = await this.getOptionsInfo();
const _selt = this; this.actId = this.LaunchOptions['actId'] || '';
_selt.ReportParams.productCode = _selt.sdkParams.product_code = SDKConfig.productCode; this.SystemInfo = await this.getSystemInfo();
_selt.sdkParams.appid = SDKConfig.appid; this.SystemInfo['networkType'] = await this.getNetworkType();
_selt.sdkParams.version = _selt.sdkVersion; this.SDKCOMMDATA['os'] = this.SystemInfo['system'].split(' ')[0].toLowerCase();
this.getGameLabel();
const options = _selt.getOptionsInfo(); // 返回参数对象
_selt.ReportParams.from = options.from || 0;
_selt.ReportParams.tag = options.tag || 0;
_selt.ReportParams.cpsAppid = options.appid || '';
_selt.ReportParams.passthroughParams = options.passthroughParams || '';
_selt.actId = options.actId || '';
_selt.ReportParams.fromOpenId = options.fromOpenId || ''; // 分享用户来源的
_selt.sdkParams.from_openid = options.from_openid || ''; // 跳转游戏前用户标识
_selt.sdkParams.from_product = options.from_product || '';
_selt.sdkParams.from_uid = options.from_uid || '';
await _selt.getNetworkType();
await _selt.getSystemInfo();
console.log("--SDK初始化结束", _selt.ReportParams);
}
public async updateShareMsgInfo(updateInfo) { // 更新动态消息接口
if (!updateInfo.activity_id) {
updateInfo.activity_id = this.actId;
updateInfo.version_type = SDKConfig.navPayEnv;
}
const postData = this.deepCopy({}, this.sdkParams, updateInfo);
let res = await this.sdkRequest(Links.setActShareInfo, postData, 'POST').catch(err => {
console.log("--SDK异常::updateShareMsgInfo", err);
});
console.log("--SDK更新动态消息接口::", res);
} }
public async getActiveShareInfo() { // 查询动态消息接口 public Login = async (retry = 0) => {
let _self = this; if (retry > 2) {
let postData = { this.showMsg('登录异常,请联系客服.');
product_code: SDKConfig.productCode, return { error: "登录超时.." }
activity_id: _self.actId
} }
let { code, data } = await this.sdkRequest(Links.getActShareInfo, postData, 'POST').catch(err => { const res = await this.getWechatCode(); // 获取微信登录code
console.log("--SDK异常::getActiveShareInfo", err); if (res.code) {
}); // 请求openid
return code == 0 ? data : 0; const { data } = await this.sdkRequest(Links.init, {
} ...this.SDKCOMMDATA,
public async Login() {
const _selt = this;
let res = await _selt._login() // 微信登录换取code
if (res && res.code) {
let { code, data, msg } = await _selt.sdkRequest(Links.init, {
product_code: _selt.sdkParams.product_code,
source: _selt.sdkParams.source,
appid: SDKConfig.appid, appid: SDKConfig.appid,
code: res.code code: res.code
}); });
if (code == 0) { this.LoginData = { ...data }
_selt.ReportParams.openId = _selt.sdkParams.open_id = _selt.sdkParams.uniqueid = _selt.heartParams.uuid = data.openid; this.SDKCOMMDATA['uuid'] = data.open_id;
_selt.sdkParams.session_key = data.session_key; // SDK后台调试模式开关
// 调试白名单,SDK后台管理
if (typeof (data.debug_mode) != "undefined" && data.debug_mode == 1) { if (typeof (data.debug_mode) != "undefined" && data.debug_mode == 1) {
console.log('--进入调试白名单.');
(wx as any).setEnableDebug({ (wx as any).setEnableDebug({
enableDebug: true enableDebug: true
}) })
} }
if (_selt.actId) { this.actId != "" && this.updateShareMsgInfo({});
let shareInfo = { return this.sdkActive();
activity_id: _selt.actId,
target_state: 0,
version_type: SDKConfig.navPayEnv
};
_selt.updateShareMsgInfo(shareInfo);
}
} else {
_selt.sdkAlert(msg);
}
return _selt.sdkActive()
} else { // 失败状态下执行重登
_selt.Login()
} }
retry += 1;
this.Login(retry);
} }
// SDK激活 // SDK激活
private async sdkActive() { private sdkActive = async () => {
const _selt = this const { data } = await this.sdkRequest(Links.active, { ...this.SDKCOMMDATA, ...this.LoginData });
console.log("--SDK激活", _selt.sdkParams) this.LoginData['pay_channel'] = data.default_pay_channel;
let { code, data, msg } = await _selt.sdkRequest(Links.active, this.sdkParams).catch(err => { this.ActiReport(); // 上报激活
console.log("--SDK激活异常:", err) return this.sdkLogin();
_selt.sdkAlert("--SDK激活异常:" + err)
});
if (code == 0) {
_selt.sdkParams.pay_channel = data.default_pay_channel;
_selt.ActiReport(); // 上报激活
} else {
_selt.sdkAlert(msg);
}
return _selt.sdkLogin();
} }
private async sdkLogin() { private async sdkLogin() {
const _selt = this delete this.LoginData['token']; // 强制清空登录toekn
// 获取用户信息 const { data, msg } = await this.sdkRequest(Links.login, { ...this.SDKCOMMDATA, ...this.LoginData });
_selt.sdkParams.token = '' // 强制清空登录toekn
let { code, data, msg} = await _selt.sdkRequest(Links.login, _selt.sdkParams).catch(err => {
console.log("--SDK登陆异常:", err)
_selt.sdkAlert("--SDK登陆异常:" + err)
});
console.log("--SDK登录接口返回::", data); console.log("--SDK登录接口返回::", data);
let LoginCallBack = {}; if (Object.keys(data).length == 0) {
if (code == 0) { this.showMsg(msg);
// 根据SDK返回用户状态来判断用户是否注册 return { error: msg }
_selt.sdkParams.token = data.token // 记录用户toekn }
_selt.ReportParams.userId = _selt.heartParams.userid = data.uid // 记录用户ID this.LoginData = { ...this.LoginData, ...data }
LoginCallBack = _selt.deepCopy(LoginCallBack, data, { const filters = (({create_time, ip, nickname, open_id, uid, enter_game, origin_uid, origin_open_id}) => ({ create_time, ip, nickname, open_id, uid, enter_game, origin_uid, origin_open_id }))(data);
os: _selt.sdkParams.os, // 返回系统类型IOS或者android return {
session_key: _selt.sdkParams.session_key, // 返回session_key ...filters,
scene: _selt.ReportParams.sceneId, // 用户来源场景值 os: this.SDKCOMMDATA['os'], // 返回系统类型IOS或者android
from_appid: _selt.ReportParams.cpsAppid // cps的appid session_key: this.LoginData['session_key'], // 返回session_key
}) scene: this.LaunchOptions['scene'], // 用户来源场景值
} else { from_appid: this.LaunchOptions['appid'] // cps的appid
const params = { }
title: '登录异常', }
content: msg, public payOrder = async (Params, showMessage = true) => {
showCancel: false, this.showLoading();
success: function () {
_selt.exitApp();
}
}
_selt.showModal(params);
}
return LoginCallBack
}
public async payOrderStatus(Params) {
let payResult = await this.payOrder(Params, false);
return payResult;
}
// SDK支付接口
public async payOrder(Params, showSDKAlert = true) {
const _selt = this;
_selt.MidasPaymentParams.offerId = SDKConfig.offerid;
_selt.LoadingOn();
// 支付前先获取用户订单状态,如果没有未完成订单则继续支付 // 支付前先获取用户订单状态,如果没有未完成订单则继续支付
let res = await _selt.sdkRequest(Links.order, _selt.deepCopy(_selt.sdkParams, Params)).catch(err => { const { code, data, msg } = await this.fetchUri(Links.order, this.md5_sign({ ...this.SDKCOMMDATA, ...Params, token: this.LoginData['token'], pay_channel: this.LoginData['pay_channel'] }), 'GET');
_selt.LoadingOff(); this.hideLoading();
console.log("--SDK异常::payOrder", err); if (code == 0 && data.weixin_mini_program_app_id) {
});
console.log("--订单返回---->", res);
_selt.LoadingOff();
if (res.code == 0) {
if (res.data.weixin_mini_program_app_id) { // 跳小程序支付
const postParams = _selt.deepCopy({}, _selt.sdkParams, Params, {
weixin_mini_program_app_id: res.data.weixin_mini_program_app_id, // 跳转小程序的appid,获取新openid用
sub_product_code: res.data.sub_product_code, // 跳转小程序的productcode
pay_channel: res.data.pay_channel, // 支付方式改变
productKey: SDKConfig.productKey
}) // 合并后附上签名参数
const params = { // 跳转参数 const params = { // 跳转参数
appId: res.data.weixin_mini_program_app_id, // 跳转的小程序appid appId: data.weixin_mini_program_app_id, // 跳转的小程序appid
path: '', // 跳转到首页 path: '', // 跳转到首页
envVersion: SDKConfig.navPayEnv, //跳转方式 envVersion: SDKConfig.navPayEnv, //跳转方式
extraData: postParams, extraData: {
success: () => { console.log("跳转成功") }, ...this.SDKCOMMDATA, ...Params,
fail: () => { console.log("跳转失败") }, weixin_mini_program_app_id: data.weixin_mini_program_app_id, // 跳转小程序的appid,获取新openid用
complete: () => { _selt.LoadingOff(); } sub_product_code: data.sub_product_code, // 跳转小程序的productcode
pay_channel: data.pay_channel, // 支付方式改变
productKey: SDKConfig.productKey
},
} }
_selt.navigateToMiniProgram(params); this.navigateToMiniProgram(params);
return { order_code: 2, msg: '' }; // 切支付状态 return { order_code: 2, msg: '' }; // 切支付状态
} else if (res.data.open_customer_service) { // 客服切支付
let order = {
sessionFrom: 'order_id=' + (res.data.order_num || '') + '&payload=' + (res.data.payload || ''),
showMessageCard: true,
sendMessageTitle: '回复【充值】获取充值链接',
sendMessageImg: 'https://h5sdk.pthc8.com/resource/images/payTips.jpg',
} }
console.log('--客服切支付:', order); if (code == 0 && data.open_customer_service) {
const params = { const params = {
title: '充值教程', title: '充值教程',
content: '即将跳转官方【客服会话】进行充值, 向客服回复【充值】获取充值链接', content: '即将跳转官方【客服会话】进行充值, 向客服回复【充值】获取充值链接',
showCancel: false, showCancel: false,
success: function () { success: () => {
_selt.Customer(order); this.Customer({
sessionFrom: 'order_id=' + (data.order_num || '') + '&payload=' + (data.payload || ''),
showMessageCard: true,
sendMessageTitle: '回复【充值】获取充值链接',
sendMessageImg: 'https://h5sdk.pthc8.com/resource/images/payTips.jpg',
});
} }
} }
_selt.showModal(params); this.showModal(params);
return { order_code: 2, msg: '' }; return { order_code: 2, msg: '' };
} else { }
// 根据返回的用户订单状态判断是新订单还是未完成订单 if (code == 0 && data.order_type == 1) {
if (res.data.order_type == 1) { // 新订单 this.MidasPaymentParams['buyQuantity'] = <number>(Params.money / 100) * <number>data.weixin_proportion // 充值金额
_selt.MidasPaymentParams.buyQuantity = <number>(Params.money / 100) * <number>res.data.weixin_proportion // 充值金额 console.log("--米大师支付参数:", this.MidasPaymentParams);
console.log("--SDK -> 发起支付参数:", _selt.MidasPaymentParams);
// 调微信米大师支付接口 // 调微信米大师支付接口
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
(wx as any).requestMidasPayment(_selt.deepCopy({}, _selt.MidasPaymentParams, { (wx as any).requestMidasPayment({
success: async function (data) { ...this.MidasPaymentParams,
success: async (data) => {
console.log("--SDK -> 支付成功:", data); console.log("--SDK -> 支付成功:", data);
let coinsResult = await _selt.getCoins(_selt.deepCopy({}, _selt.sdkParams, { order_num: res.data.order_num })); let coinsResult = await this.getCoins({ ...this.SDKCOMMDATA, order_num: data.order_num });
if (coinsResult.code == 0 || coinsResult.code == 3012) { if (coinsResult.code == 0 || coinsResult.code == 3012) {
resolve({ order_code: 200, msg: '' }); resolve({ order_code: 200, msg: '' });
} }
...@@ -228,578 +142,197 @@ class WechatSDK { ...@@ -228,578 +142,197 @@ class WechatSDK {
resolve({ order_code: 0, msg: (coinsResult.msg || '') }); resolve({ order_code: 0, msg: (coinsResult.msg || '') });
} }
}, },
fail: function (err) { fail: (err) => {
console.log("--SDK -> 支付失败:", err); console.log("--米大师支付失败:", err);
let msg = '支付异常'; let msg = this.MidasErrorCode[JSON.stringify(err.errCode)] || '支付异常';
switch (JSON.stringify(err.errCode)) { if (showMessage) {
case '-1':
msg = '系统失败';
break;
case '-2':
msg = '支付取消';
break;
case '-15001':
msg = '缺少参数';
break;
case '-15002':
msg = '参数不合法';
break;
case '-15003':
msg = '订单重复';
break;
case '-15004':
msg = '后台错误';
break;
case '-15005':
msg = 'appId权限被封禁';
break;
case '-15006':
msg = '货币类型不支持';
break;
case '-15007':
msg = '订单已支付';
break;
case '-15009':
msg = '由于健康系统限制,本次支付已超过限额';
break;
case '1':
msg = '用户取消支付';
break;
case '3':
msg = 'Android 独有错误:用户使用 Google Play 支付,而手机未安装 Google Play';
break;
case '4':
msg = '用户操作系统支付状态异常';
break;
case '5':
msg = '操作系统错误';
break;
case '6':
msg = '其他错误';
break;
case '1000':
msg = '参数错误';
break;
case '1003':
msg = '米大师Portal错误';
break;
}
if (showSDKAlert) {
const params = { const params = {
title: '支付提示', title: '支付提示',
content: msg, content: msg,
showCancel: false showCancel: false
} }
_selt.showModal(params); this.showModal(params);
} }
resolve({ order_code: err.errCode, msg: msg }); resolve({ order_code: err.errCode, msg: msg });
_selt.reportPaymentError({ order_code: err.errCode, msg: msg, order_num: res.data.order_num }); this.reportPaymentError({ order_code: err.errCode, msg: msg, order_num: data.order_num });
} }
}));
}); });
} else if (res.data.order_type == 103) { // 二维码支付
let payback = {
order_code: res.data.order_type,
order_num: res.data.order_num,
payload: res.data.payload,
msg: ''
};
// 调用微信API显示图片
(wx as any).previewImage({
urls: [res.data.payload],
success: () => console.log('支付图片显示成功'),
fail: (err) => console.log('支付图片显示失败', err)
})
return payback;
}
else { // 已有未完成订单,弹窗提示
const params = {
title: SDKConfig.shareTitle,
content: '订单发货中,请稍候下单..'
}
_selt.showModal(params);
}
}
} else if (res.code == 3023) {
const params = {
title: '支付提示',
content: res.msg
}
if (res.dialog == 1) _selt.showModal(params);
return { order_code: 3023, msg: res.msg };
} else { // 输出订单失败消息
const errmsg = res.msg || '支付失败..'
if (showSDKAlert) {
const params = {
title: '支付提示',
content: errmsg,
showCancel: false
}
_selt.showModal(params);
}
return { order_code: 0, msg: errmsg };
}
}
private async getCoins(orderParams) { // 通知服务端扣费
console.log("--SDK通知扣费", orderParams)
let coinsResult = await this.sdkRequest(Links.pay, orderParams).catch(err => {
console.log("--SDK异常::getCoins", err);
}); });
return coinsResult;
} }
public async getUserPaymentType(roleInfo) { // 是否支持切支付
const _selt = this;
const postData = _selt.deepCopy({}, _selt.sdkParams, roleInfo);
let payType = await _selt.sdkRequest(Links.payType, postData);
return payType && (payType.code === 0);
} }
public async checkUserPhoneBind() { // 查询用户绑定状态 private getCoins = async (orderParams) => { // 通知服务端扣费
const _selt = this; return await this.sdkRequest(Links.pay, orderParams)
let postData = _selt.deepCopy({}, _selt.sdkParams, { uid: _selt.ReportParams.userId });
let bindType = await _selt.sdkRequest(Links.bindPhone, postData);
return (bindType.code == 0);
}
public async phoneCode(phoneInfo, callback?) {
const _selt = this;
let postData = this.deepCopy({}, _selt.sdkParams, phoneInfo);
postData.type = 'SDK.BIND_MOBILE'; // 小程序专属短信类型
// 发送验证码接口
let { code } = await this.sdkRequest(Links.sendCode, postData).catch(err => {
console.log("--SDK::验证码发送失败", err);
_selt.sdkAlert("发送失败,请重试..");
});
if (callback) code == 0 ? callback(true) : callback(false);
}
public async userPhone(phoneInfo, callback) {
const _selt = this;
let postData = this.deepCopy({}, _selt.sdkParams, phoneInfo);
postData.source = 'WEIXIN'; // 用户平台来源
//保存用户手机信息
let { code, msg } = await this.sdkRequest(Links.saveNum, postData).catch(err => {
console.log("--SDK::保存手机失败", err);
});
callback(code);
} }
public async checkUserAdvised() { // 防沉迷验证 public createActiveShare = async (shareInfo) => { //动态消息
const _selt = this; let { code, data, msg } = await this.sdkRequest(Links.getActShareId, {
let time = _selt.onlineTime * 60; // 转成成秒 ...this.SDKCOMMDATA,
return new Promise((resolve, reject) => { room_limit: shareInfo.room_limit,
(wx as any).checkIsUserAdvisedToRest({ target_state: 0
todayPlayedTime: time, }, 'POST');
success: function (res) { if (code == 0) {
resolve(res.result); // 是否建议用户休息 const actId = data.activity_id;
const totalMembers = shareInfo.room_limit || '0';
(wx as any).updateShareMenu({
withShareTicket: true,
isUpdatableMessage: true,
activityId: this.actId, // 活动 ID
templateInfo: {
parameterList: [{
name: 'member_count',
value: '1' // 设置房间初始玩家1
}, {
name: 'room_limit',
value: totalMembers
}]
}, },
fail: function (res) { success: (res) => {
reject(res); let ShareParams = {
title: shareInfo.title ? shareInfo.title : SDKConfig.shareTitle,
imageUrl: shareInfo.image ? shareInfo.image : SDKConfig.shareImageUrl,
imageId: shareInfo.imageId ? shareInfo.imageId : SDKConfig.shareImageId,
query: 'fromOpenId=' + this.LoginData['open_id'] + '&from=share&tag=0&actId=' + actId
}
this.share(ShareParams);
}, },
})
}); });
}
// 米大师支付参数
private MidasPaymentParams = {
mode: 'game', // 支付的类型
env: SDKConfig.midasPayEnv, // 米大师环境
offerId: null, // 在米大师侧申请的应用id
currencyType: 'CNY', // 币种
platform: 'android', // 客户端平台
buyQuantity: 10, // buyQuantity * 游戏币单价 = 限定的价格等级(1,3,6,8,12,18,25,30,40,45,50,60,68,73,78,88,98,108,118,128,148,168,188,198,328,648)
zoneId: '1', // 分区ID,默认1
}
//把字符串转换成json
private toJson(str: string) {
let json = {}
const jsonArr = str.split('&')
for (let i = 0; i < jsonArr.length; i++) {
const keyArr = jsonArr[i].split('=')
json[keyArr[0]] = keyArr[1] || '' // 附上key和对应的value
}
return json
}
//接口签名,直接返回完整对象
private md5_sign(obj) {
obj.time = Date.parse(new Date().toString()) // 获取请求的时间戳秒
let keys = Object.keys(obj).sort();
let key_url = "";
for (let i = 0; i < keys.length; i++) {
if (keys[i] != 'sign') key_url += keys[i] + '=' + obj[keys[i]] + '&'
}
key_url = key_url + SDKConfig.productKey
obj.sign = md5(key_url)
return obj
}
private isArray(arr) {
let toStr = Object.prototype.toString;
if (typeof Array.isArray === 'function') {
return Array.isArray(arr);
}
return toStr.call(arr) === '[object Array]';
}
private isPlainObject(obj) {
let toStr = Object.prototype.toString;
let hasOwn = Object.prototype.hasOwnProperty;
if (!obj || toStr.call(obj) !== '[object Object]') {
return false;
}
let hasOwnConstructor = hasOwn.call(obj, 'constructor');
let hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
return false;
}
let key;
for (key in obj) { /**/ }
return typeof key === 'undefined' || hasOwn.call(obj, key);
}
// 数据深拷贝
public deepCopy(a, b, c?, d?, e?) {
const that = this
let options, name, src, copy, copyIsArray, clone;
let target = arguments[0];
let i = 1;
let length = arguments.length;
let deep = false;
if (typeof target === 'boolean') {
deep = target;
target = arguments[1] || {};
i = 2;
}
if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {
target = {};
}
for (; i < length; ++i) {
options = arguments[i];
if (options != null) {
for (name in options) {
src = target[name];
copy = options[name];
if (target !== copy) {
if (deep && copy && (that.isPlainObject(copy) || (copyIsArray = that.isArray(copy)))) {
if (copyIsArray) {
copyIsArray = false;
clone = src && that.isArray(src) ? src : [];
} else { } else {
clone = src && that.isPlainObject(src) ? src : {}; console.log("--SDK错误::createActiveSahre", msg);
}
target[name] = that.deepCopy(deep, clone, copy);
} else if (typeof copy !== 'undefined') {
target[name] = copy;
}
} }
} }
public updateShareMsgInfo = (updateInfo) => { // 更新动态消息接口
if (!updateInfo.activity_id || updateInfo.activity_id == '') {
updateInfo = {
...updateInfo,
activity_id: this.actId,
version_type: SDKConfig.navPayEnv
} }
} }
return target this.sdkRequest(Links.setActShareInfo, { ...this.SDKCOMMDATA, ...updateInfo }, 'POST')
}
// 获取启动参数
public getOptionsInfo(all?) {
const _selt = this
const options = (wx as any).getLaunchOptionsSync()
console.log("--启动参数--->", options)
this.ReportParams.sceneId = options.scene;
if (all) return options
if (options.query && Object.keys(options.query).length > 0) {
if (options.query.scene && options.query.scene != '') { // 扫码参数
const scene = _selt.toJson(decodeURIComponent(options.query.scene))
return scene
} else return options.query // 普通url参数
} else if (options.referrerInfo && Object.keys(options.referrerInfo).length > 0 && options.referrerInfo.extraData && Object.keys(options.referrerInfo.extraData).length > 0) {
return options.referrerInfo.extraData // 小程序跳转附带参数
} else {
return {}
} }
public getActiveShareInfo = async () => { // 查询动态消息接口
let { code, data } = await this.sdkRequest(Links.getActShareInfo, {
product_code: SDKConfig.productCode,
activity_id: this.actId
}, 'POST')
return !code ? data : 0;
} }
public getLaunchOptions() { public async phoneCode(phoneInfo, callback?) { // 发送验证码接口
return (wx as any).getLaunchOptionsSync() const { code } = await this.sdkRequest(Links.sendCode, { ...this.SDKCOMMDATA, ...phoneInfo, type: 'SDK.BIND_MOBILE' });
callback && callback(!code);
} }
public async getNetworkType() { public async userPhone(phoneInfo, callback) { // 绑定手机
const _selt = this; const { code } = await this.sdkRequest(Links.saveNum, { ...this.SDKCOMMDATA, ...phoneInfo, source: 'WEIXIN' })
return new Promise((resolve, reject) => { callback(code);
(wx as any).getNetworkType({
success: (res) => {
_selt.ReportParams.networkType = _selt.heartParams.info.network = _selt.sdkParams.network_type = res.networkType
resolve(res.networkType)
},
fail: (err) => {
console.log("--SDK错误->getNetworkType", err)
reject('')
}
})
});
} }
private async getSystemInfo() { public async checkUserPhoneBind() { // 查询用户绑定状态
const _selt = this const { code } = await this.sdkRequest(Links.bindPhone, { ...this.SDKCOMMDATA, uid: this.LoginData['uid'] });
await (wx as any).getSystemInfo({ return !code;
success: (res) => {
console.log(res);
_selt.ReportParams.model = _selt.sdkParams.equipmentname = _selt.heartParams.info.model = res.model
_selt.ReportParams.screenWidth = res.screenWidth
_selt.ReportParams.screenHeight = res.screenHeight
_selt.heartParams.resolution = res.screenWidth + '*' + res.screenHeight
_selt.ReportParams.language = _selt.heartParams.language = res.language
_selt.ReportParams.system = _selt.sdkParams.equipmentos = res.system
_selt.ReportParams.version = res.version
_selt.ReportParams.SDKVersion = res.sdkVersion
// this.MidasPaymentParams.platform = res.platform || 'android'
_selt.sdkParams.os = _selt.heartParams.osname = (res.system).split(' ')[0].toLowerCase()
} }
}) public async getUserPaymentType(roleInfo) { // 是否支持切支付
let { code } = await this.sdkRequest(Links.payType, { ...this.SDKCOMMDATA, ...roleInfo });
return !code;
} }
private _login(): Promise<any> { // 创建录屏对象
const _selt = this; public createGameRecorder = (startEventCallBack?, stopEventCallBack?, cpCallback?) => {
return new Promise((resolve, reject) => {
try { try {
(wx as any).login({ this.GameRecorder = (wx as any).getGameRecorder();
success: (res) => { if (!this.GameRecorder.isFrameSupported()) {
if (res.code) { if (cpCallback) cpCallback({ status: 0, msg: '设备不支持录屏功能.' });
resolve(res); return;
} else {
reject("执行wx.login返回成功,但无code参数");
}
},
fail: () => {
reject("执行wx.login返回失败");
},
complete: (res) => {
console.log("--SDK执行登录,微信返回数据:", res);
}
});
} catch (err) {
_selt.sdkAlert("微信登录接口返回失败");
} }
this.GameRecorder.on('start', () => {
if (startEventCallBack) startEventCallBack();
}); });
} this.GameRecorder.on('stop', (res) => {
// 退出小游戏 console.log('--对局回放时长:', res.duration);
public async exitApp(): Promise<any> { if (stopEventCallBack) stopEventCallBack(res);
return new Promise((resolve, reject) => {
(wx as any).exitMiniProgram({
success: (res) => {
console.log('退出成功')
resolve(res)
},
fail: (res) => {
console.log('退出失败')
reject(res)
}
})
}) })
if (cpCallback) cpCallback({ status: 1, msg: null })
} catch (err) {
console.log("--录屏异常:", err);
if (cpCallback) cpCallback({ status: 0, msg: err })
} }
// SDK上报接口
private sdkRequest(link: string, portData, method?) {
this.md5_sign(portData) // 附上签名参数
console.log("--SDK接口参数", link, portData)
return this.request(link, portData, method)
}
// 上报心跳
private heartBeat() {
const _selt = this;
const obj = this.heartParams;
const tmp = Date.parse(new Date().toString()).toString() // 获取请求的时间戳秒
obj.time = obj.gentime = tmp.substr(0, 10);
obj.action = 'heartBeat';
obj.content.click_times = null;
this.reportEncode(obj);
setTimeout(function () {
_selt.heartBeat();
_selt.clickReport();
}, 60000);
}
// 上报点击
private clickCounter = 0 // 当前用户点击次数
public userClickEvent() {
this.clickCounter++;
// console.log("--SDK当前点击次数", this.clickCounter);
}
private async clickReport() {
if (this.clickCounter > 0) {
const obj = this.heartParams;
const tmp = Date.parse(new Date().toString()).toString() // 获取请求的时间戳秒
obj.time = obj.gentime = tmp.substr(0, 10);
obj.action = 'userappclick';
obj.content.click_times = this.clickCounter;
await this.reportEncode(obj);
}
this.clickCounter = 0; // 上报后归零
}
private reportEncode(obj) {
let keys = Object.keys(obj).sort();
let key_url = "";
for (let i = 0; i < keys.length; i++) {
if (keys[i] != 'sign' && keys[i] != 'info' && keys[i] != 'content') key_url += keys[i] + '=' + obj[keys[i]] + '&'
}
obj.sign = md5(key_url + 'BA886FF52827126DCD18E73E0E16420C')
this.request(Links.heartReport, obj, 'POST');
}
// 上报支付异常
private reportPaymentError(err: Object) {
let portData = {
...this.sdkParams,
uid: this.ReportParams.userId,
event_code: 'PaymentError', event_data: JSON.stringify(err),
}
this.sdkRequest(Links.paymentErrorReport, portData, 'POST');
}
// 上报激活
public ActiReport() {
this.ReportData({ action: 'activation' });
this.heartBeat();
}
// 上报注册
public RegisterReport() {
this.ReportData({ action: 'register' })
}
// 上报登录
public LoginReport() {
this.ReportData({ action: 'login' })
}
// 上报等级
public RoleLevelReport(roleInfo) {
let reportData = this.deepCopy(roleInfo, { action: 'roleUpgrade' });
this.ReportData(reportData);
}
// 自定义上报
public CustomReport(custInfo) {
let reportData = this.deepCopy(custInfo, { action: 'customevent' });
this.ReportData(reportData);
}
// 数据上报接口,外部调用,参数中必须含有action值
public ReportData(portData) {
const that = this
portData = that.deepCopy({}, that.ReportParams, portData)
portData.time = Date.parse(new Date().toString()) // 获取当前时间戳秒
console.log("--SDK统计上报参数", portData)
this.request(SDKConfig.report, portData, 'POST')
}
// 调用微信请求接口
private request(URI: string, Params: any, Method = 'GET') {
return this.fetchUri(URI, Params, Method).then(res => res.data)
} }
private fetchUri(URI, DATA, METHOD): Promise<any> { public startGameRecorder(recorderInfo: RecorderInfo) {
return new Promise((resolve, reject) => {
try { try {
(wx as any).request({ this.GameRecorder.start({
url: URI, duration: recorderInfo.duration
method: METHOD, });
data: DATA,
header: {
'Content-Type': 'json'
},
success: resolve,
fail: reject
})
} catch (err) { } catch (err) {
reject(err) console.log("$$SDK录屏异常::gameRecorder", err);
}
})
}
// 消息提示框
public sdkAlert(str) {
this.showMsg(str)
} }
private showMsg(str) {
(wx as any).showToast({
title: str,
icon: 'none',
duration: 3000
})
} }
// 客服 public stopGameRecorder(shareInfo) {
public Customer(_orderInfo?) {
try { try {
(wx as any).openCustomerServiceConversation(_orderInfo) this.GameRecorder.stop();
if (this.recorderBtn) this.recorderBtn.show();
else this.createRecorderShareButton(shareInfo);
} catch (err) { } catch (err) {
console.log("访问客服异常-->", err) console.log("$$SDK录屏异常::gameRecorder", err);
}
}
// 切换游戏
public navToOtherGame(params) {
const _self = this;
const obj = { // 跳转参数
appId: params.appid, // 跳转的小程序appid
path: '', // 跳转到首页
envVersion: SDKConfig.navPayEnv, //跳转方式
extraData: {
from_openid: _self.sdkParams.open_id,
from_product: SDKConfig.productCode,
from_uid: _self.ReportParams.userId
}
}
this.navigateToMiniProgram(obj);
}
private navigateToMiniProgram(params) {
if (this.ReportParams.SDKVersion < '2.2') {
this.sdkAlert('微信版本不兼容,请升级..')
} else {
(wx as any).navigateToMiniProgram(params)
} }
} }
private LoadingOn() { private createRecorderShareButton(shareInfo) {
(wx as any).showLoading({ let recorderShareInfo = {
title: '请稍候..', style: {
mask: true left: shareInfo.left,
}) top: shareInfo.top,
height: shareInfo.height,
iconMarginRight: shareInfo.iconMarginRight,
fontSize: shareInfo.fontSize,
color: shareInfo.color,
paddingLeft: shareInfo.paddingLeft,
paddingRight: shareInfo.paddingRight
},
icon: shareInfo.icon || '',
image: shareInfo.image || '',
text: shareInfo.text || '',
share: {
query: 'fromOpenId=' + this.LoginData['open_id'] + '&from=share&tag=0&' + (shareInfo.query ? shareInfo.query : ''),
bgm: shareInfo.bgm,
timeRange: shareInfo.timeRange
} }
private LoadingOff() { };
(wx as any).hideLoading() this.recorderBtn = (wx as any).createGameRecorderShareButton(recorderShareInfo);
// 当分享出现异常时才会触发点击回调
this.recorderBtn.onTap(res => {
console.log('--录屏异常:', res);
});
} }
private showModal(DATA) { public hideGameRecorderShareButton() {
(wx as any).showModal(this.deepCopy({}, DATA, { if (this.recorderBtn) this.recorderBtn.hide();
cancelText: '取消',
confirmText: '确认'
}))
} }
// 获取用户画像 public async checkUserAdvised() { // 防沉迷验证
private getGameLabel() { let time = this.onlineTime * 60; // 转成成秒
const _selt = this; return new Promise((resolve, reject) => {
try { (wx as any).checkIsUserAdvisedToRest({
(wx as any).getUserGameLabel({ todayPlayedTime: time,
success: function (res) { success: function (res) {
if (res) _selt.ReportParams.userGameLabel = res.label || 0; resolve(res.result); // 是否建议用户休息
} },
fail: function (res) {
reject(res);
},
})
}); });
} catch (err) { }
} }
// 定义wechat方法 // 获取用户信息
public async getUserInfo(): Promise<any> { public getUserInfo = async () => {
const _selt = this; let status = await this._getSetting();
return new Promise(async function (resolve, reject) { if (status == 1) {
let status = await _selt._getSetting();
console.log("--SDK用户授权状态", status)
switch (status) {
case 1:
try {
// 用户已授权,可以直接调用相关 API // 用户已授权,可以直接调用相关 API
let userInfo = await _selt._getUserInfo(); let userInfo = await this._getUserInfo();
// 上报用户授权 // 上报用户授权
_selt.ReportData(_selt.deepCopy({}, userInfo, { this.ReportData({
action: 'authorize', userInfo: { ...userInfo, nickName: encodeURI(userInfo.nickName) },
nickName: encodeURI(userInfo.nickName) action: 'authorize',
})) })
resolve(userInfo); return userInfo;
} catch (err) {
let userBtn = _selt.createUserInfoButton();
userBtn.onTap(
function (res) {
if (res.userInfo) {
//上报授权
userBtn.offTap(this);
userBtn.destroy();
userBtn = null;
let userInfo = res["userInfo"];
// 上报用户授权
_selt.ReportData(_selt.deepCopy({}, userInfo, {
action: 'authorize',
nickName: encodeURI(userInfo.nickName)
}))
resolve(userInfo);
}
}
);
} }
break; else if (status == 0) {
case 0:
// 用户已拒绝授权,再调用相关 API 或者 wx.authorize 会失败,需要引导用户到设置页面打开授权开关 // 用户已拒绝授权,再调用相关 API 或者 wx.authorize 会失败,需要引导用户到设置页面打开授权开关
let w = (wx as any).getSystemInfoSync().windowWidth; const w = (wx as any).getSystemInfoSync().windowWidth;
let h = (wx as any).getSystemInfoSync().windowHeight; const h = (wx as any).getSystemInfoSync().windowHeight;
let OpenSettingButton = (wx as any).createOpenSettingButton({ let OpenSettingButton = (wx as any).createOpenSettingButton({
type: "text", type: "text",
text: "", text: "",
...@@ -810,27 +343,27 @@ class WechatSDK { ...@@ -810,27 +343,27 @@ class WechatSDK {
height: h height: h
} }
}); });
OpenSettingButton.onTap(async function (res) { OpenSettingButton.onTap(async (res) => {
let t_status = await _selt._getSetting(); let t_status = await this._getSetting();
console.log("--SDK:点击设置按钮返回t_status=", t_status); console.log("--SDK:点击设置按钮返回t_status=", t_status);
if (t_status == 1) { if (t_status == 1) {
OpenSettingButton.offTap(this); OpenSettingButton.offTap(this);
OpenSettingButton.destroy(); OpenSettingButton.destroy();
OpenSettingButton = null; OpenSettingButton = null;
let userInfo = await _selt._getUserInfo(); let userInfo = await this._getUserInfo();
// 上报用户授权 // 上报用户授权
_selt.ReportData(_selt.deepCopy({}, userInfo, { this.ReportData({
...userInfo,
action: 'authorize', action: 'authorize',
nickName: encodeURI(userInfo.nickName) nickName: encodeURI(userInfo.nickName)
})) })
resolve(userInfo); return userInfo;
} }
}); });
break; }
case -1: else if (status == -1) {
let userBtn = _selt.createUserInfoButton(); let userBtn = this.createUserInfoButton();
userBtn.onTap( userBtn.onTap((res) => {
function (res) {
if (res.userInfo) { if (res.userInfo) {
//上报授权 //上报授权
userBtn.offTap(this); userBtn.offTap(this);
...@@ -838,20 +371,17 @@ class WechatSDK { ...@@ -838,20 +371,17 @@ class WechatSDK {
userBtn = null; userBtn = null;
let userInfo = res["userInfo"]; let userInfo = res["userInfo"];
// 上报用户授权 // 上报用户授权
_selt.ReportData(_selt.deepCopy({}, userInfo, { this.ReportData({
...userInfo,
action: 'authorize', action: 'authorize',
nickName: encodeURI(userInfo.nickName) nickName: encodeURI(userInfo.nickName)
})) })
resolve(userInfo); return userInfo;
}
} }
); });
break;
} }
})
} }
private createUserInfoButton() { private createUserInfoButton() {
const _selt = this;
// 未询问过用户授权,调用相关 API 或者 wx.authorize 会弹窗询问用户 // 未询问过用户授权,调用相关 API 或者 wx.authorize 会弹窗询问用户
let w = (wx as any).getSystemInfoSync().windowWidth; let w = (wx as any).getSystemInfoSync().windowWidth;
let h = (wx as any).getSystemInfoSync().windowHeight; let h = (wx as any).getSystemInfoSync().windowHeight;
...@@ -883,9 +413,6 @@ class WechatSDK { ...@@ -883,9 +413,6 @@ class WechatSDK {
}); });
}); });
} }
/**
* 检查授权配置
*/
private async _getSetting(): Promise<any> { private async _getSetting(): Promise<any> {
return new Promise(async function (resolve, reject) { return new Promise(async function (resolve, reject) {
(wx as any).getSetting({ (wx as any).getSetting({
...@@ -904,35 +431,37 @@ class WechatSDK { ...@@ -904,35 +431,37 @@ class WechatSDK {
fail: function () { fail: function () {
reject(); reject();
}, },
complete: function () { }
}); });
}); });
} }
private async share(DATA): Promise<any> { public addShareEvent = (shareInfo: shareInfo, callback?) => {
const _selt = this (wx as any).onShareAppMessage(() => {
return new Promise(async (resolve, reject) => { if (callback) callback();
try { const ShareParams = {
let sharePromise = await _selt._share(DATA); title: shareInfo.title ? shareInfo.title : SDKConfig.shareTitle,
if (sharePromise) { imageUrl: shareInfo.image ? shareInfo.image : SDKConfig.shareImageUrl,
resolve(sharePromise) imageUrlId: shareInfo.imageId ? shareInfo.imageId : SDKConfig.shareImageId,
} query: 'fromOpenId=' + this.LoginData['open_id'] + '&from=share&tag=0&' + (shareInfo.query ? shareInfo.query : ''),
else if (this.ReportParams.SDKVersion >= '2.3') { //10月10号开始2.3和以上版本用户取消share回调 withShareTicket: true,
resolve(-1) };
} return ShareParams;
else { });
reject(sharePromise) (wx as any).showShareMenu({ withShareTicket: true })
console.log("--SDK分享错误", sharePromise)
} }
} catch (err) { public ShareGameInfo = (shareInfo?) => {
reject(err) // 参数,记录分享的用户openid
const ShareParams = {
title: shareInfo && shareInfo.title ? shareInfo.title : SDKConfig.shareTitle,
imageUrl: shareInfo && shareInfo.image ? shareInfo.image : SDKConfig.shareImageUrl,
imageId: shareInfo && shareInfo.imageId ? shareInfo.imageId : SDKConfig.shareImageId,
query: 'fromOpenId=' + this.LoginData['open_id'] + '&from=share&tag=0&' + (shareInfo.extraData ? shareInfo.extraData : '')
} }
}) return this.share(ShareParams)
} }
private _share(DATA) { private share = (DATA): Promise<any> => {
const _selt = this;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { (wx as any).shareAppMessage({
(wx as any).shareAppMessage(_selt.deepCopy(DATA, { ...DATA,
withShareTicket: true, withShareTicket: true,
success: res => { success: res => {
resolve(1); resolve(1);
...@@ -940,278 +469,255 @@ class WechatSDK { ...@@ -940,278 +469,255 @@ class WechatSDK {
fail: res => { fail: res => {
resolve(-1); resolve(-1);
}, },
complete() { })
resolve(0); setTimeout(function () { // 两秒后直接当分享成功返回
}
}))
setTimeout(function () { // 两秒后直接当分享成功返回,避免回调取消引起await问题
resolve(2) resolve(2)
}, 3000) }, 3000)
})
}
// 切换游戏
public navToOtherGame = (params) => {
const obj = { // 跳转参数
appId: params.appid, // 跳转的小程序appid
path: '', // 跳转到首页
envVersion: SDKConfig.navPayEnv, //跳转方式
extraData: {
from_openid: this.LoginData['open_id'],
from_product: SDKConfig.productCode,
from_uid: this.LoginData['uid']
}
}
this.navigateToMiniProgram(obj);
}
private navigateToMiniProgram = (params) => {
if (this.SystemInfo['sdkVersion'] < '2.2') {
this.showMsg('微信版本不兼容,请升级..')
} else {
(wx as any).navigateToMiniProgram(params)
}
}
// 客服
public Customer = (_orderInfo?) => {
try {
(wx as any).openCustomerServiceConversation(_orderInfo)
} catch (err) { } catch (err) {
resolve(err) console.log("访问客服异常-->", err)
this.showMsg('打开客服链接失败.')
} }
})
} }
//动态消息 public ActiReport() {
public async createActiveShare(shareInfo) { this.ReportData({ action: 'activation' });
const _self = this; this.heartBeatReport();
let postData = this.deepCopy({}, _self.sdkParams, { // 组合请求参数 } // 上报激活
room_limit: shareInfo.room_limit, public RegisterReport() { this.ReportData({ action: 'register' }) } // 上报注册
target_state: 0 // 新建动态消息状态 public LoginReport() { this.ReportData({ action: 'login' }) } // 上报登录
}); public RoleLevelReport(roleInfo) { this.ReportData({ ...roleInfo, action: 'roleUpgrade' }) } // 上报等级
let actInfo = await _self.sdkRequest(Links.getActShareId, postData, 'POST').catch(err => { public CustomReport(custInfo) { this.ReportData({ ...custInfo, action: 'customevent' }) } // 自定义上报
console.log("--SDDK错误::createActiveSahre", err); public userClickEvent() { this.clickCounter++ }
}); private heartBeatReport() {
if (actInfo.code == 0) { setTimeout(() => {
const actId = actInfo.data.activity_id; this.clickReport();
const totalMembers = shareInfo.room_limit || '0'; this.heartBeatReport();
(wx as any).updateShareMenu({ }, 60 * 1000);
withShareTicket: true, }
isUpdatableMessage: true, private clickReport = async () => {
activityId: actId, // 活动 ID this.ReportData({ action: 'heartBeat' })
templateInfo: { this.clickCounter > 0 && this.ReportData({ action: 'userappclick', click_times: this.clickCounter });
parameterList: [{ this.clickCounter = 0; // 上报后归零
name: 'member_count', }
value: '1' // 设置房间初始玩家1 // 上报支付异常
}, { private reportPaymentError(err: Object) {
name: 'room_limit', let portData = {
value: totalMembers ...this.SDKCOMMDATA,
}] uid: this.LoginData['uid'],
}, event_code: 'PaymentError', event_data: JSON.stringify(err),
success: function (res) { }
let ShareParams = { this.sdkRequest(Links.paymentErrorReport, portData, 'POST');
title: shareInfo.title ? shareInfo.title : SDKConfig.shareTitle, }
imageUrl: shareInfo.image ? shareInfo.image : SDKConfig.shareImageUrl, // 数据上报接口,外部调用,参数中必须含有action值
imageId: shareInfo.imageId ? shareInfo.imageId : SDKConfig.shareImageId, public ReportData(portData) {
query: 'fromOpenId=' + _self.ReportParams.openId + '&from=share&tag=0&actId=' + actId portData['launchOptions'] = this.LaunchOptions;
portData['userInfo'] = { ...portData['userInfo'], ...{ userId: this.LoginData['uid'] || '', open_id: this.LoginData['open_id'] } };
portData['systemInfo'] = this.SystemInfo;
portData['product_code'] = SDKConfig.productCode;
portData['time'] = Date.parse(new Date().toString()) // 获取当前时间戳秒
this.request(SDKConfig.report, portData, 'POST')
}
// 退出小游戏
public exitApp = () => {
(wx as any).exitMiniProgram()
}
private getWechatCode = (): Promise<any> => {
return new Promise((resolve, reject) => {
try {
(wx as any).login({
success: (res) => {
if (res.code) resolve(res);
else {
this.showMsg("执行wx.login返回成功,但无code参数", 5000);
resolve({ code: 0 });
} }
console.log("^^SDK::ShareParams", ShareParams);
_self.share(ShareParams);
}, },
fail: function (err) { } fail: () => {
this.showMsg("执行wx.login返回失败", 5000);
resolve({ code: 0 });
},
}); });
} else { } catch (err) {
console.log("--SDK错误::createActiveSahre", actInfo.msg); this.showMsg("微信登录接口返回失败");
} }
});
} }
private shareInit() { private showLoading() {
(wx as any).showShareMenu({ (wx as any).showLoading({
withShareTicket: true, title: '请稍候..',
success: () => { }, mask: true
fail: () => { },
complete: () => { }
}) })
} }
// 分享 private hideLoading() { (wx as any).hideLoading() }
public addShareEvent(shareInfo: shareInfo, callback?) { private showModal(DATA) {
const that = this; (wx as any).showModal({
(wx as any).onShareAppMessage(() => { ...DATA,
if (callback) callback(); cancelText: '取消',
const ShareParams = { confirmText: '确认'
title: shareInfo.title ? shareInfo.title : SDKConfig.shareTitle,
imageUrl: shareInfo.image ? shareInfo.image : SDKConfig.shareImageUrl,
imageUrlId: shareInfo.imageId ? shareInfo.imageId : SDKConfig.shareImageId,
query: 'fromOpenId=' + that.ReportParams.openId + '&from=share&tag=0&' + (shareInfo.query ? shareInfo.query : ''),
withShareTicket: true,
success: shareInfo.success,
fail: shareInfo.fail,
complete: shareInfo.complete
};
return ShareParams;
}) })
that.shareInit();
} }
public ShareApp(params?: string) { public showMsg = (str, duration = 3000) => {
const that = this (wx as any).showToast({
// 参数,记录分享的用户openid title: str,
const ShareParams = { icon: 'none',
title: SDKConfig.shareTitle, duration: duration
imageUrl: SDKConfig.shareImageUrl, })
imageId: SDKConfig.shareImageId,
query: 'fromOpenId=' + that.ReportParams.openId + '&from=share&tag=0&' + (params ? params : '')
} }
return this.share(ShareParams) private getSystemInfo = (): Promise<any> => {
return new Promise((resolve, reject) => {
(wx as any).getSystemInfo({
success: (res) => { resolve(res) },
})
})
} }
public ShareGameInfo(shareInfo?) { public getNetworkType = (): Promise<any> => {
const that = this return new Promise((resolve, reject) => {
// 参数,记录分享的用户openid (wx as any).getNetworkType({
const ShareParams = { success: (res) => { resolve(res.networkType) },
title: shareInfo && shareInfo.title ? shareInfo.title : SDKConfig.shareTitle, })
imageUrl: shareInfo && shareInfo.image ? shareInfo.image : SDKConfig.shareImageUrl, })
imageId: shareInfo && shareInfo.imageId ? shareInfo.imageId : SDKConfig.shareImageId,
query: 'fromOpenId=' + that.ReportParams.openId + '&from=share&tag=0&' + (shareInfo.extraData ? shareInfo.extraData : '')
} }
return this.share(ShareParams) public getOptionsInfo = () => {
const options = (wx as any).getLaunchOptionsSync()
console.log("--启动参数--->", options)
if (options.query && Object.keys(options.query).length > 0) {
if (options.query.scene && options.query.scene != '') { // 扫码参数
const scene = this.toJson(decodeURIComponent(options.query.scene))
return scene
} else return { ...options.query, scene: options.scene || '' } // 普通url参数
} else if (options.referrerInfo && Object.keys(options.referrerInfo).length > 0 && options.referrerInfo.extraData && Object.keys(options.referrerInfo.extraData).length > 0) {
return options.referrerInfo.extraData // 小程序跳转附带参数
} else {
return {}
} }
// 录屏功能
private GameRecorder: any
// 创建录屏对象
public createGameRecorder(startEventCallBack?, stopEventCallBack?, cpCallback?) {
const _self = this;
try {
this.GameRecorder = (wx as any).getGameRecorder();
if (!this.GameRecorder.isFrameSupported()) {
if (cpCallback) cpCallback({ status: 0, msg: '设备不支持录屏功能.' });
return;
} }
this.GameRecorder.on('start', () => { // SDK上报接口
if (startEventCallBack) startEventCallBack(); private sdkRequest = async (link: string, portData, method?) => {
}); portData = this.md5_sign(portData) // 附上签名参数
this.GameRecorder.on('stop', res => { return await this.request(link, portData, method);
console.log('--对局回放时长:', res.duration);
if (stopEventCallBack) stopEventCallBack(res);
})
if (cpCallback) cpCallback({ status: 1, msg: null })
} catch (err) {
console.log("$$SDK录屏异常::gameRecorder", err);
if (cpCallback) cpCallback({ status: 0, msg: err })
} }
// 调用微信请求接口
private request = async (URI: string, Params: any, Method = 'GET') => {
const { code, data, msg } = await this.fetchUri(URI, Params, Method);
if (!data) return { code, data: {}, msg }
if (!code) return { code, data, msg };
if (code) this.showMsg(msg); // 输出接口异常
} }
public startGameRecorder(recorderInfo: RecorderInfo) { private fetchUri = (URI, DATA, METHOD): Promise<any> => {
return new Promise((resolve, reject) => {
try { try {
this.GameRecorder.start({ (wx as any).request({
duration: recorderInfo.duration url: URI,
}); method: METHOD,
data: DATA,
header: {
'Content-Type': 'json'
},
success: (response) => {
resolve(response.data)
},
fail: resolve
})
} catch (err) { } catch (err) {
console.log("$$SDK录屏异常::gameRecorder", err); reject(err)
}
})
} }
//把字符串转换成json
private toJson = (str: string) => {
let json = {}
const jsonArr = str.split('&')
for (let i = 0; i < jsonArr.length; i++) {
const keyArr = jsonArr[i].split('=')
json[keyArr[0]] = keyArr[1] || '' // 附上key和对应的value
} }
public stopGameRecorder(shareInfo) { return json
try {
this.GameRecorder.stop();
if (this.recorderBtn) this.recorderBtn.show();
else this.createRecorderShareButton(shareInfo);
} catch (err) {
console.log("$$SDK录屏异常::gameRecorder", err);
} }
//接口签名,直接返回完整对象
private md5_sign = (obj) => {
obj.time = Date.parse(new Date().toString()) // 获取请求的时间戳秒
let keys = Object.keys(obj).sort();
let key_url = "";
for (let i = 0; i < keys.length; i++) {
if (keys[i] != 'sign') key_url += keys[i] + '=' + obj[keys[i]] + '&'
} }
private recorderBtn = null // 对局回放分享按钮对象 key_url = key_url + SDKConfig.productKey
private createRecorderShareButton(shareInfo) { obj.sign = md5(key_url)
const _selt = this; return obj
let recorderShareInfo = {
style: {
left: shareInfo.left,
top: shareInfo.top,
height: shareInfo.height,
iconMarginRight: shareInfo.iconMarginRight,
fontSize: shareInfo.fontSize,
color: shareInfo.color,
paddingLeft: shareInfo.paddingLeft,
paddingRight: shareInfo.paddingRight
},
icon: shareInfo.icon || '',
image: shareInfo.image || '',
text: shareInfo.text || '',
share: {
query: 'fromOpenId=' + _selt.ReportParams.openId + '&from=share&tag=0&' + (shareInfo.query ? shareInfo.query : ''),
bgm: shareInfo.bgm,
timeRange: shareInfo.timeRange
} }
}; private LaunchOptions: Object; // 启动参数对象
this.recorderBtn = (wx as any).createGameRecorderShareButton(recorderShareInfo); private SystemInfo: Object; // 设备信息
// 当分享出现异常时才会触发点击回调 private LoginData: Object; // 登录信息
this.recorderBtn.onTap(res => { // SDK接口通用参数
console.log('--录屏异常:', res); private SDKCOMMDATA: Object = {
}); source: 'WEIXIN',
product_code: SDKConfig.productCode,
uuid: '',
equipmentos: '',
package_code: '',
time: '',
sign: '',
os: '',
version: this.sdkVersion
} }
public hideGameRecorderShareButton() { // 米大师支付参数
if (this.recorderBtn) this.recorderBtn.hide(); private MidasPaymentParams = {
mode: 'game', // 支付的类型
env: SDKConfig.midasPayEnv, // 米大师环境
currencyType: 'CNY', // 币种
platform: 'android', // 客户端平台
zoneId: '1', // 分区ID,默认1
} }
private heartParams = { private MidasErrorCode = {
action: "heartbeat", '-1': '系统失败',
appid: SDKConfig.productCode, '-2': '支付取消',
time: null, // 【发送请求时间】 unix时间戳,要求是10位数字 '-15001': '缺少参数',
gentime: null, // 【数据生成时间】 unix时间戳,要求是10位数字 '-15002': '参数不合法',
advid: "", // 广告活动ID '-15003': '订单重复',
osname: "", // 操作系统名字 '-15004': '后台错误',
userid: "", // 玩家ID '-15005': 'appId权限被封禁',
osversion: "", // 操作系统版本号 '-15006': '货币类型不支持',
sdkversion: this.sdkVersion, // sdk 版本号 '-15007': '订单已支付',
appname: SDKConfig.appName, // 当前应用的app名字 '-15009': '由于健康系统限制,本次支付已超过限额',
packagename: "", // 当前应用的包名 '1': '用户取消支付',
appversion: SDKConfig.appVersion, // 当前应用的版本号 '2': '客户端错误,判断到小程序在用户处于支付中时,又发起了一笔支付请求',
resolution: "", // 屏幕分辨率 '3': 'Android 独有错误:用户使用 Google Play 支付,而手机未安装 Google Play',
language: "", // 语言CODE '4': '用户操作系统支付状态异常',
country: "", // 国家 '5': '操作系统错误',
timezone: "", // 时区 '6': '其他错误',
uuid: "", // openid '1000': '参数错误',
testid: "", // 测试序列号 '1003': '米大师Portal错误',
sign: "",
info: {
idfa: "",
imei: "",
imsi: "",
mac: "",
model: "", // 手机型号
buildid: "",
manufacturer: "",
memory_free: "",
memory_total: "",
network: "", // 网络状态
battery: "", // 电量
androidid: "",
advertisingid: "",
deeplink: "",
wifiname: ""
},
source: "weixinmp-api",
content: {
click_times: 0
}
}
// 统计上报参数
private ReportParams = {
action: null, // 必填,事件类型
openId: null, // 必填,微信openid,通过code去SDK接口换取
userId: '', // 必传,用户ID
productCode: null, // 必填,产品代号,配置文件配置
from: null, // 必填,广告标识,附带在url上
tag: null, // 必填,创意标识,附带在url上
passthroughParams: null, // 透传参数
fromOpenId: null, // 选填,分享来源的用户openid
model: null, // 必填,手机型号,微信api获取
system: null, // 必填,操作系统,微信api获取
networkType: null, // 选填,网络类型,微信api获取
language: null, // 选填,微信设置的语言,微信api获取
version: null, // 选填,微信版本号,微信api获取
SDKVersion: null, // 选填,微信客户端基础库版本
appVersion: null, // 选填,产品版本号,配置文件配置
screenWidth: null, // 选填,屏幕宽度,微信api获取
screenHeight: null, // 选填,屏幕高度,微信api获取
time: null, // 必填,请求的时间戳(秒)
sceneId: '', // 启动场景值
userGameLabel: '', // 用户画像
cpsAppid: '',
}
// SDK上报参数
private sdkParams = {
product_code: "", // 产品code
appid: "", // 小游戏appid
time: "", // 当前时间戳秒
uniqueid: '', // 设备唯一号
mac: '', // 网卡mac地址
idfa: '', // 苹果设备IDFA
open_id: "", // 用户openid
password: '', // 登录密码(微信免密)
source: 'WEIXIN', // 用户来源
token: '', // 登录成功返回
os: 'H5', // 系统类型
equipmentos: "", // 系统版本
equipmentname: "", // 手机型号
version: "", // SDK版本
package_code: '', // 渠道标识
sign: "", // 签名
unionid: '', // 用户Unionid,用于切支付
pay_channel: '', // 支付方式,初始化接口返回
client_type: 'weixin_minigame', // 客户端类型
session_key: '', // 用户session_key
from_openid: '', // 跳转前小游戏的用户openid
from_product: '', // 跳转前小游戏对接的产品CODE
from_uid: '', // 跳转前小游戏登录的SDK用户UID
network_type: '', // 用户当前网络类型
} }
} }
interface RecorderInfo {
duration: number
}
// SDK后端接口(勿改) // SDK后端接口(勿改)
const Links = { const Links = {
init: SDKConfig.sdk_domain + '/weixin/access_token.php', // 获取openid init: SDKConfig.sdk_domain + '/weixin/access_token.php', // 获取openid
...@@ -1227,20 +733,5 @@ const Links = { ...@@ -1227,20 +733,5 @@ const Links = {
getActShareId: SDKConfig.active_domain + '/weixin/updatable_message/create_activity_id', // 获取活动消息id getActShareId: SDKConfig.active_domain + '/weixin/updatable_message/create_activity_id', // 获取活动消息id
setActShareInfo: SDKConfig.active_domain + '/weixin/updatable_message/updatablemsg', // 更新活动消息内容 setActShareInfo: SDKConfig.active_domain + '/weixin/updatable_message/updatablemsg', // 更新活动消息内容
getActShareInfo: SDKConfig.active_domain + '/weixin/updatable_message/get_activity', // 查询活动消息内容 getActShareInfo: SDKConfig.active_domain + '/weixin/updatable_message/get_activity', // 查询活动消息内容
heartReport: 'https://s.pthzwl.net/sdkapi.php', // 心跳上报接口
paymentErrorReport: SDKConfig.sdk_domain + '/v2/analytics/event', // 上报支付错误信息 paymentErrorReport: SDKConfig.sdk_domain + '/v2/analytics/event', // 上报支付错误信息
} }
\ No newline at end of file
class shareInfo {
title?: string
image?: string
imageId?: string
query?: string
success: any
fail: any
complete?: any
}
class RecorderInfo {
duration: number
}
// md5加密
const rotateLeft = (lValue, iShiftBits) => { return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)) }; var addUnsigned = function (lX, lY) { var lX4, lY4, lX8, lY8, lResult; lX8 = (lX & 2147483648); lY8 = (lY & 2147483648); lX4 = (lX & 1073741824); lY4 = (lY & 1073741824); lResult = (lX & 1073741823) + (lY & 1073741823); if (lX4 & lY4) { return (lResult ^ 2147483648 ^ lX8 ^ lY8) } if (lX4 | lY4) { if (lResult & 1073741824) { return (lResult ^ 3221225472 ^ lX8 ^ lY8) } else { return (lResult ^ 1073741824 ^ lX8 ^ lY8) } } else { return (lResult ^ lX8 ^ lY8) } }; var F = function (x, y, z) { return (x & y) | ((~x) & z) }; var G = function (x, y, z) { return (x & z) | (y & (~z)) }; var H = function (x, y, z) { return (x ^ y ^ z) }; var I = function (x, y, z) { return (y ^ (x | (~z))) }; var FF = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b) }; var GG = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b) }; var HH = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b) }; var II = function (a, b, c, d, x, s, ac) { a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac)); return addUnsigned(rotateLeft(a, s), b) }; var convertToWordArray = function (string) { var lWordCount; var lMessageLength = string.length; var lNumberOfWordsTempOne = lMessageLength + 8; var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64; var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16; var lWordArray = Array(lNumberOfWords - 1); var lBytePosition = 0; var lByteCount = 0; while (lByteCount < lMessageLength) { lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition)); lByteCount++ } lWordCount = (lByteCount - (lByteCount % 4)) / 4; lBytePosition = (lByteCount % 4) * 8; lWordArray[lWordCount] = lWordArray[lWordCount] | (128 << lBytePosition); lWordArray[lNumberOfWords - 2] = lMessageLength << 3; lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; return lWordArray }; var wordToHex = function (lValue) { var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount; for (lCount = 0; lCount <= 3; lCount++) { lByte = (lValue >>> (lCount * 8)) & 255; WordToHexValueTemp = "0" + lByte.toString(16); WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2) } return WordToHexValue }; var uTF8Encode = function (string) { string = string.replace(/\x0d\x0a/g, "\x0a"); var output = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { output += String.fromCharCode(c) } else { if ((c > 127) && (c < 2048)) { output += String.fromCharCode((c >> 6) | 192); output += String.fromCharCode((c & 63) | 128) } else { output += String.fromCharCode((c >> 12) | 224); output += String.fromCharCode(((c >> 6) & 63) | 128); output += String.fromCharCode((c & 63) | 128) } } } return output }; function md5(string) { var x = Array(); var k, AA, BB, CC, DD, a, b, c, d; var S11 = 7, S12 = 12, S13 = 17, S14 = 22; var S21 = 5, S22 = 9, S23 = 14, S24 = 20; var S31 = 4, S32 = 11, S33 = 16, S34 = 23; var S41 = 6, S42 = 10, S43 = 15, S44 = 21; string = uTF8Encode(string); x = convertToWordArray(string); a = 1732584193; b = 4023233417; c = 2562383102; d = 271733878; for (k = 0; k < x.length; k += 16) { AA = a; BB = b; CC = c; DD = d; a = FF(a, b, c, d, x[k + 0], S11, 3614090360); d = FF(d, a, b, c, x[k + 1], S12, 3905402710); c = FF(c, d, a, b, x[k + 2], S13, 606105819); b = FF(b, c, d, a, x[k + 3], S14, 3250441966); a = FF(a, b, c, d, x[k + 4], S11, 4118548399); d = FF(d, a, b, c, x[k + 5], S12, 1200080426); c = FF(c, d, a, b, x[k + 6], S13, 2821735955); b = FF(b, c, d, a, x[k + 7], S14, 4249261313); a = FF(a, b, c, d, x[k + 8], S11, 1770035416); d = FF(d, a, b, c, x[k + 9], S12, 2336552879); c = FF(c, d, a, b, x[k + 10], S13, 4294925233); b = FF(b, c, d, a, x[k + 11], S14, 2304563134); a = FF(a, b, c, d, x[k + 12], S11, 1804603682); d = FF(d, a, b, c, x[k + 13], S12, 4254626195); c = FF(c, d, a, b, x[k + 14], S13, 2792965006); b = FF(b, c, d, a, x[k + 15], S14, 1236535329); a = GG(a, b, c, d, x[k + 1], S21, 4129170786); d = GG(d, a, b, c, x[k + 6], S22, 3225465664); c = GG(c, d, a, b, x[k + 11], S23, 643717713); b = GG(b, c, d, a, x[k + 0], S24, 3921069994); a = GG(a, b, c, d, x[k + 5], S21, 3593408605); d = GG(d, a, b, c, x[k + 10], S22, 38016083); c = GG(c, d, a, b, x[k + 15], S23, 3634488961); b = GG(b, c, d, a, x[k + 4], S24, 3889429448); a = GG(a, b, c, d, x[k + 9], S21, 568446438); d = GG(d, a, b, c, x[k + 14], S22, 3275163606); c = GG(c, d, a, b, x[k + 3], S23, 4107603335); b = GG(b, c, d, a, x[k + 8], S24, 1163531501); a = GG(a, b, c, d, x[k + 13], S21, 2850285829); d = GG(d, a, b, c, x[k + 2], S22, 4243563512); c = GG(c, d, a, b, x[k + 7], S23, 1735328473); b = GG(b, c, d, a, x[k + 12], S24, 2368359562); a = HH(a, b, c, d, x[k + 5], S31, 4294588738); d = HH(d, a, b, c, x[k + 8], S32, 2272392833); c = HH(c, d, a, b, x[k + 11], S33, 1839030562); b = HH(b, c, d, a, x[k + 14], S34, 4259657740); a = HH(a, b, c, d, x[k + 1], S31, 2763975236); d = HH(d, a, b, c, x[k + 4], S32, 1272893353); c = HH(c, d, a, b, x[k + 7], S33, 4139469664); b = HH(b, c, d, a, x[k + 10], S34, 3200236656); a = HH(a, b, c, d, x[k + 13], S31, 681279174); d = HH(d, a, b, c, x[k + 0], S32, 3936430074); c = HH(c, d, a, b, x[k + 3], S33, 3572445317); b = HH(b, c, d, a, x[k + 6], S34, 76029189); a = HH(a, b, c, d, x[k + 9], S31, 3654602809); d = HH(d, a, b, c, x[k + 12], S32, 3873151461); c = HH(c, d, a, b, x[k + 15], S33, 530742520); b = HH(b, c, d, a, x[k + 2], S34, 3299628645); a = II(a, b, c, d, x[k + 0], S41, 4096336452); d = II(d, a, b, c, x[k + 7], S42, 1126891415); c = II(c, d, a, b, x[k + 14], S43, 2878612391); b = II(b, c, d, a, x[k + 5], S44, 4237533241); a = II(a, b, c, d, x[k + 12], S41, 1700485571); d = II(d, a, b, c, x[k + 3], S42, 2399980690); c = II(c, d, a, b, x[k + 10], S43, 4293915773); b = II(b, c, d, a, x[k + 1], S44, 2240044497); a = II(a, b, c, d, x[k + 8], S41, 1873313359); d = II(d, a, b, c, x[k + 15], S42, 4264355552); c = II(c, d, a, b, x[k + 6], S43, 2734768916); b = II(b, c, d, a, x[k + 13], S44, 1309151649); a = II(a, b, c, d, x[k + 4], S41, 4149444226); d = II(d, a, b, c, x[k + 11], S42, 3174756917); c = II(c, d, a, b, x[k + 2], S43, 718787259); b = II(b, c, d, a, x[k + 9], S44, 3951481745); a = addUnsigned(a, AA); b = addUnsigned(b, BB); c = addUnsigned(c, CC); d = addUnsigned(d, DD) } var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); return tempValue.toLowerCase() };
\ No newline at end of file
...@@ -6,7 +6,7 @@ const SDKConfig = { ...@@ -6,7 +6,7 @@ const SDKConfig = {
active_domain: 'https://open.pthzwl.net', // SDK活动接口域名 active_domain: 'https://open.pthzwl.net', // SDK活动接口域名
report: 'https://s.pthzwl.net/weixinmp/api.php', // 数据上报接口域名 report: 'https://s.pthzwl.net/v2/sdkapi.php?jy_platform=wx_min_game', // 数据上报接口域名(新)
appid: "wx953104af9b9484c8", // 换openid appid: "wx953104af9b9484c8", // 换openid
...@@ -18,7 +18,7 @@ const SDKConfig = { ...@@ -18,7 +18,7 @@ const SDKConfig = {
appVersion: "产品版本号(cp)", // 产品版本号 appVersion: "产品版本号(cp)", // 产品版本号
offerid: "1450018223", // 支付 offerid: "1450018223", // 支付offerid
midasPayEnv: '1', // 米大师支付环境 0:正式环境, 1:沙盒模式 midasPayEnv: '1', // 米大师支付环境 0:正式环境, 1:沙盒模式
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论