PAYATHON 2026

如何修复 CCAvenue Split Payment API 的 command 缺失错误

支付小周

结论

command is mandatory 通常不是因为加密数据里缺少 command,而是因为 CCAvenue 没有从外层表单参数中读到它。

需要修正两处:

  1. 参数名必须是小写的 command,不能写成 Command。
  2. 请求体必须使用 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

然后添加以下字段:

KeyValue
commandcreateSplitPayout
enc_request加密后的请求内容
access_codeCCAvenue 提供的 access code
request_typeJSON
response_typeJSON

不要选择 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。

备注:内容仅供参考。