条带发票项目并非总是在一张发票中一起发送

时间:2018-08-15 22:35:56

标签: javascript node.js stripe-payments

发送带有一个发票项目的发票效果很好,但是当我尝试发送包含多个发票项目的发票时,事情变得有些麻烦。

有时会正确发送多张发票,但通常发票中缺少一个发票项目,但下一张发票中会包含该发票。有时甚至会收到错误消息:Error: Nothing to invoice for customer,甚至以为我刚运行过stripe.invoiceItems.create。还有其他人遇到过这个问题吗?

要创建多个发票项目,我有如下逻辑:

  await req.body.items.map(item => {
    const unitAmount = (item.wholesale_price + (item.shipping_amount/item.quantity) + (item.s_h/item.quantity));
    stripe.invoiceItems.create({
      unit_amount: unitAmount,
      currency: 'usd',
      customer: stripe_cus_id,
      description: item.description,
      quantity: item.quantity
    }, function(err, invoiceItem) {
      if(err) {
        console.error(err);
      } else {
        console.log(`CREATED: ${item.description}`);
      }
    });
  });

然后我像这样发送发票:

const invoice = await stripe.invoices.create({
  customer: stripe_cus_id,
  billing: 'send_invoice',
  days_until_due: 15
});

2 个答案:

答案 0 :(得分:1)

我认为预期的行为是将发票项目添加到客户的即将到来的发票中,而不是当前的。

我不确定这是否是您希望的行为,但是要排除一切,我首先会尝试检索客户即将发出的发票。我尝试了3个发票项目(1 + 2 + 3),下一张发票的总金额正确为6

https://api.stripe.com/v1/invoices/upcoming?customer=cus_DQk9sobcA4UnlQ

Postman Representation

答案 1 :(得分:0)

我发现问题与await一起使用Array.prototype.map。 在MDN docs for await中说:

If the value of the expression following 
the await operator is not a Promise, it's
converted to a resolved Promise.

问题在于await之后的值是Array.prototype.map,这不是一个承诺。这导致await过早解决。

我找到了解决此问题的方法here。用Promise.all包装地图可以解决此问题,就像这样:

    await Promise.all(
      req.body.items.map(item => {
        return new Promise(function( resolve, reject) {
          const unitAmount = (item.wholesale_price + (item.shipping_amount/item.quantity) + (item.s_h/item.quantity));
          stripe.invoiceItems.create({
            unit_amount: unitAmount,
            currency: 'usd',
            customer: stripe_cus_id,
            description: item.description,
            quantity: item.quantity
          }, {
            idempotency_key: uuidv4()
          }, function(err, invoiceItem) {
            if(err) {
              console.error(err);
              reject(err);
            } else {
              console.log(`CREATED: ${item.description}`);
              resolve();
            }
          });
        })
      })
    );