Created
October 11, 2017 14:25
-
-
Save neilbradley/b5b7d0621065f08a2abf7703bced9ee0 to your computer and use it in GitHub Desktop.
sharedapps/eway/payment.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os, logging | |
import requests | |
import json | |
from django.conf import settings | |
RESPONSE_CODES = { | |
'F7000': "Undefined Fraud", | |
'V5000': "Undefined System", | |
'A0000': "Undefined Approved", | |
'A2000': "Transaction Approved", | |
'A2008': "Honour With Identification", | |
'A2010': "Approved For Partial Amount", | |
'A2011': "Approved VIP", | |
'A2016': "Approved Update Track 3", | |
'V6000': "Undefined Validation", | |
'V6001': "Invalid Request CustomerIP", | |
'V6002': "Invalid Request DeviceID", | |
'V6011': "Invalid Payment Amount", | |
'V6012': "Invalid Payment InvoiceDescription", | |
'V6013': "Invalid Payment InvoiceNumber", | |
'V6014': "Invalid Payment InvoiceReference", | |
'V6015': "Invalid Payment CurrencyCode", | |
'V6016': "Payment Required", | |
'V6017': "Payment CurrencyCode Required", | |
'V6018': "Unknown Payment CurrencyCode", | |
'V6021': "Cardholder Name Required", | |
'V6022': "Card Number Required", | |
'V6023': "CVN Required", | |
'V6031': "Invalid Card Number", | |
'V6032': "Invalid CVN", | |
'V6033': "Invalid Expiry Date", | |
'V6034': "Invalid Issue Number", | |
'V6035': "Invalid Start Date", | |
'V6036': "Invalid Month", | |
'V6037': "Invalid Year", | |
'V6040': "Invalid Token Customer Id", | |
'V6041': "Customer Required", | |
'V6042': "Customer First Name Required", | |
'V6043': "Customer Last Name Required", | |
'V6044': "Customer Country Code Required", | |
'V6045': "Customer Title Required", | |
'V6046': "Token Customer ID Required", | |
'V6047': "RedirectURL Required", | |
'V6051': "Invalid Customer First Name", | |
'V6052': "Invalid Customer Last Name", | |
'V6053': "Invalid Customer Country Code", | |
'V6054': "Invalid Customer Email", | |
'V6055': "Invalid Customer Phone", | |
'V6056': "Invalid Customer Mobile", | |
'V6057': "Invalid Customer Fax", | |
'V6058': "Invalid Customer Title", | |
'V6059': "Redirect URL Invalid", | |
'V6060': "Redirect URL Invalid", | |
'V6061': "Invalid Customer Reference", | |
'V6062': "Invalid Customer CompanyName", | |
'V6063': "Invalid Customer JobDescription", | |
'V6064': "Invalid Customer Street1", | |
'V6065': "Invalid Customer Street2", | |
'V6066': "Invalid Customer City", | |
'V6067': "Invalid Customer State", | |
'V6068': "Invalid Customer Postalcode", | |
'V6069': "Invalid Customer Email", | |
'V6070': "Invalid Customer Phone", | |
'V6071': "Invalid Customer Mobile", | |
'V6072': "Invalid Customer Comments", | |
'V6073': "Invalid Customer Fax", | |
'V6074': "Invalid Customer Url", | |
'V6075': "Invalid ShippingAddress FirstName", | |
'V6076': "Invalid ShippingAddress LastName", | |
'V6077': "Invalid ShippingAddress Street1", | |
'V6078': "Invalid ShippingAddress Street2", | |
'V6079': "Invalid ShippingAddress City", | |
'V6080': "Invalid ShippingAddress State", | |
'V6081': "Invalid ShippingAddress PostalCode", | |
'V6082': "Invalid ShippingAddress Email", | |
'V6083': "Invalid ShippingAddress Phone", | |
'V6084': "Invalid ShippingAddress Country", | |
'V6091': "Unknown Country Code", | |
'V6092': "Undefined Error - clarify meaning of this error", | |
'V6100': "Invalid ProcessRequest name", | |
'V6101': "Invalid ProcessRequest ExpiryMonth", | |
'V6102': "Invalid ProcessRequest ExpiryYear", | |
'V6103': "Invalid ProcessRequest StartMonth", | |
'V6104': "Invalid ProcessRequest StartYear", | |
'V6105': "Invalid ProcessRequest IssueNumber", | |
'V6106': "Invalid ProcessRequest CVN", | |
'V6107': "Invalid ProcessRequest AccessCode", | |
'V6108': "Invalid ProcessRequest CustomerHostAddress", | |
'V6109': "Invalid ProcessRequest UserAgent", | |
'V6110': "Invalid ProcessRequest Number", | |
'D4401': "Refer to Issuer", | |
'D4402': "Refer to Issuer, special", | |
'D4403': "No Merchant", | |
'D4404': "Pick Up Card", | |
'D4405': "Do Not Honour", | |
'D4406': "Error", | |
'D4407': "Pick Up Card, Special", | |
'D4409': "Request In Progress", | |
'D4412': "Invalid Transaction", | |
'D4413': "Invalid Amount", | |
'D4414': "Invalid Card Number", | |
'D4415': "No Issuer", | |
'D4419': "Re-enter Last Transaction", | |
'D4421': "No Method Taken", | |
'D4422': "Suspected Malfunction", | |
'D4423': "Unacceptable Transaction Fee", | |
'D4425': "Unable to Locate Record On File", | |
'D4430': "Format Error", | |
'D4431': "Bank Not Supported By Switch", | |
'D4433': "Expired Card, Capture", | |
'D4434': "Suspected Fraud, Retain Card", | |
'D4435': "Card Acceptor, Contact Acquirer, Retain Card", | |
'D4436': "Restricted Card, Retain Card", | |
'D4437': "Contact Acquirer Security Department, Retain Card", | |
'D4438': "PIN Tries Exceeded, Capture", | |
'D4439': "No Credit Account", | |
'D4440': "Function Not Supported", | |
'D4441': "Lost Card", | |
'D4442': "No Universal Account", | |
'D4443': "Stolen Card", | |
'D4444': "No Investment Account", | |
'D4451': "Insufficient Funds", | |
'D4452': "No Cheque Account", | |
'D4453': "No Savings Account", | |
'D4454': "Expired Card", | |
'D4455': "Incorrect PIN", | |
'D4456': "No Card Record", | |
'D4457': "Function Not Permitted to Cardholder", | |
'D4458': "Function Not Permitted to Terminal", | |
'D4460': "Acceptor Contact Acquirer", | |
'D4461': "Exceeds Withdrawal Limit", | |
'D4462': "Restricted Card", | |
'D4463': "Security Violation", | |
'D4464': "Original Amount Incorrect", | |
'D4466': "Acceptor Contact Acquirer, Security", | |
'D4467': "Capture Card", | |
'D4475': "PIN Tries Exceeded", | |
'D4482': "CVV Validation Error", | |
'D4490': "Cutoff In Progress", | |
'D4491': "Card Issuer Unavailable", | |
'D4492': "Unable To Route Transaction", | |
'D4493': "Cannot Complete, Violation Of The Law", | |
'D4494': "Duplicate Transaction", | |
'D4496': "System Error", | |
'S5000': 'System Error', | |
'S5011': 'PayPal Connection Error', | |
'S5012': 'PayPal Settings Error' | |
} | |
class Payment(object): | |
""" | |
The eway payment class | |
""" | |
data = { | |
"Customer": { | |
"Reference": "", | |
"Title": "", | |
"FirstName": "", | |
"LastName": "", | |
"CompanyName": "", | |
"JobDescription": "", | |
"Street1": "", | |
"Street2": "", | |
"City": "", | |
"State": "", | |
"PostalCode": "", | |
"Country": "", # e.g nz | |
"Phone": "", | |
"Mobile": "" | |
}, | |
"ShippingAddress": { | |
"FirstName": "", | |
"LastName": "", | |
"Street1": "", | |
"Street2": "", | |
"City": "", | |
"State": "", | |
"Country": "", | |
"PostalCode": "", | |
"Phone": "" | |
}, | |
"Payment": { | |
"TotalAmount": 0, | |
"InvoiceNumber": "", | |
}, | |
"RedirectUrl": "http://au.cloudninehair.com/shop/confirmation/", | |
"CancelUrl":"http://au.cloudninehair.com/shop/checkout/", | |
"Method": "ProcessPayment", | |
"TransactionType": "Purchase" # Purchase, MOTO or Recurring - we'll only use Purchase | |
} | |
def __init__(self, *args, **kwargs): | |
self.api_key = getattr(settings, 'EWAY_API_KEY', None) | |
self.username = getattr(settings, 'EWAY_USERNAME', None) | |
self.password = getattr(settings, 'EWAY_PASSWORD', None) | |
if getattr(settings, 'EWAY_SANDBOX', False): | |
self.url = 'https://api.sandbox.ewaypayments.com/' | |
else: | |
self.url = 'https://api.ewaypayments.com/' | |
def data_from_order(self, order): | |
"""Store the cloud nine form data in the local data collection """ | |
self.data['Customer']['Reference'] = order.account.id | |
self.data['Customer']['Title'] = '' | |
self.data['Customer']['FirstName'] = order.account.user.first_name | |
self.data['Customer']['LastName'] = order.account.user.last_name | |
self.data['Customer']['CompanyName'] = '' | |
self.data['Customer']['JobDescription'] = '' | |
self.data['Customer']['Street1'] = order.account.default_address.line1 | |
self.data['Customer']['Street2'] = order.account.default_address.line2 | |
self.data['Customer']['City'] = order.account.default_address.city | |
self.data['Customer']['State'] = order.account.default_address.county | |
self.data['Customer']['PostalCode'] = order.account.default_address.postcode | |
self.data['Customer']['Country'] = order.account.default_address.country.iso_code | |
self.data['Customer']['Phone'] = order.account.telephone | |
self.data['Customer']['Email'] = order.account.user.email | |
self.data['Customer']['Mobile'] = '' | |
self.data['ShippingAddress']['FirstName'] = order.account.user.first_name | |
self.data['ShippingAddress']['LastName'] = order.account.user.last_name | |
self.data['ShippingAddress']['Street1'] = order.delivery_address.line1 | |
self.data['ShippingAddress']['Street2'] = order.delivery_address.line2 | |
self.data['ShippingAddress']['City'] = order.delivery_address.city | |
self.data['ShippingAddress']['State'] = order.delivery_address.county | |
self.data['ShippingAddress']['Country'] = order.delivery_address.country.iso_code | |
self.data['ShippingAddress']['PostalCode'] = order.delivery_address.postcode | |
self.data['ShippingAddress']['Phone'] = order.delivery_address.account.telephone | |
self.data['Payment']['TotalAmount'] = int(order.total*100) | |
self.data['Payment']['InvoiceNumber'] = order.order_number | |
def create_access_code(self, order): | |
self.data_from_order(order) | |
#data = self.make_request('AccessCodes', self.data) | |
data = self.make_request('CreateAccessCode.json', self.data) | |
return (data['AccessCode'], data['FormActionURL'],) if not self.errors else (None, None,) | |
def make_request(self, url, data): | |
""" Do an API request to eway """ | |
if data: | |
resp = requests.post(os.path.join(self.url, url), data=json.dumps(data), auth=(self.api_key, self.password)) | |
else: | |
resp = requests.get(os.path.join(self.url, url), auth=(self.api_key, self.password)) | |
if resp.status_code == 200: | |
out = resp.json() | |
if out['Errors']: | |
self.errors = [RESPONSE_CODES[code].replace('ProcessRequest ', '') for code in out['Errors'].split(",")] | |
else: | |
self.errors = [] | |
return out | |
else: | |
raise Exception("Unhandled none 200 response code from eway: %d / %s" % (resp.status_code, resp.content,) ) | |
def get_access_code_result(self, access_code): | |
data = self.make_request('AccessCode/%s' % access_code, {}) | |
if data['ResponseMessage']: | |
self.errors = [RESPONSE_CODES[code] for code in data['ResponseMessage'].split(",")] | |
return data['TransactionStatus'], data['AuthorisationCode'], data |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment