Tokenization Payments
Process Flow
Flow Diagram
Overview of payment processing
First time payment & save card
- Step 1: Customers check out order and choose to pay using Credit 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 will redirect to Momo's Credit card payment page, using provided URL in step 3.
- Step 5,6: Customers provide Credit card information and make payment. Users can choose to save card.
- Step 7: MoMo executes the transaction, notify the merchant and redirect users back to merchant website.
- Step 8: Merchant verifies the transaction result & display transaction result to customers.
- Step 9: If there is callbackToken, merchant requests for payment token (encrypted using AES) to be used for next payments.
- Step 10: MoMo response recuring token as aesToken & return to merchant
- Step 11: After received, merchant save aesToken for each user that request to bind.
Next payment
- Step 12: Users check the order and choose 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 rsaToken (encrypted token) to pay. MoMo notifies merchant and redirects users to the merchant website.
- Step 15: Merchant checks transaction results and displays transaction results to users.
API Configuration
Initiate binding method
HTTP RequestHTTP 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 | Long | Payment amount Min: 1.000 VND Max: 10.000.000 VND 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 | Merchant's unique user identification. | |
extraData | String | Default value is empty "" Encode base64 follow Jsonformat: {"key": "value"} Example with data: {"username": "momo"} => data of extraData : eyJ1c2VybmFtZSI6ICJtb21vIn0= | |
userInfo | Object | Info of the customer, in which email is required. | |
requestType | String(20) | payWithCC | |
lang | String(20) | Language return: vi or en | |
signature | String(65) | HMAC_SHA256accessKey=$accessKey&amount=$amount &extraData=$extraData&ipnUrl=$ipnUrl&orderId=$orderId &orderInfo=$orderInfo&partnerClientId=$partnerClientId &partnerCode=$partnerCode&redirectUrl=$redirectUrl &requestId=$requestId&requestType=$requestType, secretKey) |
Details of userInfo
content
If this is provided, customer as MoMo user will be receive a notification or email (by choices).
Attribute | Type | Required | Description |
---|---|---|---|
name | String | Name of the customer as registered on merchant site | |
phoneNumber | String | Phone number of the customer as registered on merchant site | |
String | Email address of the customer as registered on merchant site |
{
"partnerCode": "MOMOIQA420180417",
"accessKey": "SvDmj2cOTYZmQQ3H",
"requestId": "1516771499398",
"amount": "0",
"orderId": "1516771499398",
"ipnUrl": "http://example.com",
"redirectUrl": "http://example.com",
"partnerClientId": "abc@gmail.com",
"requestType": "payWithCC",
"userInfo": {
"email": "email_add@domain.com",
}
"lang": "vi",
"extraData": "eyJlbWFpbCI6ICJleGFtcGxlQGdtYWlsLmNvbSJ9",
"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
{
"partnerCode": "MOMOIOLD20190129",
"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 | |
orderId | String | OrderId of partner, unique for each request | |
requestId | String | Partner's requestId | |
amount | Long | Payment amount | |
orderInfo | String | Order's information | |
partnerUserId | String | MoMo's unique identifier for each MoMo eWallet account. | |
orderType | String | momo_wallet | |
transId | Long | MoMo's transaction ID | |
resultCode | Integer | Transaction status of the order Result Code | |
message | String | Error description, languague is based on lang | |
payType | String | Payment type: credit | |
responseTime | Long | Time to respond payment results to partner Format: timestamp | |
extraData | String | Extra Data. Default: "" | |
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 &message=$message&orderId=$orderId&orderInfo=$orderInfo &orderType=$orderType&partnerCode=$partnerCode&payType= $payType&requestId=$requestId&responseTime= $responseTime&resultCode=$resultCode&transId=$transId |
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) | |
cardType | String | MASTERCARD , VISA or JCB |
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: 1.000 VND Max: 10.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 | |
autoCapture | Boolean | If set to false, the payment will not be automatically captured. | |
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. |
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
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
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"
}
Unbind
Request header:
application/jsonResponse header:
application/json
MoMo also allowed to remove saved card (token to be provoked) from MoMo App
Merchant 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 payWithCC | |
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 | credit | |
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": "credit",
"signature": "bd4df3f3bad6815a9a7be1f1f5c8576f3f97eab25327247425f12a3fb4a78873"
}
You need to respond with HTTP code 204 (No Content)!
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
}
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 linkWallet | |
partnerClientId | String | It must be matched with partnerClientId used in linkWallet | |
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 Credit 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 |
4015 | 3DS verification failed. | Yes | User authentication failed. Please request another authentication verification for retry. | User error |