Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jBenes
Last active July 6, 2016 22:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jBenes/636fa89e52b47dc5d20d to your computer and use it in GitHub Desktop.
Save jBenes/636fa89e52b47dc5d20d to your computer and use it in GitHub Desktop.
import requests
import ujson
from pprint import pprint
from random import SystemRandom
from string import digits, ascii_uppercase
from time import sleep
possible_characters = ascii_uppercase + digits
def gp(length=32):
"""Generate a random string using the OS"""
rng = SystemRandom()
return "".join([rng.choice(possible_characters) for i in range(length)])
def gen_udid():
"""
ZooZ-UDID should identify the user to prevent fraud. As we are doing the fraud detection on our side, this can be a random string.
Sample ZooZ-UDID: A6092EF-ASCX-ASDE-NKSD-AB75129B9375"""
udid = "zooz_%s-%s-%s-%s-%s" % (gp(8), gp(4), gp(4), gp(4), gp(12) )
return udid
def check_flights():
"""
Confirms the price of the flights
Use the realtime parameter to get the fastest possible response
The response is shortly described in the gist file below. Though, most of
the values in the response can be ignored by our partners.
The most important fields are only total, which is the total price and flights_invalid, which should be False.
"""
parameters = {
'v':2, # default
'pnum':1, # passenger number
'bnum':1, # bags number
'booking_token':"bcEuJfu3fWne+z+50B2d1FLlFWEq6njGjUEUpGFn1DvjlNr7ieM4H5cvU6x9XSmssAVHCS1pt3KjNQ2VnuHSpJl+t6nAsPvJlPJkF1OOMNALHDt6Pmjk1C118CuA4iD1aB3B113leGOLKfeW0t3sDglcz4+DVwbaUFs/cqd37ZjTTFw4gMXalcgMG+KyZ1Rw6YIXWZrN2cxX+GXn1YjfMw==",
'affily':'dohop', # affiliate ID
'booked_at':'dohop', # booked at site ID
'realtime': True # set to True for cases, when check flights cant be repeated or you want the response asap
}
print 'check_flights start'
response = requests.get('https://api.skypicker.com/api/v0.1/check_flights', params=parameters ).json()
print 'check_flights response'
pprint(response)
# flights must be checked and cannot be invalid
return response['flights_checked'] and not response['flights_invalid']
def save_booking():
"""Initiates the booking on Skypicker backend
The specified data is sent to the API as a json payload
The data sent to this API call should be confirmed before by the check_flights call
Response from save_booking is nearly the same as from check_flights, with the following parameters added
{ 'transaction_id': False,
'zooz_token': '4XWBRXPFUD4YSXXPGBKEUNSKR4', // use this token to send credit card data to Zooz
'booking_id': 47808, // the unique booking identified (this ID will be also passed in the callbacks to identify the booking)
'sandbox': True, // indicates if the payment is processed in a sandbox mode. Can be also triggered by using Test Test as a passenger name
'status': 'success'
}
"""
data = {
"lang":"en", # user language
"bags":0, # number of bags
"passengers":[ # array with passengers data
{
"surname":"test",
"cardno":None, # ID card/passport ID. In case, check flights will return document_options.document_need 2,
#this needs to be filled in by the user togerther with the expiration field. Otherwise, those field can stay hidden from the booking form to increase conversion rate
"phone":"+44 564564568456", # needed only for the first passenger in the array
"birthday":724118400, # passenger birth day, utc unix timestamp in seconds
"nationality":"United Kingdom",
"checkin":"REMOVED, DEPRECATED", # DEPRECATED, leave an empty string here
"issuer":"REMOVED, DEPRECATED", # DEPRECATED, leave an empty string here
"name":"test",
"title":"mr", # mr/ms/mrs
"expiration":None, # expiration date of the ID from the cardno field
"email":"lubos@skypicker.com" # needed only for the first passenger in the array
}
],
"locale":"en",
"customerLoginID":"unknown", # loginID for zooz payments
"currency":"czk", # SP only
'booking_token':'bcEuJfu3fWne+z+50B2d1FLlFWEq6njGjUEUpGFn1DvjlNr7ieM4H5cvU6x9XSmssAVHCS1pt3KjNQ2VnuHSpJl+t6nAsPvJlPJkF1OOMNALHDt6Pmjk1C118CuA4iD1aB3B113leGOLKfeW0t3sDglcz4+DVwbaUFs/cqd37ZjTTFw4gMXalcgMG+KyZ1Rw6YIXWZrN2cxX+GXn1YjfMw==',
"customerLoginName":"unknown", # login name for zooz payments
"affily":"dohop", # affil id, can contain any subID string, max length 64
"booked_at":"dohop", # basic affil id, without any subIDs
}
url = "https://api.skypicker.com/api/v0.1/save_booking?v=2"
print 'save_booking start'
response = requests.post(url,data = ujson.dumps(data)).json()
pprint(response)
print 'save_booking response'
return response
def zooz_init(response):
"""
Sends credit card data to zooz
'responseStatus': 0 in the response means success
"""
uuid = gen_udid()
headers = {
"productType":"Checkout API",
"ZooZ-Token":response["zooz_token"],
"ZooZ-UDID":gen_udid(),
"deviceSignature":gen_udid(),
"ZooZResponseType":"JSon",
"programId":"dohop2"
}
url_zooz = "https://sandbox.zooz.co/mobile/ZooZClientPaymentAPI" # use app.zooz.com for production
init_data = {"cmd":"init","paymentToken":response["zooz_token"]}
print 'zooz_init start'
init_response = requests.post(url_zooz,data = ujson.dumps(init_data),headers = headers).json()
print 'zooz_init response'
pprint(init_response)
add_payment_method_data = {
"cmd":"addPaymentMethod",
"paymentToken":response["zooz_token"],
"paymentMethod":{
"paymentMethodType":"CreditCard",
"paymentMethodDetails":{
"cardNumber":"4580458045804580",
"cardHolderName":"testtest",
"expirationDate":"12/2015",
"cvvNumber":"321"
},
},
"email":"lubos@skypicker.com",
"configuration": {
"rememberPaymentMethod":True
},
}
print 'zooz_add_payment start'
add_payment_response = requests.post(url_zooz,data = ujson.dumps(add_payment_method_data),headers = headers).json()
print 'zooz_add_payment response'
pprint(add_payment_response)
return add_payment_response
def confirm_to_skypicker(response,add_payment_response):
"""Confirms the successful sending of cc data and requests a charge on the credit card for the amount sent on save_booking
Successful response {'status': 0} (the payment is done and the booking will be processed)
Error response {'msg': u'server error', 'status': u'error'}
"""
confirm_payment_data = dict(
paymentToken=response["zooz_token"],
paymentMethodToken=add_payment_response["responseObject"]["paymentMethodToken"],
)
print 'confirm_to_skypicker start'
final = requests.post("https://api.skypicker.com/api/v0.1/confirm_payment", data = confirm_payment_data).json()
print 'confirm_to_skypicker response'
pprint(final)
return final
#trigger the first check flight to refresh the price and sleep for a few seconds. Needed until the realtime=True parameter is not on production
check_flights()
sleep(5)
#check if the flight is Valid for booking
if check_flights():
#request a Booking ID and a zooz token for initializing the payment
response = save_booking()
#init the payment on zooz
zooz_response = zooz_init(response)
#confirm success. Only response status 0 means the payment will be successful
if zooz_response['responseStatus'] == 0:
confirmation = confirm_to_skypicker(response,zooz_response)
if confirmation['status'] == 0:
print '=== Booking is successfully paid ==='
else:
print '=== Error: booking is not paid ==='
else:
print '=== Error: Zooz init failed ==='
else:
print '=== Error: check flights is probably Invalid ==='
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment