PAYATHON 2026

无法存储 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 和接口返回结构为准。

备注:内容仅供参考。