Back to list
Rytass

payment-development

by Rytass

7🍴 2📅 Jan 19, 2026

SKILL.md


name: payment-development description: Development guide for @rytass/payments base package (支付基底套件開發指南). Use when creating new payment adapters (新增支付 adapter), understanding base interfaces, or extending payment functionality. Covers PaymentGateway, Order, BindCardPaymentGateway interfaces and implementation patterns for Taiwan payment providers (台灣金流服務提供商). Keywords - payment adapter, 支付 adapter, gateway, order lifecycle, 訂單生命週期, card binding, 卡片綁定, credit card, 信用卡, virtual account, ATM 虛擬帳號, CVS payment, 超商代碼, event emitter, 事件監聽

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

ChannelDescriptionCommit Type
CREDIT_CARDCredit/Debit CardSync
VIRTUAL_ACCOUNTATM Virtual AccountAsync
WEB_ATMOnline ATMAsync
CVS_KIOSKConvenience Store CodeAsync
CVS_BARCODEConvenience Store BarcodeAsync
APPLE_PAYApple PaySync
LINE_PAYLINE PaySync

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',
}
StateDescription
INITEDOrder initialized
PRE_COMMITOrder created, awaiting payment
ASYNC_INFO_RETRIEVEDAsync payment info ready (ATM/CVS)
COMMITTEDPayment successful
FAILEDPayment failed
REFUNDEDOrder 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',
}
EventWhen Triggered
SERVER_LISTENEDBuilt-in server started
ORDER_PRE_COMMITOrder created (form/URL ready)
ORDER_INFO_RETRIEVEDAsync payment info ready
ORDER_COMMITTEDPayment successful
ORDER_FAILEDPayment failed
CARD_BOUNDCard bound successfully
CARD_BINDING_FAILEDCard 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:

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon