解决 PhonePe 自动扣款 API 报错 "Incorrect Request"
2025-03-12 02:10:04
PhonePe 自动扣款 API (/v3/recurring/debit/init) 报 "Incorrect Request" 错误的排查与解决
最近在对接 PhonePe 的自动扣款 (Auto-Debit) API,调用 /v3/recurring/debit/init
接口时,总是返回 "status": "error","message": "Please check the inputs you have provided. [message = Incorrect Request.]"
错误。 遇到这种情况,确实让人头疼。下面我就把排查和解决这个问题的思路和方法分享给大家。
一、问题原因分析
报 "Incorrect Request" 这种错,通常意味着发给 PhonePe 服务器的请求数据有问题。具体来说,可能有以下几种原因:
-
请求参数缺失或格式错误:
v3/recurring/debit/init
接口需要一系列参数,比如金额、用户信息、回调 URL 等。如果漏掉了某个必填参数,或者参数的格式不对(例如,数字写成了字符串),就会报错。 -
签名 (checksum) 错误: PhonePe 为了保证 API 调用的安全,采用了签名机制。如果计算签名的方法不对,或者使用了错误的密钥,服务器校验签名不通过,就会拒绝请求。
-
请求头 (Headers) 设置不正确: 有些 API 对请求头有特殊要求。 比如,
Content-Type
可能需要设置为application/json
, 或者需要特定的X-VERIFY
头信息。 -
IP 地址未加入白名单: 有可能是你的服务器IP地址没有被添加到PhonePe允许的白名单内,从而导致访问受限。
-
编码问题 极少数情况也可能是字符编码引起的,比如不是UTF-8编码。
二、解决方案
针对上面分析的原因,可以按下面步骤逐一排查、解决问题。
1. 仔细核对请求参数
原理: 确保所有必填参数都已提供,并且参数值符合 PhonePe API 文档的要求。
操作步骤:
- 认真阅读 PhonePe 关于
/v3/recurring/debit/init
接口的文档,找出所有必填参数。 - 对照文档,逐个检查你的请求数据:
- 有没有漏掉参数?
- 参数名是否正确?(注意大小写)
- 参数值的类型是否正确?(例如,金额应该是数字,不能是字符串)
- 参数值的格式是否符合要求?(例如,日期格式、字符串长度限制)
代码示例 (Python):
import requests
import json
import hashlib
def create_auto_debit_request(merchant_id, merchant_user_id, amount, callback_url, salt_key, salt_index):
"""创建自动扣款请求"""
payload = {
"merchantId": merchant_id,
"merchantUserId": merchant_user_id,
"amount": amount, # 确保是整数,单位是分
"merchantOrderId": "order_" + str(int(time.time() * 1000)), # 使用一个不会重复的orderId
"callbackUrl": callback_url,
"expiry": {
"type": "DATE",
"value": "2024-12-31" # 设置一个合理的过期时间
},
"instrument":{
"type": "TOKEN", #通常对于定期扣款为token
# 根据具体情况,这里需要填充其他信息,例如 card details 或 UPI details
},
"subscriptionType":"MONTHLY", #定期类型 MONTHLY or ON_DEMAND.
# ... 其他必要参数 ...
}
#Phonepe请求需要先做base64编码,再做sha256加密。
payload_string = json.dumps(payload, separators=(',', ':'))
encoded_payload = base64.b64encode(payload_string.encode('utf-8')).decode('utf-8')
# checksum的生成方式: base64(sha256(encoded_payload + /v3/recurring/debit/init + salt_key) + ### + salt_index
checksum_string = encoded_payload + "/v3/recurring/debit/init" + salt_key
checksum_hash = hashlib.sha256(checksum_string.encode('utf-8')).hexdigest()
checksum = checksum_hash + "###" + str(salt_index)
headers = {
"Content-Type": "application/json",
"X-VERIFY": checksum, # 签名放在 X-VERIFY 头
# ... 其他可能的请求头 ...
}
url = "https://api.phonepe.com/apis/hermes/v3/recurring/debit/init" # 生产环境 URL
#url = "https://api-preprod.phonepe.com/apis/pg-sandbox/v3/recurring/debit/init" # 沙盒环境URL
try:
response = requests.post(url, headers=headers, data=json.dumps({"request": encoded_payload}))
response.raise_for_status() # 如果响应状态码不是 2xx,会抛出异常
return response.json()
except requests.exceptions.RequestException as e:
print(f"请求出错: {e}")
return None
except Exception as e:
print(f"处理响应出错:{e}")
# 示例调用
import time
import base64
merchant_id = "YOUR_MERCHANT_ID"
merchant_user_id = "user123"
amount = 10000 # 金额,单位是分
callback_url = "https://your-website.com/callback"
salt_key = "YOUR_SALT_KEY" #PhonePe分配的salt_key
salt_index = 1 # salt key index
response_data = create_auto_debit_request(merchant_id, merchant_user_id, amount, callback_url, salt_key, salt_index)
if response_data:
print(f"响应数据:{response_data}")
安全建议:
- 不要在代码中直接写死密钥 (salt_key),应从安全的地方(例如环境变量、密钥管理服务)读取。
- 确保回调 URL (callbackUrl) 使用 HTTPS,保护数据传输安全。
2. 验证签名 (checksum)
原理: PhonePe 使用签名来确保请求的完整性和真实性。 签名算法通常是: 将请求数据、API 路径、salt key 拼接起来,进行 SHA256 哈希,然后加上 ###
和 salt key index。
操作步骤:
- 仔细阅读 PhonePe 的签名文档,了解具体的签名算法。
- 确保你用于生成签名的:
- 请求数据与实际发送的请求数据完全一致。
- API 路径正确 (在本例中是
/v3/recurring/debit/init
)。 - 使用了正确的 salt key 和 salt index。
- 使用与 PhonePe 文档一致的哈希算法 (SHA256) 和拼接方式。
代码示例(Python,接上一节):
代码中的checksum
变量的生成, 已经实现了签名生成逻辑,请参考上述Python示例代码。需要特别注意以下几点:
- base64编码 :PhonePe要求对请求体先进行base64编码。
- 数据排序 : 部分请求的json结构内key需要排序.(不是全部)
- 分隔符 :
json.dumps()
使用separators=(',', ':')
来移除空格,确保生成的 JSON 字符串最紧凑.
进阶使用技巧:
可以编写一个独立的签名函数,方便在多个 API 调用中复用。 签名函数应接收请求数据、API 路径、salt key、salt index 作为参数,返回计算出的签名。
3. 检查请求头 (Headers)
原理: 确保 Content-Type
设置为 application/json
,X-VERIFY
头包含了正确的签名。
操作步骤:
- 在代码中明确设置
Content-Type
为application/json
。 - 将上一步计算出的签名放在
X-VERIFY
头中。
代码示例 (Python,接上一节):
headers = {
"Content-Type": "application/json",
"X-VERIFY": checksum, # 签名放在 X-VERIFY 头
# ... 其他可能的请求头 ...
}
已经包含在上述Python代码示例里。
4. 联系 PhonePe 支持
原理: 如果以上方法都试过了还是不行,很可能是 PhonePe 那边的问题,或者你的账户配置有问题。
操作步骤:
- 准备好你的商户 ID (merchant ID)、错误信息、以及你发送的请求数据(脱敏后)。
- 通过 PhonePe 提供的支持渠道(例如邮件、工单系统)联系他们,详细你的问题。
- 询问他们你的服务器IP地址是否已经在白名单中。
5.检查编码
原理 : 确保编码一致性,可以减少出错可能性
操作步骤 :
- 确认文件编码是UTF-8
- 代码中编码设置与文档一致.
三、总结
解决 PhonePe API 报 "Incorrect Request" 错误,需要细心和耐心。从请求参数、签名、请求头这几个方面入手,逐一排查,通常都能找到问题所在。如果自己实在搞不定,及时联系 PhonePe 官方支持也是一个好办法。