4ce4486b26
新增 IndexedDB 与最近文件 L1 缓存、云保存/打开链路;首页支持下载与清空本地缓存;修复清空 storage 后语言初始化报错;优化 design2 背景加载与侧栏标签样式;完善会员激活/支付弹层样式;后端补充文件缩略图字段与 thumb 接口。 Co-authored-by: Cursor <cursoragent@cursor.com>
547 lines
20 KiB
JavaScript
547 lines
20 KiB
JavaScript
(function () {
|
||
'use strict';
|
||
|
||
var POLL_TIMEOUT_MS = 5 * 60 * 1000;
|
||
var PAY_STEP_LABELS = ['选择支付', '扫码付款', '激活生效'];
|
||
var _displayChannels = ['alipay'];
|
||
var _settingsPromise = null;
|
||
|
||
var CHANNEL_UI = {
|
||
alipay: { name: '支付宝', hint: '网页支付', icon: '支', iconCls: 'alipay' },
|
||
wechat: { name: '微信支付', hint: '扫码付款', icon: '微', iconCls: 'wechat' },
|
||
};
|
||
|
||
function esc(s) {
|
||
if (s == null) return '';
|
||
return String(s)
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"');
|
||
}
|
||
|
||
function apiBase() {
|
||
var cfg = (typeof window !== 'undefined' && window.SOON_DEPLOY_CONFIG && window.SOON_DEPLOY_CONFIG.api_v1_base);
|
||
if (cfg) return String(cfg).replace(/\/+$/, '');
|
||
if (typeof window !== 'undefined' && window.location) {
|
||
return window.location.origin + '/api/v1';
|
||
}
|
||
return '/api/v1';
|
||
}
|
||
|
||
function apiFetch(url, opts) {
|
||
if (typeof window.soonAuthedFetch === 'function') return window.soonAuthedFetch(url, opts || {});
|
||
opts = opts || {};
|
||
var token = localStorage.getItem('soon_access') || '';
|
||
opts.headers = Object.assign({}, opts.headers || {});
|
||
if (token) opts.headers.Authorization = 'Bearer ' + token;
|
||
return fetch(url, opts);
|
||
}
|
||
|
||
function parseApiJson(r) {
|
||
return r.text().then(function (text) {
|
||
try {
|
||
return JSON.parse(text);
|
||
} catch (e) {
|
||
return { ok: false, message: '服务暂时不可用,请稍后重试' };
|
||
}
|
||
});
|
||
}
|
||
|
||
function apiGet(p) {
|
||
return apiFetch(apiBase() + p).then(function (r) {
|
||
if (!r.ok && r.status === 401) return { ok: false, message: '未登录或会话已过期' };
|
||
return parseApiJson(r);
|
||
});
|
||
}
|
||
|
||
function apiPost(p, body) {
|
||
return apiFetch(apiBase() + p, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify(body || {}),
|
||
}).then(function (r) {
|
||
if (!r.ok && r.status === 401) return { ok: false, message: '未登录或会话已过期' };
|
||
return parseApiJson(r);
|
||
});
|
||
}
|
||
|
||
function isSafeAlipayGateway(url) {
|
||
if (!url || typeof url !== 'string') return false;
|
||
try {
|
||
var u = new URL(url);
|
||
return u.protocol === 'https:'
|
||
&& (u.hostname === 'openapi.alipay.com' || u.hostname === 'openapi.alipaydev.com');
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
function submitAlipayForm(payForm) {
|
||
if (!payForm || !payForm.gateway || !payForm.params) return false;
|
||
if (!isSafeAlipayGateway(payForm.gateway)) return false;
|
||
var form = document.createElement('form');
|
||
form.method = 'POST';
|
||
form.action = payForm.gateway;
|
||
form.acceptCharset = 'UTF-8';
|
||
form.style.display = 'none';
|
||
Object.keys(payForm.params).forEach(function (key) {
|
||
var val = payForm.params[key];
|
||
if (val == null || val === '') return;
|
||
var input = document.createElement('input');
|
||
input.type = 'hidden';
|
||
input.name = key;
|
||
input.value = String(val);
|
||
form.appendChild(input);
|
||
});
|
||
document.body.appendChild(form);
|
||
form.submit();
|
||
return true;
|
||
}
|
||
|
||
function parseDisplayChannels(raw) {
|
||
if (Array.isArray(raw)) {
|
||
var list = raw.filter(function (ch) { return ch === 'alipay' || ch === 'wechat'; });
|
||
return list.length ? list : ['alipay'];
|
||
}
|
||
var parts = String(raw || 'alipay').split(/[\s,]+/).filter(Boolean);
|
||
var out = [];
|
||
parts.forEach(function (ch) {
|
||
if ((ch === 'alipay' || ch === 'wechat') && out.indexOf(ch) < 0) out.push(ch);
|
||
});
|
||
return out.length ? out : ['alipay'];
|
||
}
|
||
|
||
function loadDisplayChannels() {
|
||
if (_settingsPromise) return _settingsPromise;
|
||
_settingsPromise = apiGet('/settings').then(function (j) {
|
||
if (j.ok && j.data) {
|
||
if (j.data.payment_display_channels) {
|
||
_displayChannels = parseDisplayChannels(j.data.payment_display_channels);
|
||
} else if (j.data['payment.display_channels'] != null) {
|
||
_displayChannels = parseDisplayChannels(j.data['payment.display_channels']);
|
||
}
|
||
}
|
||
return _displayChannels;
|
||
}).catch(function () {
|
||
_displayChannels = ['alipay'];
|
||
return _displayChannels;
|
||
});
|
||
return _settingsPromise;
|
||
}
|
||
|
||
function displayChannels() {
|
||
return _displayChannels.slice();
|
||
}
|
||
|
||
function defaultChannel(channels) {
|
||
var list = channels || _displayChannels;
|
||
return list[0] || 'alipay';
|
||
}
|
||
|
||
function resolveChannel(requested, channels) {
|
||
var list = channels || _displayChannels;
|
||
if (requested && list.indexOf(requested) >= 0) return requested;
|
||
return defaultChannel(list);
|
||
}
|
||
|
||
function channelCardHtml(ch, active, selectable) {
|
||
var ui = CHANNEL_UI[ch];
|
||
if (!ui) return '';
|
||
var cls = 'soon-pay-channel' + (active ? ' is-active' : '') + (selectable ? '' : ' is-fixed');
|
||
var inner = '<span class="soon-pay-channel__radio" aria-hidden="true"></span>' +
|
||
'<span class="soon-pay-channel__icon soon-pay-channel__icon--' + ui.iconCls + '">' + ui.icon + '</span>' +
|
||
'<span class="soon-pay-channel__text"><span class="soon-pay-channel__name">' + ui.name + '</span>' +
|
||
'<span class="soon-pay-channel__hint">' + ui.hint + '</span></span>';
|
||
if (selectable) {
|
||
return '<button type="button" class="' + cls + '" data-ch="' + ch + '">' + inner + '</button>';
|
||
}
|
||
return '<div class="' + cls + '" data-ch="' + ch + '">' + inner + '</div>';
|
||
}
|
||
|
||
function payChannelsHtml(activeChannel, channels, opts) {
|
||
opts = opts || {};
|
||
channels = channels || _displayChannels;
|
||
var showChannel = activeChannel || defaultChannel(channels);
|
||
var selectable = opts.selectable !== false && channels.length > 1;
|
||
var list = selectable ? channels : [showChannel];
|
||
var cards = list.map(function (ch) {
|
||
return channelCardHtml(ch, ch === showChannel, selectable);
|
||
}).join('');
|
||
if (!cards) return '';
|
||
return '<section class="soon-pay-section soon-pay-section--channels' +
|
||
(selectable ? '' : ' soon-pay-section--channels-fixed') + '" id="payChannels">' +
|
||
'<h4 class="soon-pay-section__title">支付方式</h4>' +
|
||
'<div class="soon-pay-channels' + (list.length === 1 ? ' soon-pay-channels--single' : '') + '">' +
|
||
cards + '</div></section>';
|
||
}
|
||
|
||
function payStepLabel(step, channel) {
|
||
if (step === 2 && channel === 'alipay') return '网页支付';
|
||
if (step === 2 && channel === 'wechat') return '扫码付款';
|
||
return PAY_STEP_LABELS[step - 1];
|
||
}
|
||
|
||
function payStepperHtml(activeStep, channel) {
|
||
var parts = [];
|
||
for (var i = 1; i <= 3; i++) {
|
||
if (i > 1) {
|
||
var bridgeCls = 'soon-pay-stepper__bridge';
|
||
if (i - 1 < activeStep) bridgeCls += ' is-done';
|
||
parts.push('<li class="' + bridgeCls + '" aria-hidden="true"></li>');
|
||
}
|
||
var cls = 'soon-pay-stepper__item';
|
||
if (i < activeStep) cls += ' is-done';
|
||
else if (i === activeStep) cls += ' is-active';
|
||
parts.push('<li class="' + cls + '">' +
|
||
'<span class="soon-pay-stepper__dot">' + (i < activeStep ? '✓' : String(i)) + '</span>' +
|
||
'<span class="soon-pay-stepper__label">' + payStepLabel(i, channel) + '</span></li>');
|
||
}
|
||
return '<ol class="soon-pay-stepper" id="payStepper">' + parts.join('') + '</ol>';
|
||
}
|
||
|
||
function updatePayStep(root, step, channel) {
|
||
if (!root) return;
|
||
var html = payStepperHtml(step, channel || defaultChannel());
|
||
var old = root.querySelector('#payStepper');
|
||
if (old) old.outerHTML = html;
|
||
}
|
||
|
||
function payEmptyStateHtml(channel) {
|
||
var ui = CHANNEL_UI[channel] || CHANNEL_UI[defaultChannel()];
|
||
return '<div class="soon-pay-checkout-empty">' +
|
||
'<div class="soon-pay-checkout-empty__icon" aria-hidden="true">' +
|
||
'<svg viewBox="0 0 48 48" fill="none"><rect x="8" y="12" width="32" height="24" rx="4" stroke="currentColor" stroke-width="1.5"/>' +
|
||
'<path d="M8 20h32" stroke="currentColor" stroke-width="1.5"/>' +
|
||
'<circle cx="32" cy="30" r="3" fill="currentColor" opacity="0.5"/></svg></div>' +
|
||
'<p class="soon-pay-checkout-empty__title">等待生成付款信息</p>' +
|
||
'<p class="soon-pay-checkout-empty__desc">点击下方按钮,将使用' + esc(ui.name) + '(' + esc(ui.hint) + ')</p></div>';
|
||
}
|
||
|
||
function renderPayPayload(data, qrEl, orderNoEl) {
|
||
if (orderNoEl && data.order_no) {
|
||
orderNoEl.textContent = '订单号 ' + data.order_no;
|
||
orderNoEl.style.display = '';
|
||
}
|
||
if (data.pay_form && data.pay_form.gateway) {
|
||
if (!isSafeAlipayGateway(data.pay_form.gateway)) return '支付网关无效';
|
||
sessionStorage.setItem('soon_pay_return', '1');
|
||
var payForm = data.pay_form;
|
||
qrEl.innerHTML =
|
||
'<div class="soon-pay-checkout-ready soon-pay-checkout-ready--alipay">' +
|
||
'<div class="soon-pay-checkout-ready__brand soon-pay-checkout-ready__brand--alipay">支</div>' +
|
||
'<p class="soon-pay-checkout-ready__title">支付宝电脑网站支付</p>' +
|
||
'<p class="soon-pay-checkout-ready__desc">点击下方按钮跳转至支付宝收银台,支付完成后将自动返回</p>' +
|
||
'<button type="button" class="soon-btn soon-pay-checkout-ready__btn" id="goAlipay">前往支付宝付款</button></div>';
|
||
var alipayBtn = qrEl.querySelector('#goAlipay');
|
||
if (alipayBtn) {
|
||
alipayBtn.onclick = function () {
|
||
if (!submitAlipayForm(payForm)) {
|
||
if (typeof window.soonToast === 'function') {
|
||
window.soonToast('无法跳转支付宝,请检查支付配置', 'warn');
|
||
}
|
||
}
|
||
};
|
||
}
|
||
return '';
|
||
}
|
||
if (data.qrcode) {
|
||
qrEl.innerHTML =
|
||
'<div class="soon-pay-checkout-ready">' +
|
||
'<div class="soon-pay-checkout-ready__brand soon-pay-checkout-ready__brand--wechat">微</div>' +
|
||
'<p class="soon-pay-checkout-ready__title">微信扫码支付</p>' +
|
||
'<div class="soon-pay-checkout-ready__qr" id="payQrCanvas"></div>' +
|
||
'<p class="soon-pay-checkout-ready__desc">请使用微信扫一扫,有效期约 2 小时</p></div>';
|
||
if (typeof QRCode !== 'undefined') {
|
||
new QRCode(qrEl.querySelector('#payQrCanvas'), { text: data.qrcode, width: 188, height: 188 });
|
||
}
|
||
return '';
|
||
}
|
||
return '未获取到支付信息';
|
||
}
|
||
|
||
function paySheetHtml(opts) {
|
||
opts = opts || {};
|
||
var resumeOrderNo = opts.orderNo || null;
|
||
var channels = opts.displayChannels || _displayChannels;
|
||
var channel = (resumeOrderNo && opts.channel)
|
||
? opts.channel
|
||
: resolveChannel(opts.channel, channels);
|
||
var embedded = opts.variant === 'embedded';
|
||
var backBtn = !embedded && opts.showBack
|
||
? '<button type="button" class="soon-btn soon-btn--ghost soon-btn--sm soon-pay-sheet__back" id="payBack">返回选择方案</button>'
|
||
: '';
|
||
var headBlock = embedded ? '' :
|
||
'<header class="soon-pay-sheet__head">' +
|
||
'<div class="soon-pay-sheet__head-main">' +
|
||
'<span class="soon-pay-sheet__eyebrow">' + (resumeOrderNo ? '继续支付' : '确认激活') + '</span>' +
|
||
'<h3 class="soon-pay-sheet__title">' + esc(opts.planName || '') + '</h3>' +
|
||
'<p class="soon-pay-sheet__order" id="payOrderNo"' +
|
||
(resumeOrderNo ? '' : ' style="display:none"') + '>' +
|
||
(resumeOrderNo ? '订单号 ' + esc(resumeOrderNo) : '') + '</p></div>' +
|
||
'<div class="soon-pay-sheet__head-price">' +
|
||
'<span class="soon-pay-sheet__currency">¥</span>' +
|
||
'<span class="soon-pay-sheet__amount">' + esc(opts.priceDisplay || '') + '</span></div></header>';
|
||
var orderInBody = embedded
|
||
? '<p class="soon-pay-sheet__order soon-pay-sheet__order--inline" id="payOrderNo"' +
|
||
(resumeOrderNo ? '' : ' style="display:none"') + '>' +
|
||
(resumeOrderNo ? '订单号 ' + esc(resumeOrderNo) : '') + '</p>'
|
||
: '';
|
||
return '<div class="soon-pay-sheet' + (embedded ? ' soon-pay-sheet--embedded' : '') + '">' +
|
||
(backBtn ? '<div class="soon-pay-sheet__toolbar">' + backBtn + '</div>' : '') +
|
||
headBlock +
|
||
'<div class="soon-pay-sheet__body">' +
|
||
orderInBody +
|
||
payStepperHtml(1, channel) +
|
||
payChannelsHtml(channel, channels, { selectable: !resumeOrderNo && channels.length > 1 }) +
|
||
'<section class="soon-pay-section soon-pay-section--checkout">' +
|
||
'<div class="soon-pay-qr-panel" id="payQr">' + payEmptyStateHtml(channel) + '</div></section>' +
|
||
'<div class="soon-pay-sheet__foot">' +
|
||
'<p class="soon-pay-status" id="payStatus"></p>' +
|
||
'<button type="button" class="soon-btn soon-pay-sheet__cta" id="payConfirm">' +
|
||
(resumeOrderNo ? '继续支付' : '确认并支付') + '</button>' +
|
||
'<button type="button" class="soon-btn soon-btn--ghost soon-btn--sm soon-pay-sheet__cta soon-pay-sheet__cta--secondary" id="payManualRefresh" style="display:none">已完成支付,刷新状态</button>' +
|
||
'</div></div></div>';
|
||
}
|
||
|
||
function bindPaySheet(sheetRoot, opts) {
|
||
opts = opts || {};
|
||
var planId = opts.planId;
|
||
var resumeOrderNo = opts.orderNo || null;
|
||
var channels = opts.displayChannels || _displayChannels;
|
||
var channel = (resumeOrderNo && opts.channel)
|
||
? opts.channel
|
||
: resolveChannel(opts.channel, channels);
|
||
var onPaid = typeof opts.onPaid === 'function' ? opts.onPaid : function () {};
|
||
var pollTimer = null;
|
||
var pollStartedAt = 0;
|
||
var orderNo = resumeOrderNo;
|
||
var paymentReady = false;
|
||
|
||
if (!sheetRoot) return { destroy: function () {} };
|
||
|
||
var manualBtn = sheetRoot.querySelector('#payManualRefresh');
|
||
var statusEl = sheetRoot.querySelector('#payStatus');
|
||
var confirmBtn = sheetRoot.querySelector('#payConfirm');
|
||
var qrEl = sheetRoot.querySelector('#payQr');
|
||
var orderNoEl = sheetRoot.querySelector('#payOrderNo');
|
||
var backBtn = sheetRoot.querySelector('#payBack');
|
||
|
||
function setStatus(text, type) {
|
||
if (!statusEl) return;
|
||
statusEl.textContent = text || '';
|
||
statusEl.className = 'soon-pay-status' + (type ? ' soon-pay-status--' + type : '');
|
||
statusEl.style.display = text ? 'block' : 'none';
|
||
}
|
||
|
||
function setStep(step) {
|
||
updatePayStep(sheetRoot, step, channel);
|
||
sheetRoot.classList.toggle('soon-pay-sheet--checkout', step >= 2);
|
||
var chSec = sheetRoot.querySelector('#payChannels');
|
||
if (chSec) chSec.style.display = step >= 2 ? 'none' : '';
|
||
}
|
||
|
||
function stopPoll() {
|
||
if (pollTimer) {
|
||
clearInterval(pollTimer);
|
||
pollTimer = null;
|
||
}
|
||
}
|
||
|
||
function startPoll() {
|
||
stopPoll();
|
||
pollStartedAt = Date.now();
|
||
pollTimer = setInterval(function () {
|
||
if (Date.now() - pollStartedAt > POLL_TIMEOUT_MS) {
|
||
stopPoll();
|
||
setStatus('自动检测超时,如已支付请点击下方按钮', 'err');
|
||
return;
|
||
}
|
||
checkOrderStatus();
|
||
}, 3000);
|
||
}
|
||
|
||
function handlePaid() {
|
||
stopPoll();
|
||
setStep(3);
|
||
setStatus('支付成功,正在更新会员状态…', 'ok');
|
||
setTimeout(onPaid, 600);
|
||
}
|
||
|
||
function checkOrderStatus() {
|
||
if (!orderNo) return;
|
||
apiGet('/pay/orders/' + encodeURIComponent(orderNo)).then(function (st) {
|
||
if (st.ok && st.data && st.data.status === 'paid') handlePaid();
|
||
});
|
||
}
|
||
|
||
if (manualBtn) manualBtn.onclick = checkOrderStatus;
|
||
|
||
function resetPaymentView() {
|
||
paymentReady = false;
|
||
stopPoll();
|
||
setStep(1);
|
||
if (manualBtn) manualBtn.style.display = 'none';
|
||
if (confirmBtn) confirmBtn.style.display = '';
|
||
qrEl.innerHTML = payEmptyStateHtml(channel);
|
||
if (orderNoEl && !resumeOrderNo) {
|
||
orderNoEl.textContent = '';
|
||
orderNoEl.style.display = 'none';
|
||
}
|
||
setStatus('');
|
||
}
|
||
|
||
function applyCheckout(data) {
|
||
orderNo = data.order_no;
|
||
var err = renderPayPayload(data, qrEl, orderNoEl);
|
||
if (err) {
|
||
setStatus(err, 'err');
|
||
return;
|
||
}
|
||
paymentReady = true;
|
||
setStep(2);
|
||
if (confirmBtn) confirmBtn.style.display = 'none';
|
||
if (manualBtn) manualBtn.style.display = '';
|
||
setStatus('等待支付结果,完成后将自动刷新', 'ok');
|
||
startPoll();
|
||
}
|
||
|
||
function submitCheckout() {
|
||
if (confirmBtn) confirmBtn.disabled = true;
|
||
setStatus('正在生成付款信息…');
|
||
qrEl.innerHTML = '<div class="soon-pay-checkout-loading"><div class="soon-skeleton soon-skeleton--h200"></div>' +
|
||
'<p>正在连接支付渠道…</p></div>';
|
||
var req;
|
||
if (resumeOrderNo || orderNo) {
|
||
var existingNo = orderNo || resumeOrderNo;
|
||
req = apiPost('/pay/orders/' + encodeURIComponent(existingNo) + '/checkout', { channel: channel });
|
||
} else {
|
||
req = apiPost('/pay/orders', { plan_id: planId, channel: channel });
|
||
}
|
||
req.then(function (j) {
|
||
if (confirmBtn) confirmBtn.disabled = false;
|
||
if (!j.ok) {
|
||
setStatus(j.message || '下单失败', 'err');
|
||
qrEl.innerHTML = payEmptyStateHtml(channel);
|
||
return;
|
||
}
|
||
applyCheckout(j.data);
|
||
}).catch(function () {
|
||
if (confirmBtn) confirmBtn.disabled = false;
|
||
setStatus('网络错误,请重试', 'err');
|
||
qrEl.innerHTML = payEmptyStateHtml(channel);
|
||
});
|
||
}
|
||
|
||
sheetRoot.querySelectorAll('.soon-pay-channel:not(.is-fixed)').forEach(function (el) {
|
||
el.onclick = function () {
|
||
if (el.classList.contains('is-active')) return;
|
||
sheetRoot.querySelectorAll('.soon-pay-channel').forEach(function (x) { x.classList.remove('is-active'); });
|
||
el.classList.add('is-active');
|
||
channel = el.dataset.ch;
|
||
if (paymentReady) resetPaymentView();
|
||
};
|
||
});
|
||
|
||
if (confirmBtn) confirmBtn.onclick = submitCheckout;
|
||
if (backBtn && typeof opts.onBack === 'function') backBtn.onclick = opts.onBack;
|
||
|
||
function destroy() {
|
||
stopPoll();
|
||
paymentReady = false;
|
||
orderNo = resumeOrderNo;
|
||
}
|
||
|
||
return {
|
||
destroy: destroy,
|
||
reset: resetPaymentView,
|
||
};
|
||
}
|
||
|
||
function openPayModal(opts) {
|
||
opts = opts || {};
|
||
if (typeof layer === 'undefined' || !layer.open) return null;
|
||
var channels = _displayChannels;
|
||
var channel = (opts.orderNo && opts.channel)
|
||
? opts.channel
|
||
: resolveChannel(opts.channel, channels);
|
||
var html = paySheetHtml({
|
||
planName: opts.planName,
|
||
priceDisplay: opts.priceDisplay,
|
||
orderNo: opts.orderNo,
|
||
channel: channel,
|
||
displayChannels: channels,
|
||
});
|
||
var payCtrl = null;
|
||
var width = Math.min(480, window.innerWidth - 32);
|
||
var idx = layer.open({
|
||
type: 1,
|
||
skin: 'soon-layer',
|
||
title: false,
|
||
closeBtn: 1,
|
||
fixed: true,
|
||
offset: 'auto',
|
||
shade: [0.72, '#000'],
|
||
shadeClose: !!opts.shadeClose,
|
||
maxWidth: width,
|
||
area: [width + 'px', 'auto'],
|
||
content: html,
|
||
success: function (layero, index) {
|
||
var layerEl = layero && layero[0] ? layero[0] : layero;
|
||
if (layerEl && layerEl.classList) {
|
||
layerEl.classList.add('soon-layer--pay');
|
||
var layerContent = layerEl.querySelector('.layui-layer-content');
|
||
if (layerContent) {
|
||
layerContent.style.padding = '0';
|
||
layerContent.style.overflow = 'visible';
|
||
layerContent.style.maxHeight = 'none';
|
||
layerContent.style.background = 'transparent';
|
||
}
|
||
}
|
||
var sheet = layerEl.querySelector('.soon-pay-sheet');
|
||
payCtrl = bindPaySheet(sheet, {
|
||
planId: opts.planId,
|
||
planName: opts.planName,
|
||
priceDisplay: opts.priceDisplay,
|
||
orderNo: opts.orderNo,
|
||
channel: channel,
|
||
displayChannels: channels,
|
||
onPaid: function () {
|
||
layer.close(idx);
|
||
if (typeof opts.onPaid === 'function') opts.onPaid();
|
||
},
|
||
onBack: opts.onBack,
|
||
});
|
||
requestAnimationFrame(function () {
|
||
if (typeof layer.style === 'function') layer.style(index);
|
||
});
|
||
},
|
||
end: function () {
|
||
if (payCtrl) payCtrl.destroy();
|
||
if (typeof opts.onClose === 'function') opts.onClose();
|
||
},
|
||
});
|
||
return idx;
|
||
}
|
||
|
||
loadDisplayChannels();
|
||
|
||
window.SoonMemberPay = {
|
||
apiBase: apiBase,
|
||
apiGet: apiGet,
|
||
apiPost: apiPost,
|
||
esc: esc,
|
||
paySheetHtml: paySheetHtml,
|
||
bindPaySheet: bindPaySheet,
|
||
openPayModal: openPayModal,
|
||
payEmptyStateHtml: payEmptyStateHtml,
|
||
renderPayPayload: renderPayPayload,
|
||
submitAlipayForm: submitAlipayForm,
|
||
loadDisplayChannels: loadDisplayChannels,
|
||
displayChannels: displayChannels,
|
||
defaultChannel: defaultChannel,
|
||
resolveChannel: resolveChannel,
|
||
POLL_TIMEOUT_MS: POLL_TIMEOUT_MS,
|
||
};
|
||
})();
|