diff --git a/.env b/.env index 9a2fa39e..0478c57c 100644 --- a/.env +++ b/.env @@ -3,7 +3,7 @@ # APP - 非微信小程序端跳转到微信小程序支付 # SHOPRO_BUILD_TARGET 为兼容旧配置的默认值,下面两项可分别覆盖支付宝和微信支付 SHOPRO_BUILD_TARGET=APP -SHOPRO_ALIPAY_BUILD_TARGET=H5 +SHOPRO_ALIPAY_BUILD_TARGET=APP SHOPRO_WECHAT_BUILD_TARGET=APP # 版本号 @@ -13,8 +13,8 @@ SHOPRO_VERSION=v2.4.1 SHOPRO_API_PATH=/app-api # 后端接口 - 测试环境(通过 process.env.NODE_ENV == development) -# SHOPRO_DEV_BASE_URL = https://api.htysapp.com -SHOPRO_DEV_BASE_URL=https://baac9a029ea84f36ba28c023fed4fc5f.hd.takin.cc +SHOPRO_DEV_BASE_URL = https://api.htysapp.com +# SHOPRO_DEV_BASE_URL=https://baac9a029ea84f36ba28c023fed4fc5f.hd.takin.cc # SHOPRO_DEV_BASE_URL=http://localhost:48083 # 后端接口 - 正式环境(通过 process.env.NODE_ENV != development) diff --git a/src/pages/profile/apply-vip.vue b/src/pages/profile/apply-vip.vue index f7f38314..e2784950 100644 --- a/src/pages/profile/apply-vip.vue +++ b/src/pages/profile/apply-vip.vue @@ -143,6 +143,7 @@ import sheep from '@/sheep'; import { jumpToWechatMiniProgram, wechatNavBack } from '@/sheep/util/wechat-tool'; import AuthUtil from '@/sheep/api/member/auth'; import appConfig from '@/sheep/config'; +import { openExternalUrl } from '@/sheep/platform/h5-shell'; const messageBox = useMessage(); const vipProtocolMessageBox = useMessage('vip-protocol-message-box'); @@ -400,12 +401,9 @@ const jumpToWechatPage = async () => { uni.showToast({ title: '获取小程序短链失败', icon: 'none' }); throw new Error('获取小程序短链失败'); } - // #ifdef H5 - window.location.href = url - // #endif - // #ifdef APP-PLUS - plus.runtime.openURL(url) - // #endif + if (!openExternalUrl(url, 'vip-mini-program')) { + uni.showToast({ title: '无法打开微信小程序', icon: 'none' }); + } } catch (error) { console.log('|跳转微信小程序|,意外的错误error:', error); } diff --git a/src/pages/profile/recharge.vue b/src/pages/profile/recharge.vue index dcf2d756..0e57b9bc 100644 --- a/src/pages/profile/recharge.vue +++ b/src/pages/profile/recharge.vue @@ -108,9 +108,10 @@ import { onLoad, onShow } from '@dcloudio/uni-app'; import sheep from '@/sheep'; // @ts-ignore import PayOrderApi from '@/sheep/api/pay/order'; -import { jumpToWechatMiniProgram, wechatNavBack } from '@/sheep/util/wechat-tool'; -import AuthUtil from '@/sheep/api/member/auth'; -import appConfig from '@/sheep/config'; +import { jumpToWechatMiniProgram, wechatNavBack } from '@/sheep/util/wechat-tool'; +import AuthUtil from '@/sheep/api/member/auth'; +import appConfig from '@/sheep/config'; +import { openExternalUrl } from '@/sheep/platform/h5-shell'; const messageBox = useMessage(); @@ -323,13 +324,10 @@ const jumpToWechatPage = async (packageId: any) => { uni.showToast({ title: '获取小程序短链失败', icon: 'none' }); throw new Error('获取小程序短链失败'); } - // #ifdef H5 - window.location.href = url - // #endif - // #ifdef APP-PLUS - plus.runtime.openURL(url) - // #endif - } catch (error) { + if (!openExternalUrl(url, 'recharge-mini-program')) { + uni.showToast({ title: '无法打开微信小程序', icon: 'none' }); + } + } catch (error) { console.log('|跳转微信小程序|,意外的错误error:', error); } }; diff --git a/src/sheep/api/member/social.js b/src/sheep/api/member/social.js index f852a4f7..f8e5a481 100644 --- a/src/sheep/api/member/social.js +++ b/src/sheep/api/member/social.js @@ -71,14 +71,22 @@ const SocialApi = { }, }); }, - // 获取微信小程短链 - getWxaQrcode: async (params) => { + // 获取微信小程序 URL Scheme + getWxaUrlScheme: async (params) => { return await request({ url: '/member/social-user/wxa-url-scheme', method: 'GET', params, }); }, + // 获取微信小程序 HTTPS URL Link + getWxaUrlLink: async (params) => { + return await request({ + url: '/member/social-user/wxa-url-link', + method: 'GET', + params, + }); + }, }; -export default SocialApi; \ No newline at end of file +export default SocialApi; diff --git a/src/sheep/platform/h5-shell.js b/src/sheep/platform/h5-shell.js index 6577a4a4..5fcf20fe 100644 --- a/src/sheep/platform/h5-shell.js +++ b/src/sheep/platform/h5-shell.js @@ -4,6 +4,65 @@ const H5_MAX_STATUS_BAR_HEIGHT = 200; let currentStatusBarHeight = H5_MIN_STATUS_BAR_HEIGHT; let statusBarStyleObserver = null; +// H5 产物运行在 5+ WebView 中时优先交给 App 打开,普通浏览器则在当前页跳转。 +export function openExternalUrl(url, source = 'unknown') { + const logPrefix = `[openExternalUrl][${source}]`; + if (!url) { + console.error(logPrefix, '跳转失败:URL 为空'); + return false; + } + + const hasGlobalThis = typeof globalThis !== 'undefined'; + const plusObject = hasGlobalThis ? globalThis.plus : null; + const runtime = plusObject?.runtime; + const currentUrl = typeof window !== 'undefined' ? window.location.href : ''; + console.log(logPrefix, '开始跳转', { + targetUrl: url, + currentUrl, + userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '', + documentReadyState: typeof document !== 'undefined' ? document.readyState : '', + hasWindow: typeof window !== 'undefined', + hasGlobalThis, + hasPlus: Boolean(plusObject), + hasPlusRuntime: Boolean(runtime), + hasPlusOpenURL: typeof runtime?.openURL === 'function', + }); + + if (runtime?.openURL) { + try { + console.log(logPrefix, '命中 5+ WebView,准备调用 plus.runtime.openURL'); + runtime.openURL(url, (error) => { + console.error(logPrefix, 'plus.runtime.openURL 错误回调', error); + }); + console.log(logPrefix, 'plus.runtime.openURL 已调用(该 API 无成功回调)'); + return true; + } catch (error) { + console.error(logPrefix, 'plus.runtime.openURL 抛出异常', error); + return false; + } + } + + if (typeof window !== 'undefined') { + try { + console.warn(logPrefix, '未检测到 plus.runtime.openURL,回退到 window.location.assign'); + window.location.assign(url); + console.log(logPrefix, 'window.location.assign 已调用'); + window.setTimeout(() => { + if (window.location.href === currentUrl) { + console.warn(logPrefix, '1.5 秒后页面 URL 未变化,跳转可能被 WebView 拦截'); + } + }, 1500); + return true; + } catch (error) { + console.error(logPrefix, 'window.location.assign 抛出异常', error); + return false; + } + } + + console.error(logPrefix, '跳转失败:window 和 plus.runtime 均不可用'); + return false; +} + // 将 URL 参数、宿主全局变量和 postMessage 消息中的高度统一转换为数字。 function normalizeStatusBarHeight(value) { if (value === undefined || value === null || value === '') { diff --git a/src/sheep/platform/pay.js b/src/sheep/platform/pay.js index a3d2ab57..74d81f3d 100644 --- a/src/sheep/platform/pay.js +++ b/src/sheep/platform/pay.js @@ -5,6 +5,7 @@ import $wxsdk from '@/sheep/libs/sdk-h5-weixin'; import { getRootUrl } from '@/sheep/helper'; import { h5Url } from '@/sheep/config'; import PayOrderApi from '@/sheep/api/pay/order'; +import { openExternalUrl } from './h5-shell'; /** * 支付 @@ -206,11 +207,8 @@ export default class SheepPay { } openH5PayUrl(url, title) { - // #ifdef H5 - window.location.href = url; - // #endif - // #ifdef APP-PLUS - plus.runtime.openURL(url); + // #ifndef MP + openExternalUrl(url, `h5-pay:${title}`); // #endif // #ifdef MP uni.showModal({ diff --git a/src/sheep/util/wechat-tool.ts b/src/sheep/util/wechat-tool.ts index e3507555..9ceda2d5 100644 --- a/src/sheep/util/wechat-tool.ts +++ b/src/sheep/util/wechat-tool.ts @@ -50,18 +50,35 @@ export const jumpToWechatMiniProgram = async ( if (!isEmpty(params)) { _params = paramsToQuery(params); console.log('|跳转微信小程序|参数_params:', _params); - } - try { - // 获取小程序短链 - const { code, data } = await SocialApi.getWxaQrcode({ - path: path, - json: _params, - }); - return data; - } catch (error) { - console.log('|获取小程序短链|意外的错误error:', error); - } -}; + } + try { + // HTTPS URL Link 可以在未注入 plus 的 App WebView 中作为普通网页打开。 + const { code, data } = await SocialApi.getWxaUrlLink({ + path: path, + json: _params, + }); + if (code === 0 && data) { + console.log('|跳转微信小程序|获取 URL Link 成功:', data); + return data; + } + console.warn('|跳转微信小程序|获取 URL Link 失败:', { code, data }); + } catch (error) { + console.error('|跳转微信小程序|获取 URL Link 异常:', error); + } + + try { + const { code, data } = await SocialApi.getWxaUrlScheme({ + path: path, + json: _params, + }); + if (code === 0 && data) { + console.warn('|跳转微信小程序|回退使用 URL Scheme:', data); + return data; + } + } catch (error) { + console.error('|跳转微信小程序|获取 URL Scheme 异常:', error); + } +}; // 商家转账用户确认模式下,拉起页面请求用户确认收款 Transfer export function requestMerchantTransfer(mchId, packageInfo, successCallback, failCallback) {