Skip to main content
Version: Lastest

Process installment result

After a credit card payment is converted to an installment plan, AppotaPay will send the result notification to the partner's registered API URL so the partner can update the installment transaction status.

Note
  • It is necessary to thoroughly check the parameters transaction.status, transaction.paymentAmount, and signature to ensure they are valid before confirming the installment transaction as successful
  • Use the signature parameter to verify the integrity of the received data. The partner generates a signature from the data received from AppotaPay, then compares it with the signature parameter sent by AppotaPay
  • The signature is calculated on the raw Base64 string of the data field (not on the decoded JSON) — verify signature before decoding data
  • The IPN may be sent more than once for the same transaction
  • The time field is only a reference to the sending time and is not part of the signature calculation

IPN (Instant Payment Notification)

AppotaPay will send the installment transaction result notification via the partner's registered API URL. The partner's server verifies the integrity of the data via the signature parameter and then updates the status of the installment transaction.

{
"Content-Type": "application/json"
}

Response params

Method: POST

ParamsData typeDescription
dataStringThe transaction information is in base64encode & json_encode format
signatureStringSignature to verify data integrity

signature = HMAC_SHA256(data, secretKey)

timeStringResponse time

Decode data

  1. The partner uses the Base64Decode function to decode the data into a string.
  2. Use the JSON_Decode function to decode the data for the second time into JSON format.
ParamsRequirementData typeDescription
transactionrequiredObjectInstallment transaction information
transaction.transactionIdrequiredStringInstallment transaction code generated by AppotaPay
transaction.partnerCoderequiredStringPartner identifier code
transaction.referenceIdrequiredStringOrder code of the original payment transaction (orderId)
transaction.bankCoderequiredStringCard-issuing bank code
transaction.authCoderequiredStringAuth code
transaction.paymentAmountrequiredIntegerTotal installment transaction amount (VND)
transaction.payPerMonthrequiredIntegerMonthly payment amount (VND)
transaction.feeConversionrequiredFloatInstallment conversion fee rate (%) of the selected loan package
transaction.loanPackageIdrequiredStringID of the applied installment loan package
transaction.gracePeriodrequiredStringInstallment term (number of months)
transaction.statusrequiredStringInstallment transaction status
transaction.statusCanceloptionalStringInstallment cancellation status
transaction.errorCoderequiredIntegerInstallment transaction error code
transaction.errorMessagerequiredStringError description corresponding to errorCode
transaction.feePartnerrequiredIntegerFee borne by the partner (VND)
transaction.feeUserrequiredIntegerFee borne by the customer (VND)
transaction.reasonCanceloptionalStringReason for cancelling the installment transaction
transaction.reasonUpdateoptionalStringReason for updating the transaction
transaction.completedAtoptionalIntegerTime the installment transaction was completed (Unix timestamp in seconds)
transaction.updatedAtrequiredIntegerLast updated time (Unix timestamp in seconds)
transaction.createdAtrequiredIntegerInstallment transaction creation time (Unix timestamp in seconds)

Status code table

StatusDescription
pendingThe transaction is pending processing.
successThe transaction is successful.
errorThe transaction has failed.

Cancellation status code table

StatusDescription
wait_vendorWaiting for the vendor to process the cancellation request
wait_bankVendor processed, waiting for bank confirmation
bank_rejectBank rejected the cancellation request
rejectedThe cancellation request was rejected
cancelledThe installment transaction has been cancelled successfully

Error code table

Error codeDescription
2Param is invalid
35System error, please try again
44An error occurred during processing
45Card is invalid
46Webhook IP is invalid
47Partner signature is invalid
49System error, not try again
50Bank code is invalid
52Have an error while connecting with provider
53Payment gateway secret key lack
54System can't cancel the transaction
55Transaction canceled
56Order ID has existed
57Amount is invalid
100New transaction
101Waiting for conversion
102Transferred request to bank
103Succeeded
104Failed (provider rejected request)
105Failed (bank rejected request)
108Canceled successfully
109Transaction failed
401Token is invalid

Example Request:

{
"data": "eyJ0cmFuc2FjdGlvbiI6eyJ0cmFuc2FjdGlvbklkIjoiQVAyMDA5MTAwMTQxMjVCIiwicGFydG5lckNvZGUiOiJNRVJDSEFOVF9DT0RFIiwicmVmZXJlbmNlSWQiOiJNUkNfT1JERVJfMTIzNDUiLCJiYW5rQ29kZSI6IlZDQiIsImF1dGhDb2RlIjoiMTMxMjMzOCIsInBheW1lbnRBbW91bnQiOjEyMDAwMDAwLCJwYXlQZXJNb250aCI6MTAwMDAwMCwiZmVlQ29udmVyc2lvbiI6Mi41LCJsb2FuUGFja2FnZUlkIjoiTFBfVkNCXzEyTSIsImdyYWNlUGVyaW9kIjoiMTIiLCJzdGF0dXMiOiJzdWNjZXNzIiwic3RhdHVzQ2FuY2VsIjpudWxsLCJlcnJvckNvZGUiOjEwMywiZXJyb3JNZXNzYWdlIjoiU3VjY2VlZGVkIiwiZmVlUGFydG5lciI6MzAwMDAwLCJmZWVVc2VyIjowLCJyZWFzb25DYW5jZWwiOm51bGwsInJlYXNvblVwZGF0ZSI6bnVsbCwiY29tcGxldGVkQXQiOjE3ODI5OTA5MDAsInVwZGF0ZWRBdCI6MTc4Mjk5MDkwMCwiY3JlYXRlZEF0IjoxNzgyOTg3MzAwfX0=",
"time": 1782990900,
"signature": "171846e6962c5537c546ec5d6e6a864800db2366c330f418d7eff87661248a4c"
}

Decoded data

{
"transaction": {
"transactionId": "AP200910014125B",
"partnerCode": "MERCHANT_CODE",
"referenceId": "MRC_ORDER_12345",
"bankCode": "VCB",
"authCode": "1312338",
"paymentAmount": 12000000,
"payPerMonth": 1000000,
"feeConversion": 2.5,
"loanPackageId": "LP_VCB_12M",
"gracePeriod": "12",
"status": "success",
"statusCancel": null,
"errorCode": 103,
"errorMessage": "Succeeded",
"feePartner": 300000,
"feeUser": 0,
"reasonCancel": null,
"reasonUpdate": null,
"completedAt": 1782990900,
"updatedAt": 1782990900,
"createdAt": 1782987300
}
}

Response format

  • When confirming a successful installment transaction via IPN, the partner needs to respond to AppotaPay to confirm that they have received the result
  • In case the partner does not respond successfully, AppotaPay will attempt to respond up to 3 times, with an interval of about 5 minutes between each attempt
  • The response is considered successful when HTTP code = 200 and the status parameter in the response body = ok

Example success response

HTTP Code: 200

Body: {"status": "ok"}