I'm running a small business that uses Stripe for accepting payments from users.
While the Stripe dashboard is quite useful, it doesn't provide a quick way to download invoice PDF files for accounting purposes.
So, I wrote a batch script to do so:
import initStripe from 'stripe'
import path from 'path'
import fs from 'fs'
import { exec } from 'child_process'
import moment from 'moment'
const stripe = initStripe('sk_live_****************')
function log(...args) {
const datetime = moment().format('YYYY-MM-DDTHH:mm:ss')
console.log.apply(console, [datetime, ...args])
}
async function run() {
let starting_after = undefined
let res
do {
res = await stripe.invoices.list({
created: {
gte: new Date('2020-01-01T00:00:00'),
lt: new Date('2020-12-31T23:59:59')
},
starting_after,
limit: 10
})
const items = res.data
log('got', items.length, 'items', { starting_after })
await Promise.all(
items.map(async (invoice) => {
try {
if (invoice.amount_paid <= 0) return
if (invoice.status !== 'paid') {
log('Invoice is not paid:', invoice.id, invoice.status)
return
}
log('Processing invoice:', invoice.id)
const paidAt = new Date(invoice.status_transitions.paid_at * 1000)
const dest = path.resolve(
__dirname,
'invoices',
'2020',
moment(paidAt).format('YYYYMMDD-') + invoice.id + '.pdf'
)
if (fs.existsSync(dest)) return
const res = await new Promise((resolve, reject) =>
exec(
`/usr/local/bin/wget '${invoice.invoice_pdf}' -O '${dest}'`,
(err, stdout, _stderr) => {
err ? reject(err) : resolve(stdout)
}
)
)
log('Downloaded:', dest, res)
} catch (e) {
log(e.stack)
log('Failed to process invoice:', invoice)
throw e
}
})
)
starting_after = items[items.length - 1].id
} while (res.has_more)
}
run().then(
function () {
log('DONE')
},
function (err) {
log('ERROR:', err.stack || err)
if (err.response) {
log(err.response)
}
}
)
How it works
It retrieves a list of the invoices of the given term by specifying created.gte
and created.lt
parameters:
res = await stripe.invoices.list({
created: {
gte: new Date('2020-01-01T00:00:00'),
lt: new Date('2020-12-31T23:59:59')
},
starting_after,
limit: 10
})
In this example, it retrieves all the invoices issued in 2020.
It only processes the invoices with paid status by checking invoice.status
and invoice.amount_paid
.
An invoice data has invoice_pdf
field, which is a URL to the invoice PDF.
Since downloading a PDF takes time because Stripe generates it on-demand, the script processes up to 10 items at once.
Then, it downloads to ./invoices/2020/
. You can change it.
Hope that helps!
Top comments (2)
Hello! Thanks in advance for this! Im wondering how do i run the script. Im working in macos and tried compiling with node but is not working. Can you guide me so i can test it with my account? Thanks again!
Bravo!
There were a few adjustments needed to make it work on Windows (especially tricky was understanding I had to remove the single quotes in the wget command), but thank you!