Reputation: 41
Sending an invoice with one invoice item works fine, but things get a bit hairy when I try an send an invoice with many invoice items.
At times multiple invoices gets sent correctly, but often one of the invoice items is missing in the invoice, but get's included in the next invoice. Or at times I will get an error message of: Error: Nothing to invoice for customer
, even thought I had just ran stripe.invoiceItems.create
. Has anyone else ran into this issue?
To create multiple invoice items I have logic like this:
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}`);
}
});
});
Then I send the invoice like so:
const invoice = await stripe.invoices.create({
customer: stripe_cus_id,
billing: 'send_invoice',
days_until_due: 15
});
Upvotes: 1
Views: 2360
Reputation: 41
I have discovered the issue to be using await
with Array.prototype.map
.
In MDN docs for await it says:
If the value of the expression following
the await operator is not a Promise, it's
converted to a resolved Promise.
The problem was that the value following await
was Array.prototype.map
, and it is not a promise. This caused the await
to resolve prematurely.
I found a solution to this issue here. Wrapping my map in a Promise.all
fixed the issue, like so:
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();
}
});
})
})
);
Upvotes: 1
Reputation: 101
I think the expected behaviour is that invoice items are added to the customer's upcoming invoice not the current.
I'm not sure that is the behaviour you're hoping for but to rule things out I would first try to retrieve the customer's upcoming invoice. I tried it with 3 invoice items (1+2+3) and the total amount in the upcoming invoice was correct at 6
https://api.stripe.com/v1/invoices/upcoming?customer=cus_DQk9sobcA4UnlQ
Upvotes: 1