如何修复 CCAvenue Split Payment API 的 command 缺失错误
结论
command is mandatory 通常不是因为加密数据里缺少 command,而是因为 CCAvenue 没有从外层表单参数中读到它。
需要修正两处:
- 参数名必须是小写的
command,不能写成Command。 - 请求体必须使用
application/x-www-form-urlencoded,不能让 Axios 默认发送 JSON。
当前代码中的 Command: params.command 还会得到 undefined。这是因为 params 定义的是大写的 Command,读取时用的却是小写的 params.command。
正确的参数结构
command、enc_request、access_code、request_type 和 response_type 都应作为外层表单字段发送。业务数据经过序列化和加密后,再放入 enc_request。
command=createSplitPayout
enc_request=<encrypted value>
access_code=<access code>
request_type=JSON
response_type=JSON
不能只把 command 放在加密数据中。CCAvenue 需要先从外层请求参数读取它,才能确定要执行的 API 操作。
修改后的代码
const axios = require('axios');
const crypto = require('crypto');
exports.splitVendorPayment = async (req, res) => {
const accessCode = process.env.CCAVENUE_ACCESS_CODE;
const apiUrl =
'https://apitest.ccavenue.com/apis/servlet/DoWebTrans';
const requestData = {
split_tdr_charge_type: 'M',
merComm: '2.0',
reference_no: '',
split_data_list: [
{
splitAmount: '40.76',
subAccId: 'TEST01'
}
]
};
const encryptedParams = encryptRequestParams(requestData);
const formData = new URLSearchParams();
formData.append('command', 'createSplitPayout');
formData.append('enc_request', encryptedParams);
formData.append('access_code', accessCode);
formData.append('request_type', 'JSON');
formData.append('response_type', 'JSON');
try {
const response = await axios.post(apiUrl, formData.toString(), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
console.log('API Response:', response.data);
return res.status(200).send(response.data);
} catch (error) {
console.error(
'CCAvenue API Error:',
error.response?.data || error.message
);
return res.status(error.response?.status || 500).json({
message: 'CCAvenue Split Payment API request failed',
error: error.response?.data || error.message
});
}
};
function encryptRequestParams(params) {
const paramString = JSON.stringify(params);
const workingKey = process.env.CCAVENUE_WORKING_KEY;
const key = Buffer.from(workingKey, 'hex');
const iv = Buffer.alloc(16, 0);
const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
let encrypted = cipher.update(paramString, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
需要特别注意这一行:
formData.append('command', 'createSplitPayout');
参数名必须是小写的 command,而且要作为表单字段发送。
为什么原来的写法无效
原代码中的属性名大小写不一致:
const params = {
Command: 'createSplitPayout'
};
Command: params.command
JavaScript 的属性名区分大小写,所以这两个表达式的结果不同:
params.Command // "createSplitPayout"
params.command // undefined
即使改成下面的写法,也可能收到同样的错误:
await axios.post(apiUrl, {
command: 'createSplitPayout'
});
Axios 默认会把普通对象作为 JSON 发送:
Content-Type: application/json
如果 CCAvenue 按表单格式解析请求体,就无法从这段 JSON 中读取 command。
Postman 中的正确配置
在 Postman 中选择:
Body → x-www-form-urlencoded
然后添加以下字段:
| Key | Value |
|---|---|
command | createSplitPayout |
enc_request | 加密后的请求内容 |
access_code | CCAvenue 提供的 access code |
request_type | JSON |
response_type | JSON |
不要选择 raw → JSON,参数名也不要写成大写的 Command。
注意事项
command的参数名和createSplitPayout的值都要严格遵循当前 CCAvenue Split Payment API 文档,包括大小写。access_code不能为空。测试环境的凭据应与https://apitest.ccavenue.com对应。reference_no、merComm、split_data_list等业务字段能否为空,以及各字段的格式要求,应以商户账户对应的 Split Payment API 文档为准。- CCAvenue 的不同接口或接入资料可能采用不同的密钥派生方式和 IV。只有接口文档明确要求时,才能使用现有的
Buffer.from(workingKey, 'hex')和全零 IV。如果修复command后出现解密失败或请求无效等错误,还需要核对官方加密示例。 - 不要在代码中硬编码
workingKey和accessCode,应从环境变量或密钥管理服务中读取。 - Axios 的完整响应对象包含大量连接信息。排查接口返回结果时,优先查看
response.data。
备注:内容仅供参考。