Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | Last revisionBoth sides next revision | ||
integration:python [2017/06/01 04:31] – [Code] marija | integration:python [2017/06/01 04:36] – marija | ||
---|---|---|---|
Line 3: | Line 3: | ||
systems | systems | ||
name : Python Datafeed Classes # the name of the integration | name : Python Datafeed Classes # the name of the integration | ||
- | description | + | description |
tags : python | tags : python | ||
date_dt | date_dt | ||
Line 359: | Line 359: | ||
data = FoxyData.from_crypted_str(urllib.unquote_plus(request.POST[' | data = FoxyData.from_crypted_str(urllib.unquote_plus(request.POST[' | ||
</ | </ | ||
+ | |||
+ | ===== Python 3 Example Code ===== | ||
+ | view.py | ||
+ | <code python> | ||
+ | """ | ||
+ | Example Django view for receiving and decrypting datafeed. | ||
+ | """ | ||
+ | ## My View, I have a session variable I submit to foxy cart, that's my booking_id. | ||
+ | |||
+ | @csrf_exempt | ||
+ | def FoxyCartIPNView(request): | ||
+ | if request.POST and ' | ||
+ | try: | ||
+ | # IMPORTANT: unquote_plus is necessary for the non-ASCII binary that | ||
+ | # FoxyCart sends. | ||
+ | # MKR als important to set the encoding when using python3! | ||
+ | |||
+ | data = FoxyData.from_crypted_str((unquote_plus(request.POST[' | ||
+ | | ||
+ | |||
+ | for transaction in data.transactions: | ||
+ | |||
+ | # get the booking id, and verify it so BMCM can see it in admin | ||
+ | # also save foxy's xml for archive purposes, finally, we mail the customer. | ||
+ | booking = transaction.booking_id | ||
+ | booking = RetreatBooking.objects.get(pk=booking) | ||
+ | booking.verified_transaction = True | ||
+ | booking.foxycart_xml = data.markup | ||
+ | booking.save() | ||
+ | |||
+ | mail_customer(request, | ||
+ | print(" | ||
+ | |||
+ | return HttpResponse(' | ||
+ | |||
+ | |||
+ | except: | ||
+ | # Something went wrong, handle the error... right? :P | ||
+ | raise | ||
+ | |||
+ | return HttpResponseForbidden(' | ||
+ | |||
+ | |||
+ | ## my utils for the view - Python 3 compatible! | ||
+ | |||
+ | class ARC4: | ||
+ | def __init__(self, | ||
+ | self.state = list(range(256)) # Initialize state array with values 0 .. 255 | ||
+ | self.x = self.y = 0 # Our indexes. x, y instead of i, j | ||
+ | |||
+ | if key is not None: | ||
+ | self.init(key) | ||
+ | |||
+ | # KSA | ||
+ | def init(self, key): | ||
+ | for i in list(range(256)): | ||
+ | self.x = (ord(key[i % len(key)]) + self.state[i] + self.x) & 0xFF | ||
+ | self.state[i], | ||
+ | self.x = 0 | ||
+ | |||
+ | # PRGA | ||
+ | def crypt(self, input): | ||
+ | output = [None]*len(input) | ||
+ | for i in range(len(input)): | ||
+ | self.x = (self.x + 1) & 0xFF | ||
+ | self.y = (self.state[self.x] + self.y) & 0xFF | ||
+ | self.state[self.x], | ||
+ | r = self.state[(self.state[self.x] + self.state[self.y]) & 0xFF] | ||
+ | output[i] = chr(ord(input[i]) ^ r) | ||
+ | return '' | ||
+ | |||
+ | @classmethod | ||
+ | def from_crypted_str(self, | ||
+ | a = ARC4(crypt_key) | ||
+ | return FoxyData.from_str(a.crypt(data_str)) | ||
+ | |||
+ | |||
+ | class FoxyData: | ||
+ | DateFmt = ' | ||
+ | DateTimeFmt = ' | ||
+ | |||
+ | class Transaction: | ||
+ | def __init__(self, | ||
+ | def extract_kv_node(node, | ||
+ | # print(' | ||
+ | el = node.getElementsByTagName(key_name) | ||
+ | return len(el) > 0 and el[0].firstChild.data or '' | ||
+ | |||
+ | self.id = extract_kv_node(node, | ||
+ | self.date = datetime.strptime( | ||
+ | extract_kv_node(node, | ||
+ | self.customer_id = extract_kv_node(node, | ||
+ | self.customer_email = extract_kv_node(node, | ||
+ | |||
+ | self.attributes = attrs = {} | ||
+ | self.items = items = attrs[' | ||
+ | |||
+ | self.custom_fields = attrs[' | ||
+ | for custom_field in node.getElementsByTagName(' | ||
+ | self.custom_fields[extract_kv_node(custom_field, | ||
+ | extract_kv_node(custom_field, | ||
+ | |||
+ | # import pdb; | ||
+ | self.booking_id = self.custom_fields.get(' | ||
+ | |||
+ | self.transaction_details = attrs[' | ||
+ | |||
+ | |||
+ | def __init__(self, | ||
+ | self.markup = markup | ||
+ | self.doc = parseString(self.markup) | ||
+ | self.transactions = [] | ||
+ | |||
+ | for transaction in self.doc.getElementsByTagName(' | ||
+ | self.transactions.append(FoxyData.Transaction(transaction)) | ||
+ | |||
+ | |||
+ | def __str__(self): | ||
+ | return str(self.markup) | ||
+ | |||
+ | |||
+ | @classmethod | ||
+ | def from_str(self, | ||
+ | return FoxyData(data_str) | ||
+ | |||
+ | |||
+ | """ | ||
+ | Given a string containing RC4-crypted FoxyCart datafeed XML and the | ||
+ | cryptographic key, decrypt the contents and create a FoxyData object | ||
+ | containing all of the Transactions in the data feed. | ||
+ | """ | ||
+ | |||
+ | @classmethod | ||
+ | def from_crypted_str(self, | ||
+ | a = ARC4(crypt_key) | ||
+ | return FoxyData.from_str(a.crypt(data_str)) | ||
+ | |||
+ | |||
+ | def __len__(self): | ||
+ | return len(self.transactions)</ | ||
+ |