|
|
@@ -1039,8 +1039,15 @@
|
|
|
*/
|
|
|
var API_BASE = 'https://test.ailien.shop/alienStore';
|
|
|
|
|
|
- /** 微信开放标签:移动应用 AppID(与 wx-open-launch-app appid 一致) */
|
|
|
+ /** 微信开放标签 wx-open-launch-app 的 appid(移动应用,与开放平台移动应用一致) */
|
|
|
var WECHAT_OPEN_APP_ID = 'wxff2fb6413a14a561';
|
|
|
+ /** 已知移动应用 AppID;getWxConfig 若只返回此类 id,不能用于 wx.config */
|
|
|
+ var WECHAT_KNOWN_MOBILE_APP_IDS = ['wxf5f1efe3a9f5012e', 'wxff2fb6413a14a561'];
|
|
|
+ /**
|
|
|
+ * wx.config 必须用公众号 AppID(服务号)。若后端在 data 里单独返回 mpAppId / officialAppId 会优先使用。
|
|
|
+ * 也可在分享链接加 ?wxMpAppId=wx公众号appid 临时联调(正式应由后端返回)。
|
|
|
+ */
|
|
|
+ var WECHAT_MP_APP_ID = '';
|
|
|
/**
|
|
|
* 进入页 GET {API_BASE}/wx/getWxConfig?url={页面地址,不含 query/hash}
|
|
|
* 例:.../wx/getWxConfig?url=https://test.ailien.shop/h5/HBuilderProjects/shareIndex.html
|
|
|
@@ -1220,12 +1227,39 @@
|
|
|
return H5_PAGE_BASE_FALLBACK + rel;
|
|
|
}
|
|
|
|
|
|
+ function isWeChatMobileAppId(appId) {
|
|
|
+ var id = String(appId || '').trim();
|
|
|
+ if (!id) return false;
|
|
|
+ for (var i = 0; i < WECHAT_KNOWN_MOBILE_APP_IDS.length; i++) {
|
|
|
+ if (id === WECHAT_KNOWN_MOBILE_APP_IDS[i]) return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ function resolveWxConfigAppIdFromSignData(d) {
|
|
|
+ if (!d || typeof d !== 'object') return '';
|
|
|
+ var mp =
|
|
|
+ d.mpAppId ||
|
|
|
+ d.mpAppid ||
|
|
|
+ d.officialAppId ||
|
|
|
+ d.officialAccountAppId ||
|
|
|
+ d.gzhAppId ||
|
|
|
+ d.serviceAppId;
|
|
|
+ if (mp != null && String(mp).trim() !== '') return String(mp).trim();
|
|
|
+ var fromQuery = String(q('wxMpAppId') || WECHAT_MP_APP_ID || '').trim();
|
|
|
+ if (fromQuery) return fromQuery;
|
|
|
+ var raw = d.appId || d.appid || d.wxAppId;
|
|
|
+ if (raw == null || String(raw).trim() === '') return '';
|
|
|
+ raw = String(raw).trim();
|
|
|
+ if (isWeChatMobileAppId(raw)) return '';
|
|
|
+ return raw;
|
|
|
+ }
|
|
|
+
|
|
|
function normalizeWxJssdkSignPayload(res) {
|
|
|
if (!res || typeof res !== 'object') return null;
|
|
|
var d = res.data != null && typeof res.data === 'object' ? res.data : res;
|
|
|
if (!d || typeof d !== 'object') return null;
|
|
|
- /** wx.config 必须用公众号 appId;不可用移动应用 WECHAT_OPEN_APP_ID 顶替 */
|
|
|
- var appId = d.appId || d.appid || d.wxAppId;
|
|
|
+ var appId = resolveWxConfigAppIdFromSignData(d);
|
|
|
var timestamp = d.timestamp != null ? d.timestamp : d.timeStamp;
|
|
|
var nonceStr = d.nonceStr || d.noncestr || d.nonce;
|
|
|
var signature = d.signature || d.sign;
|
|
|
@@ -1238,6 +1272,36 @@
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+ function formatWxConfigErrorTip(err, signPageUrl, rawAppId) {
|
|
|
+ var errMsg = '';
|
|
|
+ if (err && err.errMsg) errMsg = String(err.errMsg);
|
|
|
+ else if (typeof err === 'string') errMsg = err;
|
|
|
+ var tip = '微信 JSSDK 配置失败';
|
|
|
+ if (rawAppId && isWeChatMobileAppId(rawAppId)) {
|
|
|
+ return (
|
|
|
+ tip +
|
|
|
+ ':接口返回的 appId(' +
|
|
|
+ rawAppId +
|
|
|
+ ')是移动应用 ID。wx.config 必须使用公众号 AppID,请后端用公众号 AppSecret 签名并返回公众号 appId(或 data.mpAppId)。'
|
|
|
+ );
|
|
|
+ }
|
|
|
+ if (/invalid signature/i.test(errMsg)) {
|
|
|
+ return (
|
|
|
+ tip +
|
|
|
+ ':签名无效(invalid signature)。请确认后端签名使用的 url 与前端完全一致:' +
|
|
|
+ (signPageUrl || getWxConfigSignUrl())
|
|
|
+ );
|
|
|
+ }
|
|
|
+ if (/invalid appid/i.test(errMsg)) {
|
|
|
+ return tip + ':appId 无效,请使用已认证服务号的公众号 AppID。';
|
|
|
+ }
|
|
|
+ if (/invalid url/i.test(errMsg)) {
|
|
|
+ return tip + ':域名未在公众号 JS 接口安全域名中,或未在开放平台绑定域名与移动应用。';
|
|
|
+ }
|
|
|
+ if (errMsg) return tip + ':' + errMsg;
|
|
|
+ return tip + ',开放标签不可用。';
|
|
|
+ }
|
|
|
+
|
|
|
function fetchWeChatJssdkSign() {
|
|
|
var signPageUrl = getWxConfigSignUrl();
|
|
|
var urls = [];
|
|
|
@@ -1268,10 +1332,19 @@
|
|
|
}
|
|
|
}
|
|
|
var pack = normalizeWxJssdkSignPayload(res);
|
|
|
- if (!pack) throw new Error('empty sign payload');
|
|
|
+ if (!pack) {
|
|
|
+ var rd =
|
|
|
+ res.data != null && typeof res.data === 'object' ? res.data : res;
|
|
|
+ var rawId = rd && (rd.appId || rd.appid) ? String(rd.appId || rd.appid) : '';
|
|
|
+ if (rawId && isWeChatMobileAppId(rawId)) {
|
|
|
+ return Promise.reject({ mobileAppId: rawId });
|
|
|
+ }
|
|
|
+ throw new Error('empty sign payload');
|
|
|
+ }
|
|
|
return pack;
|
|
|
})
|
|
|
- .catch(function () {
|
|
|
+ .catch(function (err) {
|
|
|
+ if (err && err.mobileAppId) return Promise.reject(err);
|
|
|
return tryUrl(idx + 1);
|
|
|
});
|
|
|
}
|
|
|
@@ -1373,13 +1446,14 @@
|
|
|
}
|
|
|
bindWeChatLaunchTagEvents();
|
|
|
if (!sign) {
|
|
|
- console.warn('[wx] GET ' + WECHAT_GET_WX_CONFIG_PATH + ' failed — check url param or ?wxSignPath=');
|
|
|
+ console.warn('[wx] GET ' + WECHAT_GET_WX_CONFIG_PATH + ' — invalid sign for wx.config');
|
|
|
showAppOpenFailTip(
|
|
|
- '微信打开 App 需 GET /wx/getWxConfig 返回签名,当前未配置成功,无法使用「APP内打开」。'
|
|
|
+ formatWxConfigErrorTip(null, signPageUrl, 'wxf5f1efe3a9f5012e')
|
|
|
);
|
|
|
setFabLaunchMode('scheme');
|
|
|
return false;
|
|
|
}
|
|
|
+ console.log('[wx.config] appId=', sign.appId, 'signUrl=', signPageUrl);
|
|
|
return new Promise(function (resolve) {
|
|
|
wx.config({
|
|
|
debug: String(q('wxDebug') || '') === '1',
|
|
|
@@ -1387,7 +1461,7 @@
|
|
|
timestamp: sign.timestamp,
|
|
|
nonceStr: sign.nonceStr,
|
|
|
signature: sign.signature,
|
|
|
- jsApiList: [],
|
|
|
+ jsApiList: ['checkJsApi'],
|
|
|
openTagList: ['wx-open-launch-app']
|
|
|
});
|
|
|
wx.ready(function () {
|
|
|
@@ -1404,7 +1478,7 @@
|
|
|
wx.error(function (err) {
|
|
|
console.warn('[wx.config]', err);
|
|
|
weChatJssdkConfigured = false;
|
|
|
- showAppOpenFailTip('微信 JSSDK 配置失败,开放标签不可用。');
|
|
|
+ showAppOpenFailTip(formatWxConfigErrorTip(err, signPageUrl, ''));
|
|
|
setFabLaunchMode('scheme');
|
|
|
resolve(false);
|
|
|
});
|
|
|
@@ -1413,6 +1487,11 @@
|
|
|
.catch(function (e) {
|
|
|
console.warn('[wx] init failed', e);
|
|
|
if (inWx) {
|
|
|
+ if (e && e.mobileAppId) {
|
|
|
+ showAppOpenFailTip(
|
|
|
+ formatWxConfigErrorTip(null, signPageUrl, e.mobileAppId)
|
|
|
+ );
|
|
|
+ }
|
|
|
setFabLaunchMode('scheme');
|
|
|
}
|
|
|
return false;
|