Sage Payment Solutions example code

Hello Guys
I'm looking for a simple example of submitting a payment for processing in ColdFusion.
LVL 25
Who is Participating?
Gurpreet Singh RandhawaWeb DeveloperCommented:
Hi Scott, Here it is Pasted

<cfset settings.sagepayVendorName = "xxxxxxxxxxxx">
<cfset settings.encryptionPassword = "xxxxxxxxxxxx">
<!--- Select Transaction Mode (simulator|test| live) --->
<cfset settings.transactionMode = 'test'>
<cfset settings.sagepaySimulatorVendorName = "xxxxxxxxxxxx">
<cfset settings.simulatorEncryptionPassword = "xxxxxxxxxxxx">
<cfset settings.transactionDescription = application.companyName & ' Purchase'>
<cfset settings.transactionEmail = '1'>
<cfset settings.emailHeader = 'Thank you for your order. Contact #application.companyName# at #application.companyEmail# if you have any questions about this order.'>
<!--- Select Currency (GBP|EUR|USD) --->
<cfset settings.currency = 'GBP'>
<cfset settings.autoSubmit = 'true'>
<!--- SagePay AVS/CV2, default 0 (0|1|2|3) --->
<cfset settings.AVSmode = '0'>
<cfset settings.3DsecureMode = '0'>
<cfif settings.transactionMode is 'simulator'>
  <cfset settings.authURL = ''>
  <cfset settings.sagepayVendorName = settings.sagepaySimulatorVendorname>
  <cfset settings.encryptionPassword = settings.simulatorEncryptionPassword>
  <cfelseif settings.transactionMode is 'test'>
  <cfset settings.authURL = ''>
  <cfset settings.authURL = ''>
<cfset settings.methodImg = ''>
<!--- shippay message: optional message shown to customer on shipping selection --->
<cfset settings.methodSelectMessage = 'Pay with SagePay'>
<!--- submit message: optional message shown to customer on final order submission --->
<cfset settings.methodSubmitMessage = 'Click to pay with SagePay'>
<!--- confirm message: optioal message shown to customer after order is approved --->
<cfset settings.methodConfirmMessage = 'SagePay transaction complete'>
<!--- SUBMIT TEXT --->
<!--- submit button value --->
<cfset settings.submitText = '&raquo;&nbsp;Click to Pay with SagePay'>
<!--- processing/loading message --->
<cfset settings.loadingText = 'Submitting to SagePay...'>
<!--- method name: the user-friendly name shown for this payment option at checkout --->
<cfset settings.methodName = 'SagePay UK'>
<!--- method type: processor (off-site processing), gateway (integrated credit card form) --->
<cfset settings.methodType = 'processor'>
<!--- key field: transaction variable specific to this payment method --->
<cfset settings.methodTransKeyField = "url.crypt">
<!--- notification URLs (callback transactions) --->
<cfset settings.cancelURL = application.appPageConfirmOrderUrl & '?mode=cancel'>
<cfset settings.confirmURL = application.appPageConfirmOrderUrl & '?mode=confirm'>
<cfset settings.returnURL = application.appPageConfirmOrderUrl & '?mode=return'>
<!--- default processing values --->
<cfparam name="form.fieldNames" default="">
<cfparam name="attributes.trans_data" default="">
<cfparam name="attributes.auth_mode" default="">
<cfparam name="request.trans.errormessage" default="">
<!--- CAPTURE MODE --->
<cfif isDefined('attributes.auth_mode') and attributes.auth_mode is 'capture'>
  <!--- verify transaction data is ok --->
  <cfif not isStruct(attributes.trans_data)>
    <cfset request.trans.errorMessage = listAppend(request.trans.errorMessage,'Payment Data Incomplete')>
    <!--- if data is ok, run processing --->
    <!--- simplify to 'tdata' struct --->
    <cfset tdata = attributes.trans_data>
    <!--- defaults for transaction data --->
    <!--- customer --->
    <cfparam name="tdata.customerid" default="" type="string">
    <cfparam name="tdata.customercompany" default="" type="string">
    <cfparam name="tdata.customeremail" default="" type="string">
    <cfparam name="tdata.customerphone" default="" type="string">
    <cfparam name="tdata.customeraddress1" default="" type="string">
    <cfparam name="tdata.customeraddress2" default="" type="string">
    <cfparam name="tdata.customercity" default="" type="string">
    <cfparam name="tdata.customerstate" default="" type="string">
    <cfparam name="tdata.customerzip" default="" type="string">
    <cfparam name="tdata.customercountry" default="" type="string">
    <cfparam name="tdata.customershipcompany" default="" type="string">
    <cfparam name="tdata.customershipaddress1" default="" type="string">
    <cfparam name="tdata.customershipaddress2" default="" type="string">
    <cfparam name="tdata.customershipcity" default="" type="string">
    <cfparam name="tdata.customershipstate" default="" type="string">
    <cfparam name="tdata.customershipzip" default="" type="string">
    <cfparam name="tdata.customershipcountry" default="" type="string">
    <!--- order/payment --->
    <cfparam name="tdata.orderid" default="" type="string">
    <cfparam name="tdata.paymentamount" default="0" type="numeric">
    <!--- SagePay 'crypt' combines all data into a single field --->
    <cfset tdata.combined = 'VendorTxCode=' & tdata.orderID>
    <cfset tdata.combined = tdata.combined & '&Amount=' & trim(numberFormat(tdata.paymentamount,'_.__'))>
    <cfset tdata.combined = tdata.combined & '&Currency=' & settings.currency>
    <cfset tdata.combined = tdata.combined & '&Description=' & settings.transactionDescription>
    <cfset tdata.combined = tdata.combined & '&SuccessURL=' & settings.confirmURL>
    <cfset tdata.combined = tdata.combined & '&FailureURL=' & settings.cancelURL>
    <cfset tdata.combined = tdata.combined & '&CustomerName=' & tdata.customernamefirst & ' ' & tdata.customernamelast>
    <cfset tdata.combined = tdata.combined & '&CustomerEmail=' & tdata.customeremail>
    <cfset tdata.combined = tdata.combined & '&VendorEmail=' & application.companyEmail>
    <cfset tdata.combined = tdata.combined & '&SendEmail=' & settings.transactionEmail>
    <cfset tdata.combined = tdata.combined & '&eMailMessage=' & settings.emailHeader>
    <cfset tdata.combined = tdata.combined & '&BillingSurname=' & tdata.customernamelast>
    <cfset tdata.combined = tdata.combined & '&BillingFirstNames=' & tdata.customernamefirst>
    <cfset tdata.combined = tdata.combined & '&BillingAddress1=' & tdata.customeraddress1>
    <cfset tdata.combined = tdata.combined & '&BillingAddress2=' & tdata.customeraddress2>
    <cfset tdata.combined = tdata.combined & '&BillingCity=' & tdata.customercity>
    <cfset tdata.combined = tdata.combined & '&BillingPostCode=' & tdata.customerzip>
    <cfset tdata.combined = tdata.combined & '&BillingCountry=' & tdata.customercountry>
    <!--- us orders must have state appended --->
    <cfif tdata.customercountry is 'US'>
      <cfset tdata.combined = tdata.combined & '&BillingState=' & tdata.customerstate>
    <cfset tdata.combined = tdata.combined & '&BillingPhone=' & tdata.customerphone>
    <cfset tdata.combined = tdata.combined & '&DeliverySurname=' & tdata.customernamelast>
    <cfset tdata.combined = tdata.combined & '&DeliveryFirstNames=' & tdata.customernamefirst>
    <cfset tdata.combined = tdata.combined & '&DeliveryAddress1=' & tdata.customershipaddress1>
    <cfset tdata.combined = tdata.combined & '&DeliveryAddress2=' & tdata.customershipaddress2>
    <cfset tdata.combined = tdata.combined & '&DeliveryCity=' & tdata.customershipcity>
    <cfset tdata.combined = tdata.combined & '&DeliveryPostCode=' & tdata.customershipzip>
    <cfset tdata.combined = tdata.combined & '&DeliveryCountry=' & tdata.customershipcountry>
    <cfset tdata.combined = tdata.combined & '&ApplyAVSCV2=' & settings.AVSmode>
    <cfset tdata.combined = tdata.combined & '&Apply3DSecure=' & settings.3DsecureMode>
    <cfset tdata.crypt = simpleXor(tdata.combined,settings.encryptionPassword)>
  <!--- /end if data ok --->
  <!--- sagepay transaction form with hidden inputs --->
    <form action="#trim(settings.authUrl)#" id="sysformSagePayProcess" method="post">
        <input type="hidden" name="VPSProtocol" value="2.23">
        <input type="hidden" name="TxType" value="PAYMENT">
        <input type="hidden" name="Vendor" value="#settings.SagepayVendorName#">
        <input type="hidden" name="Crypt" value="#ToBase64(tdata.crypt)#">
      <!--- submit button --->
      <div class="center top40 bottom40">
        <input name="submit" id="sagepay_submit" type="submit" class="sysformButton" value="<cfoutput>#settings.submitText#</cfoutput>">
  <cfelseif isDefined('attributes.auth_mode') and attributes.auth_mode is 'process'>
  <!--- function to parse response --->
  <cffunction name="getSagePayResponse" returntype="Struct" access="private" output="false">
    <cfargument name="crypt" type="string" required="true">
    <cfset var r = "">
    <cfset var structResult =  {}>
    <cfloop list="#arguments.crypt#" index="r" delimiters="&">
      <cfset structResult[listFirst(r,"=")] = listLast(r,"=")>
    <cfreturn structResult>
  <!--- read response from SagePay --->
  <cfparam name="url.crypt" default="">
  <cfset request.trans.paymenttransresponse = base64Decode(url.crypt)>
  <!--- add heading to response data --->
  <cfset request.trans.paymenttransresponse = 'SagePay Returned Values: ' & chr(13) & '===' & chr(13) & request.trans.paymenttransresponse>
  <!--- set values into page request --->
  <cfset request.trans.paymentdata = getSagePayResponse(SimpleXor(base64decode(URL.crypt),settings.encryptionPassword))>
  <cfparam name="request.trans.paymentdata.VPSTxId" default="">
  <cfset request.trans.orderid = request.trans.paymentdata.VendorTxCode>
  <cfset request.trans.paymentamount = request.trans.paymentdata.Amount>
  <cfset request.trans.paymenttransid = request.trans.paymentdata.VPSTxId>
  <cfset request.trans.paymentstatus = request.trans.paymentdata.Status>
  <!--- take action based on response from cfhttp request (VERIFIED|INVALID)--->
  <cfset responseStr = request.trans.paymentstatus>
  <cfdump var="#responseStr#">
  <!--- Do the Procesing here --->
  <cflocation url="#settings.returnURL#" addtoken="no">

Open in new window

Gurpreet Singh RandhawaWeb DeveloperCommented:
are you saying you need an example of sage payment gateway only or any other will work
dgrafxAuthor Commented:
i'm looking for a getting started type of code - the company website doesn't have ColdFusion examples.
and as far as what - the code used to submit your payment request to them for processing.
Cloud Class® Course: Microsoft Office 2010

This course will introduce you to the interfaces and features of Microsoft Office 2010 Word, Excel, PowerPoint, Outlook, and Access. You will learn about the features that are shared between all products in the Office suite, as well as the new features that are product specific.

Gurpreet Singh RandhawaWeb DeveloperCommented:
do you need sagepay UK or US, i have a code for UK.
dgrafxAuthor Commented:
SagePay is UK
Sage Payment Solutions is US
Gurpreet Singh RandhawaWeb DeveloperCommented:
what exactly you need.. please specify
dgrafxAuthor Commented:
The type of code I'm looking for is the submitting of payment data for processing - ya know credit card info and an amount - then a response.
dgrafxAuthor Commented:
Note: I do have a developers account but the company doesn't provide ColdFusion examples. So the meat of this question is the hope that someone has some example code that I can look at.
Gurpreet Singh RandhawaWeb DeveloperCommented:
So all you need is charging a credit card - right

not specific to any any company or whatever, am i correct
dgrafxAuthor Commented:
yes - and getting a response
dgrafxAuthor Commented:
can you post the code here?

just remove an credit card or sensitive data of course.

Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
I have been in the same boat developing classic asp and there was no direct help files for asp, only .NET and PHP.  However, they did have the raw xml files and was able to interpret what needed to be done.  I don't know ColdFusion, but will try to help as I have experience with payment gateways.  

I will take a moment to look up what code samples are available.  Are you well versed in CF where you can understand how to send and receive a POST?
dgrafxAuthor Commented:
Yes I am.
What I'm looking for is just a simple example.

Also I ran into an issue posting encrypted xml back to Sage.

You have experience with Sage you say?

Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
Not with sage.  Where on the site did you find your example?
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
>is there any private comment where i post it
All you need to do is strip your personal information.

>or let me see the idea, i will share the code
That would be a good idea.

All of this works the same, just in different languages.  As long as dgrafx is comfortable with the language we can work together to make this work.
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
Thank you myselfrandhawa.  

Some code is better than none, but we need to have a solution that can be posted publicly.  This will not only help dgrafx, but it will help every other person looking for the same solution.   When your code is linked from someplace else and is later not available, the solution no longer will work.  

Is there anything you can share?

He is using Sage.  We simply need to get the documentation and apply cf to what they show.  Typically this will be a SOAP call or direct post with a return of xml or an post back to a receiving page.
Gurpreet Singh RandhawaWeb DeveloperCommented:
Hi Scott, as i have told him above also, his question is not very clear to me, I told him, i had the sagePay UK working for me but not for US, if he is looking into Sage Pay US, i may be not be able to help him but as far code sharing is concerned i can share that sage Pay UK Code too.

Let me know if that helps

Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
I can't believe there is going to be a big difference.  I did sign up as a developer with that site to look at the code. But they take 24hrs to approve.  The other payment solutions I have used have the documentation ready to see.  It is frustrating they don't  have it open on their site.

If you can please strip out anything that is private and post the code it would be great start.   If you are just worried about your own code getting out, one way or another we will figure this out and the solution will be posted.  

Looking at your pastebin, I did not see anything that needed be be kept secret but I can appreciate when you figure something out like this it can be hard to let go an share.
Gurpreet Singh RandhawaWeb DeveloperCommented:
ok, give me some time, i am stripping down the code and will paste on pastebin asap
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
Thank you!
Gurpreet Singh RandhawaWeb DeveloperCommented:
here is the code: - it will not expire

the above will give you basic idea how to work with sagepay
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
Thank you.  Just a couple of things.  First, can you please paste this code in the thread.  You will see the word "Code" in the comment box.  If you click that, start and end code tags will appear and you can paste your code there.  That will give this affect
        <input type="hidden" name="VPSProtocol" value="2.23">
        <input type="hidden" name="TxType" value="PAYMENT">
        <input type="hidden" name="Vendor" value="#settings.SagepayVendorName#">
        <input type="hidden" name="Crypt" value="#ToBase64(tdata.crypt)#">

Open in new window

I am not a CF dev, but it looks like there are some areas that will need to be changed when going from Testing to Live.  Line 5 and lines 17 - 25

A security tip I have learned and practiced is to never put anything in a form unless you are ok with the user to change it even if it is a hidden value.  For instance, a name, address item_id and quantity are ok to have in  public facing form.   Anything like an amount, payment type etc should not be in the form even if "hidden" because of course they are not really hidden and somebody can make up their own form.

What I do is send the name, address, item_id/qty arrays,  and card info to my processing script which will then recalculate the total amount by first hitting the database with the item_id to get the price and tax info, multiply by the qty to get the line total and finally loop through all items to get the grand total and figure any tax, discounts.

Finally submitting the calculated info along with other data my processor needs via httppost.  

The only time it is acceptable to have an amount as a form field (hidden or not) in the form the user sees is if it is ok to have an account receivable balance.  In that case, remember to check for amounts greater than zero.
Scott Fell, EE MVEDeveloper & EE ModeratorCommented:
Thank you myselfrandhawa.    

I had your post with the expiring link removed.
dgrafxAuthor Commented:
Hey guys !
Give me some time on this ...
The guy I'm doing some work for is out of the office for a bit and I need info from him to proceed ...
dgrafxAuthor Commented:
Thanks for the code. I haven't actually used it but when I get to it then this may save me some time ...
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.