Subscription Billing
No PCI Compliance Requirement
Unlike initial subscription setup, subscription billing operations do not require PCI compliance because:
- No sensitive card data is transmitted during renewal or update operations
- All operations utilize securely stored
tokenId
andcontractId
- Card details are already tokenized during the initial subscription process
Introduction
The Subscription Billing API is used to process subsequent charges for existing subscription contracts. This API serves two primary purposes:
Self-Managed Subscription Renewal: For merchants using the self-managed subscription model, this API must be called to process recurring payments using the stored contract and token information.
Subscription Plan Updates: For managed subscriptions, this API can be used to update subscription plans (upgrade/downgrade).
This documentation covers subscription billing for all integration methods, including Subscription API, Checkout, and SDK subscription implementations.
API Request Parameters
Note
- All
JSON
fields must be stringified before submission - Nested objects must be serialized to
JSON
string format JSON
fields must not contain unescaped special characters- Arrays in
JSON
should be properly formatted - Example of
JSON
string field:
{
"object": "{\"obj-key1\":\"v1\",\"obj-key2\":\"v2\"}",
"complex": "{\"k1\":\"v1\",\"array\":\"[{\\\"obj-key3\\\":\\\"v3\\\",\\\"obj-key4\\\":\\\"v4\\\"}]\"}"
}
2
3
4
Parameter | Type | Length | Required | Signed | Description |
---|---|---|---|---|---|
billingInformation | String | / | Yes | Yes | Billing information in JSON string format. See TransactionAddress |
merchantCustId | String | 50 | Conditional | Yes | Unique customer identifier in merchant system. |
merchantNo | String | 20 | Yes | Yes | Merchant number assigned by |
merchantTxnId | String | 64 | Yes | Yes | Unique transaction identifier for each customer payment. Must be unique for each transaction request. |
merchantTxnOriginalId | String | 128 | No | Yes | Master transaction ID generated by merchant. IDs can be duplicate but only one transaction with the same ID can succeed |
merchantTxnTime | String | / | No | Yes | Transaction timestamp (Format: |
merchantTxnTimeZone | String | 64 | No | Yes | Transaction timezone |
orderAmount | String | 19 | Yes | Yes | Order amount in units of currency with max 2 decimal places |
orderCurrency | String | 8 | Yes | Yes | Order currency code. See ISO 4217 |
productType | String | 16 | Yes | Yes | See ProductTypeEnum |
sign | String | / | Yes | No | Digital signature string for request verification. Please refer to Signature for signature generation method. |
subProductType | String | 16 | Yes | Yes | See SubProductTypeEnum |
subscription | String | / | Conditional | Yes | Subscription information in JSON string format. See Subscription. |
txnOrderMsg | String | / | Yes | Yes | Transaction business information in JSON string format. See TxnOrderMsg |
txnType | String | 16 | Yes | Yes | Transaction type. See TxnTypeEnum |
Subscription
The subscription
parameter is a JSON string containing the following fields:
Subscription Renewal Process
For subsequent subscription charges (non-initial payments):
- Managed Subscription: Onerway automatically handles recurring payments based on your configuration
- Self-Managed Subscription: You need to call the dedicated APIs documented in Subscription Billing API to initiate renewal payments
The renewal process uses the subscription contractId
and tokenId
established during the initial payment, which contains all the necessary billing details and payment methods.
Name | Type | Length | Required | Description |
---|---|---|---|---|
requestType | String | 1 | Yes | Subscription request type: Fixed value |
contractId | String | 20 | Yes | Subscription contract |
tokenId | String | 300 | Yes | Subscription token |
merchantCustId | String | 40 | No | Unique identifier for the user in the merchant's system, must be consistent with the ID provided during initial subscription. |
TxnOrderMsg
For subscription renewal and update operations, the txnOrderMsg
parameter should include:
Name | Type | Length | Required | Signature | Description |
---|---|---|---|---|---|
returnUrl | String | 256 | Yes | No | Synchronous return address. After the customer completes payment, the |
products | String | 1024 | Yes | No | |
transactionIp | String | 64 | Conditional | No | Cardholder transaction |
appId | String | 20 | Yes | No | Store |
javaEnabled | Boolean | / | Conditional | No | Whether the cardholder's browser has |
colorDepth | String | 64 | Conditional | No | Cardholder screen color depth, retrieved via: |
screenHeight | String | 64 | Conditional | No | Cardholder's screen resolution, retrieved via: |
screenWidth | String | 64 | Conditional | No | Cardholder's screen resolution, retrieved via: |
timeZoneOffset | String | 64 | Conditional | No | Cardholder browser's time zone, retrieved via: |
accept | String | 2048 | Conditional | No | Cardholder browser's |
userAgent | String | 2048 | Conditional | No | Cardholder's browser type, retrieved via: |
contentLength | String | 64 | Conditional | No | Content length of the cardholder's browser content beyond the headers |
language | String | 64 | Conditional | No | Cardholder's browser language, retrieved via: |
periodValue | String | / | Conditional | No | Installment payment period. |
notifyUrl | String | 256 | Yes | No |
Response Parameters
Name | Type | Description |
---|---|---|
respCode | String | Response code from |
respMsg | String | Response message from |
data | Object |
data
Name | Type | Description |
---|---|---|
transactionId | String | Transaction order number created by |
responseTime | String | Interface response time
|
txnTime | String | Transaction completion time
|
txnTimeZone | String | Transaction time zone
|
orderAmount | String | Order amount |
orderCurrency | String | Transaction order currency
|
txnAmount | String | Order amount after conversion to settlement currency |
txnCurrency | String | Settlement currency
|
status | String | Transaction processing result
|
redirectUrl | String | Redirection URL for 3D Secure verification |
contractId | String | Subscription contract number |
tokenId | String | Payment token |
eci | String | Electronic Commerce Indicator |
periodValue | String | Installment payment number of periods |
codeForm | String | Code form for specific payment methods
|
presentContext | String | Context information for presentation layer |
actionType | String | Action type for the transaction
|
subscriptionManageUrl | String | Subscription management URL |
sign | String |
Code Snippets
// Self-managed subscription - Sign-only mode, no immediate billing
// For local payment methods like WeChat, DANA, GCash, or TOUCH_GO_EWALLET
"subscription": "{\"requestType\":\"0\",\"merchantCustId\":\"custId_xxx\",\"productName\":\"Self-managed-Sign only\",\"frequencyType\":\"D\",\"frequencyPoint\":\"1\",\"expireDate\":\"2025-01-01\",\"selfExecute\":\"2\",\"mode\":\"1\"}"
2
3
4
// Self-managed subscription - Immediate billing mode, bills immediately
// Typically used for credit card payments or some local payment methods
"subscription": "{\"requestType\":\"0\",\"merchantCustId\":\"custId_xxx\",\"productName\":\"Self-managed-Immediate billing\",\"frequencyType\":\"D\",\"frequencyPoint\":\"1\",\"expireDate\":\"2025-01-01\",\"selfExecute\":\"2\",\"mode\":\"2\"}"
2
3
4
// Self-managed subscription - Renewal billing, using existing subscription contract to initiate a new billing cycle
// Use the contractId and tokenId received from the initial subscription webhook
"subscription": "{\"requestType\":\"1\",\"contractId\":\"contractId_xxx\",\"tokenId\":\"tokenId_xxx\",\"merchantCustId\":\"custId_xxx\"}"
2
3
4
// Example for DANA, WeChat, GCash, or TOUCH_GO_EWALLET subscription
// Zero-amount initial transaction to establish the contract
"lpmsInfo": "{\"lpmsType\":\"DANA\",\"iBan\":\"DE89370400440532013000\"}",
"productType": "LPMS",
"subProductType": "SUBSCRIBE",
"subscription": "{\"requestType\":\"0\",\"merchantCustId\":\"custId_xxx\",\"frequencyType\":\"D\",\"frequencyPoint\":\"1\",\"expireDate\":\"2025-01-01\",\"selfExecute\":\"2\",\"mode\":\"1\"}"
2
3
4
5
6
7
Subscription Renewal Process
The subscription renewal process follows a different flow depending on the subscription type:
Self-Managed Subscription Renewal
In this process:
- The merchant system must track subscription billing schedules
- At each billing cycle, merchant sends a renewal request with stored
contractId
andtokenId
- Onerway processes the payment using the tokenized card details
- The response includes the transaction result and updated subscription details
- A webhook notification with
scenarios=SUBSCRIPTION_RENEWAL
is sent to the merchant's notification URL
Managed Subscription Update
In this process:
- Merchant initiates a subscription update with the stored
contractId
andtokenId
- If
changeMode=1
(immediate effect):- Onerway calculates the proration amount based on the remaining days in the current billing cycle
- For upgrades, an immediate charge is processed; for downgrades, developers need to call the refund API to process the refund
- If
changeMode=2
(next billing cycle):- Onerway updates the subscription without an immediate charge
- Changes take effect at the next billing date
- The response includes the updated subscription details
- A webhook notification with
scenarios=SUBSCRIPTION_CHANGED
is sent to the merchant's notification URL - Onerway continues automatic billing with the updated subscription details
API Usage Examples
Onerway sends webhook notifications for all subscription events to the notifyUrl
specified in the original subscription request. These notifications provide real-time updates on subscription status changes.
Webhook Scenarios
The scenarios
field in webhook notifications indicates the specific subscription event that triggered the notification:
SUBSCRIPTION_CREATED
- New subscription createdSUBSCRIPTION_TRIAL_WILL_END
- Trial period is ending soonSUBSCRIPTION_RENEWAL
- Subscription was successfully renewedSUBSCRIPTION_PAYMENT_FAILED
- Renewal payment attempt failedSUBSCRIPTION_CHANGED
- Subscription plan or details were updatedSUBSCRIPTION_CANCELED
- Subscription has been canceledSUBSCRIPTION_ENDED
- Subscription has reached its natural end date
Subscription Status Reference
The subscriptionStatus
field in responses and webhooks indicates the current state of the subscription:
trialing
- In trial periodpaymentdue
- Payment pendingactive
- Active subscriptionpastdue
- Payment overduepaused
- Temporarily suspendedcanceled
- Canceled by user or merchantended
- Completed subscription term
Self-Managed Subscription Renewal
{
"billingInformation": "{}",
"merchantCustId": "CustId-JK6B-8850",
"merchantNo": "800209",
"merchantTxnId": "6a28ac11-d98c-4323-84a7-426b9322c4f7",
"merchantTxnTime": "2025-05-07 18:02:35",
"orderAmount": "2",
"orderCurrency": "USD",
"productType": "CARD",
"sign": "e3564ff939c35860ab0f41659588d3e9cfa556f35d3b2121d6f99faf82991c77",
"subProductType": "SUBSCRIBE",
"subscription": "{\"merchantCustId\":\"CustId-JK6B-8850\",\"requestType\":\"1\",\"tokenId\":\"b05d9de9836fe3e0dce5ba42078885cb90c729fe0604219a9cf24c092e71eb60\",\"contractId\":\"1919781071080529920\"}",
"txnOrderMsg": "{\"accept\":\"*/*\",\"appId\":\"1727880846378401792\",\"colorDepth\":\"32\",\"contentLength\":\"4096\",\"javaEnabled\":false,\"language\":\"en-US\",\"products\":\"[{\\\"currency\\\":\\\"USD\\\",\\\"name\\\":\\\"incaberry\\\",\\\"num\\\":\\\"10\\\",\\\"price\\\":\\\"824.99\\\",\\\"type\\\":\\\"laborum irure veniam velit\\\"}]\",\"returnUrl\":\"https://docs.onerway.com/\",\"notifyUrl\":\"https://docs.onerway.com/apis\",\"screenHeight\":\"915\",\"screenWidth\":\"390\",\"timeZoneOffset\":\"300\",\"transactionIp\":\"109.214.114.89\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36\"}",
"txnType": "SALE"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"respCode": "20000",
"respMsg": "Success",
"data": {
"transactionId": "1920061365985615872",
"responseTime": "2025-05-07 18:21:21",
"txnTime": "2025-05-07 18:21:17",
"txnTimeZone": "+08:00",
"orderAmount": "2.00",
"orderCurrency": "USD",
"txnAmount": null,
"txnCurrency": null,
"status": "S",
"redirectUrl": null,
"contractId": "1919781071080529920",
"tokenId": "b05d9de9836fe3e0dce5ba42078885cb90c729fe0604219a9cf24c092e71eb60",
"eci": null,
"periodValue": null,
"codeForm": null,
"presentContext": null,
"actionType": null,
"subscriptionManageUrl": null,
"sign": "67046b9c8a966c39d24294a8b336caae6517182b77c66be54c63212d98f29563"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"notifyType": "TXN",
"transactionId": "1920061365985615872",
"txnType": "SALE",
"merchantNo": "800209",
"merchantTxnId": "6a28ac11-d98c-4323-84a7-426b9322c4f7",
"responseTime": "2025-05-07 18:21:21",
"txnTime": "2025-05-07 18:21:17",
"txnTimeZone": "+08:00",
"orderAmount": "2.00",
"orderCurrency": "USD",
"status": "S",
"contractId": "1919781071080529920",
"tokenId": "b05d9de9836fe3e0dce5ba42078885cb90c729fe0604219a9cf24c092e71eb60",
"cardBinCountry": "US",
"reason": "{\"respCode\":\"20000\",\"respMsg\":\"Success\"}",
"sign": "345f09b2240dcd2084605c28024b4d6fe7da4f84e59a7268b92bb66a36c433b3",
"paymentMethod": "VISA",
"subscriptionStatus": "active",
"dataStatus": "1",
"products": "[{\"currency\":\"USD\",\"name\":\"feijoa\",\"num\":\"88\",\"price\":\"968.79\",\"type\":\"consectetur adipisicing reprehenderit sint\"},{\"currency\":\"USD\",\"name\":\"avocado\",\"num\":\"52\",\"price\":\"414.89\",\"type\":\"consectetur labore\"}]",
"metaData": "vary",
"channelRequestId": "8002091920061371823816709",
"scenarios": "SUBSCRIPTION_RENEWAL"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Managed Subscription Update (Plan Upgrade)
{
"billingInformation": "{}",
"merchantCustId": "CustId-0WQA-3549",
"merchantNo": "800209",
"merchantTxnId": "d9de61b7-3480-48ed-90e6-4b0b9e2e4640",
"merchantTxnTime": "2025-05-07 23:00:28",
"orderAmount": "42",
"orderCurrency": "USD",
"productType": "CARD",
"sign": "6a430ec13dd3249114bd000435f759d3078ed67e50c9fa2a623a0bb9b79e2fa9",
"subProductType": "SUBSCRIBE",
"subscription": "{\"requestType\":\"2\",\"tokenId\":\"195f7e75785863a66d3801ae02c12e24ea16abe164303cf3e3fd10e04d5e4188\",\"contractId\":\"1919772912228114432\",\"changeMode\":\"1\",\"productName\":\"Premium Plan - Monthly\",\"proration\":\"20\",\"prorationMode\":\"0\"}",
"txnOrderMsg": "{\"accept\":\"*/*\",\"appId\":\"1727880846378401792\",\"colorDepth\":\"24\",\"contentLength\":\"1024\",\"javaEnabled\":true,\"language\":\"en-US\",\"products\":\"[{\\\"currency\\\":\\\"USD\\\",\\\"name\\\":\\\"passionfruit\\\",\\\"num\\\":\\\"90\\\",\\\"price\\\":\\\"696.29\\\",\\\"type\\\":\\\"eu anim\\\"},{\\\"currency\\\":\\\"USD\\\",\\\"name\\\":\\\"kiwiberry\\\",\\\"num\\\":\\\"36\\\",\\\"price\\\":\\\"948.79\\\",\\\"type\\\":\\\"pariatur amet ea sint aute\\\"}]\",\"returnUrl\":\"https://docs.onerway.com/\",\"notifyUrl\":\"https://docs.onerway.com/apis\",\"screenHeight\":\"736\",\"screenWidth\":\"2560\",\"timeZoneOffset\":\"720\",\"transactionIp\":\"201.10.41.195\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36\"}",
"txnType": "SALE"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"respCode": "20000",
"respMsg": "Success",
"data": {
"transactionId": "1920133309141491712",
"responseTime": "2025-05-07 23:07:18",
"txnTime": "2025-05-07 23:07:09",
"txnTimeZone": "+08:00",
"orderAmount": "20.00",
"orderCurrency": "USD",
"txnAmount": null,
"txnCurrency": null,
"status": "S",
"redirectUrl": null,
"contractId": "1919772912228114432",
"tokenId": "195f7e75785863a66d3801ae02c12e24ea16abe164303cf3e3fd10e04d5e4188",
"eci": null,
"periodValue": null,
"codeForm": null,
"presentContext": null,
"actionType": null,
"subscriptionManageUrl": "https://sandbox-myscribe.onerway.com/pages/subscription-list/details?contractId=eyJjb250cmFjdElkIjoxOTE5NzcyOTEyMjI4MTE0NDMyLCJtZXJjaGFudE5vIjo4MDAyMDksIm1lcmNoYW50Q3VzdElkIjoiQ3VzdElkLUtYUlAtMzcxMSIsIm5vdGlmaWNhdGlvbkVtYWlsIjpudWxsLCJhcHBJZCI6IjE3Mjc4ODA4NDYzNzg0MDE3OTIifQ==",
"sign": "2cc6ee5c9d063b48267a6b8255c5a11f1cfebcabc2561d5616c6579b683a7e6e"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"notifyType": "TXN",
"transactionId": "1920133309141491712",
"txnType": "SALE",
"merchantNo": "800209",
"merchantTxnId": "d9de61b7-3480-48ed-90e6-4b0b9e2e4640",
"responseTime": "2025-05-07 23:07:18",
"txnTime": "2025-05-07 23:07:09",
"txnTimeZone": "+08:00",
"orderAmount": "20.00",
"orderCurrency": "USD",
"status": "S",
"contractId": "1919772912228114432",
"tokenId": "195f7e75785863a66d3801ae02c12e24ea16abe164303cf3e3fd10e04d5e4188",
"cardBinCountry": "US",
"reason": "{\"respCode\":\"20000\",\"respMsg\":\"Success\"}",
"sign": "cd220e77f9566e6cf20869c712c01dff34af9d0b52ffe2194510d88288827265",
"paymentMethod": "VISA",
"subscriptionManageUrl": "https://sandbox-myscribe.onerway.com/pages/subscription-list/details?contractId=eyJjb250cmFjdElkIjoxOTE5NzcyOTEyMjI4MTE0NDMyLCJtZXJjaGFudE5vIjo4MDAyMDksIm1lcmNoYW50Q3VzdElkIjoiQ3VzdElkLUtYUlAtMzcxMSIsIm5vdGlmaWNhdGlvbkVtYWlsIjpudWxsLCJhcHBJZCI6IjE3Mjc4ODA4NDYzNzg0MDE3OTIifQ==",
"subscriptionStatus": "active",
"dataStatus": "1",
"products": "[{\"name\":\"passionfruit\",\"desc\":null,\"price\":\"696.29\",\"num\":\"90\",\"currency\":\"USD\"},{\"name\":\"kiwiberry\",\"desc\":null,\"price\":\"948.79\",\"num\":\"36\",\"currency\":\"USD\"}]",
"metaData": "eventually",
"channelRequestId": "8002091920133320860106752",
"scenarios": "SUBSCRIPTION_CHANGED"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Integration Process
Self-Managed Subscription Renewal Integration
For implementing self-managed subscription renewals:
- Track Subscription Schedules: Maintain a record of your subscription contracts and their billing schedules
- Store Contract and Token IDs: Securely store the
contractId
andtokenId
received from the initial subscription - Initiate Renewal Payment: At each billing cycle, call the Subscription Billing API with:
requestType=1
(renewal payment)- Stored
contractId
andtokenId
- Current billing amount
- Process Results: Handle the API response and subsequent webhook notification
- Update Subscription Records: Update your local subscription records with the latest payment status
Managed Subscription Update Integration
For implementing managed subscription updates:
- Provide Update Interface: Create a user or admin interface for changing subscription plans
- Process Update Request: When a plan change is requested, call the Subscription Billing API with:
requestType=2
(subscription update)- Stored
contractId
andtokenId
- Updated subscription parameters (e.g.,
productName
,orderAmount
) changeMode=1
for immediate billing adjustment orchangeMode=2
for next cycle changes- For immediate updates (
changeMode=1
), includeproration
amount andprorationMode
- Handle Proration: If using
changeMode=1
, be prepared to process an immediate charge or refund for the prorated amount - Process Results: Handle the API response and webhook notification
- Update Customer Information: Inform the customer about the successful plan change
Implementation Best Practices
- Secure Storage: Always securely store the
contractId
andtokenId
using encryption and access controls - Webhook Validation: Verify webhook signatures to ensure notifications are authentic
- Error Handling: Implement robust error handling for failed renewal attempts
- Subscription Tracking: Maintain accurate records of all subscription details and payment history
- Recovery Mechanisms: Implement retry logic for failed renewal payments
- Data Synchronization: Regularly reconcile your subscription records with Onerway's system
- User Notifications: Notify customers about upcoming renewals and successful/failed payments
- Plan Change Guidelines:
- For major price increases, consider using
changeMode=2
to give customers advance notice - For minor upgrades or when customers request immediate changes, use
changeMode=1
- When using
changeMode=1
, properly calculate the proration amount based on remaining days
- For major price increases, consider using
- Testing: Thoroughly test all subscription scenarios in the sandbox environment before going live
Common Error Codes
Security Considerations
- API Authentication: All API requests must include a valid signature
- Secure Transmission: Always use HTTPS for API calls and webhook processing
- Webhook Verification: Validate the signature of all incoming webhook notifications
- Idempotency: Process webhook notifications idempotently to handle potential duplicates