stripe: Use context managers for error handling in cgi
[hcoop/portal.git] / stripe / stripe-payment.cgi
1 #!/usr/bin/env python
2 # -*- python -*-
3
4 import sys
5 sys.path.insert(0, '/afs/hcoop.net/user/h/hc/hcoop/portal3/stripe/stripe-pkg/lib/python2.6/site-packages/')
6
7 import stripe, cgi, psycopg2, cgitb, datetime, smtplib
8 from email.mime.text import MIMEText
9 from contextlib import contextmanager
10
11 cgitb.enable()
12
13 def notify_payment (charge, member):
14 msg_text = """
15 A member has paid us via Stripe. Please visit the portal money
16 page at your earliest convenience to process the payment.
17
18 Member : {0}
19 Amount (cents) : {1}
20 Stripe Charge ID: {2}
21 """.format (member, charge.amount, charge.id)
22
23 msg = MIMEText(msg_text)
24 msg['Subject'] = 'Stripe payment received from {0}'.format(member)
25 msg['From'] = 'payment@hcoop.net'
26 msg['To'] = 'payment@hcoop.net'
27
28 s = smtplib.SMTP ('mail.hcoop.net')
29 s.sendmail ('payment@hcoop.net', ['payment@hcoop.net'], msg.as_string ())
30 s.quit ()
31
32 def stripe_key ():
33 keyfile = open ("/afs/hcoop.net/user/h/hc/hcoop/.portal-private/stripe", "r")
34 keystring = keyfile.read ()
35 keyfile.close ()
36 return keystring
37
38
39 @contextmanager
40 def stripe_error_handling ():
41 try:
42 yield
43 except stripe.error.CardError, e: # The card has been declined
44 print 'Status: 200 OK'
45 print
46 print '<html>'
47 print '<head><title>Transaction Failed</title></head>'
48 print '<body>'
49 print '<h1>Failed</h1><p>Reason: '
50 print e.json_body['error']['message']
51 print '</p>'
52 print '</body>'
53 print '</html>'
54 raise
55
56 @contextmanager
57 def stripe_refund_on_error (charge):
58 try:
59 yield
60 except:
61 print 'Status: 200 OK'
62 print 'Content-Type: text/html'
63 print ''
64 print '<h1>Something went wrong after accepting payment!</h1>'
65 charge.refund ()
66 print '<p>The charge should be refunded. Please contact payment@hcoop.net if it was not!</p>'
67 raise
68
69 # Set your secret key: remember to change this to your live secret key in production
70 # See your keys here https://manage.stripe.com/account
71
72 stripe.api_key = stripe_key ()
73
74 # Get the credit card details submitted by the form
75
76 request_params = cgi.FieldStorage()
77
78 token = request_params.getvalue ('stripeToken')
79 webuser_id = request_params.getvalue('webuser_id')
80 member_name = request_params.getvalue('webuser_name')
81 amount = request_params.getvalue('stripeDues')
82
83 # Create the charge on Stripe's servers - this will charge the user's card
84
85 with stripe_error_handling ():
86 charge = stripe.Charge.create( amount=amount,
87 currency="usd",
88 card=token,
89 description='Payment for member {0}'.format (member_name))
90
91 with stripe_refund_on_error (charge):
92 with psycopg2.connect ('dbname=hcoop_portal3test user=hcoop host=postgres port=5433') as conn:
93 with conn.cursor () as cur:
94 balance = stripe.BalanceTransaction.retrieve (charge.balance_transaction);
95 cur.execute ('insert into stripe_payment (charge_id, card_name, webuser_id, paid_on, gross, fee) values (%s, %s, %s, %s, %s, %s)',
96 (charge.id, charge.card.name, webuser_id, datetime.date.today (), charge.amount, balance.fee))
97
98 notify_payment (charge, member_name)
99 print 'Status: 303 See Other'
100 print 'Location: /portal/portal?cmd=stripeSuccess'
101 print ''
102 print '<a href="/portal/portal?cmd=stripeSuccess">Go back to the portal</a>'
103