{
  "version": 3,
  "sources": ["../src/config/Env.ts", "../src/enums/CardType.ts", "../src/enums/Currency.ts", "../src/errors/TapPayConfigError.ts", "../src/errors/TapPayError.ts", "../src/errors/TapPayTimeoutError.ts", "../src/errors/TapPayValidationError.ts", "../src/services/BaseService.ts", "../src/utils/validators.ts", "../src/services/CardService.ts", "../src/services/PaymentService.ts", "../src/services/TransactionService.ts", "../src/TapPayClient.ts", "../src/utils/errorHandling.ts", "../src/utils/retry.ts", "../src/utils/webhooks.ts", "../src/index.ts"],
  "sourcesContent": [
    "/**\n * TapPay API 環境\n *\n * 定義 TapPay API 的環境端點。\n */\nexport const Env = {\n  /**\n   * 沙盒環境（用於測試）\n   *\n   * 使用測試卡片和測試資料進行開發和測試。\n   */\n  Sandbox: 'https://sandbox.tappaysdk.com',\n\n  /**\n   * 正式環境（用於實際交易）\n   *\n   * 使用真實卡片進行實際交易。\n   */\n  Production: 'https://prod.tappaysdk.com',\n} as const\n\n/**\n * TapPay API 環境類型\n */\nexport type Env = (typeof Env)[keyof typeof Env]\n",
    "/**\n * 卡片類型枚舉\n *\n * 定義 TapPay 支援的卡片類型。\n */\nexport const CardType = {\n  /** 信用卡 */\n  Credit: 1,\n  /** 金融卡 */\n  Debit: 2,\n  /** 預付卡 */\n  Prepaid: 3,\n} as const\n\n/**\n * 卡片類型\n */\nexport type CardType = (typeof CardType)[keyof typeof CardType]\n\n/**\n * 取得卡片類型名稱\n *\n * 將卡片類型數值轉換為可讀的字串名稱。\n *\n * @param type - 卡片類型數值\n * @returns 卡片類型名稱（'Credit', 'Debit', 'Prepaid' 或 'Unknown'）\n *\n * @example\n * ```typescript\n * const typeName = getCardTypeName(CardType.Credit) // 'Credit'\n * const unknown = getCardTypeName(999) // 'Unknown'\n * ```\n */\nexport function getCardTypeName(type: CardType): string {\n  switch (type) {\n    case CardType.Credit:\n      return 'Credit'\n    case CardType.Debit:\n      return 'Debit'\n    case CardType.Prepaid:\n      return 'Prepaid'\n    default:\n      return 'Unknown'\n  }\n}\n",
    "/**\n * TapPay 支援的 ISO 4217 貨幣代碼\n *\n * 定義所有 TapPay API 支援的貨幣類型。\n */\nexport const Currency = {\n  /** 新台幣 */\n  TWD: 'TWD',\n  /** 美元 */\n  USD: 'USD',\n  /** 日圓 */\n  JPY: 'JPY',\n  /** 港幣 */\n  HKD: 'HKD',\n  /** 馬來西亞令吉 */\n  MYR: 'MYR',\n  /** 新加坡幣 */\n  SGD: 'SGD',\n  /** 印尼盾 */\n  IDR: 'IDR',\n  /** 泰銖 */\n  THB: 'THB',\n  /** 菲律賓披索 */\n  PHP: 'PHP',\n  /** 越南盾 */\n  VND: 'VND',\n  /** 澳幣 */\n  AUD: 'AUD',\n  /** 歐元 */\n  EUR: 'EUR',\n  /** 英鎊 */\n  GBP: 'GBP',\n} as const\n\n/**\n * 貨幣類型\n */\nexport type Currency = (typeof Currency)[keyof typeof Currency]\n\n/**\n * 貨幣金額乘數\n *\n * 大部分貨幣需要乘以 100 才能傳送給 TapPay API（例如：USD $1.00 = 100）。\n * 例外：TWD、JPY、IDR、VND 使用實際數值。\n *\n * @example\n * ```typescript\n * // TWD 使用實際數值\n * const twdAmount = 100 // 100 TWD\n *\n * // USD 需要乘以 100\n * const usdAmount = 100 * CurrencyMultiplier[Currency.USD] // 100 = $1.00\n * ```\n */\nexport const CurrencyMultiplier: Record<Currency, number> = {\n  [Currency.TWD]: 1,\n  [Currency.USD]: 100,\n  [Currency.JPY]: 1,\n  [Currency.HKD]: 100,\n  [Currency.MYR]: 100,\n  [Currency.SGD]: 100,\n  [Currency.IDR]: 1,\n  [Currency.THB]: 100,\n  [Currency.PHP]: 100,\n  [Currency.VND]: 1,\n  [Currency.AUD]: 100,\n  [Currency.EUR]: 100,\n  [Currency.GBP]: 100,\n}\n",
    "/**\n * TapPay 配置錯誤\n *\n * 當客戶端配置無效時拋出此錯誤。\n *\n * @example\n * ```typescript\n * try {\n *   const client = new TapPayClient({\n *     partnerKey: '', // 無效的 partner key\n *     merchantId: 'test_merchant_id'\n *   })\n * } catch (error) {\n *   if (error instanceof TapPayConfigError) {\n *     console.error(`配置錯誤欄位: ${error.field}`)\n *   }\n * }\n * ```\n */\nexport class TapPayConfigError extends Error {\n  /**\n   * 導致錯誤的配置欄位名稱\n   *\n   * @readonly\n   */\n  readonly field: string | undefined\n\n  /**\n   * 建立 TapPay 配置錯誤實例\n   *\n   * @param message - 錯誤訊息\n   * @param field - 導致錯誤的配置欄位名稱（可選）\n   */\n  constructor(message: string, field?: string) {\n    super(message)\n    this.name = 'TapPayConfigError'\n    this.field = field\n\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, TapPayConfigError)\n    }\n  }\n}\n",
    "/**\n * TapPay 基礎錯誤類別\n *\n * 代表從 TapPay API 返回的錯誤。\n * 所有其他 TapPay 錯誤類別都繼承自此類別。\n *\n * @example\n * ```typescript\n * try {\n *   await client.payByPrime({ prime: 'invalid', amount: 100 })\n * } catch (error) {\n *   if (error instanceof TapPayError) {\n *     console.error(`錯誤狀態碼: ${error.status}`)\n *     console.error(`交易 ID: ${error.recTradeId}`)\n *   }\n * }\n * ```\n */\nexport class TapPayError extends Error {\n  /**\n   * TapPay 狀態碼\n   *\n   * 0 表示成功，其他值表示錯誤。\n   *\n   * @readonly\n   */\n  readonly status: number\n\n  /**\n   * TapPay 交易 ID（如果可用）\n   *\n   * @readonly\n   */\n  readonly recTradeId: string | undefined\n\n  /**\n   * 原始回應資料\n   *\n   * @readonly\n   */\n  readonly response?: unknown\n\n  /**\n   * 建立 TapPay 錯誤實例\n   *\n   * @param message - 錯誤訊息\n   * @param status - TapPay 狀態碼\n   * @param recTradeId - TapPay 交易 ID（可選）\n   * @param response - 原始回應資料（可選）\n   */\n  constructor(message: string, status: number, recTradeId?: string, response?: unknown) {\n    super(message)\n    this.name = 'TapPayError'\n    this.status = status\n    this.recTradeId = recTradeId\n    this.response = response\n\n    // Maintains proper stack trace for where error was thrown\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, TapPayError)\n    }\n  }\n\n  /**\n   * 檢查錯誤是否表示交易失敗\n   *\n   * @returns 如果狀態碼不為 0 則返回 true，否則返回 false\n   * @readonly\n   */\n  get isTransactionFailed(): boolean {\n    return this.status !== 0\n  }\n\n  /**\n   * 從 API 回應建立 TapPayError\n   *\n   * @param response - TapPay API 回應物件\n   * @returns TapPayError 實例\n   * @static\n   */\n  static fromResponse(response: {\n    status: number\n    msg: string\n    rec_trade_id?: string\n  }): TapPayError {\n    return new TapPayError(response.msg, response.status, response.rec_trade_id, response)\n  }\n}\n",
    "/**\n * TapPay 超時錯誤\n *\n * 當 API 請求超時時拋出此錯誤。\n *\n * @example\n * ```typescript\n * try {\n *   await client.payByPrime({ prime: 'test', amount: 100 })\n * } catch (error) {\n *   if (error instanceof TapPayTimeoutError) {\n *     console.error(`請求超時: ${error.timeout}ms`)\n *     console.error(`端點: ${error.endpoint}`)\n *     // 可以考慮重試\n *   }\n * }\n * ```\n */\nexport class TapPayTimeoutError extends Error {\n  /**\n   * 超時時間（毫秒）\n   *\n   * @readonly\n   */\n  readonly timeout: number\n\n  /**\n   * 超時的 API 端點\n   *\n   * @readonly\n   */\n  readonly endpoint: string | undefined\n\n  /**\n   * 建立 TapPay 超時錯誤實例\n   *\n   * @param message - 錯誤訊息\n   * @param timeout - 超時時間（毫秒）\n   * @param endpoint - 超時的 API 端點（可選）\n   */\n  constructor(message: string, timeout: number, endpoint?: string) {\n    super(message)\n    this.name = 'TapPayTimeoutError'\n    this.timeout = timeout\n    this.endpoint = endpoint\n\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, TapPayTimeoutError)\n    }\n  }\n}\n",
    "/**\n * TapPay 驗證錯誤\n *\n * 當請求驗證失敗時拋出此錯誤。\n * 通常在發送 API 請求前進行輸入驗證時發生。\n *\n * @example\n * ```typescript\n * try {\n *   await client.payByPrime({\n *     prime: '', // 無效的 prime\n *     amount: 100\n *   })\n * } catch (error) {\n *   if (error instanceof TapPayValidationError) {\n *     console.error(`驗證失敗的欄位: ${error.field}`)\n *     console.error(`錯誤訊息: ${error.message}`)\n *   }\n * }\n * ```\n */\nexport class TapPayValidationError extends Error {\n  /**\n   * 驗證失敗的欄位名稱\n   *\n   * @readonly\n   */\n  readonly field: string | undefined\n\n  /**\n   * 建立 TapPay 驗證錯誤實例\n   *\n   * @param message - 錯誤訊息\n   * @param field - 驗證失敗的欄位名稱（可選）\n   */\n  constructor(message: string, field?: string) {\n    super(message)\n    this.name = 'TapPayValidationError'\n    this.field = field\n\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, TapPayValidationError)\n    }\n  }\n}\n",
    "import type { TapPayConfig } from '../config/TapPayConfig'\nimport { TapPayError } from '../errors/TapPayError'\nimport { TapPayTimeoutError } from '../errors/TapPayTimeoutError'\nimport type { TapPayBaseResponse } from '../payments/PaymentResponse'\n\n/**\n * 抽象基類，提供所有 Service 共享的功能\n *\n * 負責 HTTP 請求處理、錯誤管理和超時控制。\n * 所有 Service 類別都應繼承此類別。\n */\nexport abstract class BaseService {\n  protected readonly config: Required<TapPayConfig>\n\n  /**\n   * 建立 BaseService 實例\n   *\n   * @param config - TapPay 客戶端配置\n   */\n  constructor(config: Required<TapPayConfig>) {\n    this.config = config\n  }\n\n  /**\n   * 向 TapPay API 發送請求\n   *\n   * 將請求發送至指定的 API 端點，處理所有錯誤情況，包括：\n   * - HTTP 錯誤（狀態碼非 2xx）\n   * - 超時錯誤（超過配置的超時時間）\n   * - JSON 解析錯誤\n   * - TapPay 回應錯誤（status !== 0）\n   *\n   * 請求會附上 API 密鑰作為 `x-api-key` 標頭。\n   *\n   * @template T - 回應資料類型，必須包含 `status` 欄位\n   * @param endpoint - API 端點路徑（例如：`/tpc/payment/pay-by-prime`）\n   * @param body - 請求 payload（將轉換為 JSON）\n   * @returns 解析後的 TapPay API 回應\n   * @throws {TapPayError} 當 HTTP 請求失敗或 TapPay 回應狀態碼非 0 時\n   * @throws {TapPayTimeoutError} 當請求超過配置的超時時間時\n   *\n   * @example\n   * ```typescript\n   * const response = await this.sendRequest<PaymentResponse>(\n   *   '/tpc/payment/pay-by-prime',\n   *   { prime: 'token_from_frontend', amount: 100, ... }\n   * )\n   * ```\n   */\n  protected async sendRequest<T extends TapPayBaseResponse>(\n    endpoint: string,\n    body: Record<string, unknown>\n  ): Promise<T> {\n    const url = `${this.config.env}${endpoint}`\n\n    const controller = new AbortController()\n    let timeoutId: ReturnType<typeof setTimeout> | undefined\n\n    try {\n      timeoutId = setTimeout(() => controller.abort(), this.config.timeout)\n\n      const response = await fetch(url, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          'x-api-key': this.config.partnerKey,\n        },\n        body: JSON.stringify(body),\n        signal: controller.signal,\n      })\n\n      // Handle HTTP errors with better error message extraction\n      if (!response.ok) {\n        let errorMessage = `HTTP ${response.status}: ${response.statusText}`\n        try {\n          const errorText = await response.text()\n          if (errorText) {\n            try {\n              const errorData = JSON.parse(errorText) as { msg?: string; message?: string }\n              if (errorData.msg) {\n                errorMessage = errorData.msg\n              } else if (errorData.message) {\n                errorMessage = errorData.message\n              }\n            } catch {\n              // If JSON parsing fails, use the raw text if it's not too long\n              if (errorText.length < 500) {\n                errorMessage = errorText\n              }\n            }\n          }\n        } catch {\n          // Ignore errors when reading response, use default message\n        }\n        throw new TapPayError(errorMessage, response.status)\n      }\n\n      // Parse JSON response with error handling\n      let data: T\n      try {\n        const text = await response.text()\n        if (!text) {\n          throw new TapPayError('Empty response from server', response.status)\n        }\n        data = JSON.parse(text) as T\n      } catch (parseError) {\n        throw new TapPayError(\n          `Failed to parse response: ${parseError instanceof Error ? parseError.message : 'Unknown parsing error'}`,\n          response.status\n        )\n      }\n\n      // Check TapPay status code\n      if (data.status !== 0) {\n        throw TapPayError.fromResponse(data as TapPayBaseResponse & { rec_trade_id?: string })\n      }\n\n      return data\n    } catch (error) {\n      // Re-throw TapPay errors as-is\n      if (error instanceof TapPayError) {\n        throw error\n      }\n\n      // Handle timeout errors\n      if (error instanceof Error && error.name === 'AbortError') {\n        throw new TapPayTimeoutError(\n          `Request timeout after ${this.config.timeout}ms`,\n          this.config.timeout,\n          endpoint\n        )\n      }\n\n      // Handle other errors with more detailed messages\n      const errorMessage =\n        error instanceof Error ? `${error.name}: ${error.message}` : 'Unknown error occurred'\n      throw new TapPayError(`Network error: ${errorMessage}`, -1)\n    } finally {\n      // Ensure timeout is always cleared\n      if (timeoutId) {\n        clearTimeout(timeoutId)\n      }\n    }\n  }\n}\n",
    "import type { TapPayConfig } from '../config/TapPayConfig'\nimport { TapPayConfigError } from '../errors/TapPayConfigError'\nimport { TapPayValidationError } from '../errors/TapPayValidationError'\n\n/**\n * 驗證字串為必填且非空\n *\n * 檢查提供的值是否為非空字串。如果值為 undefined、null 或空字串（包括只有空格的字串），\n * 將拋出 TapPayValidationError。\n *\n * @param value - 要驗證的字串值\n * @param fieldName - 欄位名稱（用於錯誤訊息）\n * @throws {TapPayValidationError} 當 value 為 undefined、null、空字串或只有空格時\n *\n * @example\n * ```typescript\n * validateRequired('prime_value', 'prime') // ✓ 通過\n * validateRequired('', 'prime') // ✗ 拋出錯誤\n * validateRequired(undefined, 'prime') // ✗ 拋出錯誤\n * ```\n */\nexport function validateRequired(\n  value: string | undefined,\n  fieldName: string\n): asserts value is string {\n  if (!value || value.trim() === '') {\n    throw new TapPayValidationError(`${fieldName} is required`, fieldName)\n  }\n}\n\n/**\n * 驗證金額為正數\n *\n * 檢查提供的金額是否為正數（> 0）。如果金額為 undefined 或 <= 0，\n * 將拋出 TapPayValidationError。\n *\n * @param amount - 要驗證的金額\n * @param fieldName - 欄位名稱（用於錯誤訊息）\n * @throws {TapPayValidationError} 當 amount 為 undefined 或 <= 0 時\n *\n * @example\n * ```typescript\n * validateAmount(100, 'amount') // ✓ 通過\n * validateAmount(0, 'amount') // ✗ 拋出錯誤\n * validateAmount(undefined, 'amount') // ✗ 拋出錯誤\n * ```\n */\nexport function validateAmount(\n  amount: number | undefined,\n  fieldName: string\n): asserts amount is number {\n  if (amount === undefined || amount <= 0) {\n    throw new TapPayValidationError(`${fieldName} must be positive`, fieldName)\n  }\n}\n\n/**\n * 驗證可選欄位（允許 undefined，但不允許空字串）\n *\n * 檢查提供的值是否為有效的可選字串。允許 undefined，但如果值已定義，\n * 則不允許空字串或只有空格的字串。\n *\n * @param value - 要驗證的字串值\n * @param fieldName - 欄位名稱（用於錯誤訊息）\n * @throws {TapPayValidationError} 當 value 已定義但為空字串或只有空格時\n *\n * @example\n * ```typescript\n * validateOptionalField(undefined, 'order_number') // ✓ 通過\n * validateOptionalField('ORDER-123', 'order_number') // ✓ 通過\n * validateOptionalField('', 'order_number') // ✗ 拋出錯誤\n * ```\n */\nexport function validateOptionalField(value: string | undefined, fieldName: string): void {\n  if (value !== undefined && value.trim() === '') {\n    throw new TapPayValidationError(`${fieldName} must be non-empty if provided`, fieldName)\n  }\n}\n\n/**\n * 驗證必填欄位（通用驗證，無 trim）\n *\n * 檢查提供的值是否為已定義（truthy）。用於驗證不支援 trim 的欄位，\n * 例如 enum 類型或其他非字串類型的值。\n *\n * @param value - 要驗證的值\n * @param fieldName - 欄位名稱（用於錯誤訊息）\n * @throws {TapPayValidationError} 當 value 為 undefined、null 或 falsy 時\n *\n * @example\n * ```typescript\n * validateRequiredField(Currency.TWD, 'currency') // ✓ 通過\n * validateRequiredField(undefined, 'currency') // ✗ 拋出錯誤\n * ```\n */\nexport function validateRequiredField(value: unknown, fieldName: string): void {\n  if (!value) {\n    throw new TapPayValidationError(`${fieldName} is required`, fieldName)\n  }\n}\n\n/**\n * 驗證 TapPay 客戶端配置\n *\n * 驗證所有必要的配置欄位是否有效。檢查 partnerKey 和 merchantId 不為空字串，\n * 並檢查 timeout（如果提供）為正數。\n *\n * @param config - TapPay 客戶端配置物件\n * @throws {TapPayConfigError} 當配置無效時\n *\n * @example\n * ```typescript\n * validateConfig({\n *   partnerKey: 'key123',\n *   merchantId: 'merchant456'\n * }) // ✓ 通過\n *\n * validateConfig({\n *   partnerKey: '',\n *   merchantId: 'merchant456'\n * }) // ✗ 拋出錯誤\n * ```\n */\nexport function validateConfig(config: TapPayConfig): void {\n  if (!config.partnerKey || config.partnerKey.trim() === '') {\n    throw new TapPayConfigError('Partner Key is required', 'partnerKey')\n  }\n\n  if (!config.merchantId || config.merchantId.trim() === '') {\n    throw new TapPayConfigError('Merchant ID is required', 'merchantId')\n  }\n\n  if (config.timeout !== undefined && config.timeout <= 0) {\n    throw new TapPayConfigError('Timeout must be positive', 'timeout')\n  }\n}\n",
    "import type {\n  BindCardRequest,\n  RemoveCardRequest,\n  TradeHistoryRequest,\n} from '../payments/PaymentRequest'\nimport type {\n  BindCardResponse,\n  RemoveCardResponse,\n  TradeHistoryResponse,\n} from '../payments/PaymentResponse'\nimport { validateRequired, validateRequiredField } from '../utils/validators'\nimport { BaseService } from './BaseService'\n\n/**\n * 卡片管理服務\n *\n * 提供卡片相關的 API 方法，包括綁定卡片、移除卡片和查詢卡片交易歷史。\n */\nexport class CardService extends BaseService {\n  /**\n   * 綁定卡片\n   *\n   * 綁定卡片以供未來的 token 付款使用。\n   * 會執行一筆 1 TWD 的測試交易並立即退款。\n   *\n   * @param options - 綁定卡片選項\n   * @returns Promise 解析為綁定卡片回應（包含 card_key 和 card_token）\n   * @throws {TapPayValidationError} 當必要欄位缺失或無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const response = await cardService.bindCard({\n   *   prime: 'prime_from_frontend',\n   *   currency: Currency.TWD,\n   *   cardholder: {\n   *     phone_number: '+886912345678',\n   *     name: 'Test User',\n   *     email: 'test@example.com'\n   *   }\n   * })\n   *\n   * if (response.card_secret) {\n   *   const { card_key, card_token } = response.card_secret\n   *   // 儲存以供未來付款使用\n   * }\n   * ```\n   */\n  async bindCard(\n    options: Omit<BindCardRequest, 'partner_key' | 'merchant_id'>\n  ): Promise<BindCardResponse> {\n    // Validate required fields\n    validateRequired(options.prime, 'prime')\n    validateRequiredField(options.currency, 'currency')\n\n    const body: BindCardRequest = {\n      ...options,\n      partner_key: this.config.partnerKey,\n      merchant_id: this.config.merchantId,\n    }\n\n    return this.sendRequest<BindCardResponse>(\n      '/tpc/card/bind',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 移除綁定的卡片\n   *\n   * 從 TapPay 伺服器移除已綁定的卡片。\n   *\n   * @param cardKey - 要移除的卡片 key\n   * @param cardToken - 要移除的卡片 token\n   * @returns Promise 解析為移除卡片回應\n   * @throws {TapPayValidationError} 當 cardKey 或 cardToken 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await cardService.removeCard('card_key_123', 'card_token_123')\n   * ```\n   */\n  async removeCard(cardKey: string, cardToken: string): Promise<RemoveCardResponse> {\n    // Validate required fields\n    validateRequired(cardKey, 'cardKey')\n    validateRequired(cardToken, 'cardToken')\n\n    const body: RemoveCardRequest = {\n      partner_key: this.config.partnerKey,\n      card_key: cardKey,\n      card_token: cardToken,\n    }\n\n    return this.sendRequest<RemoveCardResponse>(\n      '/tpc/card/remove',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 查詢卡片交易歷史\n   *\n   * 取得使用特定卡片進行的所有交易記錄。\n   *\n   * @param recTradeId - TapPay 交易 ID（用於標識卡片）\n   * @returns Promise 解析為交易歷史回應\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const history = await cardService.getTradeHistory('D20231201123456789')\n   * ```\n   */\n  async getTradeHistory(recTradeId: string): Promise<TradeHistoryResponse> {\n    // Validate required fields\n    validateRequired(recTradeId, 'recTradeId')\n\n    const body: TradeHistoryRequest = {\n      partner_key: this.config.partnerKey,\n      rec_trade_id: recTradeId,\n    }\n\n    return this.sendRequest<TradeHistoryResponse>(\n      '/tpc/transaction/trade-history',\n      body as unknown as Record<string, unknown>\n    )\n  }\n}\n",
    "import type { PayByPrimeRequest, PayByTokenRequest } from '../payments/PaymentRequest'\nimport type { PaymentResponse } from '../payments/PaymentResponse'\nimport {\n  validateAmount,\n  validateOptionalField,\n  validateRequired,\n  validateRequiredField,\n} from '../utils/validators'\nimport { BaseService } from './BaseService'\n\n/**\n * 支付操作服務\n *\n * 提供支付相關的 API 方法，包括使用 Prime Token 支付和使用已儲存的卡片支付。\n */\nexport class PaymentService extends BaseService {\n  /**\n   * 使用 Prime Token 付款\n   *\n   * 使用從前端取得的 Prime Token 進行付款。\n   * Prime Token 由 TapPay 前端 SDK 產生，單次使用。\n   *\n   * @param options - 付款選項（包含 Prime Token）\n   * @returns Promise 解析為付款回應\n   * @throws {TapPayValidationError} 當必要欄位缺失或無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const response = await paymentService.payByPrime({\n   *   prime: 'prime_from_frontend',\n   *   amount: 100,\n   *   currency: Currency.TWD,\n   *   details: 'Order #12345'\n   * })\n   * ```\n   */\n  async payByPrime(\n    options: Omit<PayByPrimeRequest, 'partner_key' | 'merchant_id'>\n  ): Promise<PaymentResponse> {\n    // Validate required fields\n    validateRequired(options.prime, 'prime')\n    validateAmount(options.amount, 'amount')\n    validateOptionalField(options.order_number, 'order_number')\n\n    const body: PayByPrimeRequest = {\n      ...options,\n      partner_key: this.config.partnerKey,\n      merchant_id: this.config.merchantId,\n    }\n\n    return this.sendRequest<PaymentResponse>(\n      '/tpc/payment/pay-by-prime',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 使用卡片 Token 付款\n   *\n   * 使用已儲存的卡片憑證進行付款。\n   * 需要從之前使用 remember=true 的 Pay by Prime 交易中取得的 card_key 和 card_token。\n   *\n   * @param options - 付款選項（包含卡片憑證）\n   * @returns Promise 解析為付款回應\n   * @throws {TapPayValidationError} 當必要欄位缺失或無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const response = await paymentService.payByToken({\n   *   card_key: 'saved_card_key',\n   *   card_token: 'saved_card_token',\n   *   amount: 100,\n   *   currency: Currency.TWD,\n   *   details: 'Recurring Payment'\n   * })\n   * ```\n   */\n  async payByToken(\n    options: Omit<PayByTokenRequest, 'partner_key' | 'merchant_id'>\n  ): Promise<PaymentResponse> {\n    // Validate required fields\n    validateRequired(options.card_key, 'card_key')\n    validateRequired(options.card_token, 'card_token')\n    validateAmount(options.amount, 'amount')\n    validateRequiredField(options.currency, 'currency')\n    validateOptionalField(options.order_number, 'order_number')\n\n    const body: PayByTokenRequest = {\n      ...options,\n      partner_key: this.config.partnerKey,\n      merchant_id: this.config.merchantId,\n    }\n\n    return this.sendRequest<PaymentResponse>(\n      '/tpc/payment/pay-by-token',\n      body as unknown as Record<string, unknown>\n    )\n  }\n}\n",
    "import type {\n  CapCancelRequest,\n  CapTodayRequest,\n  RecordRequest,\n  RefundCancelRequest,\n  RefundRequest,\n} from '../payments/PaymentRequest'\nimport type {\n  CapCancelResponse,\n  CapTodayResponse,\n  RecordResponse,\n  RefundCancelResponse,\n  RefundResponse,\n} from '../payments/PaymentResponse'\nimport { validateAmount, validateRequired } from '../utils/validators'\nimport { BaseService } from './BaseService'\n\n/**\n * 交易管理服務\n *\n * 提供交易相關的 API 方法，包括退款、請款、取消等操作。\n */\nexport class TransactionService extends BaseService {\n  /**\n   * 退款\n   *\n   * 對已完成的交易進行退款，支援全額或部分退款。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @param options - 退款選項（金額為可選，若未指定則為全額退款）\n   * @returns Promise 解析為退款回應\n   * @throws {TapPayValidationError} 當交易 ID 無效或金額格式不正確時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * // 全額退款\n   * await transactionService.refund('D20231201123456789')\n   *\n   * // 部分退款\n   * await transactionService.refund('D20231201123456789', { amount: 50 })\n   * ```\n   */\n  async refund(\n    recTradeId: string,\n    options?: Omit<RefundRequest, 'partner_key' | 'rec_trade_id'>\n  ): Promise<RefundResponse> {\n    // Validate required fields\n    validateRequired(recTradeId, 'recTradeId')\n\n    // Validate amount if provided (must be positive)\n    if (options?.amount !== undefined) {\n      validateAmount(options.amount, 'amount')\n    }\n\n    const body: RefundRequest = {\n      ...options,\n      partner_key: this.config.partnerKey,\n      rec_trade_id: recTradeId,\n    }\n\n    return this.sendRequest<RefundResponse>(\n      '/tpc/transaction/refund',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 取消退款\n   *\n   * 在銀行批次處理前取消待處理的退款。\n   * 目前僅支援台新銀行。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @param refundId - 要取消的退款 ID\n   * @returns Promise 解析為取消退款回應\n   * @throws {TapPayValidationError} 當交易 ID 或退款 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await transactionService.cancelRefund('D20231201123456789', 'R20231201123456789')\n   * ```\n   */\n  async cancelRefund(recTradeId: string, refundId: string): Promise<RefundCancelResponse> {\n    // Validate required fields\n    validateRequired(recTradeId, 'recTradeId')\n    validateRequired(refundId, 'refundId')\n\n    const body: RefundCancelRequest = {\n      partner_key: this.config.partnerKey,\n      rec_trade_id: recTradeId,\n      refund_id: refundId,\n    }\n\n    return this.sendRequest<RefundCancelResponse>(\n      '/tpc/transaction/refund/cancel',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 立即請款（當日）\n   *\n   * 立即請款交易（當日）。\n   * 用於將延遲請款交易的請款日期改為當日。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @returns Promise 解析為請款回應\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await transactionService.capToday('D20231201123456789')\n   * ```\n   */\n  async capToday(recTradeId: string): Promise<CapTodayResponse> {\n    // Validate required fields\n    validateRequired(recTradeId, 'recTradeId')\n\n    const body: CapTodayRequest = {\n      partner_key: this.config.partnerKey,\n      rec_trade_id: recTradeId,\n    }\n\n    return this.sendRequest<CapTodayResponse>(\n      '/tpc/transaction/cap',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 取消請款\n   *\n   * 在銀行批次處理前取消待處理的請款。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @returns Promise 解析為取消請款回應\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await transactionService.cancelCapture('D20231201123456789')\n   * ```\n   */\n  async cancelCapture(recTradeId: string): Promise<CapCancelResponse> {\n    // Validate required fields\n    validateRequired(recTradeId, 'recTradeId')\n\n    const body: CapCancelRequest = {\n      partner_key: this.config.partnerKey,\n      rec_trade_id: recTradeId,\n    }\n\n    return this.sendRequest<CapCancelResponse>(\n      '/tpc/transaction/cap/cancel',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 查詢交易記錄\n   *\n   * 使用篩選和分頁功能取得交易記錄。\n   * 時間範圍篩選限制為 90 天。\n   *\n   * @param options - 查詢選項（篩選、分頁、排序）\n   * @returns Promise 解析為交易記錄回應\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const records = await transactionService.getRecords({\n   *   records_per_page: 10,\n   *   page: 0,\n   *   filters: {\n   *     rec_trade_id: 'D20231201123456789'\n   *   }\n   * })\n   * ```\n   */\n  async getRecords(options?: Omit<RecordRequest, 'partner_key'>): Promise<RecordResponse> {\n    const body: RecordRequest = {\n      ...options,\n      partner_key: this.config.partnerKey,\n    }\n\n    return this.sendRequest<RecordResponse>(\n      '/tpc/transaction/query',\n      body as unknown as Record<string, unknown>\n    )\n  }\n\n  /**\n   * 根據 ID 取得單筆交易\n   *\n   * 便利方法，用於查詢單筆交易記錄。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @returns Promise 解析為交易記錄，如果找不到則返回 null\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const record = await transactionService.getTransaction('D20231201123456789')\n   * if (record) {\n   *   console.log(`Status: ${record.status}`)\n   * }\n   * ```\n   */\n  async getTransaction(recTradeId: string) {\n    // Validate required fields\n    validateRequired(recTradeId, 'recTradeId')\n\n    const response = await this.getRecords({\n      filters: {\n        rec_trade_id: recTradeId,\n      },\n    })\n\n    return response.trade_records?.[0] ?? null\n  }\n}\n",
    "import { Env } from './config/Env'\nimport type { TapPayConfig } from './config/TapPayConfig'\nimport type {\n  BindCardRequest,\n  PayByPrimeRequest,\n  PayByTokenRequest,\n  RecordRequest,\n  RefundRequest,\n} from './payments/PaymentRequest'\nimport type {\n  BindCardResponse,\n  CapCancelResponse,\n  CapTodayResponse,\n  PaymentResponse,\n  RecordResponse,\n  RefundCancelResponse,\n  RefundResponse,\n  RemoveCardResponse,\n  TradeHistoryResponse,\n} from './payments/PaymentResponse'\nimport { CardService } from './services/CardService'\nimport { PaymentService } from './services/PaymentService'\nimport { TransactionService } from './services/TransactionService'\nimport { validateConfig } from './utils/validators'\n\n/**\n * Default timeout in milliseconds\n * TapPay recommends at least 30 seconds for peak hours\n */\nconst DEFAULT_TIMEOUT = 30000\n\n/**\n * TapPay 後端付款客戶端\n *\n * 與 TapPay 後端 API 互動的核心類別。\n * 提供付款處理、退款、卡片管理和交易查詢等方法。\n *\n * @example\n * ```typescript\n * import { TapPayClient, Env, Currency } from '@carllee1983/tappay-backend-payment-node'\n *\n * const client = new TapPayClient({\n *   partnerKey: 'your_partner_key',\n *   merchantId: 'your_merchant_id',\n *   env: Env.Sandbox\n * })\n *\n * const response = await client.payByPrime({\n *   prime: 'prime_from_frontend',\n *   amount: 100,\n *   currency: Currency.TWD,\n *   details: 'Test Payment'\n * })\n * ```\n */\nexport class TapPayClient {\n  private readonly config: Required<TapPayConfig>\n  private readonly paymentService: PaymentService\n  private readonly transactionService: TransactionService\n  private readonly cardService: CardService\n\n  /**\n   * 建立 TapPay 客戶端實例\n   *\n   * @param config - TapPay 客戶端配置\n   * @throws {TapPayConfigError} 當配置無效時（例如：缺少必要欄位、timeout 為負數等）\n   *\n   * @example\n   * ```typescript\n   * const client = new TapPayClient({\n   *   partnerKey: 'partner_key_from_portal',\n   *   merchantId: 'merchant_id_from_portal',\n   *   env: Env.Sandbox,\n   *   timeout: 30000 // 30 秒\n   * })\n   * ```\n   */\n  constructor(config: TapPayConfig) {\n    this.validateConfig(config)\n\n    this.config = {\n      partnerKey: config.partnerKey,\n      merchantId: config.merchantId,\n      env: config.env ?? Env.Sandbox,\n      timeout: config.timeout ?? DEFAULT_TIMEOUT,\n    }\n\n    // Initialize service instances\n    this.paymentService = new PaymentService(this.config)\n    this.transactionService = new TransactionService(this.config)\n    this.cardService = new CardService(this.config)\n  }\n\n  /**\n   * 驗證客戶端配置\n   *\n   * 檢查必要的配置欄位是否有效，如果無效則拋出 TapPayConfigError。\n   *\n   * @param config - TapPay 客戶端配置\n   * @throws {TapPayConfigError} 當配置無效時拋出\n   * @private\n   */\n  private validateConfig(config: TapPayConfig): void {\n    // 使用驗證模組中的 validateConfig 函數\n    validateConfig(config)\n  }\n\n  // ============================================================================\n  // Payment APIs\n  // ============================================================================\n\n  /**\n   * 使用 Prime Token 付款\n   *\n   * 使用前端 SDK 產生的 prime token 進行付款。\n   * 每個 prime token 只能使用一次，有效期限為 90 秒。\n   *\n   * @param options - 付款選項（不包含 partner_key 和 merchant_id）\n   * @returns Promise 解析為付款回應\n   * @throws {TapPayValidationError} 當必要欄位缺失或無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const response = await client.payByPrime({\n   *   prime: 'test_prime_123',\n   *   amount: 100,\n   *   currency: Currency.TWD,\n   *   details: 'Test Payment',\n   *   cardholder: {\n   *     phone_number: '+886912345678',\n   *     name: 'Test User',\n   *     email: 'test@example.com'\n   *   }\n   * })\n   * console.log(response.rec_trade_id)\n   * ```\n   */\n  async payByPrime(\n    options: Omit<PayByPrimeRequest, 'partner_key' | 'merchant_id'>\n  ): Promise<PaymentResponse> {\n    return this.paymentService.payByPrime(options)\n  }\n\n  /**\n   * 使用卡片 Token 付款\n   *\n   * 使用已儲存的卡片憑證進行付款。\n   * 需要從之前使用 remember=true 的 Pay by Prime 交易中取得的 card_key 和 card_token。\n   *\n   * @param options - 付款選項（包含卡片憑證）\n   * @returns Promise 解析為付款回應\n   * @throws {TapPayValidationError} 當必要欄位缺失或無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const response = await client.payByToken({\n   *   card_key: 'saved_card_key',\n   *   card_token: 'saved_card_token',\n   *   amount: 100,\n   *   currency: Currency.TWD,\n   *   details: 'Recurring Payment'\n   * })\n   * ```\n   */\n  async payByToken(\n    options: Omit<PayByTokenRequest, 'partner_key' | 'merchant_id'>\n  ): Promise<PaymentResponse> {\n    return this.paymentService.payByToken(options)\n  }\n\n  // ============================================================================\n  // Transaction Management APIs\n  // ============================================================================\n\n  /**\n   * 退款交易\n   *\n   * 處理全額或部分退款。\n   * 省略 amount 參數則進行全額退款。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @param options - 可選的退款選項（amount, bank_refund_id）\n   * @returns Promise 解析為退款回應\n   * @throws {TapPayValidationError} 當交易 ID 無效或退款金額為負數時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * // 全額退款\n   * await client.refund('D20231201123456789')\n   *\n   * // 部分退款\n   * await client.refund('D20231201123456789', { amount: 50 })\n   * ```\n   */\n  async refund(\n    recTradeId: string,\n    options?: Omit<RefundRequest, 'partner_key' | 'rec_trade_id'>\n  ): Promise<RefundResponse> {\n    return this.transactionService.refund(recTradeId, options)\n  }\n\n  /**\n   * 取消退款\n   *\n   * 在銀行批次處理前取消待處理的退款。\n   * 目前僅支援台新銀行。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @param refundId - 要取消的退款 ID\n   * @returns Promise 解析為取消退款回應\n   * @throws {TapPayValidationError} 當交易 ID 或退款 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await client.cancelRefund('D20231201123456789', 'R20231201123456789')\n   * ```\n   */\n  async cancelRefund(recTradeId: string, refundId: string): Promise<RefundCancelResponse> {\n    return this.transactionService.cancelRefund(recTradeId, refundId)\n  }\n\n  /**\n   * 立即請款（當日）\n   *\n   * 立即請款交易（當日）。\n   * 用於將延遲請款交易的請款日期改為當日。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @returns Promise 解析為請款回應\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await client.capToday('D20231201123456789')\n   * ```\n   */\n  async capToday(recTradeId: string): Promise<CapTodayResponse> {\n    return this.transactionService.capToday(recTradeId)\n  }\n\n  /**\n   * 取消請款\n   *\n   * 在銀行批次處理前取消待處理的請款。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @returns Promise 解析為取消請款回應\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await client.cancelCapture('D20231201123456789')\n   * ```\n   */\n  async cancelCapture(recTradeId: string): Promise<CapCancelResponse> {\n    return this.transactionService.cancelCapture(recTradeId)\n  }\n\n  // ============================================================================\n  // Card Management APIs\n  // ============================================================================\n\n  /**\n   * 綁定卡片\n   *\n   * 綁定卡片以供未來的 token 付款使用。\n   * 會執行一筆 1 TWD 的測試交易並立即退款。\n   *\n   * @param options - 綁定卡片選項\n   * @returns Promise 解析為綁定卡片回應（包含 card_key 和 card_token）\n   * @throws {TapPayValidationError} 當必要欄位缺失或無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const response = await client.bindCard({\n   *   prime: 'prime_from_frontend',\n   *   currency: Currency.TWD,\n   *   cardholder: {\n   *     phone_number: '+886912345678',\n   *     name: 'Test User',\n   *     email: 'test@example.com'\n   *   }\n   * })\n   *\n   * if (response.card_secret) {\n   *   const { card_key, card_token } = response.card_secret\n   *   // 儲存以供未來付款使用\n   * }\n   * ```\n   */\n  async bindCard(\n    options: Omit<BindCardRequest, 'partner_key' | 'merchant_id'>\n  ): Promise<BindCardResponse> {\n    return this.cardService.bindCard(options)\n  }\n\n  /**\n   * 移除綁定的卡片\n   *\n   * 從 TapPay 伺服器移除已綁定的卡片。\n   *\n   * @param cardKey - 要移除的卡片 key\n   * @param cardToken - 要移除的卡片 token\n   * @returns Promise 解析為移除卡片回應\n   * @throws {TapPayValidationError} 當 cardKey 或 cardToken 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * await client.removeCard('card_key_123', 'card_token_123')\n   * ```\n   */\n  async removeCard(cardKey: string, cardToken: string): Promise<RemoveCardResponse> {\n    return this.cardService.removeCard(cardKey, cardToken)\n  }\n\n  // ============================================================================\n  // Query APIs\n  // ============================================================================\n\n  /**\n   * 查詢交易記錄\n   *\n   * 使用篩選和分頁功能取得交易記錄。\n   * 時間範圍篩選限制為 90 天。\n   *\n   * @param options - 查詢選項（篩選、分頁、排序）\n   * @returns Promise 解析為交易記錄回應\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const records = await client.getRecords({\n   *   records_per_page: 10,\n   *   page: 0,\n   *   filters: {\n   *     rec_trade_id: 'D20231201123456789'\n   *   }\n   * })\n   * ```\n   */\n  async getRecords(options?: Omit<RecordRequest, 'partner_key'>): Promise<RecordResponse> {\n    return this.transactionService.getRecords(options)\n  }\n\n  /**\n   * 根據 ID 取得單筆交易\n   *\n   * 便利方法，用於查詢單筆交易記錄。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @returns Promise 解析為交易記錄，如果找不到則返回 null\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const record = await client.getTransaction('D20231201123456789')\n   * if (record) {\n   *   console.log(`Status: ${record.status}`)\n   * }\n   * ```\n   */\n  async getTransaction(recTradeId: string) {\n    return this.transactionService.getTransaction(recTradeId)\n  }\n\n  /**\n   * 取得交易歷史記錄\n   *\n   * 取得詳細的交易歷史記錄，包含所有事件（授權、請款、退款等）。\n   *\n   * @param recTradeId - TapPay 交易 ID\n   * @returns Promise 解析為交易歷史回應\n   * @throws {TapPayValidationError} 當交易 ID 無效時\n   * @throws {TapPayError} 當 API 回應錯誤時\n   * @throws {TapPayTimeoutError} 當請求超時時\n   *\n   * @example\n   * ```typescript\n   * const history = await client.getTradeHistory('D20231201123456789')\n   * history.trade_history?.forEach(event => {\n   *   console.log(`${event.event_type}: ${event.status}`)\n   * })\n   * ```\n   */\n  async getTradeHistory(recTradeId: string): Promise<TradeHistoryResponse> {\n    return this.cardService.getTradeHistory(recTradeId)\n  }\n\n  // ============================================================================\n  // Utility Getters\n  // ============================================================================\n\n  /**\n   * 取得當前環境\n   *\n   * @returns 當前使用的 TapPay API 環境（Sandbox 或 Production）\n   * @readonly\n   */\n  get environment(): Env {\n    return this.config.env\n  }\n\n  /**\n   * 檢查是否使用沙盒環境\n   *\n   * @returns 如果使用沙盒環境則返回 true，否則返回 false\n   * @readonly\n   */\n  get isSandbox(): boolean {\n    return this.config.env === Env.Sandbox\n  }\n\n  /**\n   * 取得商家 ID\n   *\n   * @returns 商家 ID\n   * @readonly\n   */\n  get merchantId(): string {\n    return this.config.merchantId\n  }\n}\n",
    "/**\n * 敏感資訊清理規則\n *\n * @internal\n */\nconst SENSITIVE_PATTERNS = [\n  { pattern: /\"prime\"\\s*:\\s*\"[^\"]*\"/gi, replacement: '\"prime\":\"***\"' },\n  { pattern: /\"card_number\"\\s*:\\s*\"[^\"]*\"/gi, replacement: '\"card_number\":\"****\"' },\n  { pattern: /\"card\"\\s*:\\s*{\\s*\"number\"\\s*:\\s*\"[^\"]*\"/gi, replacement: '\"card\":{\"number\":\"****\"' },\n  { pattern: /\"amount\"\\s*:\\s*\\d+/gi, replacement: '\"amount\":\"***\"' },\n  { pattern: /\"partner_key\"\\s*:\\s*\"[^\"]*\"/gi, replacement: '\"partner_key\":\"***\"' },\n  { pattern: /\"nonce\"\\s*:\\s*\"[^\"]*\"/gi, replacement: '\"nonce\":\"***\"' },\n  { pattern: /\"token\"\\s*:\\s*\"[^\"]*\"/gi, replacement: '\"token\":\"***\"' },\n] as const\n\n/**\n * 清理錯誤物件中的敏感資訊以供日誌記錄\n *\n * 移除信用卡號、金額、prime、partner key 等敏感資訊，\n * 同時保留除錯所需的錯誤類型、狀態碼和訊息。\n *\n * @param error - 任何類型的錯誤物件\n * @returns 清理後的錯誤訊息字串\n *\n * @example\n * ```typescript\n * import { scrubErrorForLogging } from '@carllee1983/tappay-backend-payment-node'\n *\n * try {\n *   await client.payByPrime({\n *     prime: 'sensitive_prime',\n *     amount: 1000,\n *     // ...\n *   })\n * } catch (error) {\n *   // 記錄清理後的錯誤（不包含敏感資訊）\n *   const safeLog = scrubErrorForLogging(error)\n *   logger.error('Payment failed:', safeLog)\n *   // 輸出: Payment failed: {\"statusCode\":400,\"message\":\"Invalid prime\",\"details\":\"***\"}\n * }\n * ```\n */\nexport function scrubErrorForLogging(error: unknown): string {\n  try {\n    let errorString: string\n\n    if (error instanceof Error) {\n      // 標準 Error 物件\n      errorString = JSON.stringify({\n        name: error.name,\n        message: error.message,\n        stack: process.env.NODE_ENV === 'development' ? error.stack : undefined,\n      })\n    } else if (error && typeof error === 'object') {\n      // 泛型物件（包括 TapPayError、Response 等）\n      const errorObj = error as Record<string, unknown>\n\n      // 先將整個物件轉換為 JSON 字串，以便應用正規表達式清理\n      errorString = JSON.stringify(errorObj)\n    } else if (typeof error === 'string') {\n      errorString = error\n    } else {\n      errorString = String(error)\n    }\n\n    // 應用敏感資訊清理規則\n    for (const { pattern, replacement } of SENSITIVE_PATTERNS) {\n      errorString = errorString.replace(pattern, replacement)\n    }\n\n    return errorString\n  } catch {\n    // 如果清理過程出錯，返回通用訊息\n    return '[Error occurred during error scrubbing]'\n  }\n}\n\n/**\n * 判斷錯誤是否應該重試\n *\n * 根據錯誤類型和 HTTP 狀態碼判斷是否應該重試。\n * 通常應重試的錯誤包括：\n * - 5xx 伺服器錯誤\n * - 429 Too Many Requests\n * - 連接超時\n * - 網路錯誤\n *\n * @param error - 要判斷的錯誤物件\n * @returns true 表示應該重試，false 表示應該放棄\n *\n * @example\n * ```typescript\n * import { isRetryableError, retryWithBackoff } from '@carllee1983/tappay-backend-payment-node'\n *\n * // 在重試邏輯中使用\n * const result = await retryWithBackoff(\n *   async () => client.getTransaction(id),\n *   {\n *     maxRetries: 3,\n *     shouldRetry: isRetryableError\n *   }\n * )\n *\n * // 或用於錯誤處理決策\n * try {\n *   const data = await fetchData()\n * } catch (error) {\n *   if (isRetryableError(error)) {\n *     // 可以重試\n *     return retryWithBackoff(() => fetchData())\n *   } else {\n *     // 不應重試的錯誤（如驗證錯誤）\n *     throw error\n *   }\n * }\n * ```\n */\nexport function isRetryableError(error: unknown): boolean {\n  if (!error) {\n    return false\n  }\n\n  // 檢查 HTTP 狀態碼\n  if (typeof error === 'object') {\n    const errorObj = error as Record<string, unknown>\n\n    // 檢查 statusCode 或 status\n    const statusCode =\n      (errorObj.statusCode as number) || (errorObj.status as number) || (errorObj.code as number)\n\n    if (typeof statusCode === 'number') {\n      // 重試 5xx 錯誤和 429 Too Many Requests\n      return statusCode >= 500 || statusCode === 429\n    }\n\n    // 檢查特定的錯誤訊息（如超時、連接錯誤）\n    const message = (errorObj.message as string) || ''\n    const messageLower = message.toLowerCase()\n    const retryableMessages = [\n      'timeout',\n      'econnrefused',\n      'econnreset',\n      'ehostunreach',\n      'enetunreach',\n      'enotfound',\n      'connection',\n    ]\n\n    return retryableMessages.some((msg) => messageLower.includes(msg))\n  }\n\n  // 檢查 Error 訊息\n  if (error instanceof Error) {\n    const message = error.message.toLowerCase()\n    return message.includes('timeout') || message.includes('connection')\n  }\n\n  return false\n}\n",
    "/**\n * 重試選項配置\n *\n * @interface RetryOptions\n * @property maxRetries - 最大重試次數（預設 3）\n * @property baseDelay - 初始延遲毫秒數（預設 100）\n * @property maxDelay - 最大延遲毫秒數（預設 5000）\n * @property backoffMultiplier - 退避倍數（預設 2）\n * @property shouldRetry - 自訂重試條件函數\n */\nexport interface RetryOptions {\n  /**\n   * 最大重試次數\n   *\n   * @default 3\n   */\n  maxRetries?: number\n\n  /**\n   * 初始延遲毫秒數\n   *\n   * @default 100\n   */\n  baseDelay?: number\n\n  /**\n   * 最大延遲毫秒數\n   *\n   * @default 5000\n   */\n  maxDelay?: number\n\n  /**\n   * 指數退避倍數\n   *\n   * @default 2\n   */\n  backoffMultiplier?: number\n\n  /**\n   * 自訂重試判斷函數\n   * 返回 true 表示應該重試此錯誤\n   *\n   * @param error - 拋出的錯誤物件\n   * @returns 是否應該重試\n   */\n  shouldRetry?: (error: unknown) => boolean\n}\n\n/**\n * 預設重試選項\n *\n * @internal\n */\nconst DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {\n  maxRetries: 3,\n  baseDelay: 100,\n  maxDelay: 5000,\n  backoffMultiplier: 2,\n  shouldRetry: () => true,\n} as const\n\n/**\n * 計算指數退避延遲時間\n *\n * @internal\n */\nfunction calculateDelay(\n  attempt: number,\n  baseDelay: number,\n  maxDelay: number,\n  backoffMultiplier: number\n): number {\n  const exponentialDelay = baseDelay * backoffMultiplier ** attempt\n  return Math.min(exponentialDelay, maxDelay)\n}\n\n/**\n * 暫停執行指定毫秒數\n *\n * @internal\n */\nfunction delay(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * 帶指數退避的非同步重試執行\n *\n * 自動重試失敗的非同步操作，採用指數退避演算法。\n * 每次失敗時延遲遞增，直到達到最大延遲時間。\n *\n * @typeParam T - 操作返回的結果類型\n * @param operation - 要執行的非同步操作函數\n * @param options - 重試配置選項\n * @returns 操作的返回值\n * @throws {Error} 達到最大重試次數後拋出原始錯誤\n *\n * @example\n * ```typescript\n * import { retryWithBackoff } from '@carllee1983/tappay-backend-payment-node'\n *\n * // 基本用法：預設配置（最多 3 次重試）\n * const result = await retryWithBackoff(async () => {\n *   return await fetch('https://api.example.com/data')\n * })\n *\n * // 自訂重試次數和延遲\n * const response = await retryWithBackoff(\n *   async () => client.getTransaction(id),\n *   {\n *     maxRetries: 5,\n *     baseDelay: 200,\n *     maxDelay: 10000,\n *     backoffMultiplier: 2\n *   }\n * )\n *\n * // 自訂重試判斷（只重試特定錯誤）\n * const data = await retryWithBackoff(\n *   async () => client.fetchData(),\n *   {\n *     maxRetries: 3,\n *     shouldRetry: (error: unknown) => {\n *       // 只重試 5xx 錯誤和 429 Too Many Requests\n *       if (error instanceof Response) {\n *         return error.status >= 500 || error.status === 429\n *       }\n *       return false\n *     }\n *   }\n * )\n * ```\n */\nexport async function retryWithBackoff<T>(\n  operation: () => Promise<T>,\n  options?: RetryOptions\n): Promise<T> {\n  const mergedOptions: Required<RetryOptions> = {\n    maxRetries: options?.maxRetries ?? DEFAULT_RETRY_OPTIONS.maxRetries,\n    baseDelay: options?.baseDelay ?? DEFAULT_RETRY_OPTIONS.baseDelay,\n    maxDelay: options?.maxDelay ?? DEFAULT_RETRY_OPTIONS.maxDelay,\n    backoffMultiplier: options?.backoffMultiplier ?? DEFAULT_RETRY_OPTIONS.backoffMultiplier,\n    shouldRetry: options?.shouldRetry ?? DEFAULT_RETRY_OPTIONS.shouldRetry,\n  }\n\n  let lastError: unknown\n\n  for (let attempt = 0; attempt <= mergedOptions.maxRetries; attempt++) {\n    try {\n      return await operation()\n    } catch (error) {\n      lastError = error\n\n      // 檢查是否應該重試\n      if (!mergedOptions.shouldRetry(error)) {\n        throw error\n      }\n\n      // 如果是最後一次嘗試，拋出錯誤\n      if (attempt === mergedOptions.maxRetries) {\n        throw error\n      }\n\n      // 計算延遲時間並等待\n      const delayMs = calculateDelay(\n        attempt,\n        mergedOptions.baseDelay,\n        mergedOptions.maxDelay,\n        mergedOptions.backoffMultiplier\n      )\n\n      await delay(delayMs)\n    }\n  }\n\n  // 此行不會被執行，但需要用於類型檢查\n  throw lastError\n}\n",
    "import { createHmac, timingSafeEqual } from 'node:crypto'\n\n/**\n * Webhook 簽名驗證配置\n *\n * @internal\n */\nconst WEBHOOK_CONFIG = {\n  algorithm: 'sha256',\n  encoding: 'hex' as const,\n} as const\n\n/**\n * 驗證 TapPay Webhook 簽名\n *\n * 使用 HMAC-SHA256 驗證 Webhook payload 的簽名，防止重放攻擊和未授權修改。\n * 採用時序安全的比較方式避免計時側信道攻擊。\n *\n * @param payload - Webhook payload 物件（未序列化）\n * @param signature - 接收到的 Webhook 簽名（十六進位字串）\n * @param partnerKey - TapPay Partner Key\n * @returns 簽名是否有效\n *\n * @throws {Error} 如果 payload 無法序列化\n *\n * @example\n * ```typescript\n * import { verifyTapPayWebhook } from '@carllee1983/tappay-backend-payment-node'\n *\n * // 在 Express/Fastify webhook 處理器中\n * app.post('/webhook', (req, res) => {\n *   const { signature, body } = req.headers\n *   const payload = req.body\n *\n *   const isValid = verifyTapPayWebhook(\n *     payload,\n *     signature as string,\n *     process.env.TAPPAY_PARTNER_KEY!\n *   )\n *\n *   if (!isValid) {\n *     return res.status(401).json({ error: 'Invalid signature' })\n *   }\n *\n *   // 處理 webhook\n *   processWebhook(payload)\n *   res.json({ success: true })\n * })\n * ```\n */\nexport function verifyTapPayWebhook(\n  payload: Record<string, unknown>,\n  signature: string,\n  partnerKey: string\n): boolean {\n  if (!payload || typeof payload !== 'object') {\n    return false\n  }\n\n  if (!signature || typeof signature !== 'string') {\n    return false\n  }\n\n  if (!partnerKey || typeof partnerKey !== 'string') {\n    return false\n  }\n\n  try {\n    const expectedSignature = generateWebhookSignature(payload, partnerKey)\n    // 時序安全的比較防止計時攻擊\n    return timingSafeEqual(\n      Buffer.from(signature, WEBHOOK_CONFIG.encoding),\n      Buffer.from(expectedSignature, WEBHOOK_CONFIG.encoding)\n    )\n  } catch {\n    return false\n  }\n}\n\n/**\n * 生成 TapPay Webhook 簽名\n *\n * 將 payload 序列化後使用 HMAC-SHA256 計算簽名。\n * 供測試和內部使用。\n *\n * @param payload - Webhook payload 物件\n * @param partnerKey - TapPay Partner Key\n * @returns 簽名字串（十六進位格式）\n *\n * @throws {Error} 如果 payload 無法序列化\n *\n * @example\n * ```typescript\n * import { generateWebhookSignature } from '@carllee1983/tappay-backend-payment-node'\n *\n * // 生成簽名用於測試\n * const payload = {\n *   status: 0,\n *   message: 'Success',\n *   info: { transactionId: '12345' }\n * }\n * const signature = generateWebhookSignature(payload, 'your_partner_key')\n * ```\n */\nexport function generateWebhookSignature(\n  payload: Record<string, unknown>,\n  partnerKey: string\n): string {\n  const payloadString = JSON.stringify(payload)\n  const hmac = createHmac(WEBHOOK_CONFIG.algorithm, partnerKey)\n  hmac.update(payloadString)\n  return hmac.digest(WEBHOOK_CONFIG.encoding)\n}\n",
    "/**\n * TapPay 後端付款 SDK for Node.js\n *\n * 一個完整的 TypeScript SDK，用於與 TapPay 後端付款 API 互動。\n * 提供完整的類型支援、錯誤處理和輸入驗證。\n *\n * @module @carllee1983/tappay-backend-payment-node\n * @see {@link https://docs.tappaysdk.com/tutorial/zh/back.html TapPay 官方文件}\n *\n * @example\n * ```typescript\n * import { TapPayClient, Env, Currency } from '@carllee1983/tappay-backend-payment-node'\n *\n * const client = new TapPayClient({\n *   partnerKey: 'your_partner_key',\n *   merchantId: 'your_merchant_id',\n *   env: Env.Sandbox\n * })\n *\n * const response = await client.payByPrime({\n *   prime: 'prime_from_frontend',\n *   amount: 100,\n *   currency: Currency.TWD,\n *   details: 'Test Payment'\n * })\n * ```\n */\n\n// Export version from package.json\nimport packageJson from '../package.json'\n\n/**\n * SDK 版本號\n *\n * 從 package.json 自動匯出的版本號。\n *\n * @example\n * ```typescript\n * import { VERSION } from '@carllee1983/tappay-backend-payment-node'\n * console.log(`SDK Version: ${VERSION}`)\n * ```\n */\nexport const VERSION = packageJson.version\n\n// ============================================================================\n// Configuration\n// ============================================================================\nexport { Env } from './config/Env'\nexport type { TapPayConfig } from './config/TapPayConfig'\nexport type { Cardholder } from './domain/Cardholder'\n// ============================================================================\n// Domain Types\n// ============================================================================\nexport type { CardInfo, CardSecret } from './domain/CardInfo'\nexport type { ResultUrl } from './domain/ResultUrl'\n\n// ============================================================================\n// Enums\n// ============================================================================\nexport { CardType, getCardTypeName } from './enums/CardType'\nexport { Currency, CurrencyMultiplier } from './enums/Currency'\n\n// ============================================================================\n// Errors\n// ============================================================================\nexport { TapPayConfigError } from './errors/TapPayConfigError'\nexport { TapPayError } from './errors/TapPayError'\nexport { TapPayTimeoutError } from './errors/TapPayTimeoutError'\nexport { TapPayValidationError } from './errors/TapPayValidationError'\n\n// ============================================================================\n// Request Types\n// ============================================================================\nexport type {\n  BindCardRequest,\n  CapCancelRequest,\n  CapTodayRequest,\n  PayByPrimeRequest,\n  PayByTokenRequest,\n  RecordFilters,\n  RecordOrder,\n  RecordRequest,\n  RefundCancelRequest,\n  RefundRequest,\n  RemoveCardRequest,\n  TradeHistoryRequest,\n} from './payments/PaymentRequest'\n\n// ============================================================================\n// Response Types\n// ============================================================================\nexport type {\n  BackendNotifyPayload,\n  BindCardResponse,\n  CapCancelResponse,\n  CapTodayResponse,\n  PaymentResponse,\n  RecordResponse,\n  RefundCancelResponse,\n  RefundRecord,\n  RefundResponse,\n  RemoveCardResponse,\n  TapPayBaseResponse,\n  TradeHistoryEvent,\n  TradeHistoryResponse,\n  TradeRecord,\n} from './payments/PaymentResponse'\n\n// ============================================================================\n// Service classes (new in v1.8.0)\n// ============================================================================\nexport { BaseService } from './services/BaseService'\nexport { CardService } from './services/CardService'\nexport { PaymentService } from './services/PaymentService'\nexport { TransactionService } from './services/TransactionService'\n// ============================================================================\n// Core Client\n// ============================================================================\nexport { TapPayClient } from './TapPayClient'\n// ============================================================================\n// Utility functions (new in v1.8.0)\n// ============================================================================\nexport { isRetryableError, scrubErrorForLogging } from './utils/errorHandling'\nexport { type RetryOptions, retryWithBackoff } from './utils/retry'\nexport {\n  generateWebhookSignature,\n  verifyTapPayWebhook,\n} from './utils/webhooks'\n"
  ],
  "mappings": "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",
  "debugId": "729EA6AB4BCB227464756E2164756E21",
  "names": []
}