Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download
Views: 39588
1
###
2
Render a stripe invoice/receipt using pdfkit = http://pdfkit.org/
3
###
4
5
path = require('path')
6
fs = require('fs')
7
async = require('async')
8
9
misc = require('smc-util/misc')
10
theme = require('smc-util/theme')
11
{DOMAIN_NAME, COMPANY_NAME, BILLING_EMAIL, SITE_NAME, BILLING_ADDRESS, BILLING_TAXID} = theme
12
13
misc_node = require('smc-util-node/misc_node')
14
15
WEBAPP_LIB = misc_node.WEBAPP_LIB
16
17
exports.stripe_render_invoice = (stripe, invoice_id, download, res) ->
18
if not stripe?
19
# stripe not available, configured or initaialized yet
20
res.status(404).send("stripe not available")
21
return
22
invoice = undefined
23
customer = undefined
24
charge = undefined
25
async.series([
26
(cb) ->
27
stripe.invoices.retrieve invoice_id, (err, x) ->
28
invoice = x; cb(err)
29
(cb) ->
30
stripe.customers.retrieve invoice.customer, (err, x) ->
31
customer = x; cb(err)
32
(cb) ->
33
if not invoice.paid
34
# no time paid
35
cb()
36
else if not invoice.charge
37
# there was no charge (e.g., a trial)
38
cb()
39
else
40
stripe.charges.retrieve invoice.charge, (err, x) ->
41
charge = x; cb(err)
42
(cb) ->
43
render_invoice_to_pdf(invoice, customer, charge, res, download, cb)
44
], (err) ->
45
if err
46
res.status(404).send(err)
47
)
48
49
render_invoice_to_pdf = (invoice, customer, charge, res, download, cb) ->
50
PDFDocument = require('pdfkit')
51
doc = new PDFDocument
52
53
# Use a unicode friendly font: see http://stackoverflow.com/questions/18718559/how-to-output-euro-symbol-in-pdfkit-for-nodejs
54
# This should just be in our git repo, so should work.
55
font = "#{__dirname}/fonts/Cardo-Regular.ttf"
56
if fs.existsSync(font)
57
doc.registerFont('Cardo', font)
58
doc.font('Cardo')
59
60
if download
61
res.setHeader('Content-disposition', 'attachment')
62
63
doc.pipe(res)
64
65
doc.image(path.join(process.env.SMC_ROOT, "#{WEBAPP_LIB}/android-chrome-192x192.png"), 268, 15, {width: 64, align: 'center'})
66
y = 100
67
c1 = 100
68
if invoice.paid
69
doc.fontSize(35).text("#{COMPANY_NAME} - Receipt", c1, y)
70
else
71
doc.fontSize(35).text("#{COMPANY_NAME} - Invoice", c1, y)
72
73
y += 60
74
c2 = 260
75
doc.fontSize(14)
76
doc.fillColor('#555')
77
doc.text("Date", c1, y)
78
doc.text("ID")
79
doc.text("Name")
80
doc.text("Email")
81
if invoice.paid
82
doc.text("Card charged")
83
84
doc.fillColor('black')
85
doc.text(misc.stripe_date(invoice.date), c2, y)
86
#doc.text(invoice.id.slice(invoice.id.length-6).toLowerCase())
87
doc.text("#{invoice.date}")
88
doc.text(customer.description)
89
doc.text(customer.email)
90
if invoice.paid and charge?.source?
91
doc.text("#{charge.source.brand} ending #{charge.source.last4}")
92
93
y += 120
94
doc.fontSize(24).text("Items", c1, y)
95
96
y += 40
97
doc.fontSize(12)
98
v = []
99
for x in invoice.lines.data
100
if x.description
101
desc = misc.trunc(x.description, 60)
102
else if x.plan?
103
desc = x.plan.name
104
else
105
desc = "#{SITE_NAME} services"
106
v.push
107
desc : desc
108
amount : "USD $#{x.amount/100}"
109
if invoice.tax
110
v.push
111
desc : "Sales Tax"
112
amount : "USD $#{invoice.tax/100}"
113
114
for i in [0...v.length]
115
if i == 0
116
doc.text("#{i+1}. #{v[i].desc}", c1, y)
117
else
118
doc.text("#{i+1}. #{v[i].desc}")
119
doc.moveDown()
120
if invoice.paid
121
doc.text("PAID")
122
else
123
doc.text("DUE")
124
125
for i in [0...v.length]
126
if i == 0
127
doc.text(v[i].amount, c2+100+90, y)
128
else
129
doc.text(v[i].amount)
130
doc.moveDown()
131
doc.text("USD $#{invoice.total/100}")
132
133
y += 300
134
doc.fontSize(12)
135
doc.text("#{BILLING_ADDRESS.split('\n').join(', ')} -- #{BILLING_TAXID}", c1, y)
136
doc.moveDown()
137
doc.text("Contact us with any questions by emailing #{BILLING_EMAIL}.")
138
doc.moveDown()
139
doc.fontSize(14)
140
if not invoice.paid
141
doc.text("To pay, sign into your account at #{DOMAIN_NAME} and add a payment method in the billing tab under account settings.")
142
else
143
doc.text("Thank you for using #{SITE_NAME} -- #{DOMAIN_NAME}.")
144
145
doc.end()
146
cb()
147
148