checkout.py

<---Back

Select Code Highlighting Style:

Bright | SEASHELL | Darkness

Select Font Size:

Small | Normal | Large

View bugs:

BUG #1

BUG #2

../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