Solved

Sage Payment Solutions example code

Posted on 2014-03-25
26
1,063 Views
Last Modified: 2014-04-04
Hello Guys
I'm looking for a simple example of submitting a payment for processing in ColdFusion.
0
Comment
Question by:dgrafx
  • 9
  • 8
  • 8
26 Comments
 
LVL 15

Expert Comment

by:myselfrandhawa
ID: 39955330
are you saying you need an example of sage payment gateway only or any other will work
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39955598
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.
0
 
LVL 15

Expert Comment

by:myselfrandhawa
ID: 39958042
do you need sagepay UK or US, i have a code for UK.
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39958514
SagePay is UK
Sage Payment Solutions is US
0
 
LVL 15

Expert Comment

by:myselfrandhawa
ID: 39958571
what exactly you need.. please specify
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39958626
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.
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39961370
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.
0
 
LVL 15

Expert Comment

by:myselfrandhawa
ID: 39961487
So all you need is charging a credit card - right

not specific to any any company or whatever, am i correct
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39961578
yes - and getting a response
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39962277
can you post the code here?

just remove an credit card or sensitive data of course.

thanks
0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39962304
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?
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39962325
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?

Thanks
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39962359
Not with sage.  Where on the site did you find your example?
0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39962390
>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.
0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39962508
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.
0
 
LVL 15

Expert Comment

by:myselfrandhawa
ID: 39962519
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

Regards
0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39962554
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.
0
 
LVL 15

Expert Comment

by:myselfrandhawa
ID: 39962562
ok, give me some time, i am stripping down the code and will paste on pastebin asap
0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39962583
Thank you!
0
 
LVL 15

Expert Comment

by:myselfrandhawa
ID: 39963313
here is the code:

http://pastebin.com/WQQKEcJK - it will not expire

the above will give you basic idea how to work with sagepay
0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39963348
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
<div>
        <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)#">
</div>

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.
0
 
LVL 15

Accepted Solution

by:
myselfrandhawa earned 500 total points
ID: 39963378
Hi Scott, Here it is Pasted

<cfsilent>
<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 = 'https://test.sagepay.com/Simulator/VSPFormGateway.asp'>
  <cfset settings.sagepayVendorName = settings.sagepaySimulatorVendorname>
  <cfset settings.encryptionPassword = settings.simulatorEncryptionPassword>
  <cfelseif settings.transactionMode is 'test'>
  <cfset settings.authURL = 'https://test.sagepay.com/gateway/service/vspform-register.vsp'>
  <cfelse>
  <cfset settings.authURL = 'https://live.sagepay.com/gateway/service/vspform-register.vsp'>
</cfif>
<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="">
</cfsilent>
 
<!--- 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 --->
    <cfelse>
    <!--- 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>
    </cfif>
    <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)>
  </cfif>
  <!--- /end if data ok --->
  <!--- sagepay transaction form with hidden inputs --->
  <cfoutput>
    <form action="#trim(settings.authUrl)#" id="sysformSagePayProcess" method="post">
      <div>
        <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)#">
      </div>
      <div>
      <!--- submit button --->
      <div class="center top40 bottom40">
        <input name="submit" id="sagepay_submit" type="submit" class="sysformButton" value="<cfoutput>#settings.submitText#</cfoutput>">
      </div>
    </form>
  </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,"=")>
    </cfloop>
    <cfreturn structResult>
  </cffunction>
  <!--- 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">
</cfif>

Open in new window

0
 
LVL 52

Expert Comment

by:Scott Fell, EE MVE
ID: 39963400
Thank you myselfrandhawa.    

I had your post with the expiring link removed.
0
 
LVL 24

Author Comment

by:dgrafx
ID: 39968058
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 ...
0
 
LVL 24

Author Closing Comment

by:dgrafx
ID: 39978450
Thanks for the code. I haven't actually used it but when I get to it then this may save me some time ...
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Why do we like using grid based layouts in website design? Let's look at the live examples of websites and compare them to grid based WordPress themes.
Any business that wants to seriously grow needs to keep the needs and desires of an international audience of their websites in mind. Making a website friendly to international users isn’t prohibitively expensive and can provide an incredible return…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now