Payment Init API
Payment Init API is used when the merchant/Provider wants to initiate a Payment request for their PhonePe EDC or DQR Device.
UAT Endpoints:POST https://mercury-uat.phonepe.com/enterprise-sandbox/v1/payment/init
Prod Endpoints:POST https://mercury-t2.phonepe.com/v1/payment/init
| Header Name | Header Value |
|---|---|
Content-Type | application/json |
X-VERIFY | SHA256(base64 encoded payload + “/v1/payment/init”+ salt key) + ### + salt index |
X-PROVIDER-ID | Used for the cases where the merchants are getting onboarded via their Providers |
Sample JSON Payload for DQR Device
{
"storeId": "MS2603301457425143586306",
"merchantId": "MERCHANTUAT",
"terminalId": "MST2603301758302811969831",
"merchantTransactionId": "TXN0015985",
"orderId": "MRCHN1RORDID10111114",
"amount": 100,
"solutionType": "DQR_DEVICE",
"expiresIn": 180
}Sample JSON Payload for EDC
{
"merchantId": "MERCHANTUAT",
"storeId": "MS2403212004046998204201",
"orderId": "testorder1",
"terminalId": "MST2405301213090857163565",
"merchantTransactionId": "test_transaction1",
"amount": 200,
"paymentModes": [
"CARD",
"DQR"
],
"solutionType" : "EDC",
"timeAllowedForHandoverToTerminalSeconds": 60,
"integrationMappingType": "ONE_TO_ONE"
}Sample Base64 Encoded Payload DQR Device
{"request": "eyJzdG9yZUlkIjogIk1TMjYwMzMwMTQ1NzQyNTE0MzU4NjMwNiIsICJtZXJjaGFudElkIjogIkNPR1dBVkVPRkZMSU5FIiwgInRlcm1pbmFsSWQiOiAiTVNUMjYwMzMwMTc1ODMwMjgxMTk2OTgzMSIsICJtZXJjaGFudFRyYW5zYWN0aW9uSWQiOiAiVFhOMDAxOTQ0MCIsICJvcmRlcklkIjogIk1SQ0hOMVJPUkRJRDEwMTExMTE0IiwgImFtb3VudCI6IDEwMCwgInNvbHV0aW9uVHlwZSI6ICJEUVJfREVWSUNFIiwgImV4cGlyZXNJbiI6IDE4MH0="}Sample Base64 Encoded Payload for EDC
{
"request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKICAic3RvcmVJZCI6ICJNUzI0MDMyMTIwMDQwNDY5OTgyMDQyMDEiLAogICJvcmRlcklkIjogInRlc3RvcmRlcjEiLAogICJ0ZXJtaW5hbElkIjogIk1TVDI0MDUzMDEyMTMwOTA4NTcxNjM1NjUiLAogICJ0cmFuc2FjdGlvbklkIjogInRlc3RfdHJhbnNhY3Rpb24xIiwKICAiYW1vdW50IjogMjAwLAogICJwYXltZW50TW9kZXMiOiBbCiAgICAiQ0FSRCIsCiAgICAiRFFSIgogIF0sCiAgInRpbWVBbGxvd2VkRm9ySGFuZG92ZXJUb1Rlcm1pbmFsU2Vjb25kcyI6IDYwLAogICJpbnRlZ3JhdGlvbk1hcHBpbmdUeXBlIjogIk9ORV9UT19PTkUiCn0="
}Request Parameters
| Parameter Name | Type | Description | Mandatory | |
|---|---|---|---|---|
merchantId | String | Unique Merchant ID assigned to the merchant by PhonePe. Special chars allowed: UNDERSCORE | Yes | |
merchantTransactionId | String | Unique Transaction ID generated by the merchant and the length of transaction ID should be less than 40 characters. Special characters allowed: UNDERSCORE | Yes | |
amount | LONG | Amount is in Paisa INR format and accepts LONG type value. | Yes | |
solutionType | Enum | Type of the device DQR or EDC | Yes | |
storeId | String | Store Id of store. This will be a Phonepe generated storeId. Special chars allowed: UNDERSCORE | Yes | |
terminalId | String | Terminal Id of a store and it would be unique for a store. This will be a Phonepe generated terminalId. TerminalId param is optional in case integrationMappingType: OPEN, and its mandatory in case integrationMappingType: ONE_TO_ONE. Special chars allowed: UNDERSCORE | Yes | |
orderId | String | Billing System Order Id for which payment tender is generated. This param can be duplicated and multiple transactions can be initiated for single order. Special chars allowed: UNDERSCORE | Yes | |
EDC Context JSON Object | shortOrderId | String | BillingPOS generated shortOrderId for fetching order on EDC, it is mandatory only in case of integrationMappingType: OPEN, in other cases if shortOrderId passed in request, server with return error. ShortOrderID should be min 4 and max 8 digits. | No |
integrationMappingType | Enum | ONE_TO_ONE: In case Terminal is hardly-coupled to the Billing System. OPEN: In case Terminals are not hardly-coupled to Billing System and any terminal within the Store can fetch the generated request by passing the shortOrderId. | Yes | |
timeAllowedForHandoverToTerminalSeconds | LONG | Sale request will remain alive for this duration( Range 60sec ), if sale request is not fetched by the Terminal in this duration it will auto expire. | No | |
paymentModes | List | Based on the payment modes passed in this list, a particular mode will only be accepted on EDC terminal. Valid payment modes: “CARD”, “DQR”. List can contain one or more valid payment modes & but List cannot be empty | Yes | |
autoAccept | String | By default param is False, this implies when the sale request is pushed/pulled by the EDC terminal, a Pop-up will be shown to Cashier with basic details of request such as amount and TransactionId and Cashier can choose to confirm/reject the request. | No | |
DQR Device Context JSON Object | expiresIn | Long | Expiry time of the DQR on device in seconds |
Success Response
{
"success": true,
"code": "SUCCESS",
"message": "Your request has been successfully completed.",
"data": {
"merchantId": "MERCHANTUAT",
"transactionId": "test_transaction1",
"amount": 200
}
}
// Http Status: 200 OKFailed Response
// Reason: X-VERIFY header not constructed correctly
{
"success": false,
"code": "UNAUTHORIZED",
"message": "checksum verification failed",
"data": null
}Failed Response
// Reason: Unique transaction id not passed in request
{
"success": false,
"code": "DUPLICATE_TRANSACTION_ID",
"message": "The transaction id you have entered seems to be invalid. [message = Duplicate transaction id]"
}Python SampleCode for DQR Device Testing
import requests
import json
import base64
import hashlib
import random
apiUrl = "/v1/payment/init"
url = "https://mercury-uat.phonepe.com/enterprise-sandbox" + apiUrl
keyindex = "<insertYourSaltIndex>"
req = json.dumps({
"storeId": "teststore1",
"merchantId": "MERCHANTUAT",
"terminalId":"testterminal1",
"merchantTransactionId": "TXN001" + str(random.randint(1, 9999)),
"orderId": "MRCHN1RORDID10111114",
"amount": 100,
"solutionType": "DQR_DEVICE",
"expiresIn": 180
})
# print(req)
byte_msg = req.encode('ascii')
base64_val = base64.b64encode(byte_msg)
base64_req = base64_val.decode('ascii')
payload = json.dumps({
"request": base64_req
})
hashStr = base64_req+apiUrl+"<insertYourSaltKey>"
xVerifyStr = hashlib.sha256(hashStr.encode()).hexdigest()
xVerifyStr = xVerifyStr +"###" +keyindex
headers = {
'accept': 'application/json',
'x-verify': xVerifyStr,
'x-callback-url': "http://www.google.dom",
'X-PROVIDER-ID': "MERCHANTPROVIDER",
'Content-Type': 'application/json'
}
curl_command = f"curl -X POST '{url}' \\\n"
for k, v in headers.items():
curl_command += f" -H '{k}: {v}' \\\n"
curl_command += f" -d '{payload}'"
print(curl_command)
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
print(response.status_code)Python SampleCode for EDC Testing
import requests
import json
import base64
import hashlib
import random
apiUrl = "/v1/payment/init"
secret_key = "<insertYourSaltKey>"
# Generate unique transaction ID (you can customize this)
transactionId = "TXb" + str(random.randint(1, 999))
orderId = "order" + str(random.randint(1, 999))
req = {
"merchantId":"MERCHANTUAT",
"storeId": "teststore1",
"terminalId": "testterminal1",
"orderId": orderId,
"merchantTransactionId": transactionId,
"amount": 100,
"paymentModes": [
"CARD",
"DQR"
],
"solutionType" : "EDC",
"timeAllowedForHandoverToTerminalSeconds": 60,
"integrationMappingType": "ONE_TO_ONE"
}
req_json = json.dumps(req)
base64_req = base64.b64encode(req_json.encode('ascii')).decode('ascii')
payload = json.dumps({"request": base64_req})
hash_str = base64_req + apiUrl + secret_key
x_verify = hashlib.sha256(hash_str.encode()).hexdigest() + "###" + "<insertYourSaltIndex>"
headers = {
'accept': 'application/json',
'x-verify': x_verify,
'X-PROVIDER-ID':"MERCHANTPROVIDER",
'Content-Type': 'application/json'
}
curl_command = f"curl -X POST 'https://mercury-uat.phonepe.com/enterprise-sandbox{apiUrl}' \\\n"
for k, v in headers.items():
curl_command += f" -H '{k}: {v}' \\\n"
curl_command += f" -d '{payload}'"
print(curl_command)
response = requests.request("POST",f"https://mercury-uat.phonepe.com/enterprise-sandbox{apiUrl}" , headers=headers, data=payload)
print(response)
print(response.json())Response Parameters
| Parameter Name | Type | Description |
|---|---|---|
success | BOOLEAN | Success status of the request |
code | ENUM | See below section for list of codes |
message | STRING | Short message about status of request |
data | JSON Object | Data JSON Object |
Data JSON Object
| Parameter Name | Type | Description |
|---|---|---|
merchantId | String | Unique Merchant ID assigned to the merchant by PhonePe |
| String | Unique Transaction ID generated by the merchant |
amount | LONG | Amount is in Paisa INR format |
Response Codes
| Parameter Name | Description |
|---|---|
SUCCESS | Your request has been successfully completed |
SOLUTION_NOT_ENABLED | EDC Sale API is not enabled for the merchant |
UNAUTHORIZED | X-VERIFY SHA logic is incorrect |
INVALID_MERCHANT_ID | The merchant id is invalid or activated |
INVALID_STORE_ID | The passed Store Id is invalid |
INVALID_TERMINAL_ID | The passed Terminal ID is invalid |
DUPLICATE_TRANSACTION_ID | The passed Transaction ID is duplicate in Sale API |
INVALID_TRANSACTION_ID | The format of Transaction ID is invalid |
INVALID_INTEGRATION_MAPPING_TYPE | The Integration_Mapping_Type param is having invalid fields |
INVALID_SHORTCODE_LENGTH | The shortCode length is not valid as per the API needs |
INTEGRATEDMODE_NOT_ENABLED_ON_TERMINAL | The Terminal is not in integrated mode |
SHORT_CODE_IS_REQUIRED | The Shortcode is mandatory as per the API needs |
SHORT_CODE_NOT_REQUIRED | Short Order Id is not required |
INVALID_TERMINAL_HANDOVER_TIME | No Active request exists. |
INVALID_AMOUNT | The amount value is not valid as per API needs |
INVALID_PAYMENT_MODES | The paymentModes is not valid |