嵌入模式识别
This commit is contained in:
@@ -3,6 +3,13 @@ let _defineConfig = {
|
||||
}
|
||||
|
||||
let _defConfig = {
|
||||
/**
|
||||
* iframe / 嵌入场景下是否把调用转发到父页面的同名 SDK(postMessage)。
|
||||
* - 'auto'(默认):只要处于子 frame(parent !== window)即转发,含 startScan 等均走父页逻辑
|
||||
* - true | 'on' | 'parent':在存在父 window 时强制转发
|
||||
* - false | 'off' | 'local':始终在本页执行(子页自己要跑扫码时用)
|
||||
*/
|
||||
embedProxyMode: 'auto',
|
||||
}
|
||||
|
||||
let _customConfig = {
|
||||
|
||||
40
src/services/embedEnvProbe.js
Normal file
40
src/services/embedEnvProbe.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 嵌入场景下由父页探测得到的微信环境结论(子页跨域时无法读 top UA)
|
||||
*/
|
||||
let parentWxEnvReport = null;
|
||||
|
||||
export function setParentWxEnvReport(wx) {
|
||||
parentWxEnvReport = wx ? true : false;
|
||||
}
|
||||
|
||||
export function getParentWxEnvReport() {
|
||||
return parentWxEnvReport;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在给定 window 上探测微信系 WebView(公众号 / 部分企业微信)
|
||||
* 与外层页面是否为同一套 SDK无关:依赖 UA / WeixinJSBridge
|
||||
*/
|
||||
export function readWxLikeEnvFromWindow(win) {
|
||||
if (!win) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const nav = win.navigator;
|
||||
if (nav) {
|
||||
const ua = nav.userAgent || "";
|
||||
if (/micromessenger/i.test(ua)) {
|
||||
return true;
|
||||
}
|
||||
if (/wxwork/i.test(ua)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (win.WeixinJSBridge) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
37
src/services/embedProxy.js
Normal file
37
src/services/embedProxy.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { getConfig } from "./config";
|
||||
|
||||
/** 是否存在可与 postMessage 交互的父 browsing context(自身不是顶层 opener/parent) */
|
||||
export function hasDistinctParentWindow() {
|
||||
if (typeof window === "undefined") {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return window.parent != null && window.parent !== window;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否通过父页面 SDK 代理执行(每次调用重新读取 config)
|
||||
*
|
||||
* embedProxyMode 为 auto(默认)时:只要 window.parent !== window(处于子 frame),
|
||||
* 所有对外 API(含 startScan)均走 postMessage 由父页同一套 SDK 执行,避免子页重复跑扫码逻辑。
|
||||
*/
|
||||
export function resolveUseParentProxy() {
|
||||
const mode = getConfig("embedProxyMode");
|
||||
if (mode === false || mode === "local" || mode === "off") {
|
||||
return false;
|
||||
}
|
||||
const parentOk = hasDistinctParentWindow();
|
||||
if (!parentOk) {
|
||||
return false;
|
||||
}
|
||||
if (mode === true || mode === "on" || mode === "parent") {
|
||||
return true;
|
||||
}
|
||||
if (mode === "auto" || mode === undefined || mode === null) {
|
||||
return parentOk;
|
||||
}
|
||||
return !!mode;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import { getConfig } from "../config";
|
||||
import { readWxLikeEnvFromWindow, getParentWxEnvReport } from "../embedEnvProbe";
|
||||
import { resolveUseParentProxy } from "../embedProxy";
|
||||
import { request } from "../../utils/request";
|
||||
import { toAny } from "../../utils/toany";
|
||||
|
||||
@@ -46,6 +48,27 @@ function loadWxScript() {
|
||||
});
|
||||
}
|
||||
|
||||
/** 微信 JS-SDK 签名 URL:嵌入且走父页代理时用父页地址(与微信内打开的页面一致);可配置 wxJssdkSignatureUrl 覆盖 */
|
||||
function getPageUrlForWxJssdkSignature() {
|
||||
const override = getConfig("wxJssdkSignatureUrl");
|
||||
if (override) {
|
||||
return String(override).split("#")[0];
|
||||
}
|
||||
if (resolveUseParentProxy()) {
|
||||
try {
|
||||
if (typeof window !== "undefined" && window.parent && window.parent !== window) {
|
||||
return window.parent.location.href.split("#")[0];
|
||||
}
|
||||
} catch (e) {
|
||||
// 跨域父页不可读 location,由调用方配置 wxJssdkSignatureUrl
|
||||
}
|
||||
}
|
||||
if (typeof window === "undefined") {
|
||||
return "";
|
||||
}
|
||||
return window.location.href.split("#")[0];
|
||||
}
|
||||
|
||||
function fetchWxConfig() {
|
||||
let initWechatJssdk = toAny(getConfig("initWechatJssdk"), {});
|
||||
if (!!initWechatJssdk.sdkConfig) {
|
||||
@@ -59,7 +82,7 @@ function fetchWxConfig() {
|
||||
url: apiUrl,
|
||||
method: "GET",
|
||||
data: {
|
||||
url: window.location.href.split("#")[0]
|
||||
url: getPageUrlForWxJssdkSignature()
|
||||
}
|
||||
}).then(res => {
|
||||
let data = toAny(res.data, {});
|
||||
@@ -77,8 +100,22 @@ function fetchWxConfig() {
|
||||
}
|
||||
|
||||
export function isWxEnv() {
|
||||
return typeof navigator !== "undefined"
|
||||
&& /micromessenger/i.test(navigator.userAgent || "");
|
||||
if (readWxLikeEnvFromWindow(typeof window !== "undefined" ? window : null)) {
|
||||
return true;
|
||||
}
|
||||
if (typeof window !== "undefined") {
|
||||
try {
|
||||
if (window.top && window.top !== window && readWxLikeEnvFromWindow(window.top)) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
// 跨域不可读 top:依赖父页 probeWxEnv / embedEnvProbe 缓存
|
||||
}
|
||||
}
|
||||
if (resolveUseParentProxy() && getParentWxEnvReport() === true) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isWxMiniProgramEnv() {
|
||||
@@ -88,11 +125,14 @@ export function isWxMiniProgramEnv() {
|
||||
|
||||
export function isSupportWxScan() {
|
||||
const wx = getWx();
|
||||
return isWxMiniProgramEnv()
|
||||
|| isWxEnv()
|
||||
&& _wxReady
|
||||
&& wx
|
||||
&& wx.scanQRCode;
|
||||
if (isWxMiniProgramEnv()) {
|
||||
return true;
|
||||
}
|
||||
// 嵌入且 API 走父页时,子页未必初始化 wx;只要识别为微信环境即视为支持(实际能力由父页 SDK 决定)
|
||||
if (resolveUseParentProxy() && isWxEnv()) {
|
||||
return true;
|
||||
}
|
||||
return !!(isWxEnv() && _wxReady && wx && wx.scanQRCode);
|
||||
}
|
||||
|
||||
export function initWxJssdk() {
|
||||
|
||||
Reference in New Issue
Block a user