| |
| |
| |
|
|
| |
|
|
| export interface ConfigFieldDef { |
| key: string |
| label: string |
| sensitive: boolean |
| optional?: boolean |
| clearable?: boolean |
| defaultValue?: string |
| hintKey?: string |
| options?: TypeOption[] |
| } |
|
|
| export interface TypeOption { |
| value: string |
| label: string |
| [key: string]: unknown |
| } |
|
|
| |
| export interface CallbackPaths { |
| notifyUrl?: string |
| returnUrl?: string |
| } |
|
|
| |
|
|
| |
| export const PROVIDER_SUPPORTED_TYPES: Record<string, string[]> = { |
| easypay: ['alipay', 'wxpay'], |
| alipay: ['alipay'], |
| wxpay: ['wxpay'], |
| stripe: ['card', 'alipay', 'wxpay', 'link'], |
| airwallex: ['airwallex'], |
| } |
|
|
| |
| export const EASYPAY_PAYMENT_MODES = ['qrcode', 'popup'] as const |
|
|
| |
| export const METHOD_ORDER = ['alipay', 'alipay_direct', 'wxpay', 'wxpay_direct', 'stripe', 'airwallex'] as const |
|
|
| |
| export const PAYMENT_MODE_QRCODE = 'qrcode' |
| export const PAYMENT_MODE_POPUP = 'popup' |
| |
| |
| |
| |
| export const PAYMENT_MODE_REDIRECT = 'redirect' |
|
|
| export const PAYMENT_CURRENCY_OPTIONS: TypeOption[] = [ |
| { value: 'CNY', label: 'CNY' }, |
| { value: 'HKD', label: 'HKD' }, |
| { value: 'USD', label: 'USD' }, |
| { value: 'EUR', label: 'EUR' }, |
| { value: 'GBP', label: 'GBP' }, |
| { value: 'AUD', label: 'AUD' }, |
| { value: 'CAD', label: 'CAD' }, |
| { value: 'SGD', label: 'SGD' }, |
| { value: 'JPY', label: 'JPY' }, |
| { value: 'KRW', label: 'KRW' }, |
| { value: 'NZD', label: 'NZD' }, |
| ] |
|
|
| |
| export const STRIPE_SDK_API_VERSION = '2026-03-25.dahlia' |
|
|
| |
| |
| const PAYMENT_POPUP_PREFERRED_WIDTH = 1250 |
| const PAYMENT_POPUP_PREFERRED_HEIGHT = 900 |
|
|
| |
| |
| |
| export function getPaymentPopupFeatures(): string { |
| const screen = typeof window !== 'undefined' ? window.screen : null |
| const availW = screen?.availWidth ?? PAYMENT_POPUP_PREFERRED_WIDTH |
| const availH = screen?.availHeight ?? PAYMENT_POPUP_PREFERRED_HEIGHT |
| const width = Math.min(PAYMENT_POPUP_PREFERRED_WIDTH, availW - 40) |
| const height = Math.min(PAYMENT_POPUP_PREFERRED_HEIGHT, availH - 40) |
| const left = Math.max(0, Math.floor((availW - width) / 2)) |
| const top = Math.max(0, Math.floor((availH - height) / 2)) |
| return `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes` |
| } |
|
|
| |
| export const WEBHOOK_PATHS: Record<string, string> = { |
| easypay: '/api/v1/payment/webhook/easypay', |
| alipay: '/api/v1/payment/webhook/alipay', |
| wxpay: '/api/v1/payment/webhook/wxpay', |
| stripe: '/api/v1/payment/webhook/stripe', |
| airwallex: '/api/v1/payment/webhook/airwallex', |
| } |
|
|
| export const RETURN_PATH = '/payment/result' |
|
|
| |
| export const PROVIDER_CALLBACK_PATHS: Record<string, CallbackPaths> = { |
| easypay: { notifyUrl: WEBHOOK_PATHS.easypay, returnUrl: RETURN_PATH }, |
| alipay: { notifyUrl: WEBHOOK_PATHS.alipay, returnUrl: RETURN_PATH }, |
| wxpay: { notifyUrl: WEBHOOK_PATHS.wxpay }, |
| |
| |
| } |
|
|
| |
| export const PROVIDER_CONFIG_FIELDS: Record<string, ConfigFieldDef[]> = { |
| easypay: [ |
| { key: 'pid', label: 'PID', sensitive: false }, |
| { key: 'pkey', label: 'PKey', sensitive: true }, |
| { key: 'apiBase', label: '', sensitive: false }, |
| { key: 'cidAlipay', label: '', sensitive: false, optional: true }, |
| { key: 'cidWxpay', label: '', sensitive: false, optional: true }, |
| ], |
| alipay: [ |
| { key: 'appId', label: 'App ID', sensitive: false }, |
| { key: 'privateKey', label: '', sensitive: true }, |
| { key: 'publicKey', label: '', sensitive: true }, |
| ], |
| wxpay: [ |
| { key: 'appId', label: 'App ID', sensitive: false }, |
| { key: 'mchId', label: '', sensitive: false }, |
| { key: 'privateKey', label: '', sensitive: true }, |
| { key: 'apiV3Key', label: '', sensitive: true }, |
| { key: 'certSerial', label: '', sensitive: false }, |
| { key: 'publicKey', label: '', sensitive: true }, |
| { key: 'publicKeyId', label: '', sensitive: false }, |
| ], |
| stripe: [ |
| { key: 'secretKey', label: '', sensitive: true }, |
| { key: 'publishableKey', label: '', sensitive: false }, |
| { key: 'webhookSecret', label: '', sensitive: true }, |
| { key: 'currency', label: '', sensitive: false, defaultValue: 'CNY', hintKey: 'admin.settings.payment.field_paymentCurrencyHint', options: PAYMENT_CURRENCY_OPTIONS }, |
| ], |
| airwallex: [ |
| { key: 'clientId', label: '', sensitive: false }, |
| { key: 'apiKey', label: '', sensitive: true }, |
| { key: 'webhookSecret', label: '', sensitive: true }, |
| { key: 'apiBase', label: '', sensitive: false, defaultValue: 'https://api.airwallex.com/api/v1', hintKey: 'admin.settings.payment.field_airwallexApiBaseHint' }, |
| { key: 'countryCode', label: '', sensitive: false, defaultValue: 'CN' }, |
| { key: 'currency', label: '', sensitive: false, defaultValue: 'CNY', hintKey: 'admin.settings.payment.field_paymentCurrencyHint', options: PAYMENT_CURRENCY_OPTIONS }, |
| { key: 'accountId', label: '', sensitive: false, optional: true, clearable: true, hintKey: 'admin.settings.payment.field_accountIdHint' }, |
| ], |
| } |
|
|
| |
|
|
| |
| export function resolveTypeLabel( |
| typeVal: string, |
| _providerKey: string, |
| allTypes: TypeOption[], |
| _redirectLabel: string, |
| ): TypeOption { |
| return allTypes.find(pt => pt.value === typeVal) || { value: typeVal, label: typeVal } |
| } |
|
|
| |
| export function getAvailableTypes( |
| providerKey: string, |
| allTypes: TypeOption[], |
| redirectLabel: string, |
| ): TypeOption[] { |
| const types = PROVIDER_SUPPORTED_TYPES[providerKey] || [] |
| return types.map(t => resolveTypeLabel(t, providerKey, allTypes, redirectLabel)) |
| } |
|
|
| |
| export function extractBaseUrl(fullUrl: string, path: string): string { |
| if (!fullUrl) return '' |
| if (fullUrl.endsWith(path)) return fullUrl.slice(0, -path.length) |
| |
| try { return new URL(fullUrl).origin } catch { return fullUrl } |
| } |
|
|