npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@carllee1983/tappay-backend-payment-node

v1.7.0

Published

TapPay Backend Payment SDK for Node.js - A TypeScript SDK for TapPay Backend Payment APIs with full type support

Readme

TapPay Backend Payment SDK

English | 繁體中文

A TypeScript SDK for TapPay Backend Payment APIs

npm version License: MIT Node.js

Features

  • 🔒 Full TypeScript Support - Complete type definitions for all APIs
  • 🚀 Modern Architecture - Built with ES Modules and CommonJS support
  • Zero Dependencies - Uses native fetch API (Node.js 18+)
  • 🛡️ Error Handling - Typed error classes for precise error handling
  • 📦 Small Bundle Size - Minimal footprint for production use

Installation

npm install @carllee1983/tappay-backend-payment-node-node
# or
yarn add @carllee1983/tappay-backend-payment-node-node
# or
pnpm add @carllee1983/tappay-backend-payment-node-node
# or
bun add @carllee1983/tappay-backend-payment-node-node

Quick Start

import { TapPayClient, Env, Currency } from '@carllee1983/tappay-backend-payment-node-node'

// Create client
const client = new TapPayClient({
  partnerKey: 'your_partner_key',
  merchantId: 'your_merchant_id',
  env: Env.Sandbox, // Use Env.Production for production
})

// Pay by Prime
const payment = await client.payByPrime({
  prime: 'prime_from_frontend',
  amount: 100,
  currency: Currency.TWD,
  details: 'Product Description',
  cardholder: {
    phone_number: '+886912345678',
    name: 'Test User',
    email: '[email protected]',
  },
})

console.log(`Transaction ID: ${payment.rec_trade_id}`)

API Reference

TapPayClient

The main client class for interacting with TapPay APIs.

Constructor

new TapPayClient({
  partnerKey: string,   // Required: Partner Key from TapPay Portal
  merchantId: string,   // Required: Merchant ID
  env?: Env,            // Optional: Env.Sandbox (default) or Env.Production
  timeout?: number,     // Optional: Request timeout in ms (default: 30000)
})

Payment Methods

Pay by Prime

Process a payment using a prime token from frontend SDK.

const response = await client.payByPrime({
  prime: 'test_prime_123',
  amount: 100,
  currency: Currency.TWD,
  details: 'Test Payment',
  cardholder: {
    phone_number: '+886912345678',
    name: 'Test User',
    email: '[email protected]',
  },
  // Optional: Enable 3D Secure
  three_domain_secure: true,
  result_url: {
    frontend_redirect_url: 'https://example.com/payment/success',
    backend_notify_url: 'https://example.com/api/notify',
  },
  // Optional: Remember card for future payments
  remember: true,
})

// If remember=true, save these for future payments
if (response.card_secret) {
  const { card_key, card_token } = response.card_secret
  // Store securely for recurring payments
}

Pay by Card Token

Process a payment using saved card credentials.

const response = await client.payByToken({
  card_key: 'saved_card_key',
  card_token: 'saved_card_token',
  amount: 100,
  currency: Currency.TWD,
  details: 'Recurring Payment',
})

Transaction Management

Refund

Process a full or partial refund.

// Full refund
await client.refund('D20231201123456789')

// Partial refund
await client.refund('D20231201123456789', { amount: 50 })

Query Records

Retrieve transaction records with filtering and pagination.

const records = await client.getRecords({
  records_per_page: 10,
  page: 0,
  filters: {
    time: {
      start_time: Date.now() - 7 * 24 * 60 * 60 * 1000, // Last 7 days
      end_time: Date.now(),
    },
  },
  order_by: {
    attribute: 'time',
    is_descending: true,
  },
})

Get Single Transaction

const record = await client.getTransaction('D20231201123456789')
if (record) {
  console.log(`Status: ${record.status}`)
}

Get Trade History

Get detailed transaction history including all events.

const history = await client.getTradeHistory('D20231201123456789')
history.trade_history?.forEach(event => {
  console.log(`${event.event_type}: ${event.status}`)
})

Advanced APIs

Capture Today

Capture a delayed-capture transaction immediately.

await client.capToday('D20231201123456789')

Cancel Capture

Cancel a pending capture before bank batch processing.

await client.cancelCapture('D20231201123456789')

Cancel Refund

Cancel a pending refund (currently only supported by Taishin Bank).

await client.cancelRefund('D20231201123456789', 'R20231201123456789')

Card Management

Bind Card

Bind a card for future token-based payments without charging.

const response = await client.bindCard({
  prime: 'prime_from_frontend',
  currency: Currency.TWD,
  cardholder: {
    phone_number: '+886912345678',
    name: 'Test User',
    email: '[email protected]'
  }
})

if (response.card_secret) {
  const { card_key, card_token } = response.card_secret
  // Store for future payments
}

Remove Card

Remove a bound card from TapPay servers.

await client.removeCard('card_key_123', 'card_token_123')

Error Handling

The SDK provides typed error classes for precise error handling. All errors extend the standard Error class and can be caught using try-catch blocks.

Error Types

TapPayError

Thrown when the TapPay API returns an error response (e.g., invalid prime, insufficient funds, card declined).

import { TapPayError } from '@carllee1983/tappay-backend-payment-node'

try {
  const response = await client.payByPrime({ ... })
} catch (error) {
  if (error instanceof TapPayError) {
    console.error(`API Error: ${error.message}`)
    console.error(`Status Code: ${error.status}`)
    console.error(`Transaction ID: ${error.recTradeId}`)
    
    // Check if transaction failed
    if (error.isTransactionFailed) {
      // Handle failed transaction
    }
  }
}

Common TapPay Error Status Codes:

  • 10001: Invalid prime
  • 10002: Invalid card number
  • 10003: Insufficient funds
  • 10004: Card declined
  • See TapPay Documentation for complete list

TapPayValidationError

Thrown when input validation fails before making the API request (e.g., missing required fields, invalid values).

import { TapPayValidationError } from '@carllee1983/tappay-backend-payment-node'

try {
  await client.payByPrime({
    prime: '', // Empty prime will trigger validation error
    amount: 100,
  })
} catch (error) {
  if (error instanceof TapPayValidationError) {
    console.error(`Validation Error: ${error.message}`)
    console.error(`Field: ${error.field}`) // e.g., 'prime', 'amount'
  }
}

Common Validation Errors:

  • Missing required fields (prime, amount, currency, etc.)
  • Empty strings for required fields
  • Invalid amount (zero or negative)
  • Empty transaction IDs

TapPayTimeoutError

Thrown when the API request times out.

import { TapPayTimeoutError } from '@carllee1983/tappay-backend-payment-node'

try {
  await client.payByPrime({ ... })
} catch (error) {
  if (error instanceof TapPayTimeoutError) {
    console.error(`Request timed out after ${error.timeout}ms`)
    console.error(`Endpoint: ${error.endpoint}`)
    
    // Consider retrying the request
  }
}

TapPayConfigError

Thrown when client configuration is invalid (e.g., missing partner key, invalid timeout).

import { TapPayConfigError } from '@carllee1983/tappay-backend-payment-node'

try {
  const client = new TapPayClient({
    partnerKey: '', // Empty key will trigger config error
    merchantId: 'test_merchant_id',
  })
} catch (error) {
  if (error instanceof TapPayConfigError) {
    console.error(`Config Error: ${error.message}`)
    console.error(`Field: ${error.field}`) // e.g., 'partnerKey', 'merchantId'
  }
}

Complete Error Handling Example

import {
  TapPayClient,
  TapPayError,
  TapPayConfigError,
  TapPayTimeoutError,
  TapPayValidationError,
} from '@carllee1983/tappay-backend-payment-node'

async function processPayment(prime: string, amount: number) {
  try {
    const response = await client.payByPrime({
      prime,
      amount,
      currency: Currency.TWD,
      details: 'Product Purchase',
    })
    
    return { success: true, transactionId: response.rec_trade_id }
  } catch (error) {
    if (error instanceof TapPayValidationError) {
      // Input validation failed - fix the input and retry
      console.error(`Invalid input: ${error.field} - ${error.message}`)
      return { success: false, error: 'INVALID_INPUT', field: error.field }
    } else if (error instanceof TapPayTimeoutError) {
      // Request timed out - consider retrying
      console.error(`Request timeout: ${error.endpoint}`)
      return { success: false, error: 'TIMEOUT', retryable: true }
    } else if (error instanceof TapPayError) {
      // API returned an error
      console.error(`Payment failed: ${error.message} (Status: ${error.status})`)
      return {
        success: false,
        error: 'PAYMENT_FAILED',
        status: error.status,
        transactionId: error.recTradeId,
      }
    } else {
      // Unexpected error
      console.error('Unexpected error:', error)
      return { success: false, error: 'UNKNOWN' }
    }
  }
}

Error Handling Best Practices

  1. Always handle errors: Wrap API calls in try-catch blocks
  2. Check error types: Use instanceof to handle different error types appropriately
  3. Log errors: Include error details in logs for debugging
  4. Retry timeouts: Consider retrying on TapPayTimeoutError
  5. Validate input: Catch TapPayValidationError early to provide better user feedback

Backend Notify

For 3D Secure and e-payment transactions, TapPay will POST to your backend_notify_url:

import type { BackendNotifyPayload } from '@carllee1983/tappay-backend-payment-node'

// Express.js example
app.post('/api/notify', (req, res) => {
  const payload: BackendNotifyPayload = req.body

  if (payload.status === 0) {
    // Payment successful
    console.log(`Transaction ${payload.rec_trade_id} completed`)
  } else {
    // Payment failed
    console.log(`Transaction failed: ${payload.msg}`)
  }

  res.status(200).send('OK')
})

Currency Support

The SDK supports multiple currencies:

import { Currency, CurrencyMultiplier } from '@carllee1983/tappay-backend-payment-node'

Currency.TWD // Taiwan Dollar (multiplier: 1)
Currency.USD // US Dollar (multiplier: 100)
Currency.JPY // Japanese Yen (multiplier: 1)
Currency.EUR // Euro (multiplier: 100)
// ... and more

Note: For currencies with multiplier of 100, the amount should be multiplied by 100. For example, USD $1.00 should be sent as amount: 100.

Test Cards

For sandbox testing, use TapPay's test cards:

  • Success: 4242424242424242
  • Failed: 4111111111111111

See TapPay Documentation for more test cards.

Requirements

  • Node.js >= 18.0.0 (for native fetch support)
  • TypeScript >= 5.0 (for development)

License

MIT © Carl Lee

Related