ColdFusion and Protx VSP Direct

Protx no longer have examples of how to integrate ColdFusion with their VSP Direct Payment Gateway. Protx are one of the UK's biggest gateway providers and one would expect an integration kit in ColdFusion. They have told me they have no plans to add one now or in the near future. The old kit was ok but had no examples of the new 3D Secure system, and because it was way out date they took it off the site.

Basically here is a reverse engineered version I did from there ASP.NET example which very works well. I know its a little messy at the mo, but it will give anyone who knowns CF and Protx a good starting template. The idea is when i have time to create a custom tag.

If you want to have a go yourself here is the guide to work from: VSP Guide

My example already assumes you have created the payment details page with all the necessary form fields and have a understanding of Protx. The code also has some of my cart vars in which you would need to create or replace with your own.

First create a component called gateway-protx.cfc

view plain print about
1<cfcomponent>
2<cfscript>
3SimulatorSite ="0";
4TestSite ="0";
5LiveSite ="1";
6
</cfscript>
7
8<cffunction name="SetGateway" access="public" hint="set which gateway is to be used, simulator, test or live" returntype="struct">
9 <!--- Set up local scope. --->
10 <cfset GatewaySettings = StructNew() />
11 <cfif #SimulatorSite# is "1" >
12 <cfscript>
13 StructInsert(GatewaySettings, "Verify", "false");
14 StructInsert(GatewaySettings, "PurchaseURL", "https://ukvpstest.protx.com/VSPSimulator/VSPDirectGateway.asp");
15
StructInsert(GatewaySettings, "
RefundURL", "https://ukvpstest.protx.com/VSPSimulator/VSPServerGateway.asp?Service=VendorRefundTx");
16
StructInsert(GatewaySettings, "ReleaseURL", "https://ukvpstest.protx.com/VSPSimulator/VSPServerGateway.asp?Service=VendorReleaseTx");
17
StructInsert(GatewaySettings, "
RepeatURL", "https://ukvpstest.protx.com/VSPSimulator/VSPServerGateway.asp?Service=VendorRepeatTx");
18
StructInsert(GatewaySettings, "callbackURL", "https://ukvpstest.protx.com/VSPSimulator/VSPDirectCallback.asp");
19
</cfscript>
20 </cfif>
21 <cfif #TestSite# is "
1">
22 <cfscript>

23 StructInsert(GatewaySettings, "
Verify", "false");
24 StructInsert(GatewaySettings, "
PurchaseURL", "https://ukvpstest.protx.com/vspgateway/service/vspdirect-register.vsp");
25
StructInsert(GatewaySettings, "RefundURL", "https://ukvpstest.protx.com/vspgateway/service/refund.vsp");
26
StructInsert(GatewaySettings, "
ReleaseURL", "https://ukvpstest.protx.com/vspgateway/service/release.vsp");
27
StructInsert(GatewaySettings, "RepeatURL", "https://ukvpstest.protx.com/vspgateway/service/repeat.vsp");
28
StructInsert(GatewaySettings, "
callbackURL", "https://ukvpstest.protx.com/vspgateway/service/direct3dcallback.vsp");
29
</cfscript>
30 <!---https://ukvpstest.protx.com/showpost/showpost.asp--->
31 </cfif>
32 <cfif #LiveSite# is "1">
33 <cfscript>
34 StructInsert(GatewaySettings, "Verify", "false");
35 StructInsert(GatewaySettings, "PurchaseURL", "https://ukvps.protx.com/vspgateway/service/vspdirect-register.vsp");
36
StructInsert(GatewaySettings, "
RefundURL", "https://ukvps.protx.com/vspgateway/service/refund.vsp");
37
StructInsert(GatewaySettings, "ReleaseURL", "https://ukvps.protx.com/vspgateway/service/release.vsp");
38
StructInsert(GatewaySettings, "
RepeatURL", "https://ukvps.protx.com/vspgateway/service/repeat.vsp");
39
StructInsert(GatewaySettings, "callbackURL", "https://ukvps.protx.com/vspgateway/service/direct3dcallback.vsp");
40
</cfscript>
41 </cfif>
42 <cfreturn GatewaySettings>
43</cffunction>
44
45<!---
46'****************************************************************************************
47' Protx HTTP Call
48'****************************************************************************************
49--->

50<cffunction name="
gatewaySend" access="public" hint="checkes form dedtails" returntype="struct">
51 <cfargument name="
PurchaseURL" type="string" required="yes">
52 <cfargument name="
ProtocolVersion" type="string" required="yes">
53 <cfargument name="
Vendor" type="string" required="yes">
54 <cfargument name="
VendorTxCode" type="string" required="yes">
55 <cfargument name="
DefaultCurrency" type="string" required="yes">
56 <cfargument name="
DefaultDescription" type="string" required="yes">
57 <cfargument name="
DefaultApplyAVSCV2" type="string" required="yes">
58
59
60 <cfargument name="
DeliveryAddress" type="string" required="yes">
61 <cfargument name="
DeliveryPostCode" type="string" required="yes">
62
63 <cfargument name="
CardNumber" type="string" required="yes">
64 <cfargument name="
CardHolder" type="string" required="yes">
65 <cfargument name="
Amount" type="string" required="yes">
66 <cfargument name="
StartDate" type="string" required="no">
67 <cfargument name="
ExpiryDate" type="string" required="yes">
68 <cfargument name="
Basket" type="string" required="no">
69
70 <cfargument name="
CustomerName" type="string" required="yes">
71 <cfargument name="
BillingAddress" type="string" required="yes">
72 <cfargument name="
BillingPostCode" type="string" required="yes">
73 <cfargument name="
ContactNumber" type="string" required="yes">
74 <cfargument name="
ContactFax" type="string" required="no">
75 <cfargument name="
CustomerEmail" type="string" required="yes">
76
77 <cfargument name="
ClientIPAddress" type="string" required="yes">
78    
79
80 <cfargument name="
XID" type="string" required="no">
81 <cfargument name="
ECI" type="string" required="no">
82 <cfargument name="
DSecureStatus" type="string" required="no">
83 <cfargument name="
CV2" type="string" required="no">
84 <cfargument name="
CAVV" type="string" required="no">
85
86 <cfargument name="
IssueNumber" type="string" required="no">
87
88
89
90 <!---Get the contents of the post from the previous page and split out the variables for sending--->
91 <cfset RequestData = GetHttpRequestData()>

92 <cfset Response = StructNew()>

93 <cfloop list="
#RequestData.content#" index="line" delimiters="&">
94 <cfset line = Trim( line )>

95 <cfset StructInsert( Response, Trim( ListFirst( line, "=" ) ), URLDecode(Trim(Mid(line,Find("=",line)+1,len(line)) )) )>
96 </cfloop>
97
98
99 <!---Set the required outgoing properties for the initial HTTPS post to the VPS--->
100 <!---******************HERE IS WHERE THE ORDER GETS SENT TO PROTX VIA HTTPS*********************** --->
101 <cfhttp url="#PurchaseURL#" method="post" delimiter="," resolveurl="no" throwonerror="yes" timeout="20" charset="windows-1252">
102 <cfhttpparam name="
VPSProtocol" value="#ProtocolVersion#" type="formfield">
103 <cfhttpparam name="
TxType" value="#Response.TxType#" type="formfield">
104 <cfhttpparam name="
Vendor" value="#Vendor#" type="formfield">
105 <cfhttpparam name="
VendorTxCode" value="#VendorTxCode#" type="formfield">
106 <cfhttpparam name="
Currency" value="#DefaultCurrency#" type="formfield">
107 <cfhttpparam name="
Description" value="#DefaultDescription#" type="formfield">
108 <cfhttpparam name="
Amount" value="#Amount#" type="formfield">
109 <cfhttpparam name="
CardHolder" value="#CardHolder#" type="formfield">
110 <cfhttpparam name="
CardNumber" value="#CardNumber#" type="formfield">
111 <cfhttpparam name="
GiftAidPayment" value="0" type="formfield">
112 <cfhttpparam name="
ApplyAVSCV2" value="#DefaultApplyAVSCV2#" type="formfield">
113
114 <cfhttpparam name="
Basket" value="#Basket#" type="formfield">
115
116    <cfif #StartDate# is not "
">
117 <cfhttpparam name="
StartDate" value="#StartDate#" type="formfield">
118 </cfif>
119 <cfif #ExpiryDate# is not "
">
120 <cfhttpparam name="
ExpiryDate" value="#ExpiryDate#" type="formfield">
121 </cfif>
122
123 <cfif #DeliveryAddress# is not "
">
124 <cfhttpparam name="
DeliveryAddress" value="#DeliveryAddress#" type="formfield">
125 </cfif>
126 <cfhttpparam name="
BillingAddress" value="#BillingAddress#" type="formfield">
127
128 <cfif #IssueNumber# is not "
">
129 <cfhttpparam name="
IssueNumber" value="#IssueNumber#" type="formfield">
130 </cfif>
131 <cfhttpparam name="
CV2" value="#CV2#" type="formfield">
132
133 <cfhttpparam name="
CardType" value="#CardType#" type="formfield">
134
135 <cfhttpparam name="
BillingPostCode" value="#BillingPostCode#" type="formfield">
136
137 <cfif #DeliveryPostCode# is not "
">
138 <cfhttpparam name="
DeliveryPostCode" value="#DeliveryPostCode#" type="formfield">
139 </cfif>
140
141 <cfhttpparam name="
CustomerName" value="#CustomerName#" type="formfield">
142
143    <cfif #ContactNumber# is not "
">
144 <cfhttpparam name="
ContactNumber" value="#ContactNumber#" type="formfield">
145 </cfif>
146 <cfif #ContactFax# is not "
">
147 <cfhttpparam name="
ContactFax" value="#ContactFax#" type="formfield">
148 </cfif>
149
150 <cfhttpparam name="
CustomerEmail" value="#CustomerEmail#" type="formfield">
151
152 <cfif #ClientIPAddress# is not "
">
153 <cfhttpparam name="
ClientIPAddress" value="#ClientIPAddress#" type="formfield">
154 </cfif>
155
156
157 <cfif #CAVV# is not "
">
158 <cfhttpparam name="
CAVV" value="#CAVV#" type="formfield">
159 </cfif>
160 <cfif #XID# is not "
">
161 <cfhttpparam name="
XID" value="#XID#" type="formfield">
162 </cfif>
163 <cfif #ECI# is not "
">
164 <cfhttpparam name="
ECI" value="#ECI#" type="formfield">
165 </cfif>
166 <cfif #DSecureStatus# is not "
">
167 <cfhttpparam name="
3DSecureStatus" value="#DSecureStatus#" type="formfield">
168 </cfif>
169
170
171 </cfhttp>
172
173
174 <!--- ********************************END OF HTTPS POST TO PROTX******************************************--->
175
176
177 <cfset Response = StructNew()>

178 <cfloop list="#CFHTTP.FileContent#" index="line" delimiters="#chr(13)#">
179 <cfset line = Trim( line )>

180 <cfset StructInsert( Response, Trim( ListFirst( line, "=" ) ), Trim(Mid(line,Find("=",line)+1,len(line)) ) )>
181 </cfloop>
182 <cfreturn Response>
183</cffunction>
184</cfcomponent>
Next I create a page called seek-auth.cfm this is the page you post all you form variables off to, its this page that does all the magic.
view plain print about
1<!---check you cart session to see if its empty--->
2<cfif structisempty(session['cartItem'])>
3 <cflocation addtoken="no" url="fielderror.cfm?ErrorCode=003" />
4 <cfabort>
5</cfif>
6
7<!---
8 '****************************************************************************************
9 ' validate all your form fields here
10 '****************************************************************************************
11 --->

12
13
14
15
16<!---
17 '****************************************************************************************
18 ' Protx Payment Gateway
19 '****************************************************************************************
20 --->

21<!---
22 '****************************************************************************************
23 ' Create cfc
24 '****************************************************************************************
25 --->

26<cfscript>
27 cfcProtx = createobject("component", "components.gateway-protx");
28 gatewaysetup = cfcProtx.SetGateway();
29
</cfscript>
30<!---
31 '****************************************************************************************
32 ' Protx Create Transaction ID -
33    This needs to be a random so this is what i use but could be made more secure
34 '****************************************************************************************
35 --->

36<cfif IsDefined("FORM.Amount") >
37 <cfset VendorTxCode = "#randrange(0,999999999)##randrange(0,999999999)#">
38</cfif>
39<!---
40 '****************************************************************************************
41 ' Setup new session to store any values we may need for post back etc
42 '****************************************************************************************
43 --->

44<cfif IsDefined("FORM.Amount") >
45 <cflock timeout="60" type="exclusive">
46 <cfset SESSION.protx = structNew()>
47 <cfset SESSION.protx.TxCode = #VendorTxCode#>
48 </cflock>
49</cfif>
50
51
52
53<!---
54 '****************************************************************************************
55 ' HTTPS Request to Protx - Uses SETUP PAGE Vars, and Forms Vars
56        ' PS these are all the form vars need to make a Protx Post
57 '****************************************************************************************
58 --->

59<cfif IsDefined("FORM.Amount")><!--- we only want this to run then we have a post from checkout--->
60 <cfparam name="CustomerName" default="#form.billname#">
61 <cfparam name="BillingAddress" default="#form.billaddress1# #form.billaddress1# #form.billaddress3# #form.billCountry#">
62 <cfparam name="BillingPostCode" default="#form.billPostCode#">
63 <cfparam name="ContactNumber" default="#form.billTel#">
64 <cfparam name="ContactFax" default="#form.billFax#">
65 <cfparam name="CustomerEmail" default="#form.email#">
66
67 <cfset keyList = structkeylist(session['cartItem'])>
68 <cfset subtotal = 0 >
69 <cfloop from="1" to="#listlen(keyList)#" index="y">
70 <cfset currentListItemDsp = session['cartItem'][listgetat(keyList,y)]>
71 <cfset itemName = currentListItemDsp['aName']>
72 <cfset itemQty = currentListItemDsp['aQty']>
73 <cfset itemPrice = currentListItemDsp['aPrice']>
74 <cfset totalOutput = itemPrice * itemQty>
75 <cfset subtotal = subtotal + totalOutput>
76
77 </cfloop>
78 <cfparam name="Basket" default="">
79 <cfparam name="DeliveryAddress" default="#form.shipaddress1# #form.shipaddress1# #form.shipaddress3# #form.shipCountry#">
80 <cfparam name="DeliveryPostCode" default="#form.shipPostCode#">
81 <cfset form.CardNumber=rereplace(form.CardNumber,"([^[0-9]]*)","","all")>
82 <cfparam name="CardNumber" default="#form.CardNumber#">
83 <cfparam name="CardHolder" default="#form.CardHolder#">
84 <cfparam name="Amount" default="#form.Amount#">
85 <cfparam name="StartDate" default="#form.StartDate1##form.StartDate2#">
86 <cfparam name="ExpiryDate" default="#form.ExpiryDate1##form.ExpiryDate2#">
87 <cfparam name="ClientIPAddress" default="#CGI.REMOTE_HOST#">
88 <cfparam name="CAVV" default="">
89 <cfparam name="XID" default="">
90 <cfparam name="ECI" default="">
91 <cfparam name="DSecureStatus" default="">
92 <cfparam name="CV2" default="">
93 <cfparam name="IssueNumber" default="#form.issueNumber#">
94
95<!---
96 '****************************************************************************************
97 ' Any database store here
98        ' If you need to store any info in your database do it here
99        ' Its also a good idea to set a 'waiting for authentication' in a file or db here
100 '****************************************************************************************
101 --->

102
103
104
105<!---if statment ends here--->
106</cfif>
107
108
109
110
111<!---
112 '****************************************************************************************
113 ' 3D Secure - New responce to sort out with 3D Secure info in it.
114 '****************************************************************************************
115 --->

116<cfif isDefined('PARes')>
117 <!---re check 3d post back--->
118 <cfhttp url="#callbackURL#" method="post" delimiter="," resolveurl="no" throwonerror="yes" timeout="20" charset="windows-1252">
119 <cfhttpparam name="MD" value="#FORM.MD#" type="formfield">
120 <cfhttpparam name="PARes" value="#FORM.PARes#" type="formfield">
121 </cfhttp>
122 <cfset Response = StructNew()>
123 <cfloop list="#CFHTTP.FileContent#" index="line" delimiters="#chr(13)#">
124 <cfset line = Trim( line )>
125 <cfset StructInsert( Response, Trim( ListFirst( line, "=" ) ), Trim(Mid(line,Find("=",line)+1,len(line)) ) )>
126 </cfloop>
127</cfif>
128
129<!---
130 '****************************************************************************************
131 ' HTTPS Responce- Determine next action if we have a responce
132 '****************************************************************************************
133 --->
<!---<cfdump var=#response#><cfabort>--->
134<cfif isdefined('Response')>
135 <!---Payment OK and Charged--->
136 <cfif #Response.Status# IS "OK" OR #Response.Status# IS "ATTEMPTONLY" >
137 <!---update order db here--->
138
139 <!---send user to the tank you page--->
140 <cflocation addtoken="no" url="thank-you.cfm?txcode=#SESSION.protx.TxCode#">
141
142 <!---Card is on the 3D Secure System --->
143 <cfelseif #Response.Status# IS "3DAUTH">
144 <h1>3D Secure Verification Needed, Loading please wait...</h1>
145 <InvalidTag LANGUAGE="Javascript">
146 function OnLoadEvent() { document.form.submit(); }
147 </SCRIPT>
148 <body OnLoad="OnLoadEvent();">
149 <cfoutput>
150 <form name="form" action="#Response.ACSURL#" method="POST"/>
151 <input type="hidden" name="PaReq" value="#Response.PaReq#"/>
152 <input type="hidden" name="TermUrl" value="https://#CGI.HTTP_HOST#/seek-auth.cfm"/>
153 <input type="hidden" name="MD" value="#Response.MD#"/>
154 </cfoutput>
155 <NOSCRIPT>
156 <center>
157 <p>Please click button below to Authenticate your card</p>
158 <input type="submit" value="Go"/>
159 </p>
160 </center>
161 </NOSCRIPT>
162 </form>
163 </body>
164 <!---The transaction returned failed!!!!!--->
165 <cfelse>
166 <cflock scope="session" timeout="15">
167 <cfset SESSION.protx.details = #Response.Status# & "<br />"& #Response.StatusDetail# >

168 </cflock>
169
170 <!---Update database--->    
171
172
173 <!---clean up vars --->
174
175 <cflocation addtoken="no" url="auth-error.cfm">
176 </cfif>
177</cfif><!---END of if responce is defined--->

Related Blog Entries

TweetBacks
Comments
Glyn's Gravatar just found a small issue with the above code, if the user resubmits the page it gives them a new TX Code and could mean payment being charged more than once, to stop this i would change the 'Protx Create Transaction ID line' to below and delete the one under that, sorry did that makes sense?

<!---
'****************************************************************************************
' Protx Create Transaction ID
'****************************************************************************************
--->
<cfif IsDefined("FORM.Amount") >
<cfif not isdefined('SESSION.protx.TxCode')>
<cfset VendorTxCode = "#randrange(0,999999999)##randrange(0,999999999)#">
<cfelse>
<cfset VendorTxCode = #SESSION.protx.TxCode#>
</cfif>
<cflock timeout="60" type="exclusive">
<cfset SESSION.protx = structNew()>
<cfset SESSION.protx.TxCode = #VendorTxCode#>
</cflock>
<!---<cfoutput>#VendorTxCode# </cfoutput>--->
</cfif>
# Posted By Glyn | 07/10/08 16:58
 

About Me

Glyn Jackson, 28 years old, MD and senior developer of a development firm based in Staffordshire called Newebia Ltd. Academic background in BSc Information System & Internet Commerce. Online marketing expert (EE Ranked) and .NET developer. Has been developing with ColdFusion for 5 years and loves it. "I am not a veteran in ColdFusion but I do work on challenging projects which help me learn more about ColdFusion and if I can contribute to the community in anyway then, it's all good!"

Recommends

  • ColdFusion