Skip to content

Repository files navigation

TapPay Python SDK

CI PyPI version Python Versions Code style: ruff License: MIT

Important

Python 2 Support Dropped: As of version 0.5.0, this library no longer supports Python 2.7. Please use Python 3.8 or newer.

Note

Pydantic v2 Integration: As of version 0.6.0, this library uses Pydantic v2 for enhanced data validation, type safety, and automatic serialization. This provides better error messages and ensures data integrity when working with TapPay APIs.

Note

Typed: As of version 0.6.1, this package ships a py.typed marker (PEP 561), so mypy, Pyright, and your IDE will use the library's own type hints.

Note

Connection reuse: As of version 0.7.0, the client holds a pooled requests.Session, so repeated calls reuse an established TLS connection instead of renegotiating one each time. Close it with client.close() or use the client as a context manager.

This is the unofficial Python client library for TapPay's Backend API. To use it you'll need a TapPay account. Sign up at tappaysdk.com.

Installation

Install using pip:

pip install tappay

Usage

Initialization

import tappay

# Initialize the client
client = tappay.Client(
    is_sandbox=True,
    partner_key="YOUR_PARTNER_KEY",
    merchant_id="YOUR_MERCHANT_ID",
)

For production, you can set TAPPAY_PARTNER_KEY and TAPPAY_MERCHANT_ID environment variables and omit them in the constructor:

client = tappay.Client(is_sandbox=False)

Timeouts

Every request carries a timeout by default: (3.05, 27.0) seconds, as a (connect, read) pair. Override it for all calls on a client:

client = tappay.Client(is_sandbox=False, timeout=10.0)

Or for a single call, using the keyword-only timeout argument available on every API method:

response = client.refund(rec_trade_id="rec_trade_id", amount=100, timeout=(3.05, 60.0))

Passing timeout=None to the constructor disables the timeout entirely, which lets a stalled request block the calling thread indefinitely. This is almost never what you want in a server process.

Logging

The client logs request and response details at DEBUG level. Credentials (partner_key, x-api-key), card handles (prime, card_key, card_token), and cardholder PII (name, email, phone number, address, national ID) are replaced with ***REDACTED*** before anything reaches the logger, so enabling debug logging will not spill payment data into your log aggregator.

import logging

logging.getLogger("tappay.client").setLevel(logging.DEBUG)

Pay by Prime

# Create cardholder data
card_holder = tappay.Models.CardHolderData(
    phone_number="0912345678",
    name="Wang Xiao Ming",
    email="test@example.com",
)

# Make payment
response = client.pay_by_prime(
    prime="prime_token_from_frontend",
    amount=100,
    details="Order #123",
    card_holder_data=card_holder,
)
print(response)

Pay by Token

response = client.pay_by_token(
    card_key="card_key",
    card_token="card_token",
    amount=100,
    details="Subscription",
)

Refunds

response = client.refund(
    rec_trade_id="rec_trade_id",
    amount=100,
)

Currencies

Payments settle in TWD by default. Pass currency to override it, using either a Models.Currencies member or a plain currency string:

response = client.pay_by_prime(
    prime="prime_token_from_frontend",
    amount=100,
    details="Order #123",
    card_holder_data=card_holder,
    currency=tappay.Models.Currencies.USD,
)

Handling failures

TapPay reports business failures such as a declined card with an HTTP 200 and a non-zero status in the response body, so they are invisible to HTTP-level error handling. By default the response is returned as-is and it is your job to check:

response = client.pay_by_prime(...)
if response["status"] != 0:
    ...  # declined, invalid argument, insufficient balance, and so on

Pass raise_on_error=True to have the client raise TapPayError instead:

client = tappay.Client(is_sandbox=False, raise_on_error=True)

try:
    response = client.pay_by_prime(...)
except tappay.TapPayError as exc:
    print(exc.status, exc.msg, exc.response["rec_trade_id"])

The exception hierarchy is:

Exception Raised when
AuthenticationError HTTP 401
ClientError HTTP 4xx
ServerError HTTP 5xx, or an unexpected status code
InvalidResponseError A 2xx body that is not valid JSON (subclasses ServerError)
TapPayError Non-zero status in a 2xx body (only with raise_on_error=True)

All of them subclass tappay.Error.

An intermediary such as a proxy or WAF can answer with an HTML error page under a 2xx status. That previously surfaced as a bare json.JSONDecodeError from inside requests; it now raises InvalidResponseError, reporting the status, host, content type, and body length. The body itself is deliberately left out of the message, since exception text tends to end up in logs and error trackers.

Connection reuse and retries

Each client owns a pooled session. Close it when you are done, or use the client as a context manager:

with tappay.Client(is_sandbox=False) as client:
    client.pay_by_prime(...)

The read-only query endpoints (get_records, get_trade_history) retry twice on connection errors and on HTTP 429/500/502/503/504, with exponential backoff. Payment, refund, capture, bind, and remove endpoints are never retried automatically: TapPay exposes no idempotency key, so retrying a request that actually succeeded upstream would charge the cardholder twice. Tune the retry count with max_retries=, or disable it with max_retries=0.

For more API details, please refer to the TapPay Backend API Documentation.

Development

Setup

  1. Clone the repository:
git clone https://github.com/shihweilo/tappay-python.git
cd tappay-python
  1. Create a virtual environment and install dependencies:
python3 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install -e ".[dev]"

Testing

Run tests using pytest:

pytest

Run tests with coverage:

pytest --cov=tappay --cov-report=term-missing

Type check with mypy:

mypy tappay

Linting and Formatting

Check code with ruff:

ruff check .

Format code with ruff:

ruff format .

Contributing

Please see CONTRIBUTING.md for details.

About

TapPay Backend SDK for Python.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages