DEV Community

Takuya Matsuyama
Takuya Matsuyama

Posted on

A batch-JS for downloading invoice PDFs from Stripe

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) } } ) 
Enter fullscreen mode Exit fullscreen mode

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 }) 
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
luchodamico profile image
Luciano

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!

Collapse
 
lafaa profile image
Lafaa

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!