Tokenization Payments
Process Flow
Flow diagram
Explanation
First time payment & card saving
- Step 1: Customer (user) checks out order and chooses to pay using domestic ATM card.
- Step 2: Your server creates a payment session and sends payment request to MoMo.
- Step 3: MoMo provides a URL for merchant.
- Step 4: Merchant website redirects user to MoMo's domestic ATM card payment page, using provided URL in step 3.
- Step 5,6: User provides ATM card information and makes payment. User can choose to save card.
- Step 7: MoMo executes the transaction, notifies the merchant and redirects user back to merchant website.
- Step 8: Merchant verifies the transaction result & displays transaction result to user.
- Step 9: If there is callbackToken, merchant requests the payment token (encrypted using AES) which will be used for next payments.
- Step 10: MoMo responses the recurring token as aesToken & return to merchant.
- Step 11: After receiving the token, merchant saves aesToken for each user who requested to bind.
Nextime payments
- Step 12: User checks the order and chooses to pay by saved card.
- Step 13: Merchant server creates a payment session and sends payment request with AES token to MoMo.
- Step 14: MoMo processes the transaction, using hashToken (encrypted token) to pay. MoMo notifies merchant and redirects user to the merchant website.
- Step 15: Merchant checks transaction results and displays transaction results to user.
API Configuration
Initiate binding method
HTTP RequestPOST /v2/gateway/api/create
Attribute | Type | Required | Description |
---|---|---|---|
partnerCode | String(20) | Merchant ID Integration information | |
requestId | String(50) | Request ID, unique for each request, MoMo's partner uses the requestId field for idempotency control | |
amount | String(20) | Payment amount Min: 10.000 VND Max: 50.000.000 Currency: VND . | |
orderId | String | OrderId of partner, unique for each request | |
orderInfo | String(200) | Order info from merchant | |
redirectUrl | String(200) | MoMo Payment will redirect end-user back to Vendor using this URL, to notify result for end-user using HTTP GET request type | |
ipnUrl | String(200) | MoMo Payment will notify this URL. Vendor server needs to build this URL to receive results sent from MoMo, using HTTP POST request type with header application/json. | |
partnerClientId | String | Vendor’s unique identifier for each user (e.g.: user ID or email). This ID will be linked with end-user’s MoMo account. | |
extraData | String | Default value is empty "" Encode base64 follow Jsonformat: {"key": "value"} Example with data: {"username": "momo"} => data of extraData : eyJ1c2VybmFtZSI6ICJtb21vIn0= | |
requestType | String(20) | payWithATM | |
lang | String(20) | Language return: vi or en | |
signature | String(65) | Signature to confirm information. Secure transaction in Hmac_SHA256 algorithm with format: a String sort all key name of data field from a-z: accessKey=$accessKey&amount=$amount&extraData=$extraData &ipnUrl=$ipnUrl&orderId=$orderId&orderInfo=$orderInfo &partnerClientId=$partnerClientId&partnerCode= $partnerCode&redirectUrl=$redirectUrl&requestId= $requestId&requestType=$requestType |
In addition, in case the merchant has a partnerClientId code that wants to link with multi MoMo wallets (rule 1: multi), the merchant can transmit additional code nxxx_partnerClientId
with xxx being the link number. For example, for the first time binding for user A, merchant transmits n000_abc@gmail.com
, and user A needs to binding for a second time, merchant will transmit n001_abc@gmail.com
.
Example Request
{
"partnerCode": "MOMO_ATM_DEV",
"accessKey": "SvDmj2cOTYZmQQ3H",
"requestId": "1516771499398",
"amount": "0",
"orderId": "1516771499398",
"ipnUrl": "http://localhost:1001",
"redirectUrl": "http://localhost:8081",
"partnerClientId": "abc@gmail.com",
"requestType": "payWithATM",
"lang": "vi",
"signature": "ca3c203f0c16873e688fada17…ee116b636ff407d6fe39"
}
Attribute | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
requestId | String | Same as the original request | |
orderId | String | OrderId of partner, unique for each request | |
payUrl | String | URL for switching from the partner's page to the MoMo payment page | |
resultCode | int | Error code | |
message | String | Error description, error language is based on lang | |
responseTime | Long | Time to respond payment results to partner Format: timestamp | |
partnerClientId | String(50) | Vendor’s unique identifier for each user (e.g.: user ID or email). This ID will be linked with end-user’s MoMo account. |
Example Response
{
"partnerCode": "MOMO_ATM_DEV",
"requestId": "1616577794003",
"orderId": "1616577794003:0123456778",
"amount": 10000,
"responseTime": 1616577795018,
"message": "Thành công",
"resultCode": 0,
"payUrl": "https://test-payment.momo.vn/gateway/pay?t=TU9NT...NTY3Nzg=",
"partnerClientId": "932024090117"
}
Processing payment result
For more information, see Payment Notification.
Parameter description
Description for parameters which are used by MoMo in the URL redirectUrl
and the body content of ipnUrl
.
Attribute | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
requestId | String | Each Request’s Identification | |
amount | Long | Amount to pay | |
orderId | String | OrderId of partner, unique for each request | |
orderType | String | momo_wallet | |
orderInfo | String | Order info | |
partnerUserId | String | MoMo's unique identifier for each MoMo eWallet account. | |
partnerClientId | String | Identifier of user | |
callbackToken | String | Token info used to get payment token | |
transId | Long | MoMo's transaction ID | |
resultCode | Integer | Order status | |
message | String | description of resultCode based on lang | |
payType | String | napas | |
responseTime | Long | Time to return payment result in miliseconds | |
extraData | String | Additional info | |
signature | String | Signature to confirm information. Secure transaction in Hmac_SHA256 algorithm with format: a String sort all key name of data field from a-z: accessKey=$accessKey&amount=$amount&callbackToken= $callbackToken&extraData=$extraData&message=$message &orderId=$orderId&orderInfo=$orderInfo&orderType= $orderType&partnerClientId=$partnerClientId &partnerCode=$partnerCode&payType=$payType&requestId= $requestId&responseTime=$responseTime&resultCode= $resultCode&transId=$transId |
The signature is encrypted using secretKey and accessKey, so you must keep it secret, not expose to any chat channels, or in source code, git, etc.
Example
{
"partnerCode": "123456",
"requestId": "1527246504579",
"orderId": "1527246478428",
"partnerClientId": "MoMoAccountTest",
"lang": "vi",
"signature": "13be80957a5ee32107198920fa26aa85a4ca238a29f46e292e8c33dd9186142a"
}
Attribute | Type | Description |
---|---|---|
partnerCode | String | Merchant ID |
requestId | String | Request ID, unique for each request |
orderId | String | Partner Transaction ID Regex: ^[0-9a-zA-Z]([-_.]*[0-9a-zA-Z]+)*$ , stored on MoMo payment system |
callbackToken | String | The callback token generated by MoMo. |
resultCode | int | Result code |
message | String | Description regarding result code, based on lang |
responseTime | long | Response time |
Example
{
"partnerCode": "123456",
"requestId": "1527246504579",
"orderId": "1527246478428",
"callbackToken ": "u7YYQZnAbLQivB0p5SHT9LIhjshqarXyobE_WzCCa4vDt58r",
"resultCode": 0,
"message": "Success",
"responseTime": 127264428
}
Receive recurring token
After receiving callbackToken
from transaction result, merchant will send a request to MoMo to get user's token info
POST /v2/gateway/api/tokenization/bind
Parameter | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
callbackToken | String | callbackToken as access token, received from payment result | |
requestId | String | Unique identifier of each request | |
orderId | String | Unique identifier of each merchant's user. Must be orderId with saved token | |
partnerClientId | String | Identifier of transaction with saved token | |
lang | String | Language¸ of returned message (vi or en ) | |
signature | String | Signature to confirm information. Secure transaction in Hmac_SHA256 algorithm with format: a String sort all key name of data field from a-z: accessKey=$accessKey&callbackToken=$callbackToken&orderId= $orderId&partnerClientId=$partnerClientId&partnerCode= $partnerCode&requestId=$requestId |
Example request
{
"partnerCode": "MOMO_ATM_DEV",
"requestId": "03dc5a00-b37c-11e9-b3a3-2f10f50d933d",
"callbackToken": "v2/qml0PbOlrBYjFlZv…8StiawfZPiKoUGvywNHV",
"orderId": "03dc32f0-b37c-11e9-b3a3-2f10f50d933d",
"partnerClientId": "user@momo.vn",
"signature": "fa8b66df31cc7045783323f1e4492d7b71c1de4c9e1b71002f95a1aa869e885a",
"lang": "vi"
}
Attribute | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
requestId | String | Each Request’s Identification | |
orderId | String | OrderId of partner, unique for each request | |
aesToken | String | token object json encrypted using AES | |
resultCode | Integer | Order status | |
partnerClientId | String | Vendor’s unique identifier for each user (e.g.: user ID or email). This ID will be linked with end-user’s MoMo account | |
responseTime | Long | Time to respond payment results to partner Format: timestamp | |
message | String | Result description based on lang |
Data of token after decrypted
Attribute | Type | Required | Description |
---|---|---|---|
value | String | Token Value using for pay token | |
cardNumber | String | Card Number (only show last 4 digits) | |
bankCode | String | BankCode | |
cardType | String | napas | |
bankLogoUrl | String | Url of bank's logo |
Example response
{
"timestamp": 1600678154664,
"partnerCode": "MOMO_ATM_DEV",
"requestId": "03dc5a00-b37c-11e9-b3a3-2f10f50d933d",
"orderId": "03dc32f0-b37c-11e9-b3a3-2f10f50d933d",
"partnerClientId": "user@momo.vn",
"resultCode": 0,
"responseTime": 145784525,
"message": "Success",
"aesToken": "NplHKEhGuFoo5o5vbMeJwrsk7wXEPnCjSZv6DgivW1a8JKw1gdXq2WS7UsPwoJv0yf6rbGiVV6nOKAxU8kTNg4SZraqJnf7GAq9OSE2LiNs="
}
After receiving aesToken from MoMo, Merchant server must decrypt aesToken to get real token and store it in the Merchant's system. Decrypting payment token by AES algorithm will require secret key
, which can be found in https://business.momo.vn
Example
private static String decrypt_AES(String sercretKey, String encryptData) {
try {
IvParameterSpec iv = new IvParameterSpec(new byte[16]);
SecretKeySpec skeySpec = new SecretKeySpec(sercretKey.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.decodeBase64(encryptData));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
Pay using Token
Merchant can query token to pay
HTTP RequestPOST /v2/gateway/api/tokenization/pay
Parameter | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
partnerName | String | Partner | |
storeId | String | store Identification | |
orderId | String | OrderId of partner, unique for each request | |
amount | Long | Payment amount Min: 10.000 VND Max: 50.000.000 VND Currency: VND . | |
requestId | String(50) | Request ID, unique for each request, MoMo's partner uses the requestId field for idempotency control | |
token | String | Encrypt a object json by RSA using public Key RSA Encryption | |
partnerClientId | String | Merchant's unique user info | |
orderInfo | String | Short information | |
redirectUrl | String | URL used to redirect back from MoMo to merchant page after customer making payment Supported: AppLink and WebLink | |
ipnUrl | String | Merchant’s API Endpoint. Used by MoMo to send payment results via IPN method (server-to-server) | |
extraData | String | Default value is empty "" Encode base64 follow Jsonformat: {"key": "value"} Example with data: {"username": "momo"} => data of extraData : eyJ1c2VybmFtZSI6ICJtb21vIn0= | |
lang | String | Language of returned message (vi or en ) | |
signature | String | Signature to confirm information. Secure transaction in Hmac_SHA256 algorithm with format: a String sort all key name of data field from a-z: accessKey=$accessKey&amount=$amount&extraData=$extraData &orderId=$orderId&orderInfo=$orderInfo&partnerClientId= $partnerClientId&partnerCode=$partnerCode&requestId= $requestId&token=$token |
Data of token before encrypted
Attribute | Type | Required | Description |
---|---|---|---|
value | String | Token Value as recurring token | |
requireSecurityCode | Boolean | If set to false when the security code parameter is not used, it will not redirect to the form page to fill in the security code, but the payment will be directly sent to the payment provider. |
Example request
{
"token": "sa5s4a54s5a4s5a4s5",
"partnerCode": "MOMO_ATM_DEV",
"partnerName": "Test",
"storeId": "MoMo test store",
"ipnUrl": "abc.com",
"redirectUrl": "abc.com",
"orderId": "12545465654656",
"amount": "20000",
"lang": "vi",
"autoCapture": true,
"orderInfo": "Thanh toan MoMo",
"requestId": "365656d56sd",
"extraData": "",
"partnerClientId": "test@momo.vn",
"signature": "2512s1d2s1ds21d2s1d1ce5d1a251#@"
}
HTTP Response
If you recieved resultCode 8000
will be given in the response a payUrl, that will be used to redirect the customer to the payment provider for validating
Attribute | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
orderId | String | OrderId of partner, unique for each request | |
requestId | String | Each Request’s Identification | |
amount | Long | Amount to pay | |
transId | Long | MoMo's transaction ID | |
responseTime | Long | Time to respond payment results to partner Format: timestamp | |
partnerClientId | String | Vendor’s unique identifier for each user (e.g.: user ID or email). This ID will be linked with end-user’s MoMo account. | |
resultCode | Integer | Order status | |
message | String | Result description, language is based on lang | |
payUrl | String | URL for switching from the partner's page to the MoMo payment page | |
deeplink | String | URL to open MoMo application directly (Customers must install MoMo app first) and payment confirmation screen. | |
qrCodeUrl | String | Data to generate QR code if you want customers to scan the QR code directly on your purchase page or to print it on the invoice. Note : This URL is NOT containing the image of the QR code, you need to use an external library to generate the QR code. |
Example response
{
"partnerCode": "MOMO_ATM_DEV",
"requestId": "1599645548172",
"orderId": "1599645548172:0123456778",
"amount": 50000,
"responseTime": 145758545,
"partnerClientId": "user@momo.vn",
"resultCode": 0,
"message": "Success"
}
Delete token
Merchant can request to delete token
HTTP RequestPOST /v2/gateway/api/tokenization/delete
Parameter | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
requestId | String(50) | Request ID, unique for each request, MoMo's partner uses the requestId field for idempotency control | |
orderId | String | OrderId of partner, unique for each request | |
storeId | String | store Identification | |
token | String | Encrypt a object json by RSA using public Key RSA Encryption | |
partnerClientId | String | Merchant's unique user info | |
lang | String | Language of returned message (vi or en ) | |
signature | String | Signature to confirm information. Secure transaction in Hmac_SHA256 algorithm with format: a String sort all key name of data field from a-z: accessKey=$accessKey&orderId=$orderId&partnerClientId= $partnerClientId&partnerCode=$partnerCode&requestId= $requestId&token=$token |
Attribute | Type | Required | Description |
---|---|---|---|
partnerCode | String | Integration information | |
requestId | String | Each Request’s Identification | |
message | String | Result description, language is based on lang | |
resultCode | Integer | Order status | |
partnerClientId | String | Merchant's unique user info | |
responseTime | Long | Time to respond payment results to partner Format: timestamp |
Example response
{
"partnerCode": "MOMO_ATM_DEV",
"orderId": "1600838954650:0123456778",
"requestId": "1600838954650",
"resultCode": 0,
"message": "Success",
"partnerClientId": "test@momo.vn",
"responseTime": 14548754653232
}
Unbind
Request header:
application/jsonResponse header:
application/json
MoMo also allows to remove saved card (token to be provoked) from MoMo UI (Contact us if you need to use this feature)
Merchants have to provide the endpoint to receive notify remove sent from MoMo, using HTTP POST
HTTP RequestAttribute | Type | Required | Description |
---|---|---|---|
partnerCode | String | Merchant ID | |
requestId | String | Unique ID for each request | |
orderId | String | the initial orderId which was used to payWithATM | |
requestType | String | remove | |
partnerClientId | String | Vendor’s unique identifier of each user (e.g.: user ID or email) that linked with MoMo wallet | |
tokenType | String | atm | |
signature | String | Signature to confirm information. Secure transaction in Hmac_SHA256 algorithm with format accessKey=$accessKey&orderId=$orderId&partnerClientId=$partnerClientId &partnerCode=$partnerCode&requestId=$requestId &requestType=$requestType&tokenType=$tokenType |
Example
{
"partnerCode": "MOMOIQA420180417",
"requestId": "0e0ceb2a-ea06-4ca7-b63a-e5c8948a5bfc",
"orderId": "012457855:231454545",
"partnerClientId": "sangle@mservice.com.vn",
"requestType": "remove",
"tokenType": "atm",
"signature": "bd4df3f3bad6815a9a7be1f1f5c8576f3f97eab25327247425f12a3fb4a78873"
}
You need to respond with HTTP code 204 (No Content)!
callbackToken inquiry
Vendor system cannot receive or record callbackToken, Vendor can request MoMo Payment to query callbackToken.
Request header:
application/json - Response header:
application/json
POST /v2/gateway/api/tokenization/cbQuery
Attribute | Type | Required | Description |
---|---|---|---|
partnerCode | String | Merchant ID | |
requestId | String | Request ID, unique for each request | |
orderId | String | It must be matched with orderId used in payWithATM | |
partnerClientId | String | It must be matched with partnerClientId used in payWithATM | |
lang | String | vi or en | |
signature | String | Signature to confirm information. Secure transaction in Hmac_SHA256 algorithm with format: a String sort all key name of data field from a-z: accessKey=$accessKey&orderId=$orderId &partnerClientId=$partnerClientId&partnerCode=$partnerCode &requestId=$requestId |
Result Codes & Messages
These result codes and messages are exclusively assigned for Tokenization flow within the context of Local ATM Card Payments. Additionally, kindly locate other result codes and messages in the comprehensive list of result codes provided here.
Result code | Description | Final Status | Recommended actions | Type |
---|---|---|---|---|
0 | Successful. | Yes | ||
1002 | Transaction rejected by the issuers of the payment methods. | Yes | Please choose other payment methods. | User error |
2001 | Transaction failed due to invalid token. | Yes | The token has been deleted, please update accordingly. | Merchant error |
2007 | Transaction failed due to inactive token. | Yes | The token is inactive due to user decided to temporary lock the binding. | User error |
2012 | Request rejected due to invalid token. | Yes | The token does not exist or has been deleted. Token status can not be updated. | Merchant error |
4010 | OTP verification failed. | Yes | User authentication failed. Please request another authentication. | User error |
4011 | OTP is not sent or timeout. | Yes | Please request to send another OTP. | User error |