feat(forum): multi-gateway cashier for pay-visibility topics
Replace balance-only AJAX topic purchase with AKSRT_Topic_Pay REST cashier (resource orders + Payment_Gateway), reuse cms-download modal, and unlock on aksrt_order_paid.
This commit is contained in:
+36
-13
@@ -366,8 +366,13 @@
|
||||
};
|
||||
}
|
||||
|
||||
function buildPreviewUrl(postId, priceType, couponCode) {
|
||||
var previewUrl = REST_BASE + '/pay/content/' + postId;
|
||||
function payApiBase(apiKind) {
|
||||
return apiKind === 'topic' ? '/pay/topic/' : '/pay/content/';
|
||||
}
|
||||
|
||||
function buildPreviewUrl(postId, priceType, couponCode, apiKind) {
|
||||
apiKind = apiKind || 'content';
|
||||
var previewUrl = REST_BASE + payApiBase(apiKind) + postId;
|
||||
var qs = [];
|
||||
if (priceType) qs.push('price_type=' + encodeURIComponent(priceType));
|
||||
if (couponCode) qs.push('coupon_code=' + encodeURIComponent(couponCode));
|
||||
@@ -375,8 +380,8 @@
|
||||
return previewUrl;
|
||||
}
|
||||
|
||||
function fetchPreview(postId, priceType, couponCode) {
|
||||
return fetch(buildPreviewUrl(postId, priceType, couponCode), {
|
||||
function fetchPreview(postId, priceType, couponCode, apiKind) {
|
||||
return fetch(buildPreviewUrl(postId, priceType, couponCode, apiKind), {
|
||||
method: 'GET',
|
||||
credentials: 'same-origin',
|
||||
headers: restHeaders(),
|
||||
@@ -385,17 +390,18 @@
|
||||
});
|
||||
}
|
||||
|
||||
function openCashier(postId, returnFocusEl, priceType, couponCode) {
|
||||
function openCashier(postId, returnFocusEl, priceType, couponCode, apiKind) {
|
||||
if (!postId) return;
|
||||
priceType = priceType || '';
|
||||
couponCode = couponCode || '';
|
||||
apiKind = apiKind || 'content';
|
||||
open(
|
||||
'<h3 class="aksrt-dl-modal__title">' + tt('cashier_loading', '确认购买') + '</h3>' +
|
||||
'<p class="aksrt-dl-modal__msg">' + tt('loading', '加载中…') + '</p>',
|
||||
returnFocusEl
|
||||
);
|
||||
|
||||
fetchPreview(postId, priceType, couponCode)
|
||||
fetchPreview(postId, priceType, couponCode, apiKind)
|
||||
.then(function (r) {
|
||||
if (!r.ok || (r.json && r.json.code)) {
|
||||
const code = r.json && r.json.code ? r.json.code : '';
|
||||
@@ -418,6 +424,7 @@
|
||||
var prev = r.json || {};
|
||||
if (priceType) prev._price_type = priceType;
|
||||
if (couponCode) prev._coupon_code = couponCode;
|
||||
prev._api_kind = apiKind;
|
||||
renderCashier(prev, returnFocusEl);
|
||||
})
|
||||
.catch(function () {
|
||||
@@ -435,13 +442,19 @@
|
||||
renderError('', { vip_url: preview.vip_url }, returnFocusEl, 'aksrt_need_vip');
|
||||
return;
|
||||
}
|
||||
if (preview.has_paid_access || preview.is_free) {
|
||||
if (preview.has_paid_access) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
// Free VIP topics still need a free-order unlock POST; content free can reload.
|
||||
if (preview.is_free && preview.pay_type !== 'topic') {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
const isPoints = preview.pay_modo === 'points';
|
||||
const priceType = (preview._price_type || preview.price_type || '');
|
||||
const apiKind = preview._api_kind || (preview.pay_type === 'topic' ? 'topic' : 'content');
|
||||
let amountLabel = escapeHtml(preview.amount_label || '');
|
||||
let baseLabel = escapeHtml(preview.base_label || '');
|
||||
const listLabel = escapeHtml(preview.list_amount_label || preview.amount_label || amountLabel);
|
||||
@@ -541,7 +554,7 @@
|
||||
checkBtn.disabled = true;
|
||||
const old = checkBtn.innerHTML;
|
||||
checkBtn.innerHTML = tt('checking', '检查中…');
|
||||
fetchPreview(preview.post_id, priceType, code)
|
||||
fetchPreview(preview.post_id, priceType, code, apiKind)
|
||||
.then(function (r) {
|
||||
checkBtn.disabled = false;
|
||||
checkBtn.innerHTML = old;
|
||||
@@ -552,6 +565,7 @@
|
||||
var prev = r.json || {};
|
||||
if (priceType) prev._price_type = priceType;
|
||||
prev._coupon_code = code;
|
||||
prev._api_kind = apiKind;
|
||||
renderCashier(prev, returnFocusEl);
|
||||
})
|
||||
.catch(function () {
|
||||
@@ -571,13 +585,14 @@
|
||||
if (checked) paymentMethod = checked.value;
|
||||
const input = document.querySelector('input[name="aksrt_coupon_code"]');
|
||||
const code = input ? String(input.value || '').trim() : (preview.coupon_code || preview._coupon_code || '');
|
||||
submitPurchase(preview.post_id, mode, paymentMethod, submitBtn, returnFocusEl, code);
|
||||
submitPurchase(preview.post_id, mode, paymentMethod, submitBtn, returnFocusEl, code, apiKind);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function submitPurchase(postId, mode, paymentMethod, button, returnFocusEl, couponCode) {
|
||||
function submitPurchase(postId, mode, paymentMethod, button, returnFocusEl, couponCode, apiKind) {
|
||||
if (!postId) return;
|
||||
apiKind = apiKind || 'content';
|
||||
const original = button.innerHTML;
|
||||
button.disabled = true;
|
||||
button.innerHTML = tt('processing', '处理中…');
|
||||
@@ -588,7 +603,7 @@
|
||||
if (pt) payload.price_type = pt;
|
||||
if (mode === 'cash' && couponCode) payload.coupon_code = couponCode;
|
||||
|
||||
fetch(REST_BASE + '/pay/content/' + postId, {
|
||||
fetch(REST_BASE + payApiBase(apiKind) + postId, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: restHeaders(),
|
||||
@@ -643,6 +658,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const topicBuyBtn = e.target.closest('[data-aksrt-pay-topic]');
|
||||
if (topicBuyBtn) {
|
||||
e.preventDefault();
|
||||
const topicId = parseInt(topicBuyBtn.getAttribute('data-aksrt-pay-topic') || '0', 10);
|
||||
if (topicId) openCashier(topicId, topicBuyBtn, '', '', 'topic');
|
||||
return;
|
||||
}
|
||||
|
||||
const buyBtn = e.target.closest('[data-action="aksrt-need-purchase"], [data-aksrt-pay-content]');
|
||||
if (buyBtn) {
|
||||
e.preventDefault();
|
||||
@@ -654,7 +677,7 @@
|
||||
10
|
||||
);
|
||||
const priceType = buyBtn.getAttribute('data-price-type') || '';
|
||||
if (postId) openCashier(postId, buyBtn, priceType);
|
||||
if (postId) openCashier(postId, buyBtn, priceType, '', 'content');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -662,7 +685,7 @@
|
||||
if (cashierLink && cashierLink.hasAttribute('data-aksrt-pay-content')) {
|
||||
e.preventDefault();
|
||||
const postId = parseInt(cashierLink.getAttribute('data-aksrt-pay-content') || '0', 10);
|
||||
if (postId) openCashier(postId, cashierLink);
|
||||
if (postId) openCashier(postId, cashierLink, '', '', 'content');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -675,49 +675,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
function bindPurchaseButton(button) {
|
||||
button.addEventListener('click', function () {
|
||||
var topicId = parseInt(button.getAttribute('data-topic-id') || '0', 10);
|
||||
var price = button.getAttribute('data-price') || '0';
|
||||
var isFree = button.getAttribute('data-free') === '1';
|
||||
var feedback = button.parentElement ? button.parentElement.querySelector('.js-aksrt-action-feedback') : null;
|
||||
|
||||
if (!topicId) {
|
||||
return;
|
||||
}
|
||||
|
||||
var confirmMsg = isFree
|
||||
? '确认使用 VIP 免费解锁此主题?'
|
||||
: ('确认使用余额支付 ¥' + price + ' 购买此主题?');
|
||||
if (!window.confirm(confirmMsg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.disabled = true;
|
||||
setFeedback(feedback, isFree ? '正在解锁…' : '正在支付…', 'is-loading');
|
||||
|
||||
var data = new FormData();
|
||||
data.append('action', 'aksrt_forum_purchase_topic');
|
||||
data.append('topic_id', topicId);
|
||||
data.append('_nonce', rootData.forumNonce || '');
|
||||
|
||||
fetch((rootData.ajaxUrl || '/wp-admin/admin-ajax.php'), {
|
||||
method: 'POST',
|
||||
body: data,
|
||||
credentials: 'same-origin',
|
||||
}).then(function (r) { return r.json(); }).then(function (payload) {
|
||||
if (!payload.success) {
|
||||
throw new Error((payload.data && payload.data.message) || '购买失败');
|
||||
}
|
||||
setFeedback(feedback, '购买成功,正在刷新…', 'is-success');
|
||||
setTimeout(function () { window.location.reload(); }, 800);
|
||||
}).catch(function (error) {
|
||||
setFeedback(feedback, error.message || '购买失败', 'is-error');
|
||||
button.disabled = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function formatFollowPayLabel(pay) {
|
||||
pay = pay || {};
|
||||
if (pay.is_free) {
|
||||
@@ -1558,7 +1515,6 @@
|
||||
document.querySelectorAll('.js-aksrt-topic-score').forEach(bindScoreButton);
|
||||
document.querySelectorAll('.js-aksrt-adopt-answer').forEach(bindAdoptButton);
|
||||
document.querySelectorAll('.js-aksrt-unlock-topic').forEach(bindUnlockButton);
|
||||
document.querySelectorAll('.js-aksrt-purchase-topic').forEach(bindPurchaseButton);
|
||||
document.querySelectorAll('.js-aksrt-follow-plate').forEach(bindFollowPlateButton);
|
||||
bindForumCommentEngine();
|
||||
bindForumHomeTabs();
|
||||
|
||||
Reference in New Issue
Block a user