/** * OnePayment - Drop-in Payment Element (Web Component) * @element one-payment */ import { LitElement } from 'lit'; import type { Adapters, SDKConfig, State, PaymentMethodId, AppearanceOptions } from '@one-payments/core'; /** * Custom events emitted by this component */ export interface OnePaymentEvents { 'payment-success': CustomEvent<{ paymentIntentId: string; }>; 'payment-error': CustomEvent<{ error: string; }>; 'state-change': CustomEvent<{ state: State; }>; } /** * Main payment component - framework-agnostic web component with EXACT original design * * OnePayment is a drop-in payment element that handles the complete payment flow including * card payments, PayNow QR codes, 3D Secure authentication, and real-time status updates. * * @element one-payment * * @example * ```typescript * import '@one-payments/web-components'; * import { PaymentConfig } from '@one-payments/core'; * import { createWebAdapters } from '@one-payments/adapters'; * * const config = new PaymentConfig({ * apiKey: 'pk_test_...', * secretKey: 'sk_test_...', * environment: 'demo' * }); * * * ``` * * @fires payment-success - Emitted when payment succeeds, contains paymentIntentId * @fires payment-error - Emitted when payment fails, contains error message * @fires state-change - Emitted on every state change, contains full state object * * @public * @since 1.0.0 */ export declare class OnePayment extends LitElement { /** * SDK configuration object * * **RECOMMENDED**: Use the `PaymentConfig` class to create this configuration: * ```typescript * import { PaymentConfig } from '@one-payments/core'; * * const config = new PaymentConfig({ * apiKey: 'pk_test_...', * secretKey: 'sk_test_...', * environment: 'demo' * }); * ``` * * The config can also be a plain object: * ```typescript * const config = { * apiKey: 'pk_test_...', * secretKey: 'sk_test_...', * environment: 'demo' * }; * ``` * * **Required fields:** * - `apiKey` - Your One Payments public API key * - `secretKey` - Your One Payments secret key * - `environment` - 'prod', 'demo', or 'dev' * * **Optional fields:** * - `apiBaseUrl` - Custom API endpoint (defaults based on environment) * - `locale` - Language/locale code (e.g., 'en-US', 'zh-CN') * * @required * @type {SDKConfig | PaymentConfig} * @public */ config: SDKConfig; /** * Platform-specific adapters for HTTP and storage operations * * Adapters abstract platform differences (web, React Native, Node.js) so the * core SDK can work across all environments. * * **For web/browser environments:** * ```typescript * import { createWebAdapters } from '@one-payments/adapters'; * * * ``` * * **For React Native:** * ```typescript * import { createReactNativeAdapters } from '@one-payments/adapters'; * * * ``` * * @required * @type {Adapters} * @public */ adapters: Adapters; /** * Payment amount in smallest currency unit (cents/pence) * * **IMPORTANT**: Always provide amounts in the smallest currency unit: * - For USD/SGD/EUR: cents (e.g., 10000 = $100.00) * - For JPY/KRW: yen/won (e.g., 1000 = ¥1000) * * Examples: * - $10.00 USD = 1000 cents * - €25.50 EUR = 2550 cents * - ¥5000 JPY = 5000 yen * * The component will automatically format the display based on currency. * * @required * @type {number} * @public */ amount: number; /** * Three-letter ISO 4217 currency code * * Specifies the currency for the payment transaction. Must be a valid * ISO 4217 currency code (e.g., 'USD', 'EUR', 'SGD', 'GBP'). * * **Important currency-specific behavior:** * - PayNow is ONLY available for SGD (Singapore Dollars) * - Other payment methods work with most major currencies * * Common currency codes: * - USD - US Dollar * - EUR - Euro * - GBP - British Pound * - SGD - Singapore Dollar * - JPY - Japanese Yen * - AUD - Australian Dollar * - CAD - Canadian Dollar * * @required * @type {string} * @public */ currency: string; /** * Unique order/transaction identifier * * A unique identifier for this payment transaction from your system. * This ID is used to: * - Track the payment in your backend * - Prevent duplicate payments * - Reference the transaction in webhooks and API calls * * **Best practices:** * - Use a unique, non-sequential ID (e.g., UUID) * - Store this ID in your database before initiating payment * - Use the same format consistently across your system * * Example formats: * - `"order_abc123xyz"` * - `"txn_1234567890"` * - `"550e8400-e29b-41d4-a716-446655440000"` (UUID) * * @required * @type {string} * @public */ orderId: string; /** * Customer's first name (REQUIRED) * * The payer's first name or given name. This field is required for all * payment methods and is used for: * - Payment receipt generation * - Transaction records * - Fraud prevention and verification * * **Validation:** * - Cannot be empty or whitespace-only * - Must be provided before payment submission * * @required * @type {string} * @public */ firstName: string; /** * Customer's last name (REQUIRED) * * The payer's last name or family name. This field is required for all * payment methods and is used for: * - Payment receipt generation * - Transaction records * - Fraud prevention and verification * * **Validation:** * - Cannot be empty or whitespace-only * - Must be provided before payment submission * * @required * @type {string} * @public */ lastName: string; /** * Customer's email address (REQUIRED) * * The payer's email address. This field is required for all payment methods * and is used for: * - Sending payment receipts and confirmations * - Transaction notifications * - Customer communication * - Fraud prevention * * **Validation:** * - Cannot be empty or whitespace-only * - Must be provided before payment submission * - Should be a valid email format (validated by your application) * * @required * @type {string} * @public */ email: string; /** * Optional array of payment method IDs to exclude from display * * Use this to hide specific payment methods that you don't want to offer * for this transaction. The component will only show methods that are: * 1. Available from the API * 2. Not in this exclusion list * 3. Compatible with the transaction currency * * Available payment method IDs: * - `PAYMENT_METHODS.CARD` - Credit/debit cards * - `PAYMENT_METHODS.PAYNOW` - PayNow QR code (SGD only) * * Example: * ```typescript * import { PAYMENT_METHODS } from '@one-payments/core'; * * // Hide PayNow, only show cards * * ``` * * @optional * @type {PaymentMethodId[]} * @default undefined * @public */ excludePaymentMethods?: PaymentMethodId[]; /** * Optional custom width for the payment component * * Sets the width of the entire payment element. Can be any valid CSS width value. * * **Examples:** * - `"500px"` - Fixed pixel width * - `"100%"` - Full width of container * - `"50vw"` - 50% of viewport width * - `"auto"` - Automatic width based on content * * **Default:** `"100%"` (full width of container) * * **Note:** The component has a minimum width of 320px for proper mobile display. * * @optional * @type {string} * @default "100%" * @public */ width?: string; /** * Optional maximum width constraint for the payment component * * Sets the maximum width the payment element can grow to. Useful for * preventing the component from becoming too wide on large screens. * * **Examples:** * - `"600px"` - Max width of 600 pixels * - `"90%"` - Max 90% of container width * - `"1200px"` - Max width for large displays * * **Default:** `none` (no maximum width constraint) * * **Tip:** Combine with `width="100%"` for responsive layouts that don't * exceed a certain size: * ```typescript * * ``` * * @optional * @type {string} * @default "none" * @public */ maxWidth?: string; /** * Appearance customization options for theming and styling * * Allows customization of: * - `theme`: 'light' (default), 'dark', or 'auto' (follows system preference) * - `variables`: CSS custom property overrides for colors, fonts, spacing * * @example * ```html * * * * * * ``` * * @optional * @type {AppearanceOptions} * @public */ appearance?: AppearanceOptions; private currentState; private selectedMethod; private cardFormData; private formErrors; private paymentData; private feesExpanded; private isInitializing; private cardBrand; private paymentLocked; private show3DSModal; private showQRModal; private nextActionUrl; private qrCode; private qrCodeDataUrl; private qrAutoResumeTimer; private qrPollingInProgress; private availableBanks; private selectedBank; private banksLoading; private bankSearchQuery; private phoneInputValue; private phoneInputError; private selectedCountry; private sdk; private isInitialized; private cardNumberCleave; private expiryCleave; private leaveEventsCounter; private previousState; /** * Check if all required props are present and valid. * Used to determine if SDK initialization can proceed. * * This enables CDN/script-tag usage where props are set AFTER * the element is already in the DOM. */ private hasAllRequiredProps; /** * Check if a payment method requires phone number * Only these 5 methods require phone number: Boost, ShopeePay, Konbini, PayEasy, Atome */ private requiresPhoneNumber; /** * Check if phone number is available for payment * Returns true if the user has entered a valid number in the input field */ private hasPhoneNumber; /** * Check if the pay button should be disabled for a method */ private isPayButtonDisabled; /** * Map of appearance variable names to CSS custom property names */ private readonly cssVariableMap; /** * Media query listener for auto theme */ private themeMediaQuery; private themeMediaQueryHandler; /** * Apply appearance settings to the component * * This method: * 1. Sets the data-theme attribute based on theme option * 2. Applies CSS custom properties from variables * * @private */ private applyAppearance; /** * Apply CSS custom properties from variables object */ private applyCssVariables; /** * Setup listener for system theme changes (for theme: 'auto') */ private setupThemeMediaQueryListener; /** * Clean up theme media query listener */ private cleanupThemeMediaQueryListener; static styles: import("lit").CSSResult; connectedCallback(): void; firstUpdated(): void; /** * Called when any reactive property changes. * * This enables CDN/script-tag usage pattern where: * 1. Element is added to DOM with only HTML attributes * 2. Later, JavaScript sets config, adapters, and other props * * Without this, firstUpdated() runs before props are set, * causing permanent skeleton state. */ updated(changedProperties: Map): void; disconnectedCallback(): void; private handle3DSPostMessage; private setupCleave; private destroyCleave; /** * Get filtered payment methods * Applies filtering: * 1. API availability (from available-methods endpoint with currency filtering) * 2. User exclusions (excludePaymentMethods prop) * * Note: Currency validation is now handled server-side by the available-methods API */ private getFilteredPaymentMethods; private initializeSDK; private handleMethodSelect; private handleQRScanned; private handle3DSComplete; private handleInputChange; private luhnCheck; private validateExpiry; private validateCardForm; private handleCardPayment; private handlePayNowPayment; private handlePromptPayPayment; private handleDuitNowPayment; private handleGoPayPayment; private handleBoostPayment; private handleShopeePayPayment; private handleAtomPayment; private handleDanaPayment; private handleTngPayment; private handleAlipayCNPayment; private handleAlipayHKPayment; private handleGCashPayment; private handleKonbiniPayment; private handlePayEasyPayment; private handleGrabPaySGPayment; private handleFPXPayment; private handleWeChatPayPayment; /** * Fetch available banks for a payment method */ private fetchBanks; /** * Handle bank selection */ private handleBankSelect; /** * Get filtered banks based on search query */ private getFilteredBanks; /** * Minimum phone number length (digits only) */ private readonly MIN_PHONE_LENGTH; /** * Japan-only payment methods - phone must start with +81 * These methods require the country selector to be locked to Japan */ private readonly JAPAN_ONLY_PHONE_METHODS; /** * Country options for phone number selection * Uses ISO 3166-1 alpha-2 country codes (uppercase for libphonenumber-js) */ private readonly COUNTRY_OPTIONS; /** * Check if payment method requires Japan-only phone */ private isJapanOnlyPhoneMethod; /** * Get the full phone number with country code in international format * For display: "+81 90 1234 5678" * For API: depends on payment method */ private getFormattedPhoneWithCountryCode; /** * Get effective phone number for API submission * - Japan methods (konbini, payeasy): Convert +81 to local format (0XXXXXXXXXX) * - Other methods: Keep international format (+XX XXXX XXXX) */ private getEffectivePhoneNumber; /** * Format phone number for Japan (convert +81 to 0) * The Airwallex API for Japanese payment methods expects local format: * - Input: "+81 90 1234 5678" (international format) * - Output: "09012345678" (local format, no spaces) */ private formatPhoneForJapan; /** * Format names for Pay-Easy (max 9 chars combined) * Pay-easy has a unique requirement: combined first name + last name must be maximum 9 characters */ private formatNamesForPayEasy; /** * Format names for API submission (default: uppercase conversion) * All payment methods require names to be UPPERCASE */ private formatNamesUppercase; /** * Validate phone number input * Rules: * 1. Required - phone number cannot be empty * 2. Min 8 digits - must have at least 8 digits * 3. Japan prefix - for konbini/payeasy, must validate as Japan number * 4. Format - must be valid phone format */ private validatePhoneInput; /** * Handle phone input change with auto-formatting * Uses libphonenumber-js AsYouType formatter to format as user types */ private handlePhoneInputChange; /** * Handle country change */ private handleCountryChange; /** * Get the formatted pay amount for buttons (net amount including fees) */ private getPayButtonAmount; private getTransactionData; private renderTransactionDetailsSkeleton; private renderPaymentMethodsSkeleton; private renderSkeletons; private renderTransactionDetails; private renderCardForm; private renderPayNowContent; private renderPromptPayContent; private renderDuitNowContent; private renderGoPayContent; /** * Render phone number input for payment methods that require it * Matches react-phone-input-2 behavior: * - Country dropdown with flags and dial codes * - Auto-formatting based on country * - Japan-only lock for konbini/payeasy */ private renderPhoneInput; private renderBoostContent; private renderShopeePayContent; private renderAtomContent; private renderDanaContent; private renderTngContent; private renderAlipayCNContent; private renderAlipayHKContent; private renderGCashContent; private renderKonbiniContent; private renderPayEasyContent; private renderGrabPaySGContent; private renderFPXContent; private renderWeChatPayContent; private render3DSModal; private renderStatusBlock; render(): import("lit-html").TemplateResult<1>; } declare global { interface HTMLElementTagNameMap { 'one-payment': OnePayment; } } //# sourceMappingURL=one-payment.d.ts.map