../www/get_script_html_files/strip/checkout.py
1 #!/usr/bin/python2
2
3 #######################################
4 #
5 # This is script is for checkout
6 #
7 # Version: 1.9
8 #
9 #######################################
10
11
12 #import all functions from lib.py
13
14 from lib import *
15
16 #get dictionary of values from web form
17
18 form = cgi.FieldStorage()
19
20 try:
21 book_id = int(form['book_id'].value) #get value of variable from web form
22 except:
23 book_id = 0 #if value is not supplied by web form, assign 0
24
25
26 #we'll use variable q for quantity of books
27
28 try:
29 q = int(form['q'].value)
30 except:
31 q = 1
32
33
34 #total amount of payment
35
36 try:
37 total = float(form['total'].value)
38 except:
39 total = 0
40
41 #card number
42
43 try:
44 card_number = form['card_number'].value
45 except:
46 card_number = ''
47
48
49 #card type id
50
51 try:
52 card_type_id = int(form['card_type_id'].value)
53 except:
54 card_type_id = 0
55
56 #function to generate first checkout page
57
58 def get_first_page(book_id,q,total):
59
60 #get title, author and price of the book
61
62 book_info_dict = get_book_info(book_id)
63
64 title = book_info_dict['title']
65 author = book_info_dict['author']
66
67 #get user info
68
69 user_info_dict = get_user_info()
70
71 first_name = user_info_dict['first_name']
72 last_name = user_info_dict['last_name']
73 zip_code = user_info_dict['zip_code']
74 email = user_info_dict['email']
75 street = user_info_dict['street']
76 city = user_info_dict['city']
77 state = user_info_dict['state']
78 country = user_info_dict['country']
79
80 ############we have 3 sub-tables: Book Info & Total, Shipping, Payment
81
82 #this table is for Book Info & Total
83
84 table_1 = """
85
86 <table width=100%>"""
87
88 table_1 = table_1 + """
89
90 <tr>
91
92 <td><h2>Book Info & Total</h2></td>
93
94 </tr>
95
96 <tr align='center' class='yellow_bg'>
97
98
99 <td>author</td><td>title</td><td>quantity</td><td>total</td>
100
101 </tr>
102
103 <tr align='center'>
104
105 <td>%s</td><td><p><b>%s</b></td><td>%s</td><td>%.2f</td>
106
107 </tr>
108
109 </table>""" % (author,title,q,total/100)
110
111 #this table is for Shipping. To make it simple, no user input is possible here
112
113 table_2 = """
114
115 <table class = 'grey_bg'>
116
117 <tr>
118
119 <td><h2>Shipping</h2></td>
120
121 </tr>
122
123 <tr>
124
125 <td>First Name: </td><td><b>%s</b></td>
126
127 </tr>
128
129
130 <tr>
131
132 <td>Last Name: </td><td><b>%s</b></td>
133
134 </tr>
135
136
137 <tr>
138
139 <td>Street: </td><td><b>%s</b></td>
140
141 </tr>
142
143
144 <tr>
145
146 <td>City: </td><td><b>%s</b></td>
147
148 </tr>
149
150
151 <tr>
152
153 <td>State: </td><td><b>%s</b></td>
154
155 </tr>
156
157 <tr>
158
159 <td>Zip code: </td><td><b>%s</b></td>
160
161 </tr>
162
163
164 <tr>
165
166 <td>Country: </td><td><b>%s</b></td>
167
168 </tr>
169
170
171 </table>""" % (first_name,last_name,street,city,state,zip_code,country)
172
173
174 #this table is for Payment. To make it simple, only credit card type and number can be defined.
175
176 table_3 = """
177
178 <table>
179
180 <form action='./checkout.py'>
181
182 <tr>
183
184 <tr colspan=2><h2>Payment</h2></td>
185
186 </tr>
187
188 <input type='hidden' name='book_id' value='%s'>
189 <input type='hidden' name='q' value='%s'>
190 <input type='hidden' name='total' value='%s'>
191
192 <tr><p><font color='red'>Always use <a href='../test_portal.html'>Test Portal</a> \
193 to generate credit cards for this site
194 <p>NEVER insert your real credit card info on this site</font>""" % (book_id,q,total)
195
196
197 #### BUG #1
198 #### Expected: value for MasterCard must be '2' and value for Amex must be '3'
199 #### Actual: value='1' for all cards
200 #### Note 1:
201 #### Until this bug is fixed we'll always have:
202 #### - '1' as a first character of result column in table cc_transactions and
203 #### - 'V' as a card type in cc_transaction_log.txt
204 ####
205 #### Note 2:
206 #### This bug should've prevented users from using MasterCard and AmEx, but because of BUG #2 MasterCard and AmEx
207 #### transactions are successful as long as card number is OK and there is enough balance.
208
209 table_3 = table_3 +"""<td>Card Type: </td>
210 <td>
211 <select name='card_type_id'>
212 <option value='1'>Visa</option>
213 <option value='1'>MasterCard</option>
214 <option value='1'>AmEx</option>
215 </select>
216 </td>
217
218 </tr>
219
220 <tr>
221
222 <td>Card Number: </td><td><input type='text' name='card_number'></td>
223
224 </tr>
225
226 <tr>
227
228 <td>Expiration date: </td><td>
229
230 <select name='month' disabled>
231
232 <option value='1'>01</option>
233 <option value='2'>02</option>
234 <option value='3'>03</option>
235 <option value='4'>04</option>
236 <option value='5'>05</option>
237 <option value='6'>06</option>
238 <option value='7'>07</option>
239 <option value='8'>08</option>
240 <option value='9'>09</option>
241 <option value='10'>10</option>
242 <option value='11'>11</option>
243 <option value='12'>12</option>
244
245 </select> / <select name='year' disabled>
246
247 <option value='2010'>2010</option>
248 <option value='2011'>2011</option>
249 <option value='2012'>2012</option>
250 <option value='2013'>2013</option>
251 <option value='2014'>2014</option>
252
253 </select></td>
254
255 </tr>
256
257 <tr>
258
259 <td>CVV2: </td><td><input type='text' name='card_number' value='387' disabled></td>
260
261 </tr>
262
263 <tr>
264
265 <td></td><td><input type='submit' value='Make Payment'></td>
266
267 </tr>
268
269 </form>
270
271
272 </table>"""
273
274 #this is main table
275
276 table = """<table width=700>
277
278 <tr valign='top'>
279
280 <td colspan=2>%s</td>
281
282 </tr>
283
284 <tr valign='top'>
285
286 <td colspan=2><HR></td>
287
288 </tr>
289
290 <tr valign='top'>
291
292 <td>%s</td><td>%s</td>
293
294 </tr>
295
296
297 </table>
298
299 """ % (table_1,table_2,table_3)
300
301 return table
302
303 #function to populate log file: cc_transaction_log.txt
304
305 #Comma delimited format:
306 #<UNIX timestamp>,
307 #<card type: 'V' for Visa, 'M' for MasterCard, 'A' for AmEx>,
308 #<4 last digits of card number>,
309 #<amount in cents>,
310 #<order id>
311
312 def append_cc_transaction_log(card_type_id,card_number,total,order_id):
313
314 #create UNIX timestamp
315
316 unix_timestamp = str(int(time.time()))
317
318 #get first letter of card type
319
320 sql = "select type from cc_types where id = %s" % card_type_id
321
322 card_type = select_one(sql)[0][0].upper()
323
324 #get four last digits of card number
325
326 card_number=card_number[-4:]
327
328 #create line to append to log file
329
330 line = \
331 unix_timestamp + "," + \
332 card_type + "," + \
333 card_number + "," + \
334 str(total) + "," + \
335 order_id
336
337 #open file, append data to file, close file
338
339 file = open("../www/cc_transaction_log.txt", "a") #note "a": file is being appended
340
341 print >> file, line
342
343 file.close()
344
345 return 0
346
347
348 #function to insert new row into cc_transactions
349 #ccp_result is value returned from credit card processor. 0 is success. 1 is failure.
350
351 def insert_into_cc_transactions(card_type_id,ccp_result,user_id,order_id=0): #by default order_id = 0
352
353
354 #get result to insert into DB
355
356 result = str(card_type_id)+str(ccp_result)
357
358 #insert new row into cc_transactions
359
360 sql = "insert into cc_transactions (result,user_id,order_id) values (%s,%s,%s)" % \
361 (result,user_id,order_id)
362
363 update(sql)
364
365 return 0
366
367 #function to create order in DB and get order_id
368
369 def create_order(card_type_id,card_number,user_id,book_id,q,total):
370
371 #create order in DB
372
373 sql = "insert into orders (user_id,book_id,quantity,total,time_created) values \
374 (%s,%s,%s,%s,NOW())" % (user_id,book_id,q,total)
375
376 update(sql)
377
378 #extract unique order id
379
380 sql = "select max(id) from orders where user_id = %s" % user_id
381
382 order_id = select_one(sql)[0]
383
384 return order_id
385
386
387 #Function to generate html of confirmation page
388
389 def get_confirmation_page(order_id):
390
391 table="""
392
393 <table width='300' align='center'>
394
395 <tr>
396 <td><br></td>
397 </tr>
398
399 <tr>
400 <td><p><font color='green'><b>Thank you for your order!!!</b></font></td>
401 </tr>
402
403 <tr>
404 <td><br></td>
405 </tr>
406
407 <tr>
408 <td><p>Order id: <b>%s</b></td>
409 </tr>
410
411 <tr>
412 <td ><b>NOTE TO TESTER: </b>This order will be deleted from DB at 00 minutes next hour. For example, if now it's 14:12, it'll be deleted at 15:00</td>
413
414 </tr>
415
416 <tr>
417 <td><br></td>
418 </tr>
419
420 </table>
421
422 """ % order_id
423
424 return table
425
426 #execute code below if this script is run as standalone script
427 #don't execute code below if we import functions from this script
428
429 if __name__ == "__main__":
430
431 ############check if user is logged in
432
433 is_logged_in = is_logged_in()
434
435 ############logical part
436
437 if is_logged_in == 0:
438
439 user_id = get_user_info()['user_id']
440
441 if card_type_id == 0:
442
443 body_html = get_first_page(book_id,q,total)
444 message = ''
445
446 else:
447
448
449 #### BUG #2
450 #### Expected: function get_ccp_result() should check if card_number matches card_type_id
451 #### Actual: you can provide valid MasterCard number, but select 'VISA' and transaction will be successful.
452
453 #BTW, code of function get_ccp_result() is black box for testers
454
455 ccp_result = get_ccp_result(card_number,card_type_id,total)
456
457 if ccp_result == 1:
458
459 insert_into_cc_transactions(card_type_id,ccp_result,user_id)
460 body_html = get_first_page(book_id,q,total)
461 message = "Oops, error. Invalid card number or not enough balance for purchase"
462
463 else:
464
465 #create new order
466
467 order_id = create_order(card_type_id,card_number,user_id,book_id,q,total)
468
469 #append log file
470
471 append_cc_transaction_log(card_type_id,card_number,total,order_id)
472
473 #update cc_transactions
474
475 insert_into_cc_transactions(card_type_id,ccp_result,user_id,order_id)
476
477 #generate confirmation
478
479 body_html = get_confirmation_page(order_id)
480
481 message = ''
482
483
484 else:
485 body_html = ''
486 message = "Oops, error. You must log in"
487
488 #############generate and print html
489
490 print 'Content-Type: text/html\n\n'
491
492 caption = 'Checkout'
493
494 html=get_html(is_logged_in,body_html,caption,message)
495
496 print html
497