无法存储 iyzipay payment API 返回的数据
支付老李
结论
iyzipay.payment.create 是异步操作。外部的 console.log(returnedData) 会在 callback 执行前运行,所以此时打印的仍是初始值 {}。
不要用 setTimeout 猜测请求的完成时间。可以直接在 callback 中处理 result,也可以把 API 封装成 Promise,再通过 await 获取结果。
为什么会得到空对象
JavaScript 会先按顺序执行这些代码:
let returnedData = {};
iyzipay.payment.create(paymentRequest, callback);
console.log(returnedData);
调用 payment.create 后,请求会在后台继续,程序则立即执行下一行 console.log,不会停下来等待响应。服务器返回响应后,callback 才会执行下面的赋值:
returnedData = result;
赋值本身没有问题,只是读取数据时,异步操作还没有完成。
setTimeout(..., 1000) 偶尔能够打印出数据,是因为请求通常在一秒内完成,但这种写法并不可靠。遇到网络较慢、服务端延迟或请求失败时,一秒后仍可能拿不到结果。
方案一:直接在 callback 中处理结果
如果后续逻辑比较简单,可以直接在 callback 中使用 result:
iyzipay.payment.create(paymentRequest, function (err, result) {
if (err) {
return next(new CustomError("Ödeme başarısız.", 500));
}
console.log(result);
// 在这里保存数据库、返回 HTTP 响应或执行后续业务逻辑
return res.json(result);
});
如果需要保留变量,也必须等 callback 执行后再读取:
let returnedData = {};
iyzipay.payment.create(paymentRequest, function (err, result) {
if (err) {
return next(new CustomError("Ödeme başarısız.", 500));
}
returnedData = result;
console.log(returnedData);
});
方案二:封装为 Promise 并使用 async/await
如果后面还有数据库写入、订单更新等异步操作,用 async/await 会更清楚:
function createPayment(paymentRequest) {
return new Promise((resolve, reject) => {
iyzipay.payment.create(paymentRequest, function (err, result) {
if (err) {
return reject(err);
}
resolve(result);
});
});
}
然后在异步函数中等待结果:
async function handlePayment(req, res, next) {
try {
const returnedData = await createPayment(paymentRequest);
console.log(returnedData);
// 例如:等待数据库存储完成
// await paymentRepository.save(returnedData);
return res.json(returnedData);
} catch (err) {
return next(new CustomError("Ödeme başarısız.", 500));
}
}
使用这种写法时,包含 await 的函数必须声明为 async。同时,createPayment 必须返回一个 Promise,并在 callback 执行后再完成。
方案三:让当前函数返回 Promise
如果其他代码需要调用支付函数并获取结果,可以直接返回封装后的 Promise:
function processPayment(paymentRequest) {
return new Promise((resolve, reject) => {
iyzipay.payment.create(paymentRequest, function (err, result) {
if (err) {
return reject(err);
}
resolve(result);
});
});
}
调用方再等待执行结果:
try {
const returnedData = await processPayment(paymentRequest);
console.log(returnedData);
} catch (err) {
console.error(err);
}
注意事项
return returnedData = result返回的是 callback 的执行结果,无法让外层函数同步取得result。- 不要用固定延迟等待 API 响应,因为请求耗时并不确定。
- 如果要把支付结果写入数据库,应当在 callback 中执行,或者放在
await createPayment(...)之后。 - 错误处理时应保留原始
err,至少记录必要信息,以便区分网络错误、API 错误和业务失败。 - 支付接口即使没有返回底层
err,也可能给出业务失败结果。是否需要继续检查result.status、错误码等字段,应以当前使用的 iyzipay SDK 和接口返回结构为准。
备注:内容仅供参考。
