payment-development
Payment Development Guide
This skill provides guidance for developers working with the @rytass/payments base package, including creating new payment adapters.
Overview
The @rytass/payments package defines the core interfaces and types that all payment adapters must implement. It follows the adapter pattern to provide a unified API across different Taiwan payment providers.
Architecture
@rytass/payments (Base Package)
│
├── PaymentGateway<OCM, O> # Gateway interface
├── Order<OCM> # Order entity interface
├── BindCardPaymentGateway<...> # Card binding interface (optional)
├── Enums & Types # Shared types
└── Event System # EventEmitter-based callbacks
@rytass/payments-adapter-* # Provider implementations
│
├── [Provider]Payment # Implements PaymentGateway
├── [Provider]Order # Implements Order
└── [Provider]BindCard # Implements card binding (optional)
Installation
npm install @rytass/payments
Core Interfaces
PaymentItem
Item included in an order:
interface PaymentItem {
name: string;
unitPrice: number;
quantity: number;
}
PaymentGateway
The main interface that all adapters must implement:
interface PaymentGateway<
OCM extends OrderCommitMessage = OrderCommitMessage,
O extends Order<OCM> = Order<OCM>,
> {
emitter: EventEmitter;
prepare<N extends OCM>(input: InputFromOrderCommitMessage<N>): Promise<Order<N>>;
query<OO extends O>(id: string, options?: unknown): Promise<OO>;
}
PrepareOrderInput
Base input interface for orders:
interface PrepareOrderInput<I extends PaymentItem = PaymentItem> {
items: I[];
}
Order
The order entity interface:
interface Order<OCM extends OrderCommitMessage> extends PrepareOrderInput {
state: OrderState;
createdAt: Date | null;
committedAt: Date | null;
additionalInfo?: AdditionalInfo<OCM>;
asyncInfo?: AsyncOrderInformation<OCM>;
failedMessage: OrderFailMessage | null;
id: string;
items: PaymentItem[];
committable: boolean;
infoRetrieved<T extends OCM>(asyncInformation: AsyncOrderInformation<T>): void;
fail(code: string, message: string): void;
commit<T extends OCM>(message: T, additionalInfo?: AdditionalInfo<T>): void;
refund(amount?: number, options?: unknown): Promise<void>;
}
InputFromOrderCommitMessage
Input type for creating orders via prepare():
interface InputFromOrderCommitMessage<OCM extends OrderCommitMessage> extends PrepareOrderInput {
id?: string;
shopName?: string;
clientBackUrl?: string;
cardType?: CardType;
}
BindCardRequest
Card binding request interface:
interface BindCardRequest {
cardId: string | undefined;
memberId: string;
}
CheckoutWithBoundCardOptions
Options for checkout with bound card:
interface CheckoutWithBoundCardOptions {
cardId: string; // 綁定的卡片 ID
memberId: string; // 綁定會員 ID
items: PaymentItem[];
orderId?: string; // 可選的訂單 ID,若未提供則自動生成
}
BindCardPaymentGateway (Optional)
For adapters supporting card binding:
interface BindCardPaymentGateway<
CM extends OrderCommitMessage = OrderCommitMessage,
R extends BindCardRequest = BindCardRequest,
O extends Order<CM> = Order<CM>,
> {
prepareBindCard(memberId: string): Promise<R>;
checkoutWithBoundCard(options: CheckoutWithBoundCardOptions): Promise<O>;
}
Quick Reference
Order Lifecycle
INITED
↓ prepare()
PRE_COMMIT (Created - form/URL ready)
↓ User completes payment
ASYNC_INFO_RETRIEVED (for ATM/CVS - virtual account/code ready)
↓ User pays at bank/CVS
COMMITTED (Payment successful)
↓ OR
FAILED (Payment failed)
↓ (optional)
REFUNDED (Refund processed)
Channel Enum (支付通道)
import { Channel } from '@rytass/payments';
enum Channel {
CREDIT_CARD = 'CREDIT_CARD', // 信用卡
WEB_ATM = 'WEB_ATM', // 網路 ATM
VIRTUAL_ACCOUNT = 'VIRTUAL_ACCOUNT', // 虛擬帳號
CVS_KIOSK = 'CVS_KIOSK', // 超商代碼繳費
CVS_BARCODE = 'CVS_BARCODE', // 超商條碼繳費
APPLE_PAY = 'APPLE_PAY', // Apple Pay
LINE_PAY = 'LINE_PAY', // LINE Pay
}
Payment Channels
| Channel | Description | Commit Type |
|---|---|---|
CREDIT_CARD |
Credit/Debit Card | Sync |
VIRTUAL_ACCOUNT |
ATM Virtual Account | Async |
WEB_ATM |
Online ATM | Async |
CVS_KIOSK |
Convenience Store Code | Async |
CVS_BARCODE |
Convenience Store Barcode | Async |
APPLE_PAY |
Apple Pay | Sync |
LINE_PAY |
LINE Pay | Sync |
OrderState Enum
enum OrderState {
INITED = 'INITED',
PRE_COMMIT = 'PRE_COMMIT', // Created
ASYNC_INFO_RETRIEVED = 'ASYNC_INFO_RETRIEVED', // Async Payment Information Retrieved (ATM/CVS/Barcode...)
COMMITTED = 'COMMITTED', // Fulfilled
FAILED = 'FAILED',
REFUNDED = 'REFUNDED',
}
| State | Description |
|---|---|
INITED |
Order initialized |
PRE_COMMIT |
Order created, awaiting payment |
ASYNC_INFO_RETRIEVED |
Async payment info ready (ATM/CVS) |
COMMITTED |
Payment successful |
FAILED |
Payment failed |
REFUNDED |
Order refunded |
OrderFailMessage
interface OrderFailMessage {
code: string;
message: string;
}
Card Types
import { CardType } from '@rytass/payments';
enum CardType {
VMJ = 'VMJ', // Visa, MasterCard, JCB
AE = 'AE', // American Express
}
CVS (便利商店)
import { CVS } from '@rytass/payments';
enum CVS {
FAMILY_MART = 'FAMILY_MART', // 全家
HILIFE = 'HILIFE', // 萊爾富
OK_MART = 'OK_MART', // OK 超商
SEVEN_ELEVEN = 'SEVEN_ELEVEN', // 7-11
}
CreditCardECI (3D 驗證結果)
import { CreditCardECI } from '@rytass/payments';
enum CreditCardECI {
MASTER_3D = '2', // MasterCard 3D 驗證成功
MASTER_3D_PART = '1', // MasterCard 部分驗證
MASTER_3D_FAILED = '0', // MasterCard 驗證失敗
VISA_AE_JCB_3D = '5', // Visa/AE/JCB 3D 驗證成功
VISA_AE_JCB_3D_PART = '6', // Visa/AE/JCB 部分驗證
VISA_AE_JCB_3D_FAILED = '7', // Visa/AE/JCB 驗證失敗
}
PaymentPeriod (定期定額)
import { PaymentPeriod, PaymentPeriodType } from '@rytass/payments';
enum PaymentPeriodType {
DAY = 'DAY', // 每日
MONTH = 'MONTH', // 每月
YEAR = 'YEAR', // 每年
}
interface PaymentPeriod {
amountPerPeriod: number; // 每期金額
type: PaymentPeriodType; // 週期類型
frequency?: number; // 頻率(可選)
times: number; // 扣款次數
}
Payment Events
enum PaymentEvents {
SERVER_LISTENED = 'LISTENED',
ORDER_INFO_RETRIEVED = 'INFO_RETRIEVED',
ORDER_PRE_COMMIT = 'PRE_COMMIT',
ORDER_COMMITTED = 'COMMITTED',
ORDER_FAILED = 'FAILED',
CARD_BOUND = 'CARD_BOUND',
CARD_BINDING_FAILED = 'CARD_BINDING_FAILED',
}
| Event | When Triggered |
|---|---|
SERVER_LISTENED |
Built-in server started |
ORDER_PRE_COMMIT |
Order created (form/URL ready) |
ORDER_INFO_RETRIEVED |
Async payment info ready |
ORDER_COMMITTED |
Payment successful |
ORDER_FAILED |
Payment failed |
CARD_BOUND |
Card bound successfully |
CARD_BINDING_FAILED |
Card binding failed |
Event Usage
import { PaymentEvents } from '@rytass/payments';
payment.emitter.on(PaymentEvents.ORDER_COMMITTED, (order) => {
console.log('Payment successful:', order.id);
});
payment.emitter.on(PaymentEvents.ORDER_FAILED, (order) => {
console.error('Payment failed:', order.failedMessage);
});
OrderCommitMessage Types
Base commit message and channel-specific types:
// Base commit message
interface OrderCommitMessage {
id: string;
totalPrice: number;
committedAt: Date | null;
}
// Credit Card
interface OrderCreditCardCommitMessage extends OrderCommitMessage {
type?: Channel.CREDIT_CARD;
id: string;
totalPrice: number;
committedAt: Date;
cardType?: CardType;
}
// Virtual Account (ATM)
interface OrderVirtualAccountCommitMessage extends OrderCommitMessage {
type?: Channel.VIRTUAL_ACCOUNT;
id: string;
totalPrice: number;
committedAt: Date | null;
}
// CVS Kiosk
interface OrderCVSCommitMessage extends OrderCommitMessage {
type?: Channel.CVS_KIOSK;
id: string;
totalPrice: number;
committedAt: Date | null;
}
// CVS Barcode
interface OrderBarcodeCommitMessage extends OrderCommitMessage {
type?: Channel.CVS_BARCODE;
id: string;
totalPrice: number;
committedAt: Date | null;
}
// Apple Pay
interface OrderApplePayCommitMessage extends OrderCommitMessage {
type?: Channel.APPLE_PAY;
id: string;
totalPrice: number;
committedAt: Date | null;
}
// LINE Pay
interface OrderLinePayCommitMessage extends OrderCommitMessage {
type?: Channel.LINE_PAY;
id: string;
totalPrice: number;
committedAt: Date | null;
}
// WebATM
interface OrderWebATMCommitMessage extends OrderCommitMessage {
type?: Channel.WEB_ATM;
id: string;
totalPrice: number;
committedAt: Date | null;
}
AsyncOrderInformation Type
Conditional type for async payment info based on commit message type:
type AsyncOrderInformation<OCM extends OrderCommitMessage> =
OCM extends OrderVirtualAccountCommitMessage
? VirtualAccountInfo
: OCM extends OrderCVSCommitMessage
? CVSInfo
: OCM extends OrderBarcodeCommitMessage
? BarcodeInfo
: never;
AdditionalInfo Type
Conditional type for additional payment info based on commit message type:
type AdditionalInfo<OCM extends OrderCommitMessage> =
OCM extends OrderCreditCardCommitMessage
? CreditCardAuthInfo
: OCM extends OrderVirtualAccountCommitMessage
? VirtualAccountPaymentInfo
: OCM extends OrderWebATMCommitMessage
? WebATMPaymentInfo
: OCM extends OrderCVSCommitMessage
? CVSPaymentInfo
: OCM extends OrderBarcodeCommitMessage
? BarcodeInfo
: OCM extends OrderApplePayCommitMessage
? undefined
: never;
Info Types
For async payment channels:
// Virtual Account (ATM)
interface VirtualAccountInfo {
channel: Channel.VIRTUAL_ACCOUNT;
bankCode: string;
account: string;
expiredAt: Date;
}
// CVS Kiosk
interface CVSInfo {
channel: Channel.CVS_KIOSK;
paymentCode: string;
expiredAt: Date;
}
// CVS Barcode
interface BarcodeInfo {
channel: Channel.CVS_BARCODE;
barcodes: [string, string, string];
expiredAt: Date;
}
For credit card authorization:
interface CreditCardAuthInfo {
channel: Channel.CREDIT_CARD;
processDate: Date;
authCode: string; // 信用卡授權碼 (6 碼)
amount: number;
eci: CreditCardECI; // 3D 驗證結果
card4Number: string; // 卡號末 4 碼
card6Number: string; // 卡號前 6 碼
gwsr?: string; // 閘道序號(可選)
xid?: string; // 交易 ID(可選)
aetId?: string; // AE 交易 ID(可選)
}
For WebATM payment:
interface WebATMPaymentInfo {
channel: Channel.WEB_ATM;
buyerAccountNumber: string; // 付款人帳號
buyerBankCode: string; // 付款人銀行代碼
}
For Virtual Account payment (付款後):
interface VirtualAccountPaymentInfo {
channel: Channel.VIRTUAL_ACCOUNT;
buyerAccountNumber: string; // 付款人帳號
buyerBankCode: string; // 付款人銀行代碼
}
For CVS payment:
interface CVSPaymentInfo {
channel: Channel.CVS_KIOSK;
cvsPayFrom: CVS; // 付款超商
}
Detailed Documentation
For complete interface specifications and implementation guide:
- Base Interfaces Reference - Complete type definitions
- Creating an Adapter - Step-by-step guide
More from rytass/utils
wms-module
|
24logistics-development
|
13logistics-adapters
|
12invoice-adapters
Taiwan e-invoice integration (台灣電子發票整合). Use when working with ECPay (綠界), EZPay (藍新), BankPro (金財通), or Amego (光貿) invoice services. Covers issuing invoices (開立發票), voiding (作廢), allowances (折讓), and querying invoice data.
8payment-adapters
Taiwan payment integration (台灣支付整合). Use when working with ECPay (綠界), NewebPay (藍新), HwaNan Bank (華南銀行), CTBC (中信), iCash Pay, or Happy Card payment services. Covers credit card (信用卡), virtual account (虛擬帳號), ATM, CVS payment (超商代碼/條碼), card binding (卡片綁定), installments (分期付款), recurring payments (訂閱付款), and NestJS integration.
7member-module
|
7