[New Connector] AsiaPay — Authorize, PSync, Capture, Void, Refund, RSync, IncomingWebhook
- Dominant language
- Python
- Stars
- 4
- Forks
- 6
- PR merge metrics
- No merged PRs in 30d
Description
# AsiaPay — New Connector Integration
**Workflow:** new-connector
**Flows:** Authorize, PSync, Capture, Void, Refund, RSync, IncomingWebhook
**Auth scheme:** Signature
**Currency unit:** StringMajor
**Base URL:** https://www.paydollar.com/b2c2
**Sandbox URL:** https://test.paydollar.com/b2cDemo
**Generated by:** Grace pipeline run `run-2026-05-26T20-32-15-561Z-c21e4d`
## Discovered Docs
- https://www.asiapay.iq/integration
- https://www.readkong.com/page/paydollar-paygate-integration-guide-version-3-21-3398605
- https://www.paydollar.com/pdf/op/enpdintguide.pdf
## Acceptance Criteria
- [ ] Authorize flow compiles and runs
- [ ] gRPC Authorize call succeeds against sandbox
---
## Tech Spec
# AsiaPay UCS Connector Integration Technical Specification
## Connector Profile
AsiaPay (primary brand: **PayDollar**) is a leading Asia-Pacific payment gateway owned by **AsiaPay Limited** (Hong Kong). It operates under several regional sub-brands and also provides a separate REST API for the Middle East market under the AsiaPay IQ brand.
| Brand | Region |
|-------|--------|
| PayDollar | HK, CN, TW, SG, MY, IN, VN, AU, NZ, Macau |
| PesoPay | Philippines |
| SiamPay | Thailand |
| BimoPay | Indonesia |
| AsiaPay IQ | Middle East (Iraq) |
**Production Base URL (PayDollar):** `https://www.paydollar.com/b2c2`
**Sandbox Base URL (PayDollar):** `https://test.paydollar.com/b2cDemo`
**Merchant Administration Portal:** `https://admin.paydollar.com/b2c2/eng/merchant/index.jsp`
**AsiaPay IQ Sandbox Base URL:** `https://apitest.asiapay.iq:5443/apiaccess`
**Supported Countries:** All APAC countries (via PayDollar brands); Iraq (via AsiaPay IQ).
**Supported Currencies (ISO 4217 numeric codes used in `currCode`):**
| Currency | Numeric Code |
|----------|--------------|
| HKD | 344 |
| USD | 840 |
| SGD | 702 |
| CNY | 156 |
| JPY | 392 |
| TWD | 901 |
| AUD | 036 |
| EUR | 978 |
| GBP | 826 |
| CAD | 124 |
| MOP | 446 |
| PHP | 608 |
| THB | 764 |
| MYR | 458 |
| IDR | 360 |
PayDollar states 144+ currencies are supported; the above are the most common. AsiaPay IQ currently supports IQD.
---
## Authentication
### PayDollar (Traditional API — Primary Integration Target)
**Scheme:** Secure Hash (SHA-1 HMAC signature)
AsiaPay uses a **Secure Hash** to authenticate requests and verify incoming webhook callbacks. Merchants must contact `service@paydollar.com` to enable this feature. The `secureHashSecret` is then obtainable from the Merchant Administration Interface under **Profile → Payment Information**.
**Required Credentials:**
| Field | Description |
|-------|-------------|
| `merchantId` | Numeric identifier assigned to the merchant account |
| `secureHashSecret` | Secret key used to generate and verify SHA1 signatures |
**Outbound Request Signature (hash sent as body field):**
```
secureHash = SHA1(merchantId + "|" + orderRef + "|" + currCode + "|" + amount + "|" + payType + "|" + secureHashSecret)
```
**Callback Verification:**
```
expectedHash = SHA1(merchantId + "|" + Ref + "|" + Cur + "|" + Amt + "|" + payType + "|" + secureHashSecret)
assert secureHash == expectedHash
```
**Auth Location:** Body field (`secureHash` in form-encoded POST)
**Note:** SHA1 is the default hash function. Some accounts may use SHA256 (configurable in merchant settings and integration code).
---
### AsiaPay IQ (REST API — Secondary / Middle East)
**Scheme:** Two-phase JWT Bearer Token
**Step 1 — Acquire Token:**
```http
POST https://apitest.asiapay.iq:5443/apiaccess/payment/gateway/payment/v1/token
X-APP-Key: {app_key}
Content-Type: application/json
{"appSecret": "{appSecret}"}
```
**Response:**
```json
{
"token": "Bearer 76e0ac549fce799159aaf558694815c6",
"effectiveDate": "20250506233829",
"expirationDate": "20250507003829"
}
```
**Step 2 — Use Token on all subsequent requests:**
```
Authorization: Bearer {token}
X-APP-Key: {app_key}
```
**Request Signing:** All `biz_content` payloads include a `sign` field generated as a JWT signature using the merchant's `private_key`. `sign_type` must be `"JWTSecret"`.
**Required Credentials (AsiaPay IQ):**
| Field | Description |
|-------|-------------|
| `appid` | Application identifier |
| `app_key` | Placed in `X-APP-Key` header |
| `appSecret` | Used to obtain Bearer token |
| `private_key` | Used to generate JWT `sign` field |
| `merch_code` | Merchant code used in request body |
---
## Supported Flows
### PayDollar Flows
| Flow | HTTP Method | Endpoint Path | Idempotency | Notes |
|------|------------|---------------|-------------|-------|
| Authorize | POST | `/eng/payment/payForm.jsp` (hosted) or `/eng/directPay/payComp.jsp` (server-side) | `orderRef` | `payType="H"` for auth-only (Hold); `payType="N"` for immediate capture |
| Capture | POST | `/eng/merchant/payComp.jsp` (Merchant API) | `PayRef` | Captures a previously held/authorized transaction; within 14 days of auth |
| Void | POST | `/eng/merchant/payComp.jsp` (Merchant API) | `PayRef` | Voids authorized or captured payment before settlement |
| Refund | POST | `/eng/merchant/payComp.jsp` (Merchant API) | `PayRef` + `orderRef` | Partial or full refund; must be within 14 days |
| PSync | POST | `/eng/merchant/payComp.jsp` (Merchant API) | `PayRef` | Queries current payment status |
| RSync | POST | `/eng/merchant/payComp.jsp` (Merchant API) | `PayRef` + refund reference | Queries refund status |
| IncomingWebhook | POST | `{merchant datafeed URL}` | N/A | Async notification from AsiaPay; configured in merchant portal |
*Note: Exact Merchant API sub-paths for Capture/Void/Refund/Query require the PayDollar Merchant API Integration Guide PDF (available to registered merchants). The base endpoint pattern `/eng/merchant/payComp.jsp` is inferred from URL conventions.*
### AsiaPay IQ Flows
| Flow | HTTP Method | Endpoint Path | Idempotency | Notes |
|------|------------|---------------|-------------|-------|
| Authorize | POST | `/payment/gateway/payment/v1/merchant/preOrder` | `merch_order_id` | Creates hosted checkout order |
| PSync | POST | `/payment/gateway/payment/v1/merchant/queryOrder` | `merch_order_id` | Queries order payment status |
| Refund | POST | `/payment/gateway/payment/v1/merchant/refund` | `refund_request_no` | Full or partial refund |
| IncomingWebhook | POST | `{notify_url}` | N/A | Async notification via `notify_url` in preOrder |
---
## Request Schema
### Authorize Request (PayDollar — Hosted / Server-Side)
```json
{
"merchantId": "12345",
"orderRef": "ORD-20240101-001",
"amount": "10.00",
"currCode": "840",
"lang": "E",
"payType": "H",
"payMethod": "ALL",
"successUrl": "https://merchant.com/success",
"failUrl": "https://merchant.com/fail",
"cancelUrl": "https://merchant.com/cancel",
"secureHash": "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
"remark": "Order description"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `merchantId` | Number | Yes | Merchant account identifier |
| `orderRef` | Text(35) | Yes | Merchant unique order reference |
| `amount` | Number(12,2) | Yes | Amount in major currency units (e.g., 10.00 = $10.00) |
| `currCode` | Text(3) | Yes | ISO 4217 numeric currency code (e.g., 840=USD, 344=HKD) |
| `lang` | Text(1) | Yes | Language: E=English, C=Trad Chinese, X=Simp Chinese, K=Korean, J=Japanese, T=Thai, F=French, G=German, R=Russian, S=Spanish |
| `payType` | Text(1) | Yes | "N"=Normal sale (auth+capture), "H"=Hold (auth-only) |
| `payMethod` | Text | No | Payment method filter: ALL, CC, VISA, Master, JCB, AMEX, Diners, PPS, PAYPAL, CHINAPAY, ALIPAY, TENPAY, 99BILL, MEPS, SCB, BPM, KTB, UOB, KRUNGSRIONLINE, TMB, IBANKING, UPOP |
| `successUrl` | URL | Yes | Redirect URL on payment success (display-only; use datafeed for status) |
| `failUrl` | URL | Yes | Redirect URL on payment failure |
| `cancelUrl` | URL | No | Redirect URL on cancellation |
| `errorUrl` | URL | No | Error redirect (Direct Client method only) |
| `secureHash` | Text | No* | SHA1 signature (* required when Secure Hash is enabled on account) |
| `remark` | Text(200) | No | Merchant-defined additional data passed through to datafeed |
| `redirect` | Number | No | Seconds before auto-redirect from result page |
| `cardNo` | Text(16) | No* | Card number (* required for Direct Client/Server methods) |
| `epMonth` | Number(2) | No* | Card expiry month |
| `epYear` | Number(4) | No* | Card expiry year |
| `securityCode` | Text(4) | No* | CVV2/CVC2/4DBC |
| `cardHolder` | Text | No* | Cardholder name |
| `installment_service` | Text(1) | No | "T"=enable instalment, "F"=disable |
| `installment_period` | Number | No | Number of instalment months |
| `airline_service` | Text(1) | No | "T"=airline ticket transaction |
| `airline_ticketNumber` | Text(13) | No | Airline ticket number |
**3DS Server-Side Parameters (Server-Side Direct method only):**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `vbvTransaction` | Text(1) | No | "T"=3DS enrolled, "F"=non-3DS |
| `vbvCHReturnCode` | Number | No | Enrollment check: 0=enrolled, 1001=not enrolled, -1=unavailable |
| `vbvPAReturnCode` | Number | No | Auth result: 0=Y/success, 1000=A/attempt, 1003=N/fail, -1=error |
| `vbvTransTime` | Text | No | Format: YYYYMMDD HH:MM:SS |
| `vbvTransAuth` | Text | No | CAVV (Base64-encoded) |
| `vbvTransECI` | Text(2) | No | ECI: VISA 05-07, MC 00-02, JCB 05-07 |
| `vbvXID` | Text(20) | No | 3DS transaction identifier |
| `vbvCAVVAlgo` | Text | No | CAVV algorithm indicator |
| `vbvMerchantID` | Text | No | MPI Merchant ID |
| `vbvAcquirerBin` | Text | No | Acquirer BIN |
| `vbvTransStatus` | Text | No | MPI transaction status |
---
### PSync Request (PayDollar — Merchant API)
```json
{
"merchantId": "12345",
"payRef": "4780"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `merchantId` | Number | Yes | Merchant identifier |
| `payRef` | Number | Yes | PayDollar payment reference number from original transaction |
---
### Capture Request (PayDollar — Merchant API)
```json
{
"merchantId": "12345",
"payRef": "4780",
"amount": "10.00",
"currCode": "840"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `merchantId` | Number | Yes | Merchant identifier |
| `payRef` | Number | Yes | PayRef from the authorized (Hold) transaction |
| `amount` | Number(12,2) | No | Amount to capture (defaults to full authorized amount) |
| `currCode` | Text(3) | No | ISO 4217 numeric currency code |
---
### Void Request (PayDollar — Merchant API)
```json
{
"merchantId": "12345",
"payRef": "4780"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `merchantId` | Number | Yes | Merchant identifier |
| `payRef` | Number | Yes | PayRef of transaction to void |
---
### Refund Request (PayDollar — Merchant API)
```json
{
"merchantId": "12345",
"payRef": "4780",
"amount": "5.00",
"remark": "Customer return"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `merchantId` | Number | Yes | Merchant identifier |
| `payRef` | Number | Yes | PayRef of original transaction to refund |
| `amount` | Number(12,2) | No | Refund amount (omit for full refund) |
| `remark` | Text | No | Refund reason |
---
### AsiaPay IQ — Authorize (Create Order) Request
```json
{
"biz_content": {
"appid": "1170344370329602",
"business_type": "BuyGoods",
"merch_code": "260224",
"merch_order_id": "ORD20240101001",
"redirect_url": "https://merchant.com/return",
"notify_url": "https://merchant.com/webhook",
"timeout_express": "30m",
"title": "Order #001",
"total_amount": "12.00",
"trade_type": "Checkout",
"trans_currency": "IQD"
},
"method": "payment.preorder",
"nonce_str": "d3ef4d049ec44150b212efa76b7e2aa7",
"sign_type": "JWTSecret",
"timestamp": "1746539388",
"version": "1.0",
"sign": "{JWT_SIGNATURE}"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `biz_content.appid` | String | Yes | Application ID |
| `biz_content.business_type` | String | Yes | Transaction type, e.g. "BuyGoods" |
| `biz_content.merch_code` | String | Yes | Merchant code |
| `biz_content.merch_order_id` | String | Yes | Unique merchant order ID |
| `biz_content.redirect_url` | String | Yes | Post-payment redirect URL |
| `biz_content.notify_url` | String | Yes | Asynchronous webhook notification URL |
| `biz_content.timeout_express` | String | Yes | Order expiry window (e.g. "30m", "1h") |
| `biz_content.title` | String | Yes | Order description title |
| `biz_content.total_amount` | String | Yes | Amount as decimal string ("12.00") |
| `biz_content.trade_type` | String | Yes | "Checkout" (WebView), "Cross-App" (mobile), "PWA" (static URL) |
| `biz_content.trans_currency` | String | Yes | Currency code ("IQD") |
| `method` | String | Yes | "payment.preorder" |
| `nonce_str` | String | Yes | Random unique string per request |
| `sign_type` | String | Yes | "JWTSecret" |
| `timestamp` | String | Yes | Unix epoch timestamp |
| `version` | String | Yes | "1.0" |
| `sign` | String | Yes | JWT signature using private_key |
---
### AsiaPay IQ — PSync (Query Order) Request
```json
{
"biz_content": {
"appid": "1170344370329602",
"merch_code": "260224",
"merch_order_id": "ORD20240101001"
},
"method": "payment.queryorder",
"nonce_str": "abc123",
"sign_type": "JWTSecret",
"timestamp": "1746539388",
"version": "1.0",
"sign": "{JWT_SIGNATURE}"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `biz_content.appid` | String | Yes | Application ID |
| `biz_content.merch_code` | String | Yes | Merchant code |
| `biz_content.merch_order_id` | String | Yes | Order ID to query |
| `method` | String | Yes | "payment.queryorder" |
---
### AsiaPay IQ — Refund Request
```json
{
"biz_content": {
"appid": "1170344370329602",
"merch_code": "260224",
"merch_order_id": "ORD20240101001",
"refund_request_no": "REF20240101001",
"refund_reason": "Customer requested refund"
},
"method": "payment.refund",
"nonce_str": "abc123",
"sign_type": "JWTSecret",
"timestamp": "1746603834",
"version": "1.0",
"sign": "{JWT_SIGNATURE}"
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `biz_content.appid` | String | Yes | Application ID |
| `biz_content.merch_code` | String | Yes | Merchant code |
| `biz_content.merch_order_id` | String | Yes | Original order ID |
| `biz_content.refund_request_no` | String | Yes | Unique refund request identifier |
| `biz_content.refund_reason` | String | No | Reason for refund |
| `method` | String | Yes | "payment.refund" |
---
## Response Schema
### Authorize Response (PayDollar — Data Feed POST)
PayDollar posts to the merchant's configured datafeed URL as URL-encoded form parameters.
**Success Response:**
```
successcode=0&Ref=ORD-20240101-001&PayRef=4780&Amt=10.0&Cur=840&prc=0&src=0&Ord=6697090&Holder=John+Smith&AuthId=123456&TxTime=2024-01-01+17:48:02.0&errMsg=Transaction+completed&eci=05&secureHash=a94a8fe5...
```
**Failure Response:**
```
successcode=1&Ref=ORD-20240101-001&PayRef=0&Amt=10.0&Cur=840&prc=5&src=0&errMsg=Do+not+honor
```
| Field | Type | Description |
|-------|------|-------------|
| `successcode` | Number | Transaction result: 0=success, 1=failure, other=error |
| `Ref` | Text | Merchant order reference (echo of `orderRef`) |
| `PayRef` | Number | PayDollar's unique payment reference number |
| `Amt` | Number(12,2) | Amount charged |
| `Cur` | Text(3) | ISO 4217 numeric currency code |
| `prc` | Number | Primary response code (0=approved, non-zero=declined) |
| `src` | Number | Secondary response code (issuer-specific) |
| `Ord` | Number | Bank order/reference number |
| `Holder` | Text | Payment account holder name |
| `AuthId` | Text | Bank authorization/approval code |
| `TxTime` | Text | Transaction timestamp (YYYY-MM-DD HH:MI:SS.0) |
| `errMsg` | Text | Human-readable result message |
| `eci` | Text(2) | ECI value for 3DS transactions |
| `mpsAmt` | Number | MCP/SCP local amount |
| `mpsCur` | Text | MCP/SCP local currency |
| `mpsForeignAmt` | Number | Foreign currency amount |
| `mpsForeignCur` | Text | Foreign currency code |
| `mpsRate` | Number | Exchange rate applied |
| `remark` | Text | Echo of merchant remark field |
| `secureHash` | Text | SHA1 signature for verification |
---
### Merchant API Response (Capture / Void / Refund / PSync)
All PayDollar Merchant API responses are returned as **XML**.
**Success Response:**
```xml
0
4780
654321
10.00
840
Accepted
```
**Error Response:**
```xml
1
4780
Invalid payment reference or already settled
```
| Field | Type | Description |
|-------|------|-------------|
| `successcode` | Number | 0=success, 1=failure, other=error |
| `PayRef` | Number | PayDollar payment reference |
| `AuthId` | Text | Authorization/approval code |
| `Amt` | Number | Amount processed |
| `Cur` | Text | ISO 4217 numeric currency code |
| `errMsg` | Text | Result description |
---
### AsiaPay IQ — Authorize (preOrder) Response
**Success:**
```json
{
"result": "SUCCESS",
"code": "0",
"msg": "success",
"biz_content": {
"merch_order_id": "ORD20240101001",
"prepay_id": "120bfb1ccc3a532b197cdb6fafad7493643002",
"redirect_url": "https://apitest.asiapay.iq:5443/payment/web/paygate?token=..."
}
}
```
**Error:**
```json
{
"result": "FAIL",
"code": "1002",
"msg": "Invalid request parameters",
"biz_content": null
}
```
| Field | Type | Description |
|-------|------|-------------|
| `result` | String | "SUCCESS" or "FAIL" |
| `code` | String | "0"=success, other=error code |
| `msg` | String | Human-readable message |
| `biz_content.merch_order_id` | String | Merchant order ID echo |
| `biz_content.prepay_id` | String | Internal pre-payment token |
| `biz_content.redirect_url` | String | Hosted checkout URL to redirect customer to |
---
### AsiaPay IQ — PSync (queryOrder) Response
**Success:**
```json
{
"result": "SUCCESS",
"code": "0",
"msg": "success",
"biz_content": {
"merch_order_id": "ORD20240101001",
"order_status": "PAY_SUCCESS",
"trans_currency": "IQD",
"total_amount": "1250.000",
"trans_id": "0377830000000660613",
"trans_time": "2025-05-06 16:50:06",
"payment_order_id": "120011075616500500001001"
}
}
```
| Field | Type | Description |
|-------|------|-------------|
| `biz_content.order_status` | String | PAY_SUCCESS, PAY_FAIL, PENDING, CANCELLED |
| `biz_content.trans_id` | String | Gateway transaction ID |
| `biz_content.payment_order_id` | String | Internal payment order reference |
| `biz_content.total_amount` | String | Decimal amount string |
| `biz_content.trans_time` | String | Transaction timestamp (YYYY-MM-DD HH:MM:SS) |
---
### AsiaPay IQ — Refund Response
**Success:**
```json
{
"result": "SUCCESS",
"code": "0",
"msg": "success",
"biz_content": {
"merch_order_id": "ORD20240101001",
"trans_order_id": "120011075710424400001001",
"refund_order_id": "120010075710435500001001",
"refund_amount": "1250.000",
"refund_currency": "IQD",
"refund_status": "REFUND_SUCCESS",
"refund_time": "2025-05-07 10:43:55"
}
}
```
| Field | Type | Description |
|-------|------|-------------|
| `biz_content.refund_order_id` | String | AsiaPay refund order reference |
| `biz_content.refund_status` | String | REFUND_SUCCESS, REFUND_PENDING, REFUND_FAIL |
| `biz_content.refund_amount` | String | Refund amount (decimal string) |
| `biz_content.refund_time` | String | Refund completion timestamp |
---
## Error Handling
### PayDollar Response Codes
| HTTP Status | `successcode` | `prc` | UCS Error Mapping | Cause |
|-------------|---------------|-------|-------------------|-------|
| 200 | 0 | 0 | Success | Transaction approved |
| 200 | 1 | 1 | PAYMENT_FAILED | Generic decline |
| 200 | 1 | 2 | INVALID_CARD | Invalid card number |
| 200 | 1 | 3 | INSUFFICIENT_FUNDS | Insufficient funds |
| 200 | 1 | 4 | EXPIRED_CARD | Expired card or pickup |
| 200 | 1 | 5 | PAYMENT_DECLINED | Do not honor |
| 200 | 1 | 12 | INVALID_TRANSACTION | Invalid transaction type |
| 200 | 1 | 14 | INVALID_CARD | Invalid account number |
| 200 | 1 | 41 | CARD_LOST | Lost card — pickup |
| 200 | 1 | 43 | CARD_STOLEN | Stolen card — pickup |
| 200 | 1 | 51 | INSUFFICIENT_FUNDS | Insufficient credit |
| 200 | 1 | 54 | EXPIRED_CARD | Expired card |
| 200 | 1 | 57 | NOT_PERMITTED | Transaction not permitted to cardholder |
| 200 | 1 | 61 | EXCEEDS_LIMIT | Exceeds withdrawal limit |
| 200 | 1 | 62 | RESTRICTED_CARD | Restricted card |
| 200 | 1 | 65 | EXCEEDS_LIMIT | Exceeds withdrawal frequency |
| 200 | 1 | 91 | ISSUER_UNAVAILABLE | Card issuer unavailable |
| 200 | 1 | 96 | PROCESSING_ERROR | System malfunction |
| 200 | -1 | any | PROCESSING_ERROR | Gateway/system error |
*Full `prc`/`src` listings are in PayDollar Integration Guide Appendix A.*
### AsiaPay IQ Response Codes
| HTTP Status | `code` | UCS Error Mapping | Cause |
|-------------|--------|-------------------|-------|
| 200 | "0" | Success | Operation successful |
| 200 | "1001" | NOT_FOUND | Order not found |
| 200 | "1002" | INVALID_REQUEST | Invalid request parameters |
| 200 | "1003" | DUPLICATE_REQUEST | Duplicate order ID |
| 200 | "1004" | UNAUTHORIZED | Authentication failed / token expired |
| 200 | "2001" | PAYMENT_FAILED | Payment processing failed |
| 200 | "3001" | REFUND_FAILED | Refund processing failed |
**Retry Semantics:**
- PayDollar `successcode=-1` or HTTP 5xx → retry with exponential backoff (max 3 attempts)
- PayDollar `successcode=1` (declined) → do NOT retry automatically
- AsiaPay IQ `result=FAIL` with `code >= 5000` (server errors) → retry
- AsiaPay IQ `code` in 1000-4999 range → do NOT retry (client/business errors)
---
## Status Mapping
### PayDollar Status Mapping
| Connector Status | `successcode` | `prc` | UCS AttemptStatus | Notes |
|-----------------|---------------|-------|-------------------|-------|
| Payment Success (Normal) | 0 | 0 | Charged | payType=N |
| Auth Success (Hold) | 0 | 0 | Authorized | payType=H |
| Payment Failure | 1 | any | Failure | Any non-zero prc |
| System Error | -1 | any | Failure | Gateway error |
| Void Success | 0 | 0 | Voided | Merchant API void |
| Capture Success | 0 | 0 | Charged | Merchant API capture |
| Refund Success | 0 | 0 | AutoRefunded | Merchant API refund |
| Refund Failure | 1 | any | Failure | Refund declined |
### AsiaPay IQ Order Status Mapping
| Connector Status (`order_status`) | UCS AttemptStatus | Notes |
|----------------------------------|-------------------|-------|
| PAY_SUCCESS | Charged | Payment completed successfully |
| PAY_FAIL | Failure | Payment failed |
| PENDING | Pending | Awaiting customer action on checkout page |
| CANCELLED | Voided | Order expired or customer cancelled |
| REFUND_SUCCESS | AutoRefunded | Refund completed |
| REFUND_PENDING | Pending | Refund being processed |
| REFUND_FAIL | Failure | Refund failed |
---
## Webhooks
### PayDollar — Data Feed
**Mechanism:** Configure "Return Value Link (Datafeed)" in Merchant Administration Interface under **Profile → Payment Account Settings**. AsiaPay POSTs transaction outcomes to this URL asynchronously after each payment event.
**URL Pattern:** `POST {merchantBaseUrl}/payment/asiapay/webhook`
**Content-Type:** `application/x-www-form-urlencoded`
**Subscription Method:** Manual configuration in merchant admin portal. Must also enable the "Return Value Link" toggle in account settings.
**Payload Structure:**
```
successcode=0&Ref=ORD-20240101-001&PayRef=4780&Amt=10.0&Cur=840&prc=0&src=0&Ord=6697090&Holder=John+Smith&AuthId=123456&TxTime=2024-01-01+17:48:02.0&errMsg=Transaction+completed&eci=05&secureHash=a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
```
**Signature Verification:**
```
verificationHash = SHA1(merchantId + "|" + Ref + "|" + Cur + "|" + Amt + "|" + payType + "|" + secureHashSecret)
assert secureHash == verificationHash
```
*Header for signature:* None — signature is included as `secureHash` body field.
**Event Types and UCS Mapping:**
| Event Trigger | `successcode` | `payType` | UCS Flow |
|--------------|---------------|-----------|----------|
| Payment approved (sale) | 0 | N | IncomingWebhook → Charged |
| Payment approved (auth) | 0 | H | IncomingWebhook → Authorized |
| Payment declined | 1 | N/H | IncomingWebhook → Failure |
| Refund completed | 0 | (refund) | IncomingWebhook → AutoRefunded |
**Delivery Policy:** AsiaPay sends the data feed on a best-effort basis. Merchants are advised to use the data feed as the primary source for order updates (redirect success/fail URLs are for display only). Implement idempotent webhook handlers keyed on `PayRef`. Retry behavior of failed deliveries is not publicly documented.
---
### AsiaPay IQ — notify_url Webhook
**Mechanism:** Include `notify_url` in the `biz_content` of each `preOrder` request. AsiaPay POSTs JSON to this URL when payment status changes.
**Content-Type:** `application/json`
**Payload:** Same structure as queryOrder response, augmented with a `sign` field.
**Signature Verification:** Validate the `sign` JWT field using the merchant's `private_key`.
**Delivery Policy:** AsiaPay IQ sends notifications asynchronously. Merchant server should respond HTTP 200 to acknowledge receipt.
---
## References
**Official API Documentation:**
- [AsiaPay IQ Integration Documentation](https://www.asiapay.iq/integration)
- [AsiaPay Limited Developer Portal (requires merchant login — returned 403 in unauthenticated access)](https://developer.asiapay.com/)
- [PayDollar PayGate Integration Guide v3.67 (PDF — binary, not directly parseable)](https://www.paydollar.com/pdf/op/enpdintguide.pdf)
- [PayDollar PayGate Integration Guide v3.21 (HTML mirror)](https://www.readkong.com/page/paydollar-paygate-integration-guide-version-3-21-3398605)
- [AsiaPay GitHub Integration Guide Repository](https://github.com/asiapay-lib/integration_guide)
**Third-Party Integration Guides:**
- [Odoo 18.0 AsiaPay Provider Documentation](https://www.odoo.com/documentation/18.0/applications/finance/payment_providers/asiapay.html)
- [Odoo 19.0 AsiaPay Provider Documentation](https://www.odoo.com/documentation/19.0/applications/finance/payment_providers/asiapay.html)
- [WHMCS AsiaPay Documentation](https://docs.whmcs.com/AsiaPay)
**Source Code References:**
- [PayDollar WooCommerce Plugin (stormwild)](https://github.com/stormwild/paydollar-woocommerce/blob/master/index.php)
- [Kayue Paydollar PHP Library](https://github.com/kayue/Paydollar)
- [AsiaPay WooCommerce Official Plugin](https://github.com/asiapay-lib/asiapay-Woocommerce)
**Merchant Administration:**
- [PayDollar Merchant Administration Portal](https://admin.paydollar.com/b2c2/eng/merchant/index.jsp)
- [PayDollar Official Site](https://www.paydollar.com/en/index.html)
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.