{"version":3,"file":"payload.cjs","sources":["webpack://thai-qr-payment/../payload/src/amount.ts","webpack://thai-qr-payment/../payload/src/barcode.ts","webpack://thai-qr-payment/../payload/src/builder.ts","webpack://thai-qr-payment/../payload/src/crc.ts","webpack://thai-qr-payment/../payload/src/index.ts","webpack://thai-qr-payment/../payload/src/message.ts","webpack://thai-qr-payment/../payload/src/parser.ts","webpack://thai-qr-payment/../payload/src/recipient.ts","webpack://thai-qr-payment/../payload/src/slip-verify.ts","webpack://thai-qr-payment/../payload/src/tags.ts","webpack://thai-qr-payment/../payload/src/tlv.ts","webpack://thai-qr-payment/./src/payload.ts"],"sourcesContent":["/**\n * Amount formatting for tag 54 (Transaction Amount).\n *\n * EMVCo allows up to 13 chars including the decimal point — Thai banks\n * cap the integer part at 10 digits + 2 decimals. We accept either a\n * number (in baht) or a satang-int + flag, and always emit 2 decimals\n * because that's what every Thai banking app re-displays consistently.\n */\n\nconst MAX_BAHT = 9_999_999_999.99; // 13 chars: \"9999999999.99\"\n\nexport interface FormatAmountOptions {\n  /** When true, treat the input as integer satang (1 baht = 100 satang). */\n  fromSatang?: boolean;\n}\n\n/**\n * Format an amount for the wire. Returns `null` for static QR (caller\n * intends a \"scan and enter any amount\" code).\n */\nexport function formatAmount(\n  value: number | bigint | undefined | null,\n  options: FormatAmountOptions = {},\n): string | null {\n  if (value == null) return null;\n\n  let baht: number;\n  if (typeof value === 'bigint') {\n    baht = options.fromSatang ? Number(value) / 100 : Number(value);\n  } else {\n    baht = options.fromSatang ? value / 100 : value;\n  }\n\n  if (!Number.isFinite(baht)) {\n    throw new TypeError('Amount must be a finite number');\n  }\n  if (baht <= 0) return null;\n  if (baht > MAX_BAHT) {\n    throw new RangeError(`Amount ${baht} exceeds max wire value ${MAX_BAHT}`);\n  }\n\n  // Round to 2 decimals using integer math to dodge float-printout\n  // surprises like 0.1 + 0.2 → \"0.30000000000000004\".\n  const cents = Math.round(baht * 100);\n  const baht10 = Math.floor(cents / 100);\n  const sub = cents - baht10 * 100;\n  return `${baht10}.${sub.toString(10).padStart(2, '0')}`;\n}\n","/**\n * Bank of Thailand 1D barcode (bill-payment, counter-scanned).\n *\n * This is intentionally not part of the EMVCo TLV machinery in the rest\n * of the package. The BOT barcode is a `|`-led, `\\r`-delimited ASCII\n * string scanned at bank counters and 7-Eleven cashier stations for\n * over-the-counter bill payments — not a QR, not TLV, no CRC. It shares\n * the cross-bank biller-id concept with EMVCo tag 30 but the wire\n * format is otherwise unrelated, so it lives in its own module to keep\n * the TLV builder + parser tree-shake cleanly when callers only need\n * one or the other.\n *\n * Wire shape:  `|<billerId>\\r<ref1>\\r<ref2>\\r<amount>`\n *   - leading pipe is a fixed sentinel\n *   - billerId is 15 chars (Tax ID + suffix), zero-padded if shorter\n *   - ref1 is mandatory (customer/invoice number)\n *   - ref2 may be the empty string if unused\n *   - amount is integer satang (baht × 100), or the literal \"0\" when\n *     the cashier is expected to key the amount in by hand\n */\n\nconst FIELD_SEPARATOR = '\\r';\nconst PAYLOAD_PREFIX = '|';\nconst BILLER_ID_LENGTH = 15;\nconst NO_AMOUNT_SENTINEL = '0';\n/** 13 chars: \"9999999999.99\" — matches `formatAmount`'s cap for consistency. */\nconst MAX_BAHT = 9_999_999_999.99;\n\nexport interface BOTBarcodeInput {\n  /** Cross-bank biller id (Tax ID + suffix). ≤ 15 chars, zero-padded on emit. */\n  billerId: string;\n  /** Customer / invoice reference. Must be non-empty. */\n  ref1: string;\n  /** Optional secondary reference. Empty string on the wire if omitted. */\n  ref2?: string;\n  /**\n   * Baht amount. Omit (or pass `undefined`) for a counter-keyed total —\n   * the literal \"0\" is then written and the cashier types the amount.\n   */\n  amount?: number;\n}\n\nexport interface ParsedBOTBarcode {\n  billerId: string;\n  ref1: string;\n  ref2?: string;\n  amount?: number;\n}\n\n/**\n * Build a BOT 1D bill-payment barcode payload.\n *\n * Throws `TypeError` / `RangeError` for malformed input — the caller\n * never silently produces an unscannable barcode.\n *\n * @example\n *   buildBOTBarcode({ billerId: '099999999999990', ref1: '111222333444' })\n *   // → '|099999999999990\\r111222333444\\r\\r0'\n *\n * @example\n *   buildBOTBarcode({\n *     billerId: '099400016550100',\n *     ref1: '123456789012',\n *     ref2: '670429',\n *     amount: 3649.22,\n *   })\n *   // → '|099400016550100\\r123456789012\\r670429\\r364922'\n */\nexport function buildBOTBarcode(input: BOTBarcodeInput): string {\n  const billerId = normaliseBillerId(input.billerId);\n  const ref1 = ensureRef('ref1', input.ref1, { allowEmpty: false });\n  const ref2 = ensureRef('ref2', input.ref2 ?? '', { allowEmpty: true });\n  const amountField = formatAmountField(input.amount);\n\n  return (\n    PAYLOAD_PREFIX +\n    billerId +\n    FIELD_SEPARATOR +\n    ref1 +\n    FIELD_SEPARATOR +\n    ref2 +\n    FIELD_SEPARATOR +\n    amountField\n  );\n}\n\n/**\n * Parse a BOT 1D bill-payment barcode back into its component fields.\n *\n * Returns `null` for any structural issue (missing prefix, wrong field\n * count, biller-id too short) so callers can branch without `try/catch`.\n * The trailing amount is decoded back to baht (e.g. `'364922'` → `3649.22`),\n * and the literal \"0\" sentinel surfaces as `undefined`.\n *\n * @example\n *   parseBOTBarcode('|099999999999990\\r111222333444\\r\\r0')\n *   // → { billerId: '099999999999990', ref1: '111222333444' }\n *\n * @example\n *   parseBOTBarcode('|099400016550100\\r123456789012\\r670429\\r364922')\n *   // → {\n *   //     billerId: '099400016550100',\n *   //     ref1: '123456789012',\n *   //     ref2: '670429',\n *   //     amount: 3649.22,\n *   //   }\n */\nexport function parseBOTBarcode(barcode: string): ParsedBOTBarcode | null {\n  if (typeof barcode !== 'string') return null;\n  if (!barcode.startsWith(PAYLOAD_PREFIX)) return null;\n\n  // `\\r` delimiters resolve the otherwise-ambiguous variable-length\n  // ref1/ref2/amount tail. Four parts exactly — no more, no less.\n  const parts = barcode.slice(PAYLOAD_PREFIX.length).split(FIELD_SEPARATOR);\n  if (parts.length !== 4) return null;\n\n  const billerId = parts[0]!;\n  const ref1 = parts[1]!;\n  const ref2 = parts[2]!;\n  const amountField = parts[3]!;\n\n  if (billerId.length < BILLER_ID_LENGTH) return null;\n  if (ref1.length === 0) return null;\n\n  const result: ParsedBOTBarcode = { billerId, ref1 };\n  if (ref2.length > 0) result.ref2 = ref2;\n\n  const amount = decodeAmountField(amountField);\n  if (amount === 'invalid') return null;\n  if (amount != null) result.amount = amount;\n\n  return result;\n}\n\n/** Pad short biller ids to the 15-char wire width; reject overlong ones. */\nfunction normaliseBillerId(raw: string): string {\n  if (typeof raw !== 'string' || raw.length === 0) {\n    throw new TypeError('billerId must be a non-empty string');\n  }\n  if (raw.includes(FIELD_SEPARATOR)) {\n    throw new TypeError('billerId must not contain a carriage return');\n  }\n  if (raw.length > BILLER_ID_LENGTH) {\n    throw new RangeError(`billerId is ${raw.length} chars; max is ${BILLER_ID_LENGTH}`);\n  }\n  return raw.padStart(BILLER_ID_LENGTH, '0');\n}\n\n/** Reject CR and (optionally) empty refs without inventing extra rules. */\nfunction ensureRef(name: 'ref1' | 'ref2', value: string, options: { allowEmpty: boolean }): string {\n  if (typeof value !== 'string') {\n    throw new TypeError(`${name} must be a string`);\n  }\n  if (!options.allowEmpty && value.length === 0) {\n    throw new TypeError(`${name} must be a non-empty string`);\n  }\n  if (value.includes(FIELD_SEPARATOR)) {\n    throw new TypeError(`${name} must not contain a carriage return`);\n  }\n  return value;\n}\n\n/** Encode the trailing amount field as integer satang, or the \"0\" sentinel. */\nfunction formatAmountField(amount: number | undefined): string {\n  if (amount == null) return NO_AMOUNT_SENTINEL;\n  if (!Number.isFinite(amount)) {\n    throw new TypeError('amount must be a finite number');\n  }\n  if (amount < 0) {\n    throw new RangeError('amount must be non-negative');\n  }\n  if (amount > MAX_BAHT) {\n    throw new RangeError(`amount ${amount} exceeds max wire value ${MAX_BAHT}`);\n  }\n  // Integer math so 0.1 + 0.2 → \"30\" instead of \"30.0000000004\".\n  const satang = Math.round(amount * 100);\n  return satang === 0 ? NO_AMOUNT_SENTINEL : satang.toString(10);\n}\n\n/**\n * Decode the trailing amount field.\n *\n * Returns `'invalid'` (a discriminator, not a value) for malformed input,\n * `null` for the \"amount entered at counter\" sentinel, or the decoded\n * baht number otherwise.\n */\nfunction decodeAmountField(field: string): number | null | 'invalid' {\n  if (field.length === 0) return 'invalid';\n  if (field === NO_AMOUNT_SENTINEL) return null;\n  // BOT spec specifies the amount field as integer satang. Reject any\n  // non-digit content (including a stray decimal point or sign).\n  for (let i = 0; i < field.length; i += 1) {\n    const code = field.charCodeAt(i);\n    if (code < 0x30 || code > 0x39) return 'invalid';\n  }\n  const satang = Number.parseInt(field, 10);\n  if (!Number.isFinite(satang)) return 'invalid';\n  if (satang === 0) return null;\n  // Round-trip through integer math to keep the baht side exact.\n  const baht = Math.floor(satang / 100);\n  const sub = satang - baht * 100;\n  return baht + sub / 100;\n}\n","/**\n * Fluent builder for the Thai QR Payment wire payload.\n *\n * The builder collects field assignments in an ordered list, then renders\n * the final string in one pass with the CRC computed over the body plus\n * the CRC tag header (`6304`) — that header is part of the hashed input\n * per EMVCo §4, which surprises everyone who reads the spec for the\n * first time.\n *\n * Order on the wire is fixed by tag id (lowest first). The builder\n * stores fields in a Map keyed by tag id and emits them sorted at\n * `build()`-time so callers can set them in any order without breaking\n * the resulting checksum.\n */\n\nimport { formatAmount, type FormatAmountOptions } from './amount.js';\nimport { checksum } from './crc.js';\nimport { encodePersonalMessage } from './message.js';\nimport {\n  normaliseBankAccount,\n  normaliseRecipient,\n  type NormalisedRecipient,\n  type PromptPayRecipientType,\n} from './recipient.js';\nimport {\n  COUNTRY_TH,\n  CURRENCY_THB,\n  GUID_BILL_PAYMENT,\n  GUID_BILL_PAYMENT_CROSS_BORDER,\n  GUID_PROMPTPAY,\n  GUID_PROMPTPAY_OTA,\n  PAYLOAD_FORMAT_VERSION,\n  POI_DYNAMIC,\n  POI_STATIC,\n  SUB_ADD_BILL_NUMBER,\n  SUB_ADD_CONSUMER_DATA_REQUEST,\n  SUB_ADD_CUSTOMER_LABEL,\n  SUB_ADD_LOYALTY_NUMBER,\n  SUB_ADD_MOBILE_NUMBER,\n  SUB_ADD_PURPOSE_OF_TRANSACTION,\n  SUB_ADD_REFERENCE_LABEL,\n  SUB_ADD_STORE_LABEL,\n  SUB_ADD_TERMINAL_LABEL,\n  SUB_BILL_BILLER_ID,\n  SUB_BILL_REFERENCE_1,\n  SUB_BILL_REFERENCE_2,\n  SUB_GUID,\n  SUB_PROMPTPAY_OTA,\n  SUB_TRUE_MONEY,\n  SUB_VAT_AMOUNT,\n  SUB_VAT_RATE,\n  SUB_VAT_SELLER_TAX_BRANCH_ID,\n  TAG_ADDITIONAL_DATA,\n  TAG_CHECKSUM,\n  TAG_COUNTRY_CODE,\n  TAG_MERCHANT_ACCOUNT_BILL_PAYMENT,\n  TAG_MERCHANT_ACCOUNT_PROMPTPAY,\n  TAG_MERCHANT_CATEGORY_CODE,\n  TAG_MERCHANT_CITY,\n  TAG_MERCHANT_NAME,\n  TAG_PAYLOAD_FORMAT,\n  TAG_PERSONAL_MESSAGE,\n  TAG_POINT_OF_INITIATION,\n  TAG_POSTAL_CODE,\n  TAG_TIP_FIXED,\n  TAG_TIP_OR_CONVENIENCE_INDICATOR,\n  TAG_TIP_PERCENTAGE,\n  TAG_TRANSACTION_AMOUNT,\n  TAG_TRANSACTION_CURRENCY,\n  TAG_VAT_TQRC,\n  TIP_FIXED,\n  TIP_PERCENTAGE,\n  TIP_PROMPT,\n  TRUE_MONEY_PREFIX,\n} from './tags.js';\nimport { encodeField, encodeFields } from './tlv.js';\n\nconst OTA_CODE_LENGTH = 10;\n\nexport interface AdditionalDataFields {\n  billNumber?: string;\n  mobileNumber?: string;\n  storeLabel?: string;\n  loyaltyNumber?: string;\n  referenceLabel?: string;\n  customerLabel?: string;\n  terminalLabel?: string;\n  purposeOfTransaction?: string;\n  consumerDataRequest?: string;\n}\n\nexport type TipMode =\n  | { mode: 'prompt' }\n  | { mode: 'fixed'; value: number; fromSatang?: boolean }\n  | { mode: 'percentage'; value: number };\n\nexport interface MerchantInfo {\n  /** Up to 25 alphanumeric characters; truncated by the builder. */\n  name?: string;\n  /** Up to 15 alphanumeric characters. */\n  city?: string;\n  /** Up to 10 chars. */\n  postalCode?: string;\n  /** 4-digit Merchant Category Code from ISO 18245. */\n  categoryCode?: string;\n}\n\nexport interface VATTQRCInput {\n  /** Seller's tax branch identifier — exactly 4 characters. */\n  sellerTaxBranchId: string;\n  /** VAT rate as displayed on the receipt (e.g. \"7\" or \"7.00\"); 1–5 chars. */\n  vatRate?: string;\n  /** VAT amount as displayed on the receipt; 1–13 chars, required. */\n  vatAmount: string;\n}\n\n/**\n * Thai QR Payment payload builder.\n *\n * Three terminal methods:\n *  - `.build()` returns the wire-format string ready for QR encoding.\n *  - `.buildWithChecksum()` returns both the body and the checksum\n *    separately — useful for debugging the CRC step.\n *  - `.toBytes()` returns a `Uint8Array` of the ASCII-encoded payload\n *    for callers that want to hash or sign it.\n */\nexport class ThaiQRPaymentBuilder {\n  private readonly fields = new Map<string, string>();\n  private readonly additional: AdditionalDataFields = {};\n  private tip: TipMode | undefined;\n  private personalMessage: string | undefined;\n  private promptPayRecipient: NormalisedRecipient | undefined;\n  private otaCode: string | undefined;\n  private vat: VATTQRCInput | undefined;\n\n  constructor() {\n    this.fields.set(TAG_PAYLOAD_FORMAT, PAYLOAD_FORMAT_VERSION);\n    this.fields.set(TAG_POINT_OF_INITIATION, POI_STATIC);\n    this.fields.set(TAG_COUNTRY_CODE, COUNTRY_TH);\n    this.fields.set(TAG_TRANSACTION_CURRENCY, CURRENCY_THB);\n  }\n\n  /**\n   * Configure a PromptPay recipient (mobile, national ID, or e-wallet).\n   * Overrides any previously-set BillPayment / KShop template. Use\n   * `.bankAccount()` for credit-transfer payloads — its wire value needs\n   * the (bankCode, accountNo) split this single-string form cannot carry.\n   */\n  promptpay(recipient: string, type?: PromptPayRecipientType): this {\n    if (type === 'bankAccount') {\n      throw new TypeError('Use .bankAccount(bankCode, accountNo) for bank-account recipients');\n    }\n    this.promptPayRecipient = normaliseRecipient(recipient, type);\n    this.refreshPromptPayTemplate();\n    this.fields.delete(TAG_MERCHANT_ACCOUNT_BILL_PAYMENT);\n    return this;\n  }\n\n  /**\n   * Configure a PromptPay credit transfer to a bank account (sub-tag 04).\n   * `bankCode` is the 3-digit BoT bank identifier; `accountNo` is the\n   * variable-length numeric account.\n   *\n   * @example\n   *   new ThaiQRPaymentBuilder().bankAccount('014', '1234567890').amount(100).build()\n   */\n  bankAccount(bankCode: string, accountNo: string): this {\n    this.promptPayRecipient = normaliseBankAccount(bankCode, accountNo);\n    this.refreshPromptPayTemplate();\n    this.fields.delete(TAG_MERCHANT_ACCOUNT_BILL_PAYMENT);\n    return this;\n  }\n\n  /**\n   * Attach a One-Time Authorization code (sub-tag 05, fixed 10 chars).\n   * Flips the merchant template's AID from the standard PromptPay GUID to\n   * the OTA GUID so scanners route the payload to the single-use flow.\n   *\n   * @example\n   *   new ThaiQRPaymentBuilder().promptpay('0812345678').ota('1234567890').amount(50).build()\n   */\n  ota(otaCode: string): this {\n    if (otaCode.length !== OTA_CODE_LENGTH) {\n      throw new RangeError(`OTA code must be ${OTA_CODE_LENGTH} chars, got ${otaCode.length}`);\n    }\n    this.otaCode = otaCode;\n    this.refreshPromptPayTemplate();\n    return this;\n  }\n\n  /** Re-emit tag 29 from the current recipient + OTA state. */\n  private refreshPromptPayTemplate(): void {\n    if (this.promptPayRecipient == null) return;\n    const aid = this.otaCode != null ? GUID_PROMPTPAY_OTA : GUID_PROMPTPAY;\n    const template = encodeFields([\n      [SUB_GUID, aid],\n      [this.promptPayRecipient.subTag, this.promptPayRecipient.value],\n      [SUB_PROMPTPAY_OTA, this.otaCode],\n    ]);\n    this.fields.set(TAG_MERCHANT_ACCOUNT_PROMPTPAY, template);\n  }\n\n  /**\n   * Configure a TrueMoney Wallet recipient. Same merchant template tag\n   * (29) as PromptPay but with the literal `14` prefix on sub-tag 03 so\n   * the TrueMoney app can disambiguate its own payloads from a plain\n   * e-wallet QR. The mobile is zero-padded on the left to 13 digits\n   * before the prefix is added (final value length is always 15).\n   *\n   * The optional `message` is carried in tag 81 (UTF-16BE hex) and is\n   * surfaced inside the TrueMoney app only; other scanners ignore it.\n   */\n  trueMoney(mobileNo: string, options: { amount?: number; message?: string } = {}): this {\n    const digits = mobileNo.replace(/\\D/g, '');\n    if (digits.length === 0) {\n      throw new TypeError('TrueMoney mobile number must contain at least one digit');\n    }\n    if (digits.length > 13) {\n      throw new RangeError(`TrueMoney mobile number too long (${digits.length} digits)`);\n    }\n    const wireMobile = TRUE_MONEY_PREFIX + digits.padStart(13, '0');\n    const template = encodeFields([\n      [SUB_GUID, GUID_PROMPTPAY],\n      [SUB_TRUE_MONEY, wireMobile],\n    ]);\n    this.fields.set(TAG_MERCHANT_ACCOUNT_PROMPTPAY, template);\n    this.fields.delete(TAG_MERCHANT_ACCOUNT_BILL_PAYMENT);\n    this.promptPayRecipient = undefined;\n    this.otaCode = undefined;\n    this.personalMessage = options.message;\n    if (options.amount != null) {\n      this.amount(options.amount);\n    } else {\n      this.amount(undefined);\n    }\n    return this;\n  }\n\n  /**\n   * Configure a BillPayment recipient (Cross-Bank BillPayment / R-Bill).\n   *\n   * Pass `crossBorder: true` to emit the ASEAN-region remittance AID\n   * (`A000000677012006`) instead of the domestic one (`A000000677010112`).\n   * The template layout is otherwise identical — same sub-tags, same\n   * value rules. Pair with the `purposeOfTransaction` additional-data\n   * field (tag 62 sub-tag 08), which carries an 18-char triple in this\n   * mode: currencyCode (3 digits) + localAmount (13 digits) +\n   * countryCode (2 digits). The builder treats that field as opaque;\n   * compose / parse the triple at the call site.\n   */\n  billPayment(input: {\n    billerId: string;\n    reference1?: string;\n    reference2?: string;\n    crossBorder?: boolean;\n  }): this {\n    const aid = input.crossBorder === true ? GUID_BILL_PAYMENT_CROSS_BORDER : GUID_BILL_PAYMENT;\n    const template = encodeFields([\n      [SUB_GUID, aid],\n      [SUB_BILL_BILLER_ID, input.billerId],\n      [SUB_BILL_REFERENCE_1, input.reference1],\n      [SUB_BILL_REFERENCE_2, input.reference2],\n    ]);\n    this.fields.set(TAG_MERCHANT_ACCOUNT_BILL_PAYMENT, template);\n    this.fields.delete(TAG_MERCHANT_ACCOUNT_PROMPTPAY);\n    this.promptPayRecipient = undefined;\n    this.otaCode = undefined;\n    return this;\n  }\n\n  /**\n   * Set the transaction amount in baht. Pass `{fromSatang: true}` to\n   * supply integer satang instead. Omit / pass `undefined` to keep the\n   * QR static (the consumer's banking app will prompt for an amount).\n   */\n  amount(value: number | bigint | undefined, options?: FormatAmountOptions): this {\n    const formatted = formatAmount(value, options);\n    if (formatted == null) {\n      this.fields.delete(TAG_TRANSACTION_AMOUNT);\n      this.fields.set(TAG_POINT_OF_INITIATION, POI_STATIC);\n    } else {\n      this.fields.set(TAG_TRANSACTION_AMOUNT, formatted);\n      this.fields.set(TAG_POINT_OF_INITIATION, POI_DYNAMIC);\n    }\n    return this;\n  }\n\n  /** Set the tip / convenience-fee policy (tags 55-57). */\n  tipPolicy(mode: TipMode | undefined): this {\n    this.tip = mode;\n    return this;\n  }\n\n  /** Set merchant display info (tags 52, 59, 60, 61). */\n  merchant(info: MerchantInfo): this {\n    if (info.categoryCode != null) this.fields.set(TAG_MERCHANT_CATEGORY_CODE, info.categoryCode);\n    if (info.name != null) this.fields.set(TAG_MERCHANT_NAME, info.name.slice(0, 25));\n    if (info.city != null) this.fields.set(TAG_MERCHANT_CITY, info.city.slice(0, 15));\n    if (info.postalCode != null) this.fields.set(TAG_POSTAL_CODE, info.postalCode);\n    return this;\n  }\n\n  /** Set sub-fields of the additional-data template (tag 62). */\n  additionalData(fields: AdditionalDataFields): this {\n    Object.assign(this.additional, fields);\n    return this;\n  }\n\n  /**\n   * Attach the Bank of Thailand VAT TQRC extension (tag 80). Promotes the\n   * payment QR to an e-tax-receipt source. Pass `undefined` to clear.\n   *\n   * Field-length rules come from the BOT extension spec:\n   *  - `sellerTaxBranchId` is exactly 4 characters\n   *  - `vatRate` is 1–5 characters when present (e.g. \"7\" or \"7.00\")\n   *  - `vatAmount` is 1–13 characters and required\n   */\n  vatTqrc(input: VATTQRCInput | undefined): this {\n    if (input == null) {\n      this.vat = undefined;\n      return this;\n    }\n    if (input.sellerTaxBranchId.length !== 4) {\n      throw new RangeError(\n        `VAT TQRC sellerTaxBranchId must be exactly 4 chars (got ${input.sellerTaxBranchId.length})`,\n      );\n    }\n    if (input.vatRate != null && (input.vatRate.length < 1 || input.vatRate.length > 5)) {\n      throw new RangeError(`VAT TQRC vatRate must be 1–5 chars (got ${input.vatRate.length})`);\n    }\n    if (input.vatAmount.length < 1 || input.vatAmount.length > 13) {\n      throw new RangeError(`VAT TQRC vatAmount must be 1–13 chars (got ${input.vatAmount.length})`);\n    }\n    this.vat = { ...input };\n    return this;\n  }\n\n  /** Force the point-of-initiation flag regardless of amount presence. */\n  pointOfInitiation(method: 'static' | 'dynamic'): this {\n    this.fields.set(TAG_POINT_OF_INITIATION, method === 'static' ? POI_STATIC : POI_DYNAMIC);\n    return this;\n  }\n\n  /** Compose the additional-data template if any sub-fields are set. */\n  private composeAdditionalData(): string | null {\n    const pairs: ReadonlyArray<readonly [string, string | undefined]> = [\n      [SUB_ADD_BILL_NUMBER, this.additional.billNumber],\n      [SUB_ADD_MOBILE_NUMBER, this.additional.mobileNumber],\n      [SUB_ADD_STORE_LABEL, this.additional.storeLabel],\n      [SUB_ADD_LOYALTY_NUMBER, this.additional.loyaltyNumber],\n      [SUB_ADD_REFERENCE_LABEL, this.additional.referenceLabel],\n      [SUB_ADD_CUSTOMER_LABEL, this.additional.customerLabel],\n      [SUB_ADD_TERMINAL_LABEL, this.additional.terminalLabel],\n      [SUB_ADD_PURPOSE_OF_TRANSACTION, this.additional.purposeOfTransaction],\n      [SUB_ADD_CONSUMER_DATA_REQUEST, this.additional.consumerDataRequest],\n    ];\n    const body = encodeFields(pairs);\n    return body === '' ? null : body;\n  }\n\n  /** Apply the tip policy to tags 55-57 just before emit. */\n  private applyTip(): void {\n    if (this.tip == null) {\n      this.fields.delete(TAG_TIP_OR_CONVENIENCE_INDICATOR);\n      this.fields.delete(TAG_TIP_FIXED);\n      this.fields.delete(TAG_TIP_PERCENTAGE);\n      return;\n    }\n    switch (this.tip.mode) {\n      case 'prompt':\n        this.fields.set(TAG_TIP_OR_CONVENIENCE_INDICATOR, TIP_PROMPT);\n        this.fields.delete(TAG_TIP_FIXED);\n        this.fields.delete(TAG_TIP_PERCENTAGE);\n        break;\n      case 'fixed': {\n        const formatted = formatAmount(this.tip.value, { fromSatang: this.tip.fromSatang });\n        if (formatted == null) {\n          throw new TypeError('Tip fixed amount must be positive');\n        }\n        this.fields.set(TAG_TIP_OR_CONVENIENCE_INDICATOR, TIP_FIXED);\n        this.fields.set(TAG_TIP_FIXED, formatted);\n        this.fields.delete(TAG_TIP_PERCENTAGE);\n        break;\n      }\n      case 'percentage':\n        this.fields.set(TAG_TIP_OR_CONVENIENCE_INDICATOR, TIP_PERCENTAGE);\n        this.fields.set(TAG_TIP_PERCENTAGE, this.tip.value.toFixed(2));\n        this.fields.delete(TAG_TIP_FIXED);\n        break;\n    }\n  }\n\n  /** Render the full wire-format payload with checksum appended. */\n  build(): string {\n    this.applyTip();\n    const additional = this.composeAdditionalData();\n    if (additional != null) {\n      this.fields.set(TAG_ADDITIONAL_DATA, additional);\n    } else {\n      this.fields.delete(TAG_ADDITIONAL_DATA);\n    }\n    if (this.personalMessage != null && this.personalMessage !== '') {\n      this.fields.set(TAG_PERSONAL_MESSAGE, encodePersonalMessage(this.personalMessage));\n    } else {\n      this.fields.delete(TAG_PERSONAL_MESSAGE);\n    }\n    if (this.vat != null) {\n      // Sub-tag order inside tag 80 is 00 → 01 → 02 per the BOT\n      // supplement; `encodeFields` drops the optional rate cleanly.\n      this.fields.set(\n        TAG_VAT_TQRC,\n        encodeFields([\n          [SUB_VAT_SELLER_TAX_BRANCH_ID, this.vat.sellerTaxBranchId],\n          [SUB_VAT_RATE, this.vat.vatRate],\n          [SUB_VAT_AMOUNT, this.vat.vatAmount],\n        ]),\n      );\n    } else {\n      this.fields.delete(TAG_VAT_TQRC);\n    }\n\n    // Spec mandates ascending tag order on the wire. Map iteration\n    // preserves insertion order, so we sort explicitly here instead.\n    // Tag 80 (VAT TQRC) sorts naturally after tag 64; the CRC tag 63 is\n    // appended below regardless of sort order so it always lands last.\n    const sorted = [...this.fields.entries()]\n      .filter(([tag]) => tag !== TAG_CHECKSUM)\n      .toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n\n    let body = '';\n    for (const [tag, value] of sorted) {\n      body += encodeField(tag, value);\n    }\n\n    // The CRC is taken over `body + \"6304\"` — the tag header for the\n    // checksum is part of the hashed input. Off-by-one if you miss it.\n    const seed = body + TAG_CHECKSUM + '04';\n    return seed + checksum(seed);\n  }\n\n  /** Render and split the body/CRC for inspection. */\n  buildWithChecksum(): { body: string; checksum: string; payload: string } {\n    const payload = this.build();\n    return {\n      body: payload.slice(0, -4),\n      checksum: payload.slice(-4),\n      payload,\n    };\n  }\n\n  /** UTF-8 byte view of the payload — useful for hashing or transport. */\n  toBytes(): Uint8Array {\n    const text = this.build();\n    const out = new Uint8Array(text.length);\n    for (let i = 0; i < text.length; i += 1) {\n      out[i] = text.charCodeAt(i) & 0xff;\n    }\n    return out;\n  }\n}\n","/**\n * CRC-16/CCITT-FALSE — the variant mandated by EMVCo MPM §4 for the\n * trailing checksum tag (poly 0x1021, init 0xFFFF, no reflect, no XOR out).\n *\n * Table-driven implementation: pre-compute the 256-entry lookup at module\n * load, then xor-shift one byte per loop iteration. Roughly 4× faster than\n * the per-bit loop for typical payload sizes (~120-180 chars), and the\n * 512-byte table is dwarfed by the JS function objects around it.\n */\n\nconst CRC_TABLE: Uint16Array = (() => {\n  const table = new Uint16Array(256);\n  for (let byte = 0; byte < 256; byte += 1) {\n    let acc = byte << 8;\n    for (let bit = 0; bit < 8; bit += 1) {\n      acc = (acc & 0x8000) !== 0 ? ((acc << 1) ^ 0x1021) & 0xffff : (acc << 1) & 0xffff;\n    }\n    table[byte] = acc;\n  }\n  return table;\n})();\n\n/**\n * Compute the CRC-16/CCITT-FALSE checksum of an ASCII-encoded payload\n * and return it as a 4-character uppercase hex string. The EMVCo spec\n * requires the trailing zero-padding to keep the QR payload length stable.\n */\nexport function checksum(input: string): string {\n  let acc = 0xffff;\n  for (let i = 0; i < input.length; i += 1) {\n    const byte = input.charCodeAt(i) & 0xff;\n    acc = ((acc << 8) ^ (CRC_TABLE[(acc >> 8) ^ byte] ?? 0)) & 0xffff;\n  }\n  return acc.toString(16).toUpperCase().padStart(4, '0');\n}\n","/**\n * `@thai-qr-payment/payload` — public surface.\n *\n * Wire-format helpers for the Thai QR Payment EMVCo MPM standard. Zero\n * runtime dependencies; works in browsers, Node, Bun, Deno, and edge\n * runtimes (Cloudflare Workers, Vercel Edge, Netlify, Deno Deploy).\n */\n\nexport { ThaiQRPaymentBuilder } from './builder.js';\nexport type { AdditionalDataFields, MerchantInfo, TipMode, VATTQRCInput } from './builder.js';\n\nexport { parsePayload } from './parser.js';\nexport type {\n  ParsedAdditionalData,\n  ParsedBillPayment,\n  ParsedCRC,\n  ParsedPayload,\n  ParsedPromptPay,\n  ParsedTrueMoney,\n  ParsedVATTQRC,\n  ParsePayloadOptions,\n} from './parser.js';\n\nexport { normaliseBankAccount, normaliseRecipient } from './recipient.js';\nexport type { NormalisedRecipient, PromptPayRecipientType } from './recipient.js';\n\nexport { formatAmount } from './amount.js';\nexport type { FormatAmountOptions } from './amount.js';\n\nexport { checksum } from './crc.js';\n\nexport { decodePersonalMessage, encodePersonalMessage } from './message.js';\n\nexport {\n  buildSlipVerify,\n  buildTrueMoneySlipVerify,\n  parseSlipVerify,\n  parseTrueMoneySlipVerify,\n} from './slip-verify.js';\nexport type {\n  ParsedSlipVerify,\n  ParsedTrueMoneySlipVerify,\n  SlipVerifyInput,\n  TrueMoneySlipVerifyInput,\n} from './slip-verify.js';\n\nexport { buildBOTBarcode, parseBOTBarcode } from './barcode.js';\nexport type { BOTBarcodeInput, ParsedBOTBarcode } from './barcode.js';\n\nexport { encodeField, encodeFields, parseFields, iterateFields } from './tlv.js';\nexport type { TLVField } from './tlv.js';\n\nexport * as Tags from './tags.js';\n\nimport { ThaiQRPaymentBuilder } from './builder.js';\nimport type { PromptPayRecipientType } from './recipient.js';\nimport type { FormatAmountOptions } from './amount.js';\n\n/**\n * Shorthand for the common \"make me a PromptPay QR for this recipient\n * with this amount\" use case. Returns the wire payload string.\n *\n * @example\n *   payloadFor({ recipient: '0812345678', amount: 100 })\n *   // → '00020101021229370016A00000067701011101130066812345678530376454...'\n */\nexport function payloadFor(input: {\n  recipient: string;\n  amount?: number;\n  type?: PromptPayRecipientType;\n  fromSatang?: boolean;\n}): string {\n  const opts: FormatAmountOptions | undefined = input.fromSatang ? { fromSatang: true } : undefined;\n  return new ThaiQRPaymentBuilder()\n    .promptpay(input.recipient, input.type)\n    .amount(input.amount, opts)\n    .build();\n}\n","/**\n * Personal-message codec for tag 81 (TrueMoney Wallet).\n *\n * The wire format is the UTF-16BE encoding of the message, expressed as\n * uppercase hex. Each Unicode code unit becomes 4 hex chars; `Hello` →\n * `00480065006C006C006F`. Length on the TLV header counts the hex chars,\n * not the source characters.\n *\n * Browser/edge-safe — no `node:buffer` reach-through.\n */\n\n/** Encode a personal message string to UTF-16BE hex (uppercase). */\nexport function encodePersonalMessage(message: string): string {\n  let out = '';\n  for (let i = 0; i < message.length; i += 1) {\n    const code = message.charCodeAt(i);\n    out += code.toString(16).padStart(4, '0').toUpperCase();\n  }\n  return out;\n}\n\n/** Decode a UTF-16BE hex string back to its source message. */\nexport function decodePersonalMessage(hex: string): string {\n  if (hex.length % 4 !== 0) {\n    throw new SyntaxError(`Personal-message hex must be a multiple of 4 chars; got ${hex.length}`);\n  }\n  let out = '';\n  for (let i = 0; i < hex.length; i += 4) {\n    const unit = Number.parseInt(hex.slice(i, i + 4), 16);\n    if (!Number.isFinite(unit)) {\n      throw new SyntaxError(`Invalid hex unit \"${hex.slice(i, i + 4)}\" at offset ${i}`);\n    }\n    out += String.fromCharCode(unit);\n  }\n  return out;\n}\n","/**\n * Decoder for Thai QR Payment wire payloads.\n *\n * Validates the trailing CRC, walks the TLV tree, and surfaces a typed\n * view of the merchant template + amount + additional-data sub-fields.\n * Useful for tests, debugging, and reading back QR codes captured by a\n * scanner.\n *\n * Two non-obvious behaviours live here:\n *  - `strict` opt-in surfaces a CRC failure as an exception instead of a\n *    silent pass; older code without the flag stays backwards-compatible.\n *  - Truncated-CRC auto-fix recovers payloads that some Thai banking\n *    apps emit with the last 1–2 hex chars chopped off. We left-pad the\n *    chopped value with zeros and accept it if the result hashes back to\n *    the same body. The flag survives on the parsed object so callers\n *    can warn the user about the source app's bug.\n */\n\nimport { checksum } from './crc.js';\nimport { decodePersonalMessage } from './message.js';\nimport type { PromptPayRecipientType } from './recipient.js';\nimport {\n  COUNTRY_TH,\n  CURRENCY_THB,\n  GUID_BILL_PAYMENT,\n  GUID_BILL_PAYMENT_CROSS_BORDER,\n  GUID_PROMPTPAY,\n  GUID_PROMPTPAY_OTA,\n  POI_DYNAMIC,\n  SUB_ADD_BILL_NUMBER,\n  SUB_ADD_CONSUMER_DATA_REQUEST,\n  SUB_ADD_CUSTOMER_LABEL,\n  SUB_ADD_LOYALTY_NUMBER,\n  SUB_ADD_MOBILE_NUMBER,\n  SUB_ADD_PURPOSE_OF_TRANSACTION,\n  SUB_ADD_REFERENCE_LABEL,\n  SUB_ADD_STORE_LABEL,\n  SUB_ADD_TERMINAL_LABEL,\n  SUB_BILL_BILLER_ID,\n  SUB_BILL_REFERENCE_1,\n  SUB_BILL_REFERENCE_2,\n  SUB_GUID,\n  SUB_PROMPTPAY_BANK_ACCOUNT,\n  SUB_PROMPTPAY_EWALLET,\n  SUB_PROMPTPAY_MOBILE,\n  SUB_PROMPTPAY_NATIONAL_ID,\n  SUB_PROMPTPAY_OTA,\n  SUB_TRUE_MONEY,\n  SUB_VAT_AMOUNT,\n  SUB_VAT_RATE,\n  SUB_VAT_SELLER_TAX_BRANCH_ID,\n  TAG_ADDITIONAL_DATA,\n  TAG_CHECKSUM,\n  TAG_COUNTRY_CODE,\n  TAG_MERCHANT_ACCOUNT_BILL_PAYMENT,\n  TAG_MERCHANT_ACCOUNT_PROMPTPAY,\n  TAG_MERCHANT_CATEGORY_CODE,\n  TAG_MERCHANT_CITY,\n  TAG_MERCHANT_NAME,\n  TAG_PAYLOAD_FORMAT,\n  TAG_PERSONAL_MESSAGE,\n  TAG_POINT_OF_INITIATION,\n  TAG_POSTAL_CODE,\n  TAG_TRANSACTION_AMOUNT,\n  TAG_TRANSACTION_CURRENCY,\n  TAG_VAT_TQRC,\n  TRUE_MONEY_PREFIX,\n} from './tags.js';\nimport { iterateFields, parseFields, type TLVField } from './tlv.js';\n\nconst BANK_CODE_LENGTH = 3;\n\nexport interface ParsedPromptPay {\n  readonly kind: 'promptpay';\n  readonly recipientType: PromptPayRecipientType;\n  /**\n   * Wire value for the recipient sub-tag. For `bankAccount` this is the\n   * full `bankCode + accountNo` concatenation — split fields are exposed\n   * separately below.\n   */\n  readonly recipient: string;\n  /** Bank code (3 digits). Present only when `recipientType === 'bankAccount'`. */\n  readonly bankCode?: string;\n  /** Account number. Present only when `recipientType === 'bankAccount'`. */\n  readonly accountNo?: string;\n  /** One-Time Authorization code from sub-tag 05. Present only on OTA payloads. */\n  readonly ota?: string;\n}\n\nexport interface ParsedBillPayment {\n  readonly kind: 'billPayment';\n  readonly billerId: string;\n  readonly reference1?: string;\n  readonly reference2?: string;\n  /**\n   * `true` when the merchant template uses the ASEAN cross-border AID\n   * (`A000000677012006`). In that mode the `purposeOfTransaction` field\n   * (tag 62 sub-tag 08) carries an 18-char triple of currency + local\n   * amount + country; the parser surfaces it verbatim under\n   * `additionalData.purposeOfTransaction`.\n   */\n  readonly crossBorder: boolean;\n}\n\nexport interface ParsedTrueMoney {\n  readonly kind: 'trueMoney';\n  readonly mobileNo: string;\n  readonly message?: string;\n}\n\nexport interface ParsedAdditionalData {\n  billNumber?: string;\n  mobileNumber?: string;\n  storeLabel?: string;\n  loyaltyNumber?: string;\n  referenceLabel?: string;\n  customerLabel?: string;\n  terminalLabel?: string;\n  purposeOfTransaction?: string;\n  consumerDataRequest?: string;\n}\n\n/** Decoded VAT TQRC template (tag 80). */\nexport interface ParsedVATTQRC {\n  readonly sellerTaxBranchId: string;\n  readonly vatRate?: string;\n  readonly vatAmount: string;\n}\n\n/** Bookkeeping for the trailing checksum — useful when reporting auto-fix. */\nexport interface ParsedCRC {\n  /** The CRC text as it appeared on the wire (may be 1–4 chars). */\n  readonly value: string;\n  /** True when the wire CRC matches the recomputed value (possibly after padding). */\n  readonly valid: boolean;\n  /** True when zero-padding was needed to recover a valid CRC. */\n  readonly truncated: boolean;\n}\n\nexport interface ParsedPayload {\n  readonly payloadFormat: string;\n  readonly pointOfInitiation: 'static' | 'dynamic';\n  readonly merchant: ParsedPromptPay | ParsedBillPayment | ParsedTrueMoney | null;\n  readonly amount: number | null;\n  readonly currency: string;\n  readonly country: string;\n  readonly merchantName?: string;\n  readonly merchantCity?: string;\n  readonly merchantCategoryCode?: string;\n  readonly postalCode?: string;\n  readonly additionalData?: ParsedAdditionalData;\n  readonly vatTqrc?: ParsedVATTQRC;\n  readonly crc: ParsedCRC;\n  /** All top-level TLV fields, in wire order. Use for unknown / future tags. */\n  readonly rawTags: readonly TLVField[];\n  /** Lookup a top-level TLV field by id. Returns `undefined` if absent. */\n  getTag(id: string): TLVField | undefined;\n  /**\n   * Lookup a value by id. Pass `subId` to descend one level into a nested\n   * template (tags 29–31, 62, 64 are templated). Returns `undefined` if\n   * either the parent or the sub-field is missing.\n   */\n  getTagValue(id: string, subId?: string): string | undefined;\n}\n\nexport interface ParsePayloadOptions {\n  /**\n   * When true, throw if the CRC tag is missing or its on-wire value\n   * doesn't match the recomputed checksum. Defaults to false for\n   * backwards compatibility with callers that need to consume the\n   * truncated-CRC auto-fix path.\n   */\n  readonly strict?: boolean;\n}\n\n/** Recover the human-readable mobile (drop the `0066` prefix and re-add `0`). */\nfunction fromMobileWire(wire: string): string {\n  // Wire: 13-char zero-padded, starts with 0066 for THB. Strip leading\n  // zeros, drop the 66 country code, prepend a 0.\n  const trimmed = wire.replace(/^0+/, '');\n  if (trimmed.startsWith('66')) return `0${trimmed.slice(2)}`;\n  return trimmed;\n}\n\n/** Reverse the TrueMoney mobile-wire transform (drop `14` + restore the leading 0). */\nfunction fromTrueMoneyWire(wire: string): string {\n  // Wire layout: \"14\" + 13-char zero-padded mobile. Thai mobiles\n  // canonically start with a leading 0, so strip the zero-padding and\n  // re-add the 0 the same way `fromMobileWire` does for PromptPay.\n  const trimmed = wire.slice(TRUE_MONEY_PREFIX.length).replace(/^0+/, '');\n  return trimmed === '' ? '0' : `0${trimmed}`;\n}\n\nfunction parsePromptPayTemplate(template: string): ParsedPromptPay | null {\n  const sub = parseFields(template);\n  const guid = sub.get(SUB_GUID);\n  // OTA payloads use the `…0114` AID; everything else rides the standard\n  // PromptPay `…0111` AID. The AID is the sole discriminator — sub-tags\n  // 01-04 carry the same recipient shapes in either envelope.\n  const isOta = guid === GUID_PROMPTPAY_OTA;\n  if (guid !== GUID_PROMPTPAY && !isOta) return null;\n  const ota = isOta ? sub.get(SUB_PROMPTPAY_OTA) : undefined;\n\n  const bankAccount = sub.get(SUB_PROMPTPAY_BANK_ACCOUNT);\n  if (bankAccount != null) {\n    return {\n      kind: 'promptpay',\n      recipientType: 'bankAccount',\n      recipient: bankAccount,\n      bankCode: bankAccount.slice(0, BANK_CODE_LENGTH),\n      accountNo: bankAccount.slice(BANK_CODE_LENGTH),\n      ...(ota != null ? { ota } : {}),\n    };\n  }\n  const mobile = sub.get(SUB_PROMPTPAY_MOBILE);\n  if (mobile != null) {\n    return {\n      kind: 'promptpay',\n      recipientType: 'mobile',\n      recipient: fromMobileWire(mobile),\n      ...(ota != null ? { ota } : {}),\n    };\n  }\n  const nationalId = sub.get(SUB_PROMPTPAY_NATIONAL_ID);\n  if (nationalId != null) {\n    return {\n      kind: 'promptpay',\n      recipientType: 'nationalId',\n      recipient: nationalId,\n      ...(ota != null ? { ota } : {}),\n    };\n  }\n  const eWallet = sub.get(SUB_PROMPTPAY_EWALLET);\n  if (eWallet != null) {\n    return {\n      kind: 'promptpay',\n      recipientType: 'eWallet',\n      recipient: eWallet,\n      ...(ota != null ? { ota } : {}),\n    };\n  }\n  return null;\n}\n\nfunction parseTrueMoneyTemplate(template: string): ParsedTrueMoney | null {\n  const sub = parseFields(template);\n  const guid = sub.get(SUB_GUID);\n  if (guid !== GUID_PROMPTPAY) return null;\n  const wireValue = sub.get(SUB_TRUE_MONEY);\n  if (wireValue == null) return null;\n  if (!wireValue.startsWith(TRUE_MONEY_PREFIX)) return null;\n  return { kind: 'trueMoney', mobileNo: fromTrueMoneyWire(wireValue) };\n}\n\nfunction parseBillPaymentTemplate(template: string): ParsedBillPayment | null {\n  const sub = parseFields(template);\n  const guid = sub.get(SUB_GUID);\n  // Two recognised AIDs: domestic and cross-border (ASEAN remittance).\n  // Anything else is an unknown AID — return null so the parser leaves\n  // `merchant` as null, matching how the PromptPay branch handles a\n  // strange GUID.\n  let crossBorder: boolean;\n  if (guid === GUID_BILL_PAYMENT) {\n    crossBorder = false;\n  } else if (guid === GUID_BILL_PAYMENT_CROSS_BORDER) {\n    crossBorder = true;\n  } else {\n    return null;\n  }\n  const billerId = sub.get(SUB_BILL_BILLER_ID);\n  if (billerId == null) return null;\n  return {\n    kind: 'billPayment',\n    billerId,\n    reference1: sub.get(SUB_BILL_REFERENCE_1) ?? undefined,\n    reference2: sub.get(SUB_BILL_REFERENCE_2) ?? undefined,\n    crossBorder,\n  };\n}\n\nfunction parseAdditionalDataTemplate(template: string): ParsedAdditionalData {\n  const sub = parseFields(template);\n  return {\n    billNumber: sub.get(SUB_ADD_BILL_NUMBER),\n    mobileNumber: sub.get(SUB_ADD_MOBILE_NUMBER),\n    storeLabel: sub.get(SUB_ADD_STORE_LABEL),\n    loyaltyNumber: sub.get(SUB_ADD_LOYALTY_NUMBER),\n    referenceLabel: sub.get(SUB_ADD_REFERENCE_LABEL),\n    customerLabel: sub.get(SUB_ADD_CUSTOMER_LABEL),\n    terminalLabel: sub.get(SUB_ADD_TERMINAL_LABEL),\n    purposeOfTransaction: sub.get(SUB_ADD_PURPOSE_OF_TRANSACTION),\n    consumerDataRequest: sub.get(SUB_ADD_CONSUMER_DATA_REQUEST),\n  };\n}\n\n/**\n * Parse the VAT TQRC template (tag 80). Returns `null` when the required\n * `vatAmount` sub-tag (02) is absent — callers in strict mode escalate\n * that to an exception, lax callers surface it as `vatTqrc: undefined`.\n */\nfunction parseVatTqrcTemplate(template: string): ParsedVATTQRC | null {\n  const sub = parseFields(template);\n  const sellerTaxBranchId = sub.get(SUB_VAT_SELLER_TAX_BRANCH_ID);\n  const vatAmount = sub.get(SUB_VAT_AMOUNT);\n  if (sellerTaxBranchId == null || vatAmount == null) return null;\n  const vatRate = sub.get(SUB_VAT_RATE);\n  return vatRate != null\n    ? { sellerTaxBranchId, vatRate, vatAmount }\n    : { sellerTaxBranchId, vatAmount };\n}\n\n/**\n * Split off the CRC. Returns the canonical (possibly zero-padded) wire\n * representation when an auto-fix landed; downstream TLV parsing always\n * sees a well-formed `6304XXXX` tail so it never needs to special-case\n * the truncated path.\n */\nfunction extractCrc(payload: string, strict: boolean): { canonical: string; crc: ParsedCRC } {\n  // Standard case: payload ends with \"6304XXXX\" where XXXX is the CRC.\n  // Verify first because it's the >99% path.\n  const fullCrc = payload.slice(-4);\n  const fullSeed = payload.slice(0, -4);\n  if (fullSeed.endsWith(TAG_CHECKSUM + '04')) {\n    const expected = checksum(fullSeed);\n    if (expected === fullCrc) {\n      return {\n        canonical: payload,\n        crc: { value: fullCrc, valid: true, truncated: false },\n      };\n    }\n    if (strict) {\n      throw new Error('Invalid CRC');\n    }\n  }\n\n  // Truncated-CRC fallback: walk back 1, 2, 3 chars and try padding the\n  // tail with leading zeros. The seed includes the `6304` header per the\n  // EMVCo spec, so it stays constant and only the value grows back.\n  if (!strict) {\n    for (let dropped = 1; dropped <= 3; dropped += 1) {\n      const candidateEnd = payload.length - (4 - dropped);\n      const candidateSeed = payload.slice(0, candidateEnd);\n      if (!candidateSeed.endsWith(TAG_CHECKSUM + '04')) continue;\n      const wireCrc = payload.slice(candidateEnd);\n      const padded = wireCrc.padStart(4, '0');\n      if (checksum(candidateSeed) === padded) {\n        return {\n          canonical: candidateSeed + padded,\n          crc: { value: wireCrc, valid: true, truncated: true },\n        };\n      }\n    }\n  }\n\n  if (strict) {\n    throw new Error('Invalid CRC');\n  }\n\n  // Non-strict fall-through: surface the original checksum-mismatch\n  // error for backwards compatibility with the previous parser.\n  throw new Error(\n    `Checksum mismatch: payload trails \"${fullCrc}\" but recomputes to \"${checksum(fullSeed)}\"`,\n  );\n}\n\n/**\n * Parse a wire-format payload. By default throws on structural errors or\n * a hard checksum mismatch (with truncated-CRC auto-fix applied when\n * possible). In `strict: true` mode also throws when the CRC tag is\n * missing or its value fails to match.\n */\nexport function parsePayload(payload: string, options: ParsePayloadOptions = {}): ParsedPayload {\n  if (payload.length < 8) {\n    throw new SyntaxError(\n      `Payload too short (${payload.length} chars); not a Thai QR Payment string`,\n    );\n  }\n\n  const strict = options.strict === true;\n  const { canonical, crc } = extractCrc(payload, strict);\n\n  // Iterate the canonical (possibly zero-padded) payload so rawTags\n  // reflect what the spec says the merchant intended, not the truncated\n  // wire byte-for-byte. Tag 63 still appears in rawTags for completeness.\n  const rawTags = [...iterateFields(canonical)];\n  const root = new Map<string, string>();\n  for (const field of rawTags) {\n    if (field.tag !== TAG_CHECKSUM) root.set(field.tag, field.value);\n  }\n\n  const promptpayTemplate = root.get(TAG_MERCHANT_ACCOUNT_PROMPTPAY);\n  const billPaymentTemplate = root.get(TAG_MERCHANT_ACCOUNT_BILL_PAYMENT);\n  let merchant: ParsedPromptPay | ParsedBillPayment | ParsedTrueMoney | null = null;\n  if (promptpayTemplate != null) {\n    // TrueMoney rides on the same AID as PromptPay; the literal \"14\"\n    // prefix on sub-tag 03 is the disambiguator.\n    merchant =\n      parseTrueMoneyTemplate(promptpayTemplate) ?? parsePromptPayTemplate(promptpayTemplate);\n  } else if (billPaymentTemplate != null) {\n    merchant = parseBillPaymentTemplate(billPaymentTemplate);\n  }\n\n  // Personal message lives at tag 81 — TrueMoney's only place to put a\n  // human-readable note. Other wallets ignore it.\n  let trueMoneyWithMessage: ParsedTrueMoney | null = null;\n  if (merchant != null && merchant.kind === 'trueMoney') {\n    const messageHex = root.get(TAG_PERSONAL_MESSAGE);\n    if (messageHex != null && messageHex !== '') {\n      try {\n        trueMoneyWithMessage = { ...merchant, message: decodePersonalMessage(messageHex) };\n      } catch {\n        // Malformed message hex shouldn't kill the whole parse — drop\n        // silently and surface via `rawTags` for callers that care.\n      }\n    }\n  }\n\n  const amountText = root.get(TAG_TRANSACTION_AMOUNT);\n  const additional = root.get(TAG_ADDITIONAL_DATA);\n  const vatTemplate = root.get(TAG_VAT_TQRC);\n  let vatTqrc: ParsedVATTQRC | undefined;\n  if (vatTemplate != null) {\n    const decoded = parseVatTqrcTemplate(vatTemplate);\n    if (decoded == null && strict) {\n      throw new Error('VAT TQRC template is missing required sub-tags');\n    }\n    vatTqrc = decoded ?? undefined;\n  }\n\n  const result: ParsedPayload = {\n    payloadFormat: root.get(TAG_PAYLOAD_FORMAT) ?? '',\n    pointOfInitiation: root.get(TAG_POINT_OF_INITIATION) === POI_DYNAMIC ? 'dynamic' : 'static',\n    merchant: trueMoneyWithMessage ?? merchant,\n    amount: amountText != null ? Number.parseFloat(amountText) : null,\n    currency: root.get(TAG_TRANSACTION_CURRENCY) ?? CURRENCY_THB,\n    country: root.get(TAG_COUNTRY_CODE) ?? COUNTRY_TH,\n    merchantName: root.get(TAG_MERCHANT_NAME),\n    merchantCity: root.get(TAG_MERCHANT_CITY),\n    merchantCategoryCode: root.get(TAG_MERCHANT_CATEGORY_CODE),\n    postalCode: root.get(TAG_POSTAL_CODE),\n    additionalData: additional != null ? parseAdditionalDataTemplate(additional) : undefined,\n    vatTqrc,\n    crc,\n    rawTags,\n    getTag(id: string): TLVField | undefined {\n      for (const field of rawTags) {\n        if (field.tag === id) return field;\n      }\n      return undefined;\n    },\n    getTagValue(id: string, subId?: string): string | undefined {\n      const parent = this.getTag(id);\n      if (parent == null) return undefined;\n      if (subId == null) return parent.value;\n      for (const sub of iterateFields(parent.value)) {\n        if (sub.tag === subId) return sub.value;\n      }\n      return undefined;\n    },\n  };\n  return result;\n}\n","/**\n * Recipient normalisation for the PromptPay merchant template.\n *\n * The wire format under tag 29 has four sub-tags (01 phone, 02 national\n * ID, 03 e-wallet, 04 bank account). The expected length determines which\n * sub-tag a single-string recipient lands in, and phone numbers get the\n * country prefix swap `0` → `66`. Bank account values are composed from\n * two pieces (bank code + account number) and have their own helper.\n */\n\nimport {\n  SUB_PROMPTPAY_BANK_ACCOUNT,\n  SUB_PROMPTPAY_EWALLET,\n  SUB_PROMPTPAY_MOBILE,\n  SUB_PROMPTPAY_NATIONAL_ID,\n} from './tags.js';\n\nexport type PromptPayRecipientType = 'mobile' | 'nationalId' | 'eWallet' | 'bankAccount';\n\nexport interface NormalisedRecipient {\n  readonly subTag:\n    | typeof SUB_PROMPTPAY_MOBILE\n    | typeof SUB_PROMPTPAY_NATIONAL_ID\n    | typeof SUB_PROMPTPAY_EWALLET\n    | typeof SUB_PROMPTPAY_BANK_ACCOUNT;\n  readonly value: string;\n  readonly type: PromptPayRecipientType;\n}\n\nconst BANK_CODE_LENGTH = 3;\nconst BANK_ACCOUNT_MAX_LENGTH = 43;\n\n/** Strip every non-digit character. */\nfunction stripNonDigits(input: string): string {\n  let out = '';\n  for (let i = 0; i < input.length; i += 1) {\n    const code = input.charCodeAt(i);\n    if (code >= 0x30 && code <= 0x39) out += input[i];\n  }\n  return out;\n}\n\n/** Convert a mobile number to the 13-char `0066xxxxxxxxxx` wire form. */\nfunction toMobileWire(digits: string): string {\n  // Phones in Thailand are 9-10 digits (e.g. 0812345678). Replace the\n  // leading 0 with 66 (Thailand country code), then zero-pad to 13.\n  const trimmed = digits.replace(/^0/, '66');\n  return trimmed.padStart(13, '0');\n}\n\n/**\n * Decide the recipient type from the digit count, then format the wire\n * value. Explicit `type` arg overrides the inference — useful if a\n * national ID happens to look like a long e-wallet id or vice versa.\n * Pass `'bankAccount'` to `normaliseBankAccount` instead; it needs two\n * pieces (bank code + account number) the single-string form can't carry.\n */\nexport function normaliseRecipient(\n  raw: string,\n  explicit?: Exclude<PromptPayRecipientType, 'bankAccount'>,\n): NormalisedRecipient {\n  const digits = stripNonDigits(raw);\n  if (digits.length === 0) {\n    throw new TypeError('PromptPay recipient must contain at least one digit');\n  }\n\n  const inferred: Exclude<PromptPayRecipientType, 'bankAccount'> =\n    explicit ?? (digits.length >= 15 ? 'eWallet' : digits.length >= 13 ? 'nationalId' : 'mobile');\n\n  switch (inferred) {\n    case 'mobile':\n      return { subTag: SUB_PROMPTPAY_MOBILE, value: toMobileWire(digits), type: 'mobile' };\n    case 'nationalId':\n      if (digits.length !== 13) {\n        throw new RangeError(`National ID must be 13 digits, got ${digits.length}`);\n      }\n      return { subTag: SUB_PROMPTPAY_NATIONAL_ID, value: digits, type: 'nationalId' };\n    case 'eWallet':\n      if (digits.length !== 15) {\n        throw new RangeError(`e-Wallet ID must be 15 digits, got ${digits.length}`);\n      }\n      return { subTag: SUB_PROMPTPAY_EWALLET, value: digits, type: 'eWallet' };\n  }\n}\n\n/**\n * Format a bank-account recipient for sub-tag 04 under the PromptPay\n * merchant template. The wire value is the 3-digit bank code followed by\n * the (variable-length, numeric) account number; total length must fit\n * EMVCo's 1–43-character cap on the sub-tag.\n *\n * @example\n *   normaliseBankAccount('014', '1234567890')\n *   // → { subTag: '04', value: '0141234567890', type: 'bankAccount' }\n */\nexport function normaliseBankAccount(bankCode: string, accountNo: string): NormalisedRecipient {\n  const codeDigits = stripNonDigits(bankCode);\n  const accountDigits = stripNonDigits(accountNo);\n  if (codeDigits.length !== BANK_CODE_LENGTH) {\n    throw new RangeError(`Bank code must be ${BANK_CODE_LENGTH} digits, got ${codeDigits.length}`);\n  }\n  if (accountDigits.length === 0) {\n    throw new TypeError('Bank account number must contain at least one digit');\n  }\n  const value = codeDigits + accountDigits;\n  if (value.length > BANK_ACCOUNT_MAX_LENGTH) {\n    throw new RangeError(\n      `Bank account wire value exceeds ${BANK_ACCOUNT_MAX_LENGTH} chars (got ${value.length})`,\n    );\n  }\n  return { subTag: SUB_PROMPTPAY_BANK_ACCOUNT, value, type: 'bankAccount' };\n}\n","/**\n * Slip Verify Mini-QR — a different envelope from PromptPay payments.\n *\n * Banks print a small \"Mini-QR\" on transfer slips (and inside the PromptPay\n * mobile-app slip view) so an Open API lookup can resolve the transaction\n * after an OCR / scan. The envelope shares the EMVCo TLV grammar but uses\n * its own root tags: a single nested template at tag 00, a country tag 51,\n * and a CRC at tag 91 — not tag 63 like a payment QR. This module wraps\n * the build / parse round-trip for the standard slip-verify shape and the\n * TrueMoney variant (different sub-fields, lowercase CRC hex).\n *\n * The parsers reject any payload that doesn't carry the slip-verify\n * envelope, and tolerate banks that ship a 1-3 character CRC by padding\n * with leading zeros until the checksum matches.\n */\n\nimport { checksum } from './crc.js';\nimport { encodeField, encodeFields, parseFields } from './tlv.js';\n\n// ── Envelope tags shared by both slip-verify variants ───────────────────\nconst TAG_ROOT_TEMPLATE = '00';\nconst TAG_COUNTRY = '51';\nconst TAG_CRC = '91';\n\n// ── Standard slip-verify sub-tags (under root template) ─────────────────\nconst SUB_API_TYPE = '00';\nconst SUB_SENDING_BANK = '01';\nconst SUB_TRANS_REF = '02';\nconst SLIP_VERIFY_API_TYPE = '000001';\nconst COUNTRY_TH = 'TH';\n\n// ── TrueMoney variant sub-tags (under root template) ────────────────────\nconst SUB_TM_MARKER_A = '00';\nconst SUB_TM_MARKER_B = '01';\nconst SUB_TM_EVENT_TYPE = '02';\nconst SUB_TM_TRANSACTION_ID = '03';\nconst SUB_TM_DATE = '04';\nconst TM_MARKER_VALUE = '01';\n\nconst CRC_HEADER = TAG_CRC + '04';\nconst TM_DATE_LENGTH = 8;\n\n/** Input for `buildSlipVerify`. */\nexport interface SlipVerifyInput {\n  /** Bank code that issued the slip (e.g. `'002'` for Bangkok Bank). */\n  readonly sendingBank: string;\n  /** Transaction reference printed on the slip. */\n  readonly transRef: string;\n}\n\n/** Decoded payload from `parseSlipVerify`. */\nexport interface ParsedSlipVerify {\n  readonly sendingBank: string;\n  readonly transRef: string;\n}\n\n/** Input for `buildTrueMoneySlipVerify`. */\nexport interface TrueMoneySlipVerifyInput {\n  /** Event classification (e.g. `'P2P'`). */\n  readonly eventType: string;\n  /** Wallet transaction identifier. */\n  readonly transactionId: string;\n  /** Transfer date as a `DDMMYYYY` 8-character string. */\n  readonly date: string;\n}\n\n/** Decoded payload from `parseTrueMoneySlipVerify`. */\nexport interface ParsedTrueMoneySlipVerify {\n  readonly eventType: string;\n  readonly transactionId: string;\n  readonly date: string;\n}\n\n/**\n * Build a Slip Verify Mini-QR payload. The output is a TLV string ending\n * in a tag-91 CRC (uppercase hex), suitable for embedding in a printed\n * slip and looking the transaction up via bank Open APIs.\n *\n * @example\n *   buildSlipVerify({ sendingBank: '002', transRef: '0002123123121200011' })\n *   // → '004000060000010103002021900021231231212000115102TH91049C30'\n */\nexport function buildSlipVerify(input: SlipVerifyInput): string {\n  const inner = encodeFields([\n    [SUB_API_TYPE, SLIP_VERIFY_API_TYPE],\n    [SUB_SENDING_BANK, input.sendingBank],\n    [SUB_TRANS_REF, input.transRef],\n  ]);\n  const body = encodeField(TAG_ROOT_TEMPLATE, inner) + encodeField(TAG_COUNTRY, COUNTRY_TH);\n  const seed = body + CRC_HEADER;\n  return seed + checksum(seed);\n}\n\n/**\n * Parse a Slip Verify Mini-QR payload. Returns `null` for any string that\n * isn't a valid slip-verify envelope — wrong root tag, wrong CRC tag, or\n * checksum mismatch. CRCs of 1-3 hex chars are auto-padded with leading\n * zeros (some bank apps drop characters when re-encoding).\n *\n * @example\n *   parseSlipVerify('004000060000010103002021900021231231212000115102TH91049C30')\n *   // → { sendingBank: '002', transRef: '0002123123121200011' }\n */\nexport function parseSlipVerify(payload: string): ParsedSlipVerify | null {\n  const repaired = repairCrcEnvelope(payload, true);\n  if (repaired == null) return null;\n\n  let root: Map<string, string>;\n  try {\n    root = parseFields(repaired.body);\n  } catch {\n    return null;\n  }\n\n  const template = root.get(TAG_ROOT_TEMPLATE);\n  if (template == null) return null;\n\n  let sub: Map<string, string>;\n  try {\n    sub = parseFields(template);\n  } catch {\n    return null;\n  }\n\n  if (sub.get(SUB_API_TYPE) !== SLIP_VERIFY_API_TYPE) return null;\n  const sendingBank = sub.get(SUB_SENDING_BANK);\n  const transRef = sub.get(SUB_TRANS_REF);\n  if (sendingBank == null || transRef == null) return null;\n\n  return { sendingBank, transRef };\n}\n\n/**\n * Build a TrueMoney Slip Verify Mini-QR payload. Uses the same TLV\n * envelope as the standard variant but with a different sub-tag layout\n * and a **lowercase** hex CRC at tag 91.\n *\n * @example\n *   buildTrueMoneySlipVerify({ eventType: 'P2P', transactionId: 'TXN0001234567', date: '25012024' })\n *   // → '00480002010102010203P2P0313TXN00012345670408250120249104b425'\n */\nexport function buildTrueMoneySlipVerify(input: TrueMoneySlipVerifyInput): string {\n  if (input.date.length !== TM_DATE_LENGTH) {\n    throw new RangeError(\n      `TrueMoney slip-verify date must be ${TM_DATE_LENGTH} chars (DDMMYYYY); got ${input.date.length}`,\n    );\n  }\n  const inner = encodeFields([\n    [SUB_TM_MARKER_A, TM_MARKER_VALUE],\n    [SUB_TM_MARKER_B, TM_MARKER_VALUE],\n    [SUB_TM_EVENT_TYPE, input.eventType],\n    [SUB_TM_TRANSACTION_ID, input.transactionId],\n    [SUB_TM_DATE, input.date],\n  ]);\n  const body = encodeField(TAG_ROOT_TEMPLATE, inner);\n  const seed = body + CRC_HEADER;\n  return seed + checksum(seed).toLowerCase();\n}\n\n/**\n * Parse a TrueMoney Slip Verify Mini-QR payload. Returns `null` for any\n * string that doesn't carry the TrueMoney marker pair (sub-tags 00 + 01\n * both `'01'`) or whose CRC fails to verify. Comparison is\n * case-insensitive; truncated CRCs (1-3 chars) are auto-padded.\n *\n * @example\n *   parseTrueMoneySlipVerify('00480002010102010203P2P0313TXN00012345670408250120249104b425')\n *   // → { eventType: 'P2P', transactionId: 'TXN0001234567', date: '25012024' }\n */\nexport function parseTrueMoneySlipVerify(payload: string): ParsedTrueMoneySlipVerify | null {\n  const repaired = repairCrcEnvelope(payload, false);\n  if (repaired == null) return null;\n\n  let root: Map<string, string>;\n  try {\n    root = parseFields(repaired.body);\n  } catch {\n    return null;\n  }\n\n  const template = root.get(TAG_ROOT_TEMPLATE);\n  if (template == null) return null;\n\n  let sub: Map<string, string>;\n  try {\n    sub = parseFields(template);\n  } catch {\n    return null;\n  }\n\n  if (sub.get(SUB_TM_MARKER_A) !== TM_MARKER_VALUE) return null;\n  if (sub.get(SUB_TM_MARKER_B) !== TM_MARKER_VALUE) return null;\n  const eventType = sub.get(SUB_TM_EVENT_TYPE);\n  const transactionId = sub.get(SUB_TM_TRANSACTION_ID);\n  const date = sub.get(SUB_TM_DATE);\n  if (eventType == null || transactionId == null || date == null) return null;\n\n  return { eventType, transactionId, date };\n}\n\n/**\n * Locate the tag-91 CRC at the tail of the payload, repair a truncated\n * checksum (1-3 hex chars get padded with leading zeros until a candidate\n * matches), and return the verified body. Returns `null` if no candidate\n * passes the CRC check.\n *\n * `caseSensitive=true` enforces uppercase hex equality (standard slip\n * verify). `false` lower-cases both sides before comparing (TrueMoney\n * accepts either case on the wire).\n */\nfunction repairCrcEnvelope(payload: string, caseSensitive: boolean): { body: string } | null {\n  const headerIdx = payload.lastIndexOf(CRC_HEADER);\n  if (headerIdx === -1) return null;\n\n  const seedEnd = headerIdx + CRC_HEADER.length;\n  const seed = payload.slice(0, seedEnd);\n  const tail = payload.slice(seedEnd);\n  if (tail.length === 0 || tail.length > 4) return null;\n\n  const expected = caseSensitive ? checksum(seed) : checksum(seed).toLowerCase();\n  const padded = tail.padStart(4, '0');\n  const normalised = caseSensitive ? padded : padded.toLowerCase();\n  if (normalised === expected) {\n    return { body: payload.slice(0, headerIdx) };\n  }\n  return null;\n}\n","/**\n * EMVCo Merchant-Presented-Mode QR Code Specification — tag registry.\n *\n * Source: EMVCo MPM v1.1 §3 — public spec; Bank of Thailand and KASIKORN\n * adopt the same numbering with Thai-specific GUIDs under templates 29-31.\n *\n * Tags are stringly-typed (two-character zero-padded decimal) on the wire\n * but exposed here as named constants so call sites stay readable.\n */\n\n// ── Primary tags (root TLVs) ────────────────────────────────────────────\nexport const TAG_PAYLOAD_FORMAT = '00';\nexport const TAG_POINT_OF_INITIATION = '01';\nexport const TAG_MERCHANT_ACCOUNT_PROMPTPAY = '29';\nexport const TAG_MERCHANT_ACCOUNT_BILL_PAYMENT = '30';\nexport const TAG_MERCHANT_ACCOUNT_KSHOP = '31';\nexport const TAG_MERCHANT_CATEGORY_CODE = '52';\nexport const TAG_TRANSACTION_CURRENCY = '53';\nexport const TAG_TRANSACTION_AMOUNT = '54';\nexport const TAG_TIP_OR_CONVENIENCE_INDICATOR = '55';\nexport const TAG_TIP_FIXED = '56';\nexport const TAG_TIP_PERCENTAGE = '57';\nexport const TAG_COUNTRY_CODE = '58';\nexport const TAG_MERCHANT_NAME = '59';\nexport const TAG_MERCHANT_CITY = '60';\nexport const TAG_POSTAL_CODE = '61';\nexport const TAG_ADDITIONAL_DATA = '62';\nexport const TAG_CHECKSUM = '63';\nexport const TAG_LANGUAGE_TEMPLATE = '64';\nexport const TAG_PERSONAL_MESSAGE = '81';\n\n// ── PromptPay merchant template (under tag 29) sub-fields ──────────────\nexport const SUB_GUID = '00';\nexport const SUB_PROMPTPAY_MOBILE = '01';\nexport const SUB_PROMPTPAY_NATIONAL_ID = '02';\nexport const SUB_PROMPTPAY_EWALLET = '03';\nexport const SUB_PROMPTPAY_BANK_ACCOUNT = '04';\nexport const SUB_PROMPTPAY_OTA = '05';\n\n// ── TrueMoney Wallet (also under tag 29, shares the PromptPay AID) ─────\n// Distinguished from PromptPay e-wallet by the literal \"14\" prefix in\n// sub-tag 03's value. The remaining 13 chars are the merchant's mobile,\n// zero-padded on the left.\nexport const SUB_TRUE_MONEY = '03';\nexport const TRUE_MONEY_PREFIX = '14';\n\n// ── BillPayment merchant template (under tag 30) sub-fields ────────────\nexport const SUB_BILL_BILLER_ID = '01';\nexport const SUB_BILL_REFERENCE_1 = '02';\nexport const SUB_BILL_REFERENCE_2 = '03';\n\n// ── Additional-data template (under tag 62) sub-fields ──────────────────\nexport const SUB_ADD_BILL_NUMBER = '01';\nexport const SUB_ADD_MOBILE_NUMBER = '02';\nexport const SUB_ADD_STORE_LABEL = '03';\nexport const SUB_ADD_LOYALTY_NUMBER = '04';\nexport const SUB_ADD_REFERENCE_LABEL = '05';\nexport const SUB_ADD_CUSTOMER_LABEL = '06';\nexport const SUB_ADD_TERMINAL_LABEL = '07';\nexport const SUB_ADD_PURPOSE_OF_TRANSACTION = '08';\nexport const SUB_ADD_CONSUMER_DATA_REQUEST = '09';\n\n// ── Constants from the Thai QR Payment supplement ──────────────────────\nexport const PAYLOAD_FORMAT_VERSION = '01';\nexport const POI_STATIC = '11';\nexport const POI_DYNAMIC = '12';\nexport const CURRENCY_THB = '764';\nexport const COUNTRY_TH = 'TH';\nexport const GUID_PROMPTPAY = 'A000000677010111';\nexport const GUID_BILL_PAYMENT = 'A000000677010112';\n// One-Time Authorization rides the PromptPay envelope but swaps the AID\n// so scanners can distinguish a single-use credit transfer from a\n// repeatable PromptPay payment.\nexport const GUID_PROMPTPAY_OTA = 'A000000677010114';\n// Cross-border bill payment shares tag 30 with the domestic variant but\n// flags itself with a distinct AID so scanners route the payload through\n// the ASEAN remittance rails (PayNow/DuitNow/QRIS interop) instead of the\n// local PromptPay biller switch.\nexport const GUID_BILL_PAYMENT_CROSS_BORDER = 'A000000677012006';\n\n// ── Tip handling ────────────────────────────────────────────────────────\nexport const TIP_PROMPT = '01';\nexport const TIP_FIXED = '02';\nexport const TIP_PERCENTAGE = '03';\n\n// ── VAT TQRC template (Bank of Thailand Tax-Qualified QR extension) ────\n// Tag 80 carries a nested TLV that turns a regular payment QR into an\n// e-tax-receipt source. The \"ascending tag id\" wire rule places it after\n// tag 64 and before tag 63 — the CRC-last rule wins over ordering.\nexport const TAG_VAT_TQRC = '80';\nexport const SUB_VAT_SELLER_TAX_BRANCH_ID = '00';\nexport const SUB_VAT_RATE = '01';\nexport const SUB_VAT_AMOUNT = '02';\n","/**\n * TLV (Tag-Length-Value) primitives for the EMVCo QR wire format.\n *\n * Every field on the wire is `IILLDDDD…` where `II` is the 2-char tag id,\n * `LL` is the 2-char zero-padded byte length, and `DDDD…` is the value.\n * Nested templates (tags 29-31, 62, 64) contain TLV runs in their value\n * slot recursively.\n */\n\n/** A parsed TLV field with its (possibly-nested) value text. */\nexport interface TLVField {\n  readonly tag: string;\n  readonly value: string;\n}\n\n/** Encode one TLV. The caller guarantees that `tag` is a valid 2-digit id. */\nexport function encodeField(tag: string, value: string): string {\n  const length = value.length.toString(10).padStart(2, '0');\n  if (value.length > 99) {\n    throw new RangeError(\n      `TLV value for tag ${tag} exceeds 99 bytes (got ${value.length}); split across multiple tags`,\n    );\n  }\n  return tag + length + value;\n}\n\n/**\n * Encode an array of `[tag, value]` pairs in registration order. Empty or\n * `null`/`undefined` values are filtered out so callers can compose\n * optional fields without an `if` chain.\n */\nexport function encodeFields(\n  pairs: ReadonlyArray<readonly [string, string | null | undefined]>,\n): string {\n  let out = '';\n  for (const [tag, value] of pairs) {\n    if (value == null || value === '') continue;\n    out += encodeField(tag, value);\n  }\n  return out;\n}\n\n/**\n * Walk a TLV-encoded string and return one field at a time. Stops cleanly\n * at end-of-input; throws on malformed length headers or truncated values.\n *\n * Designed for parsing both the root payload and nested template values\n * — the same algorithm applies at any depth.\n */\nexport function* iterateFields(input: string): IterableIterator<TLVField> {\n  let cursor = 0;\n  while (cursor < input.length) {\n    if (cursor + 4 > input.length) {\n      throw new SyntaxError(`Truncated TLV header at offset ${cursor}`);\n    }\n    const tag = input.slice(cursor, cursor + 2);\n    const lengthText = input.slice(cursor + 2, cursor + 4);\n    const length = Number.parseInt(lengthText, 10);\n    if (!Number.isFinite(length) || lengthText.length !== 2) {\n      throw new SyntaxError(`Invalid TLV length \"${lengthText}\" at offset ${cursor + 2}`);\n    }\n    const valueStart = cursor + 4;\n    const valueEnd = valueStart + length;\n    if (valueEnd > input.length) {\n      throw new SyntaxError(\n        `TLV value for tag ${tag} runs past end of input (need ${length} bytes from offset ${valueStart})`,\n      );\n    }\n    yield { tag, value: input.slice(valueStart, valueEnd) };\n    cursor = valueEnd;\n  }\n}\n\n/** Convenience over `iterateFields` — collect into a Map by tag id. */\nexport function parseFields(input: string): Map<string, string> {\n  const map = new Map<string, string>();\n  for (const field of iterateFields(input)) {\n    map.set(field.tag, field.value);\n  }\n  return map;\n}\n","/** Sub-path entry — direct re-export of the payload source. */\nexport * from '../../payload/src/index.js';\n"],"names":["formatAmount","value","options","baht","Number","TypeError","RangeError","cents","Math","baht10","sub","buildBOTBarcode","input","PAYLOAD_PREFIX","normaliseBillerId","ensureRef","formatAmountField","parseBOTBarcode","barcode","parts","billerId","ref1","ref2","amountField","result","amount","decodeAmountField","raw","name","satang","field","i","code","ThaiQRPaymentBuilder","Map","_tags","recipient","type","_recipient","bankCode","accountNo","otaCode","aid","template","_tlv","mobileNo","digits","wireMobile","undefined","formatted","_amount","mode","info","fields","Object","method","pairs","body","additional","_message","sorted","tag","a","b","seed","_crc","payload","text","out","Uint8Array","checksum","CRC_TABLE","table","Uint16Array","byte","acc","bit","_builder","_barcode","_slipverify","_parser","payloadFor","opts","encodePersonalMessage","message","decodePersonalMessage","hex","SyntaxError","unit","String","parsePayload","fromMobileWire","wire","trimmed","fromTrueMoneyWire","parsePromptPayTemplate","guid","isOta","ota","bankAccount","mobile","nationalId","eWallet","parseTrueMoneyTemplate","wireValue","parseBillPaymentTemplate","crossBorder","parseAdditionalDataTemplate","parseVatTqrcTemplate","sellerTaxBranchId","vatAmount","vatRate","extractCrc","strict","fullCrc","fullSeed","expected","Error","dropped","candidateEnd","candidateSeed","wireCrc","padded","vatTqrc","canonical","crc","rawTags","root","promptpayTemplate","billPaymentTemplate","merchant","trueMoneyWithMessage","messageHex","amountText","vatTemplate","decoded","id","subId","parent","normaliseBankAccount","normaliseRecipient","stripNonDigits","toMobileWire","explicit","codeDigits","accountDigits","buildSlipVerify","buildTrueMoneySlipVerify","parseSlipVerify","parseTrueMoneySlipVerify","SLIP_VERIFY_API_TYPE","CRC_HEADER","TAG_CRC","inner","repaired","repairCrcEnvelope","sendingBank","transRef","eventType","transactionId","date","caseSensitive","headerIdx","seedEnd","tail","normalised","COUNTRY_TH","CURRENCY_THB","GUID_BILL_PAYMENT","GUID_BILL_PAYMENT_CROSS_BORDER","GUID_PROMPTPAY","GUID_PROMPTPAY_OTA","PAYLOAD_FORMAT_VERSION","POI_DYNAMIC","POI_STATIC","SUB_ADD_BILL_NUMBER","SUB_ADD_CONSUMER_DATA_REQUEST","SUB_ADD_CUSTOMER_LABEL","SUB_ADD_LOYALTY_NUMBER","SUB_ADD_MOBILE_NUMBER","SUB_ADD_PURPOSE_OF_TRANSACTION","SUB_ADD_REFERENCE_LABEL","SUB_ADD_STORE_LABEL","SUB_ADD_TERMINAL_LABEL","SUB_BILL_BILLER_ID","SUB_BILL_REFERENCE_1","SUB_BILL_REFERENCE_2","SUB_GUID","SUB_PROMPTPAY_BANK_ACCOUNT","SUB_PROMPTPAY_EWALLET","SUB_PROMPTPAY_MOBILE","SUB_PROMPTPAY_NATIONAL_ID","SUB_PROMPTPAY_OTA","SUB_TRUE_MONEY","SUB_VAT_AMOUNT","SUB_VAT_RATE","SUB_VAT_SELLER_TAX_BRANCH_ID","TAG_ADDITIONAL_DATA","TAG_CHECKSUM","TAG_COUNTRY_CODE","TAG_LANGUAGE_TEMPLATE","TAG_MERCHANT_ACCOUNT_BILL_PAYMENT","TAG_MERCHANT_ACCOUNT_KSHOP","TAG_MERCHANT_ACCOUNT_PROMPTPAY","TAG_MERCHANT_CATEGORY_CODE","TAG_MERCHANT_CITY","TAG_MERCHANT_NAME","TAG_PAYLOAD_FORMAT","TAG_PERSONAL_MESSAGE","TAG_POINT_OF_INITIATION","TAG_POSTAL_CODE","TAG_TIP_FIXED","TAG_TIP_OR_CONVENIENCE_INDICATOR","TAG_TIP_PERCENTAGE","TAG_TRANSACTION_AMOUNT","TAG_TRANSACTION_CURRENCY","TAG_VAT_TQRC","TIP_FIXED","TIP_PERCENTAGE","TIP_PROMPT","TRUE_MONEY_PREFIX","encodeField","length","encodeFields","iterateFields","cursor","lengthText","valueStart","valueEnd","parseFields","map"],"mappings":"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"}