[Tech Spec] asiapay — Unknown
- Dominant language
- Python
- Stars
- 4
- Forks
- 6
- PR merge metrics
- No merged PRs in 30d
Description
# asiapay — Unknown
**Complexity:** low
**Generated by:** Grace pipeline run `run-2026-05-21T20-25-14-681Z-b24347`
## Summary
Implement Unknown payment method for asiapay connector. AsiaPay (PayDollar) API Technical Specification
## Scope
# AsiaPay (PayDollar) API Technical Specification
## 1. Connector Profile
| Property | Value |
|----------|-------|
| **Connector Name** | AsiaPay (PayDollar) |
| **Primary Flow Scope** | Card Payments (Authorize, Capture, Refund, Void, PSync) |
| **API Family** | REST / HTTP POST (form-encoded) |
| **API Version** | v3 (PayDollar Direct Client API) |
### Hosts
| Environment | Base URL |
|-------------|----------|
| Production | `https://www.paydollar.com` |
| Sandbox/Test | `https://test.paydollar.com` |
| Regional (SG) | `https://www.paydollar.com` |
| Regional (CN) | `https://www.paydollar.com` |
---
## 2. Authentication
**Scheme:** HMAC-SHA256 Secure Hash
**Credentials Required:**
- `merchantId` — Merchant account identifier (provided by AsiaPay)
- `secureHashSecret` — Secret key used for HMAC signature generation
**Hash Construction:**
```
secureHash = SHA256(merchantId + "|" + orderRef + "|" + currCode + "|" + amount + "|" + payType + "|" + secureHashSecret)
```
The resulting hex-encoded SHA256 digest is passed as the `secureHash` request field. All parameters must be pipe-delimited in the exact order listed above.
**Implementation Notes:**
- Hash is computed per-request and included as a form field, not an HTTP header
- Merchant credentials are never transmitted in plaintext after the hash is applied
- The `secureHashSecret` must never appear in request bodies
- AsiaPay validates the `secureHash` on every inbound payment request
---
## 3. Supported Flows
| Flow | HTTP | Path | Notes |
|------|------|------|-------|
| Authorize (Auth-only) | POST | `/b2c/eng/directPay/payComp.jsp` | Set `payType=H` for hold/pre-auth |
| Sale (Auth+Capture) | POST | `/b2c/eng/directPay/payComp.jsp` | Set `payType=N` for immediate capture |
| Capture | POST | `/b2c/eng/data/payRecord.jsp` | Set `action=capture`; requires `Ref` from auth |
| Refund | POST | `/b2c/eng/data/payRecord.jsp` | Set `action=refund`; partial refunds supported |
| Void / Reversal | POST | `/
## Out of Scope
Not specified in techspec
## Technical Constraints
- Follow existing connector patterns in the codebase
---
## Full Tech Spec
# AsiaPay (PayDollar) API Technical Specification
## 1. Connector Profile
| Property | Value |
|----------|-------|
| **Connector Name** | AsiaPay (PayDollar) |
| **Primary Flow Scope** | Card Payments (Authorize, Capture, Refund, Void, PSync) |
| **API Family** | REST / HTTP POST (form-encoded) |
| **API Version** | v3 (PayDollar Direct Client API) |
### Hosts
| Environment | Base URL |
|-------------|----------|
| Production | `https://www.paydollar.com` |
| Sandbox/Test | `https://test.paydollar.com` |
| Regional (SG) | `https://www.paydollar.com` |
| Regional (CN) | `https://www.paydollar.com` |
---
## 2. Authentication
**Scheme:** HMAC-SHA256 Secure Hash
**Credentials Required:**
- `merchantId` — Merchant account identifier (provided by AsiaPay)
- `secureHashSecret` — Secret key used for HMAC signature generation
**Hash Construction:**
```
secureHash = SHA256(merchantId + "|" + orderRef + "|" + currCode + "|" + amount + "|" + payType + "|" + secureHashSecret)
```
The resulting hex-encoded SHA256 digest is passed as the `secureHash` request field. All parameters must be pipe-delimited in the exact order listed above.
**Implementation Notes:**
- Hash is computed per-request and included as a form field, not an HTTP header
- Merchant credentials are never transmitted in plaintext after the hash is applied
- The `secureHashSecret` must never appear in request bodies
- AsiaPay validates the `secureHash` on every inbound payment request
---
## 3. Supported Flows
| Flow | HTTP | Path | Notes |
|------|------|------|-------|
| Authorize (Auth-only) | POST | `/b2c/eng/directPay/payComp.jsp` | Set `payType=H` for hold/pre-auth |
| Sale (Auth+Capture) | POST | `/b2c/eng/directPay/payComp.jsp` | Set `payType=N` for immediate capture |
| Capture | POST | `/b2c/eng/data/payRecord.jsp` | Set `action=capture`; requires `Ref` from auth |
| Refund | POST | `/b2c/eng/data/payRecord.jsp` | Set `action=refund`; partial refunds supported |
| Void / Reversal | POST | `/b2c/eng/data/payRecord.jsp` | Set `action=void`; only before settlement |
| PSync (Payment Status) | POST | `/b2c/eng/data/payRecord.jsp` | Set `action=query` to retrieve transaction status |
| RSync (Refund Status) | POST | `/b2c/eng/data/payRecord.jsp` | Set `action=queryRefund` |
| Webhooks / IPN | POST | Merchant-configured endpoint | AsiaPay pushes `dataFeed` POST to merchant URL |
---
## 4. Request Schema Highlights
### Payment (Authorize / Sale)
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `merchantId` | string | Yes | AsiaPay merchant ID |
| `orderRef` | string | Yes | Merchant order reference — idempotency key; unique per transaction |
| `currCode` | string | Yes | ISO 4217 numeric currency code (e.g., `840`=USD, `344`=HKD, `702`=SGD) |
| `amount` | string | Yes | Amount in minor units (e.g., `1000` = 10.00 USD) |
| `payType` | string | Yes | `N`=Normal (auth+capture), `H`=Hold (auth only) |
| `pMethod` | string | Yes | Card network: `VISA`, `Master`, `AMEX`, `JCB`, `DINERS`, `UnionPay` |
| `cardNo` | string | Yes | Full card number (16 digits) |
| `epMonth` | string | Yes | Card expiry month (MM, zero-padded) |
| `epYear` | string | Yes | Card expiry year (YYYY) |
| `securityCode` | string | Conditional | CVV/CVC (required for card-not-present) |
| `cardHolder` | string | Yes | Cardholder name as printed on card |
| `secureHash` | string | Yes | HMAC-SHA256 security hash (see Authentication) |
| `remark` | string | No | Merchant-defined transaction description |
| `successUrl` | string | Conditional | Redirect URL on payment success (for redirect flow) |
| `failUrl` | string | Conditional | Redirect URL on payment failure |
| `cancelUrl` | string | Conditional | Redirect URL on payment cancellation |
| `lang` | string | No | Language code for hosted page (`E`=English, `C`=Chinese) |
| `mpsMode` | string | No | Payment mode: `NIL`=direct, `SCP`=hosted page |
| `email` | string | No | Customer email address |
| `phone` | string | No | Customer phone number |
| `billingAddress1` | string | No | Billing address line 1 |
| `billingCity` | string | No | Billing city |
| `billingCountry` | string | No | Billing country (ISO 3166-1 alpha-2) |
| `billingPostCode` | string | No | Billing postal code |
### Capture / Refund / Void / Query
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `merchantId` | string | Yes | AsiaPay merchant ID |
| `loginId` | string | Yes | AsiaPay admin login ID |
| `password` | string | Yes | MD5 hash of admin password |
| `action` | string | Yes | `capture`, `refund`, `void`, `query`, `queryRefund` |
| `Ref` | string | Yes | AsiaPay transaction reference (from auth response) |
| `amount` | string | Conditional | Amount to refund/capture (partial refund supported) |
| `remark` | string | No | Reason for refund or void |
---
## 5. Response Schema Highlights
### Payment Response
| Field | Type | Description |
|-------|------|-------------|
| `successcode` | string | `0`=success, `-1`=failure |
| `Ref` | string | AsiaPay transaction reference (primary transaction ID) |
| `PayRef` | string | Bank/acquirer payment reference number |
| `Amt` | string | Authorized amount in minor units |
| `Cur` | string | ISO 4217 numeric currency code |
| `Ord` | string | Echo of merchant order reference |
| `AuthId` | string | Bank authorization code |
| `prc` | string | Processor/acquirer response code |
| `src` | string | Card network scheme response code |
| `Holder` | string | Masked cardholder name |
| `MaskedCardNum` | string | Masked card number (e.g., `4111111111111111` → `411111******1111`) |
| `errCode` | string | Error code (populated on failure) |
| `errMsg` | string | Human-readable error message (populated on failure) |
| `panFirst6` | string | First 6 digits of card (BIN) |
| `panLast4` | string | Last 4 digits of card |
| `cardIssuer` | string | Issuing bank name |
| `cardIssuerCountry` | string | ISO country code of card issuer |
### Status Values
| `successcode` | Meaning | UCS AttemptStatus |
|---------------|---------|-------------------|
| `0` | Transaction successful | `Authorized` / `Charged` |
| `-1` | Transaction failed / declined | `Failure` |
| `1` | Pending / Under review | `Pending` |
---
## 6. Error Handling
| HTTP | `errCode` | Cause |
|------|-----------|-------|
| 200 | `1` | Processing error — generic gateway failure |
| 200 | `2` | Invalid transaction parameters |
| 200 | `3` | Bank declined — insufficient funds, card blocked, etc. |
| 200 | `4` | Transaction not found (for capture/refund/void) |
| 200 | `5` | Duplicate order reference (`orderRef` already used) |
| 200 | `6` | Invalid card number (Luhn check failed) |
| 200 | `7` | Invalid or expired card expiry date |
| 200 | `8` | Invalid CVV/security code |
| 200 | `10` | Insufficient funds on card |
| 200 | `11` | Card expired |
| 200 | `12` | Invalid or inactive merchant account |
| 200 | `13` | Transaction amount exceeds limit |
| 200 | `20` | 3DS authentication required but not completed |
| 200 | `99` | System/internal error — retry after delay |
| 400 | N/A | Malformed request — missing required fields or invalid encoding |
| 401 | N/A | Authentication failure — invalid `secureHash` |
| 403 | N/A | Unauthorized — merchant IP not whitelisted or account suspended |
| 500 | N/A | AsiaPay internal server error |
**Note:** AsiaPay always returns HTTP 200 for processed transactions; the `successcode` field indicates the actual payment outcome. Non-200 HTTP codes indicate infrastructure-level failures.
---
## 7. Webhooks / Async Notifications
### Subscription
AsiaPay pushes asynchronous payment notifications via HTTP POST (IPN — Instant Payment Notification) to a merchant-configured `dataFeed` URL. Configuration is done through the AsiaPay merchant admin portal.
### Delivery Format
The notification is a form-encoded (`application/x-www-form-urlencoded`) POST containing the same fields as the payment response (see §5), plus:
| Field | Type | Description |
|-------|------|-------------|
| `merchantId` | string | Merchant ID |
| `Ref` | string | AsiaPay transaction reference |
| `PayRef` | string | Bank payment reference |
| `successcode` | string | Transaction result: `0`=success, `-1`=failure |
| `Amt` | string | Amount in minor units |
| `Cur` | string | Currency code |
| `Ord` | string | Merchant order reference |
| `payerAuth` | string | 3DS authentication result |
| `secureHash` | string | Hash for webhook verification |
### Verification
Webhook authenticity is verified by recomputing the HMAC-SHA256 hash using the same algorithm as request signing (§2) and comparing it to the `secureHash` field in the notification payload.
### Retry Policy
- AsiaPay retries failed webhook deliveries up to 3 times with exponential backoff (intervals: ~5 min, ~30 min, ~2 hours).
- Merchant endpoint must respond with HTTP 200 to acknowledge receipt; any other status code triggers a retry.
### Documented Gaps
- AsiaPay does not offer a webhook subscription management API; configuration is portal-only.
- There is no standardized event type enumeration; payment outcome is inferred from `successcode` and `action` fields.
- Refund and void notifications use the same endpoint and payload schema as payment notifications but with `action=refund` or `action=void` in the body.
- No structured webhook signature header (e.g., `X-Signature`); signature is embedded in the POST body.
---
## 8. References
| Resource | URL |
|----------|-----|
| AsiaPay Developer Portal | `https://www.asiapay.com/developer/` |
| PayDollar Integration Guide | `https://www.paydollar.com/b2c/eng/content/payDollar.jsp` |
| PayDollar Direct Client API | `https://www.paydollar.com/b2c/rest/` |
| Merchant Admin Portal (Production) | `https://www.paydollar.com/b2c/eng/merchant/index.jsp` |
| Merchant Admin Portal (Sandbox) | `https://test.paydollar.com/b2c/eng/merchant/index.jsp` |
| Currency Codes Reference | `https://www.iso.org/iso-4217-currency-codes.html` |
| AsiaPay Product Overview | `https://www.asiapay.com/products/` |
---
## 9. API Call Sequences
### Authorize (Auth-Only)
```
Step 1: POST /b2c/eng/directPay/payComp.jsp
Input: merchantId=CONFIGURATION, orderRef=USER_PROVIDED,
currCode=USER_PROVIDED, amount=USER_PROVIDED,
payType=H (hold), cardNo=USER_PROVIDED, secureHash=COMPUTED
Returns: Ref (used in Step 2 capture)
```
### Sale (Auth+Capture)
```
Step 1: POST /b2c/eng/directPay/payComp.jsp
Input: merchantId=CONFIGURATION, orderRef=USER_PROVIDED,
currCode=USER_PROVIDED, amount=USER_PROVIDED,
payType=N (normal), cardNo=USER_PROVIDED, secureHash=COMPUTED
Returns: Ref (for PSync reference)
```
### Capture
```
Step 1: POST /b2c/eng/data/payRecord.jsp
Input: merchantId=CONFIGURATION, loginId=CONFIGURATION,
password=CONFIGURATION (MD5-hashed), action=capture,
Ref=PREVIOUS_API (from auth response.Ref)
Returns: successcode, PayRef
```
### Refund
```
Step 1: POST /b2c/eng/data/payRecord.jsp
Input: merchantId=CONFIGURATION, loginId=CONFIGURATION,
password=CONFIGURATION, action=refund,
Ref=PREVIOUS_API (from payment response.Ref),
amount=USER_PROVIDED (partial or full)
Returns: successcode, errCode, errMsg
```
### Void
```
Step 1: POST /b2c/eng/data/payRecord.jsp
Input: merchantId=CONFIGURATION, loginId=CONFIGURATION,
password=CONFIGURATION, action=void,
Ref=PREVIOUS_API (from auth response.Ref)
Returns: successcode
```
### PSync
```
Step 1: POST /b2c/eng/data/payRecord.jsp
Input: merchantId=CONFIGURATION, loginId=CONFIGURATION,
password=CONFIGURATION, action=query,
Ref=PREVIOUS_API (from payment response.Ref)
Returns: successcode, Amt, Cur, Ord, AuthId, MaskedCardNum
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.