NAB 3DS 请求未发送完整 JSON data
结论
accountData 和 billingAddress 不应与 cardholderInfo 并列,而应放在 cardholderInfo 内部。
NAB 的 securepay-threeds.js 会按预期结构重新组装请求,只读取 callback 返回值中的 cardholderInfo。因此,与它并列的 accountData 和 billingAddress 会被丢弃。删除 cardholderInfo 后,请求变为 null,也与这一处理方式一致。
callback 应改为:
function onRequestInputDataCallback() {
return {
cardholderInfo: {
cardNumber: '4444333322221111',
cardExpiryMonth: '07',
cardExpiryYear: '24',
cardholderName: 'Test Test',
accountData: {
emailAddress: 'test@test.com'
},
billingAddress: {
streetAddress: 'X',
city: 'X',
state: 'X',
country: 'AU',
zipCode: '3000'
}
}
};
}
原因
当前返回值的结构是:
{
billingAddress: { /* ... */ },
cardholderInfo: { /* ... */ },
accountData: { /* ... */ }
}
这三个对象都在 callback 返回值的顶层。但从实际请求来看,NAB 的 JavaScript SDK 不会直接对整个返回值执行 JSON.stringify(),而是先提取它能识别的结构,再构造请求。
其处理过程相当于:
var input = onRequestInputDataCallback();
var requestData = {
cardholderInfo: input.cardholderInfo
};
因此,最终只会保留 input.cardholderInfo。浏览器 Network 面板显示的是 SDK 实际发出的请求,不是显示错误。
文档表格将 cardholderInfo、accountData 和 billingAddress 标为 mandatory,并不表示它们一定处于同一级。PDF 中的缩进或层级关系很容易被忽略。这里需要满足的是 cardholderInfo 内部的数据结构。
推荐配置
还要确认 sp3dsConfig 引用的是修改后的 callback。问题中的配置使用了 onRequestInputDataCallback,示例函数名称却是 onRequestInputData。如果实际代码也有这一差异,SDK 调用的可能并不是预期函数。
function onRequestInputDataCallback() {
return {
cardholderInfo: {
cardNumber: '4444333322221111',
cardExpiryMonth: '07',
cardExpiryYear: '24',
cardholderName: 'Test Test',
accountData: {
emailAddress: 'test@test.com'
},
billingAddress: {
streetAddress: '123 Test Street',
city: 'Melbourne',
state: 'VIC',
country: 'AU',
zipCode: '3000'
}
}
};
}
var sp3dsConfig = {
clientId: providerClientId,
iframe: iframeElement,
token: orderToken,
simpleToken: simpleToken,
threeDSSessionId: sessionId,
onRequestInputData: onRequestInputDataCallback,
onThreeDSResultsResponse: onThreeDSResultsResponseCallback,
onThreeDSError: onThreeDSErrorCallback
};
修改后,Network 面板中的 data 应类似于:
{
"cardholderInfo": {
"cardNumber": "4444333322221111",
"cardExpiryMonth": "07",
"cardExpiryYear": "24",
"cardholderName": "Test Test",
"accountData": {
"emailAddress": "test@test.com"
},
"billingAddress": {
"streetAddress": "123 Test Street",
"city": "Melbourne",
"state": "VIC",
"country": "AU",
"zipCode": "3000"
}
}
}
关于错误码 180
修正对象层级后,如果仍然收到 180,需要继续逐项检查字段内容。仅凭这个错误码无法断定 3DS 服务不可用,因为 mandatory field 格式错误或银行卡不支持当前 3DS 流程,也可能触发该错误。
重点检查:
country是否使用网关要求的国家代码,例如AU,而不是国家全称。state、zipCode和地址字段是否符合 NAB 文档规定。- 卡号是否属于测试环境支持的卡品牌和测试卡范围。
cardExpiryMonth、cardExpiryYear的长度是否符合当前接口要求。token、simpleToken、clientId和threeDSSessionId是否来自同一环境和同一次交易流程。- 页面加载的
securepay-threeds.js与参考的 integration guide 是否为同一版本。
不要只看 callback 执行前的 console.log()。确认最终发送内容时,应以 Network 面板中的 request payload 为准。如果调整嵌套结构后,相关对象仍被 SDK 删除,就需要根据页面实际加载的 SDK 版本查阅对应文档,核对字段名称。NAB 的后续版本可能调整过数据模型。
备注:内容仅供参考。
