Add independent PayPal hosted binding mode
This commit is contained in:
@@ -327,6 +327,7 @@
|
||||
<span class="data-label">Plus 支付</span>
|
||||
<div class="data-inline">
|
||||
<select id="select-plus-payment-method" class="data-select">
|
||||
<option value="paypal-hosted">PayPal 无卡直绑</option>
|
||||
<option value="paypal">PayPal</option>
|
||||
<!--
|
||||
<option value="gopay">GoPay</option>
|
||||
@@ -352,6 +353,22 @@
|
||||
<button id="btn-add-paypal-account" class="btn btn-outline btn-sm data-inline-btn" type="button">添加</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-row" id="row-hosted-checkout-verification-url" style="display:none;">
|
||||
<span class="data-label">直绑验证码</span>
|
||||
<input type="text" id="input-hosted-checkout-verification-url" class="data-input"
|
||||
placeholder="用于读取 PayPal / OpenAI 验证码的接口地址" autocomplete="off" />
|
||||
</div>
|
||||
<div class="data-row" id="row-hosted-checkout-phone" style="display:none;">
|
||||
<span class="data-label">直绑电话</span>
|
||||
<input type="text" id="input-hosted-checkout-phone" class="data-input"
|
||||
placeholder="PayPal guest checkout 使用的电话" autocomplete="tel" />
|
||||
</div>
|
||||
<div class="data-row" id="row-plus-hosted-checkout-oauth-delay" style="display:none;">
|
||||
<span class="data-label">成功等待</span>
|
||||
<input type="number" id="input-plus-hosted-checkout-oauth-delay-seconds" class="data-input auto-delay-input"
|
||||
value="3" min="0" max="120" step="1" />
|
||||
<span class="setting-caption">支付成功页出现后再继续账号接入</span>
|
||||
</div>
|
||||
<div class="data-row" id="row-gpc-helper-api" style="display:none;">
|
||||
<span class="data-label">GPC API</span>
|
||||
<div class="data-inline">
|
||||
|
||||
+99
-27
@@ -209,6 +209,12 @@ const btnPayPalAccountMenu = document.getElementById('btn-paypal-account-menu');
|
||||
const payPalAccountCurrent = document.getElementById('paypal-account-current');
|
||||
const payPalAccountMenu = document.getElementById('paypal-account-menu');
|
||||
const btnAddPayPalAccount = document.getElementById('btn-add-paypal-account');
|
||||
const rowHostedCheckoutVerificationUrl = document.getElementById('row-hosted-checkout-verification-url');
|
||||
const inputHostedCheckoutVerificationUrl = document.getElementById('input-hosted-checkout-verification-url');
|
||||
const rowHostedCheckoutPhone = document.getElementById('row-hosted-checkout-phone');
|
||||
const inputHostedCheckoutPhone = document.getElementById('input-hosted-checkout-phone');
|
||||
const rowPlusHostedCheckoutOauthDelay = document.getElementById('row-plus-hosted-checkout-oauth-delay');
|
||||
const inputPlusHostedCheckoutOauthDelaySeconds = document.getElementById('input-plus-hosted-checkout-oauth-delay-seconds');
|
||||
const rowGpcHelperApi = document.getElementById('row-gpc-helper-api');
|
||||
const inputGpcHelperApi = document.getElementById('input-gpc-helper-api');
|
||||
const btnGpcHelperConvertApiKey = document.getElementById('btn-gpc-helper-convert-api-key');
|
||||
@@ -545,13 +551,15 @@ const btnAutoStartContinue = document.getElementById('btn-auto-start-continue');
|
||||
const autoHintText = document.querySelector('.auto-hint');
|
||||
const stepsList = document.querySelector('.steps-list');
|
||||
const PLUS_PAYMENT_METHOD_PAYPAL = 'paypal';
|
||||
const PLUS_PAYMENT_METHOD_PAYPAL_HOSTED = 'paypal-hosted';
|
||||
const PLUS_PAYMENT_METHOD_GOPAY = 'gopay';
|
||||
const PLUS_PAYMENT_METHOD_GPC_HELPER = 'gpc-helper';
|
||||
const DEFAULT_GPC_HELPER_API_URL = 'https://gpc.qlhazycoder.top';
|
||||
const GPC_HELPER_PORTAL_URL = 'https://gpc.qlhazycoder.top/';
|
||||
const GPC_HELPER_PHONE_MODE_AUTO = 'auto';
|
||||
const GPC_HELPER_PHONE_MODE_MANUAL = 'manual';
|
||||
const DEFAULT_PLUS_PAYMENT_METHOD = PLUS_PAYMENT_METHOD_PAYPAL;
|
||||
const DEFAULT_PLUS_HOSTED_CHECKOUT_OAUTH_DELAY_SECONDS = 3;
|
||||
const DEFAULT_PLUS_PAYMENT_METHOD = PLUS_PAYMENT_METHOD_PAYPAL_HOSTED;
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH = 'oauth';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION = 'sub2api_codex_session';
|
||||
const PLUS_ACCOUNT_ACCESS_STRATEGY_CPA_CODEX_SESSION = 'cpa_codex_session';
|
||||
@@ -2939,13 +2947,25 @@ function normalizePlusPaymentMethod(value = '') {
|
||||
const gopayValue = typeof PLUS_PAYMENT_METHOD_GOPAY !== 'undefined' ? PLUS_PAYMENT_METHOD_GOPAY : 'gopay';
|
||||
const gpcValue = typeof PLUS_PAYMENT_METHOD_GPC_HELPER !== 'undefined' ? PLUS_PAYMENT_METHOD_GPC_HELPER : 'gpc-helper';
|
||||
const paypalValue = typeof PLUS_PAYMENT_METHOD_PAYPAL !== 'undefined' ? PLUS_PAYMENT_METHOD_PAYPAL : 'paypal';
|
||||
const paypalHostedValue = typeof PLUS_PAYMENT_METHOD_PAYPAL_HOSTED !== 'undefined' ? PLUS_PAYMENT_METHOD_PAYPAL_HOSTED : 'paypal-hosted';
|
||||
const normalized = String(value || '').trim().toLowerCase();
|
||||
if (normalized === paypalHostedValue || normalized === 'paypal_direct' || normalized === 'paypal-direct') {
|
||||
return paypalHostedValue;
|
||||
}
|
||||
if (normalized === gpcValue) {
|
||||
return gpcValue;
|
||||
}
|
||||
return normalized === gopayValue ? gopayValue : paypalValue;
|
||||
}
|
||||
|
||||
function normalizePlusHostedCheckoutOauthDelaySeconds(value) {
|
||||
const numeric = Number(String(value ?? '').trim());
|
||||
if (!Number.isFinite(numeric)) {
|
||||
return DEFAULT_PLUS_HOSTED_CHECKOUT_OAUTH_DELAY_SECONDS;
|
||||
}
|
||||
return Math.min(120, Math.max(0, Math.floor(numeric)));
|
||||
}
|
||||
|
||||
function normalizePlusAccountAccessStrategy(value = '') {
|
||||
const normalized = String(value || '').trim().toLowerCase();
|
||||
if (normalized === PLUS_ACCOUNT_ACCESS_STRATEGY_SUB2API_CODEX_SESSION) {
|
||||
@@ -4505,6 +4525,15 @@ function collectSettingsPayload() {
|
||||
const currentKiroRsKeyValue = typeof inputKiroRsKey !== 'undefined' && inputKiroRsKey
|
||||
? String(inputKiroRsKey.value ?? '').trim()
|
||||
: null;
|
||||
const normalizeHostedCheckoutDelaySecondsSafe = typeof normalizePlusHostedCheckoutOauthDelaySeconds === 'function'
|
||||
? normalizePlusHostedCheckoutOauthDelaySeconds
|
||||
: ((value) => {
|
||||
const numeric = Number(String(value ?? '').trim());
|
||||
if (!Number.isFinite(numeric)) {
|
||||
return 3;
|
||||
}
|
||||
return Math.min(120, Math.max(0, Math.floor(numeric)));
|
||||
});
|
||||
return {
|
||||
activeFlowId,
|
||||
...(accountContributionEnabled ? {} : {
|
||||
@@ -4562,6 +4591,17 @@ function collectSettingsPayload() {
|
||||
plusModeEnabled: effectivePlusModeEnabled,
|
||||
plusPaymentMethod,
|
||||
plusAccountAccessStrategy: requestedPlusAccountAccessStrategy,
|
||||
hostedCheckoutVerificationUrl: typeof inputHostedCheckoutVerificationUrl !== 'undefined' && inputHostedCheckoutVerificationUrl
|
||||
? String(inputHostedCheckoutVerificationUrl.value || '').trim()
|
||||
: String(latestState?.hostedCheckoutVerificationUrl || '').trim(),
|
||||
hostedCheckoutPhoneNumber: typeof inputHostedCheckoutPhone !== 'undefined' && inputHostedCheckoutPhone
|
||||
? String(inputHostedCheckoutPhone.value || '').trim()
|
||||
: String(latestState?.hostedCheckoutPhoneNumber || '').trim(),
|
||||
plusHostedCheckoutOauthDelaySeconds: normalizeHostedCheckoutDelaySecondsSafe(
|
||||
typeof inputPlusHostedCheckoutOauthDelaySeconds !== 'undefined' && inputPlusHostedCheckoutOauthDelaySeconds
|
||||
? inputPlusHostedCheckoutOauthDelaySeconds.value
|
||||
: latestState?.plusHostedCheckoutOauthDelaySeconds
|
||||
),
|
||||
paypalEmail: String(currentPayPalAccount?.email || latestState?.paypalEmail || '').trim(),
|
||||
paypalPassword: String(currentPayPalAccount?.password || latestState?.paypalPassword || ''),
|
||||
currentPayPalAccountId: String(latestState?.currentPayPalAccountId || '').trim(),
|
||||
@@ -9143,6 +9183,7 @@ function updatePhoneVerificationSettingsUI() {
|
||||
|
||||
function updatePlusModeUI() {
|
||||
const paypalValue = typeof PLUS_PAYMENT_METHOD_PAYPAL !== 'undefined' ? PLUS_PAYMENT_METHOD_PAYPAL : 'paypal';
|
||||
const paypalHostedValue = typeof PLUS_PAYMENT_METHOD_PAYPAL_HOSTED !== 'undefined' ? PLUS_PAYMENT_METHOD_PAYPAL_HOSTED : 'paypal-hosted';
|
||||
const gopayValue = typeof PLUS_PAYMENT_METHOD_GOPAY !== 'undefined' ? PLUS_PAYMENT_METHOD_GOPAY : 'gopay';
|
||||
const gpcValue = typeof PLUS_PAYMENT_METHOD_GPC_HELPER !== 'undefined' ? PLUS_PAYMENT_METHOD_GPC_HELPER : 'gpc-helper';
|
||||
const oauthStrategyValue = typeof PLUS_ACCOUNT_ACCESS_STRATEGY_OAUTH !== 'undefined'
|
||||
@@ -9259,6 +9300,7 @@ function updatePlusModeUI() {
|
||||
const selectedMethod = typeof selectPlusPaymentMethod !== 'undefined' && selectPlusPaymentMethod?.value
|
||||
? normalizePlusPaymentMethod(selectPlusPaymentMethod.value)
|
||||
: method;
|
||||
const hostedRowsVisible = enabled && selectedMethod === paypalHostedValue;
|
||||
const gpcRowsVisible = enabled && selectedMethod === gpcValue;
|
||||
const canShowGpcModeSelector = gpcRowsVisible;
|
||||
const localSmsControlsVisible = gpcRowsVisible && !isGpcAutoMode;
|
||||
@@ -9277,6 +9319,8 @@ function updatePlusModeUI() {
|
||||
? `GPC ${isGpcAutoMode ? '自动' : '手动'}订阅链路`
|
||||
: method === gopayValue
|
||||
? 'GoPay 印尼订阅链路'
|
||||
: method === paypalHostedValue
|
||||
? 'PayPal 无卡直绑链路'
|
||||
: 'PayPal 订阅链路';
|
||||
}
|
||||
if (typeof plusPaymentMethodCaption !== 'undefined' && plusPaymentMethodCaption && method === gpcValue && gpcAutoModeBlocked) {
|
||||
@@ -9335,12 +9379,35 @@ function updatePlusModeUI() {
|
||||
}
|
||||
}
|
||||
if (typeof plusAccountAccessStrategyCaption !== 'undefined' && plusAccountAccessStrategyCaption) {
|
||||
plusAccountAccessStrategyCaption.textContent = !enabled || !canEditPlusAccountAccessStrategy
|
||||
plusAccountAccessStrategyCaption.textContent = !enabled
|
||||
? '当前来源仅支持 OAuth'
|
||||
: describePlusAccountAccessStrategy(
|
||||
: ((effectivePlusAccountAccessStrategy !== oauthStrategyValue || canEditPlusAccountAccessStrategy)
|
||||
? describePlusAccountAccessStrategy(
|
||||
effectivePlusAccountAccessStrategy,
|
||||
effectiveTargetId
|
||||
);
|
||||
)
|
||||
: '当前来源仅支持 OAuth');
|
||||
}
|
||||
if (enabled && effectivePlusAccountAccessStrategy === sub2apiSessionStrategyValue) {
|
||||
[
|
||||
typeof rowSub2ApiUrl !== 'undefined' ? rowSub2ApiUrl : null,
|
||||
typeof rowSub2ApiEmail !== 'undefined' ? rowSub2ApiEmail : null,
|
||||
typeof rowSub2ApiPassword !== 'undefined' ? rowSub2ApiPassword : null,
|
||||
typeof rowSub2ApiGroup !== 'undefined' ? rowSub2ApiGroup : null,
|
||||
typeof rowSub2ApiAccountPriority !== 'undefined' ? rowSub2ApiAccountPriority : null,
|
||||
typeof rowSub2ApiDefaultProxy !== 'undefined' ? rowSub2ApiDefaultProxy : null,
|
||||
].forEach((row) => {
|
||||
if (row) row.style.display = '';
|
||||
});
|
||||
}
|
||||
if (enabled && effectivePlusAccountAccessStrategy === cpaSessionStrategyValue) {
|
||||
[
|
||||
typeof rowVpsUrl !== 'undefined' ? rowVpsUrl : null,
|
||||
typeof rowVpsPassword !== 'undefined' ? rowVpsPassword : null,
|
||||
typeof rowLocalCpaStep9Mode !== 'undefined' ? rowLocalCpaStep9Mode : null,
|
||||
].forEach((row) => {
|
||||
if (row) row.style.display = '';
|
||||
});
|
||||
}
|
||||
[
|
||||
typeof rowPayPalAccount !== 'undefined' ? rowPayPalAccount : null,
|
||||
@@ -9350,6 +9417,16 @@ function updatePlusModeUI() {
|
||||
}
|
||||
row.style.display = enabled && selectedMethod === paypalValue ? '' : 'none';
|
||||
});
|
||||
[
|
||||
typeof rowHostedCheckoutVerificationUrl !== 'undefined' ? rowHostedCheckoutVerificationUrl : null,
|
||||
typeof rowHostedCheckoutPhone !== 'undefined' ? rowHostedCheckoutPhone : null,
|
||||
typeof rowPlusHostedCheckoutOauthDelay !== 'undefined' ? rowPlusHostedCheckoutOauthDelay : null,
|
||||
].forEach((row) => {
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
row.style.display = hostedRowsVisible ? '' : 'none';
|
||||
});
|
||||
[
|
||||
typeof rowGpcHelperApi !== 'undefined' ? rowGpcHelperApi : null,
|
||||
typeof rowGpcHelperCardKey !== 'undefined' ? rowGpcHelperCardKey : null,
|
||||
@@ -10507,6 +10584,17 @@ function applySettingsState(state) {
|
||||
if (typeof inputGoPayPin !== 'undefined' && inputGoPayPin) {
|
||||
inputGoPayPin.value = state?.gopayPin || '';
|
||||
}
|
||||
if (typeof inputHostedCheckoutVerificationUrl !== 'undefined' && inputHostedCheckoutVerificationUrl) {
|
||||
inputHostedCheckoutVerificationUrl.value = String(state?.hostedCheckoutVerificationUrl || '').trim();
|
||||
}
|
||||
if (typeof inputHostedCheckoutPhone !== 'undefined' && inputHostedCheckoutPhone) {
|
||||
inputHostedCheckoutPhone.value = String(state?.hostedCheckoutPhoneNumber || '').trim();
|
||||
}
|
||||
if (typeof inputPlusHostedCheckoutOauthDelaySeconds !== 'undefined' && inputPlusHostedCheckoutOauthDelaySeconds) {
|
||||
inputPlusHostedCheckoutOauthDelaySeconds.value = String(
|
||||
normalizePlusHostedCheckoutOauthDelaySeconds(state?.plusHostedCheckoutOauthDelaySeconds)
|
||||
);
|
||||
}
|
||||
inputVpsUrl.value = state?.vpsUrl || '';
|
||||
inputVpsPassword.value = state?.vpsPassword || '';
|
||||
setLocalCpaStep9Mode(state?.localCpaStep9Mode);
|
||||
@@ -14660,6 +14748,9 @@ inputVpsPassword.addEventListener('blur', () => {
|
||||
scheduleSettingsAutoSave();
|
||||
});
|
||||
input?.addEventListener('blur', () => {
|
||||
if (input === inputPlusHostedCheckoutOauthDelaySeconds) {
|
||||
input.value = String(normalizePlusHostedCheckoutOauthDelaySeconds(input.value));
|
||||
}
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
});
|
||||
@@ -14721,29 +14812,6 @@ inputPlusModeEnabled?.addEventListener('change', () => {
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
selectPlusPaymentMethod?.addEventListener('change', () => {
|
||||
selectPlusPaymentMethod.value = normalizePlusPaymentMethod(selectPlusPaymentMethod.value);
|
||||
updatePlusModeUI();
|
||||
const stepDefinitionState = typeof resolveStepDefinitionCapabilityState === 'function'
|
||||
? resolveStepDefinitionCapabilityState({
|
||||
...(latestState || {}),
|
||||
plusModeEnabled: Boolean(inputPlusModeEnabled?.checked),
|
||||
signupMethod: getSelectedSignupMethod(),
|
||||
}, {
|
||||
signupMethod: getSelectedSignupMethod(),
|
||||
})
|
||||
: {
|
||||
plusModeEnabled: Boolean(inputPlusModeEnabled?.checked),
|
||||
signupMethod: getSelectedSignupMethod(),
|
||||
};
|
||||
syncStepDefinitionsForMode(stepDefinitionState.plusModeEnabled, selectPlusPaymentMethod.value, {
|
||||
render: true,
|
||||
signupMethod: stepDefinitionState.signupMethod,
|
||||
});
|
||||
markSettingsDirty(true);
|
||||
saveSettings({ silent: true }).catch(() => { });
|
||||
});
|
||||
|
||||
btnGpcCardKeyPurchase?.addEventListener('click', () => {
|
||||
openExternalUrl('https://pay.ldxp.cn/shop/gpc');
|
||||
});
|
||||
@@ -14842,6 +14910,7 @@ btnTestKiroRs?.addEventListener('click', async () => {
|
||||
});
|
||||
|
||||
selectPlusPaymentMethod?.addEventListener('change', () => {
|
||||
selectPlusPaymentMethod.value = normalizePlusPaymentMethod(selectPlusPaymentMethod.value);
|
||||
updatePlusModeUI();
|
||||
const stepDefinitionState = typeof resolveStepDefinitionCapabilityState === 'function'
|
||||
? resolveStepDefinitionCapabilityState({
|
||||
@@ -14878,6 +14947,9 @@ selectPlusPaymentMethod?.addEventListener('change', () => {
|
||||
inputGoPayPhone,
|
||||
inputGoPayOtp,
|
||||
inputGoPayPin,
|
||||
inputHostedCheckoutVerificationUrl,
|
||||
inputHostedCheckoutPhone,
|
||||
inputPlusHostedCheckoutOauthDelaySeconds,
|
||||
].forEach((input) => {
|
||||
input?.addEventListener('input', () => {
|
||||
markSettingsDirty(true);
|
||||
|
||||
Reference in New Issue
Block a user