Direct integration¶
In this approach no platform web application is involved and all steps of the incoming payment process must be integrated by the merchant application.
The first step of the process is to generate auth token to be able to pass all authorization checks for each necessary operation.
Note
NEW
The easiest way to verify your merchant account is to use our Integration DEMO Web Application to make necessary API calls and check our Payment Web Application flow.
Payment options¶
In the second step, the customer must be challenged to select the appropriate payment option for the required transaction.
Use the POST /payins/!availablePaymentOptions endpoint to list all available payment options.
This step is optional in cases where the merchant product configuration is not dynamic and the merchant is capable of taking the responsibility for using the correct payment method / payment operator selection.
curl -X POST 'https://api.sandbox.aopay.io/payins/!availablePaymentOptions' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-API-Version: 2' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVyYXRpb25zIjpbIlBPU1QgL3BheWlucy8hYXZhaWxhYmxlUGF5bWVudE1ldGhvZHMiLCJQT1NUIC9wYXlpbnMvVFNULTExMjIzMyIsIkdFVCAvcGF5aW5zL1RTVC0xMTIyMzMiXSwiZXhwIjoxNjIyNjIzNjY5LCJqdGkiOiI5ZThhNDUwNC04MmRmLTQyY2QtOTQ3Ni03NjE2YjEzOTJlM2IiLCJpYXQiOjE2MjI2MjMwNjksInN1YiI6IllPVVJfTUVSQ0hBTlRfQ09ERSJ9.LkYT9qXY3hEixjoiUBKqxXnazWgfLCNg37RtdG_oXw0' \
-d '{
"money": {
"amount": 100,
"currencyCode": "IDR"
}
}'
{
"data": [
{
"paymentMethodCode": "VAPAY",
"paymentOperators": [
{
"code": "BNK_000",
"name": "Some real bank name"
},
{
"code": "BNK_001",
"name": "Some other real bank name"
}
]
}
]
}
Merchant information¶
In the this step, the merchant can obtain its merchant information such as merchant channel name configured in our platform to display it on the payment flow UI.
This step is optional as usually merchant displays such information from theirs own configuration when using the direct API integration.
Use the GET /merchant-info endpoint to obtain the merchant information.
curl -X POST 'https://api.sandbox.aopay.io/merchant-info' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-API-Version: 2' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVyYXRpb25zIjpbIlBPU1QgL3BheWlucy8hYXZhaWxhYmxlUGF5bWVudE1ldGhvZHMiLCJQT1NUIC9wYXlpbnMvVFNULTExMjIzMyIsIkdFVCAvcGF5aW5zL1RTVC0xMTIyMzMiXSwiZXhwIjoxNjIyNjIzNjY5LCJqdGkiOiI5ZThhNDUwNC04MmRmLTQyY2QtOTQ3Ni03NjE2YjEzOTJlM2IiLCJpYXQiOjE2MjI2MjMwNjksInN1YiI6IllPVVJfTUVSQ0hBTlRfQ09ERSJ9.LkYT9qXY3hEixjoiUBKqxXnazWgfLCNg37RtdG_oXw0' \
{
"channelInfo": {
"name": "YOUR_MERCHANT_CHANNEL_NAME"
}
}
Sensitive data encryption¶
Some payment methods require specific fields within the payment method request object to be encrypted - for more information see Payment methods
When submitting a payment method which requires encrypted values in payment method’s object, follow these steps:
Obtain the Public Key: Send a request to
GET /sensitive-data-encryption-keyendpoint using your valid token.Prepare the Plaintext value: Concatenate your idPayment and the sensitive string separated by triple colons (
:::):<idPayment>:::<sensitiveString>.Encrypt: Encrypt the combined string using the public key obtained in
keyData.Format the Field Value: Prepend the
keyIdfollowed by triple colons (:::) to the resulting encrypted ciphertext string:<keyId>:::<encryptedString>.Send Payment Request: Pass this final
<keyId>:::<encryptedString>value into the corresponding field of the payment method request object.
curl -X GET 'https://api.sandbox.aopay.io/sensitive-data-encryption-key' \
-H 'Accept: application/json' \
-H 'X-API-Version: 2' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>' \
{
"keyId": "key123",
"key": "<Base64 encoded public key>",
"keyType": "<KEY_TYPE>",
"encryptionAlgorithm": "<ENCRYPTION_ALGORITHM>"
}
Key Rotation and Error Handling¶
The encryption key is rotated periodically. To optimize performance, merchants may cache the key and its keyId rather than fetching it before every transaction.
If a payment request POST /payins/{idPayin} (or payment query GET /payins/{idPayin}) return the error DECRYPTION_FAILED, it indicates that the encrypted data could not be decrypted. In this event, your application must call GET /sensitive-data-encryption-key to fetch the new key and use this new key for encryption of sensitive payment data in subsequent payment requests.
Payment request¶
The forth step involves creating the payment request itself via POST /payins/{idPayin} endpoint.
curl -X POST 'https://api.sandbox.aopay.io/payins/TST-112233' \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'X-API-Version: 2' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVyYXRpb25zIjpbIlBPU1QgL3BheWlucy8hYXZhaWxhYmxlUGF5bWVudE1ldGhvZHMiLCJQT1NUIC9wYXlpbnMvVFNULTExMjIzMyIsIkdFVCAvcGF5aW5zL1RTVC0xMTIyMzMiXSwiZXhwIjoxNjIyNjIzNjY5LCJqdGkiOiI5ZThhNDUwNC04MmRmLTQyY2QtOTQ3Ni03NjE2YjEzOTJlM2IiLCJpYXQiOjE2MjI2MjMwNjksInN1YiI6IllPVVJfTUVSQ0hBTlRfQ09ERSJ9.LkYT9qXY3hEixjoiUBKqxXnazWgfLCNg37RtdG_oXw0' \
-d '{
"paymentRequested": {
"money": {
"amount": 100,
"currencyCode": "IDR"
}
},
"paymentMethod": {
"account": {
"accountName": "Test account",
"accountNumber": "11223344"
},
"paymentMethodCode": "VAPAY",
"paymentOperatorCode": "BNK_000",
"emailAddress": "customer@test.com"
},
"callbackUrl": "https://example.com/order-status-change",
"returnUrl": "https://example.com?id=123"
}'
{
"paymentRequested": {
"money": {
"amount": 100,
"currencyCode": "IDR"
}
},
"paymentMethodResponse": {
"idPayin": "TST-112233",
"paymentMethodCode": "VAPAY",
"account": {
"accountName": "Test account",
"accountNumber": "11223344",
"bankCode": "BNK_000",
"bankName": "Some real bank name"
},
"money": {
"amount": 100,
"currencyCode": "IDR"
},
"expireAt": "2021-05-20T08:37:05.350Z",
"reference": "VA1122334455",
"returnUrl": "https://example.com?id=123"
}
}
Get Payment status¶
The merchant is automatically notified of a payment status change via callback. This can be obtained anytime via our API.
Get payment customer account data¶
This can be obtained anytime via our API. Customer account data from request should be available shortly after payment creation. Customer account data from payment process should be available shortly after payment is successfully finished.