Python code to interact with the Payment Sense API, including full validation for all variables. Works with python 2/3.
The package can be install with:
$ pip install pypaymentsense
For a usage example see below:
# coding: utf-8
import datetime
import pytz
import requests
import pypaymentsense
from pypaymentsense import build_hash, get_paymenturl
# Lets build a POST request
#######################################
# These variables are always required #
#######################################
post_addr = "https://mms.paymentsensegateway.com/Pages/PublicPages/PaymentForm.aspx"
# Note, the below details are obtained from Payment Snese once you have setup
# an account, and will be sent in TWO seperate emails when you first register
PreSharedKey = "YOUR-PSK-HERE"
MerchantID = "YOUR-MERCHANT-ID"
Password = "YOUR=PASSWORD-HERE"
# no decimal point in values, e.g. 34120 is 341.20
Amount = "34120"
# 826 is GBP
# Full list can be found here:
# http://developers.paymentsense.co.uk/hosted-integration-resources/
CurrencyCode = "826"
# Echo certain information back to the server so you can display on your
# callback page
EchoAVSCheckResult = False
EchoCardType = False
# Anything you want here
OrderID = "test Order416"
# SALE or PREAUTH
TransactionType = "SALE"
# The url the user will be returned to once payment has been made/declined
# It is a good idea to inlcude some JS code on this page to show the
# user the results of the payment
CallbackURL = "http://example.com/your_callback"
# Self explanitory variables
EmailAddressEditable = True
PhoneNumberEditable = False
CV2Mandatory = True
Address1Mandatory = True
CityMandatory = False
PostCodeMandatory = True
StateMandatory = False
CountryMandatory = False
ResultDeliveryMethod="SERVER_PULL"
PaymentFormDisplaysResult = True
EchoCV2CheckResult = False
EchoThreeDSecureAuthenticationCheckResult = False
# Non required variables, we define these now to enable the full building
# of the URL, they can be passed as NONE if you do not want to include them
# in the post
ServerResultURL = None
OrderDescription= "Example Description"
CustomerName = "John Smith"
Address1 = "15 Faithfull Street"
Address2 = None
Address3 = None
Address4 = None
City = "Chichester"
State = "West Sussex"
PostCode = "XX2 5AW"
# List of country codes can be found here:
# http://developers.paymentsense.co.uk/hosted-integration-resources/
CountryCode = None
EmailAddress = "[email protected]"
PhoneNumber = "01243 774626"
# Now we need to set our timezone
datetime_tz = datetime.datetime.now(pytz.timezone("Europe/London"))
payment_url = get_paymenturl(
PreSharedKey=PreSharedKey, MerchantID=MerchantID,
Password=Password, Amount=Amount,
CurrencyCode=CurrencyCode,
EchoAVSCheckResult=EchoAVSCheckResult,
EchoCardType=EchoCardType, OrderID=OrderID,
TransactionType=TransactionType, CallbackURL=CallbackURL,
EmailAddressEditable=EmailAddressEditable,
PhoneNumberEditable=PhoneNumberEditable,
CV2Mandatory=CV2Mandatory,
Address1Mandatory=Address1Mandatory,
CityMandatory=CityMandatory,
PostCodeMandatory=PostCodeMandatory,
StateMandatory=StateMandatory,
CountryMandatory=CountryMandatory,
ResultDeliveryMethod=ResultDeliveryMethod,
PaymentFormDisplaysResult=PaymentFormDisplaysResult,
EchoCV2CheckResult= EchoCV2CheckResult,
EchoThreeDSecureAuthenticationCheckResult=\
EchoThreeDSecureAuthenticationCheckResult,
ServerResultURL=ServerResultURL,
OrderDescription=OrderDescription,
CustomerName=CustomerName,
Address1=Address1,
Address2=Address2,
Address3=Address3,
Address4=Address4,
City=City,
State=State,
PostCode=PostCode,
CountryCode=CountryCode,
EmailAddress=EmailAddress,
PhoneNumber=PhoneNumber,
datetime_tz=datetime_tz,
post_addr=post_addr
)
print ("Genearated Url: " + payment_url)
For this example we will use the SERVER_PULL method, what this does is, after a successful payment, certain details are passed back to your server, you then send these details back to paymentsense as a request. The request response contains the details of the transaction, for example your callback view would have the following code:
import urllib
PreSharedKey = "YOUR-PSK-HERE"
Password = "YOUR-PASSWORD-HERE"
'''
This code works in pyramid + django, flask users should use the following
to perform a GET request:
hashdigest = request.args.get('HashDigest')
'''
# Get required variables from the URL string
hashdigest = request.GET['HashDigest']
merchantid = request.GET['MerchantID']
crossreference = request.GET['CrossReference']
orderid = request.GET['OrderID']
post_addr = "https://mms.paymentsensegateway.com/Pages/PublicPages/PaymentFormResultHandler.ashx"
data = {
'MerchantID': merchantid,
'Password': Password,
'CrossReference': crossreference,
}
# Send request to payment sense
r = requests.post(post_addr, data=data)
# Result is the .text
url_raw = r.text
# Test if start of string StatusCode=0 (12 chars)
# The response returned via the callback will contain the variable StatusCode
# twice, if the first instance of the string shows a 0, this indicates the
# transaction is valid, and will contain data regarding the transaction.
url_test = url_raw[0:12]
trans_ok = "StatusCode=0"
trans_ok_len = len(trans_ok)
if url_test == trans_ok:
url_clean = url_raw[trans_ok_len:]
url_decode = urllib.parse.unquote(url_clean)
# Remove the first instance of StatusCode in the string, we no longer
# need it
else:
# Else the first StatusCode comes back as 30, this indicates the
# transaction is not legit and we then need to format the data
# differently, we just need to replace the spaces with "+"
url_decode = url_raw.replace(" ", "+")
# Yes, we can all agree that the API that returns different data with the
# same variable name is awful design, but we can thank paymentsense for
# their great design here. As the response further in will also contain
# StatusCode again, this will show if the transaction has been approved
# or declined.
# You now have a url string (variable url_deconde) E.g. Var1=abc&VAR2=def,
# pass this to another view for processing.
Now you have a URL string, you can pass this to the view used to show the payment, results, in this view you would have code similar to:
'''
This code works in pyramid + django, flask users should use the following
to perform a GET request:
status_code = request.args.get('StatusCode')
'''
# Here we will access the URL string passed from the previous view
if int(request.GET['StatusCode']) == 0:
payment['result'] = "Approved"
result_logo = True
else:
payment['result'] = "Declined"
result_logo = False
amount_raw = Decimal(request.GET['Amount'])
amount = amount_raw / 100
order_desc = request.GET['OrderDescription']
# create a dict with the results in
payment = {}
payment['result'] = result
payment['amount'] = amount
payment['card_type'] = request.GET['CardType']
payment['auth_code'] = request.GET['Message']
payment['order_desc'] = request.GET['OrderDescription']
payment['trade_name_str'] = trade_name_str
payment['trans_ref'] = request.GET['OrderID']
payment['cardholder_name'] = request.GET['CustomerName']
# You can then return the payment dict to the template for rendering
Notes: Still current as of 5th June 2019