First Coldbox Plugin, HELP?

So, my first attempt at a ColdBox Plugin works, however I cannot help but feel I could have done it better/right. You see, I know the theory of OOP it's in my nightmares as student, but applying it practically in CF is still a learning experience.

I have posted my code below. Encapsulation is the key I think, you see I am coming outside of the CFC to put back in 'SagePayURLStruct'

So my question is, how to I setup the 'setEnvironment' function in the CFC so it accessible inside the CFC, only the CFC and without going outside the CFC? For example could this be done using the init(). Could it be called on create component, so its accessible in the CFC itself after creation?

I would really welcome any feedback here, rip it to pieces it's the only way I learn! :)

handler

view plain print about
1var rc = event.getCollection();// RC reference
2var Response = "";
3
4SagePayPlugin = getPlugin(plugin="SagePay",customPlugin=true,newInstance=true);
5     SagePayURLStruct = SagePayPlugin.setEnvironment(gateway="simulator");//make my SagePay URL available in the page
6
7response = SagePayPlugin.makeCall(PurchaseURL=SagePayURLStruct.PurchaseURL,
8VendorTxCode = session.TXTCode, //transaction code
9vendor = "something",
10VPSProtocol = "2.23",
11referrerID = "someone",
12amount=rc.Amount,//transaction account
13CardHolder=rc.cardHolder,//customer name and name on card
14CardNumber=cardNumber,//card number
15StartDate=rc.startDate1&rc.startDate2,//card start date
16ExpiryDate=rc.expiryDate1&rc.expiryDate2,//card expiry date
17DeliveryAddress=rc.billaddress1,//DeliveryAddress same as billing address
18CardType=rc.cardtype,//type of card being used
19BillingPostCode=rc.billPostCode,//card post code
20DeliveryPostCode=rc.billPostCode,//DeliveryAddress same as billing address
21CustomerName=rc.cardHolder,//card holders name
22CV2=rc.CV2,//security codebillfirstName=rc.fname,//billing first name
23billlastName=rc.lname,//billing last name
24BillingAddress1=rc.billaddress1,//billing address
25billingcity=rc.billcity//billing city
26                            );
27//responce back was ok do DB stores and send customer to thank you page
28if (response.status is "OK" OR response.status IS "ATTEMPTONLY") {
29getPlugin("messagebox").setMessage("error","Thanks order approved, receipt below.");
30    setNextEvent("secure.checkoutComplete");
31        
32}
33    
34//responce back was that this card is in 3D secure
35else if (response.status IS "3DAUTH"){
36         getPlugin("messagebox").setMessage("warning","You are enrolled in the 'Verified by Visa' or 'MasterCard SecureCode' service. Please enter your details below.");
37        
38     }
39//responce was none of above
40 else {
41getPlugin("messagebox").setMessage("error",Response.Status&"<br />"&Response.StatusDetail);
42 }
Plugin Code
view plain print about
1<cfcomponent name="SagePay"
2             hint="SagePay plugin for VSP Direct"
3             extends="coldbox.system.plugin"
4             output="false"
5             cache="true">

6
7<!------------------------------------------- CONSTRUCTOR ------------------------------------------->    
8
9 <cffunction name="init" access="public" returntype="any" output="false">
10        <cfargument name="controller" type="any" required="false" />
11
12        <cfscript>
13         super.Init(arguments.controller);
14         setpluginName("SagePay");
15         setpluginVersion("0.01");
16         setpluginDescription("SagePay plugin for VSP Direct using protocol version: 2.23");
17        //Return instance
18
        return this;
19        
</cfscript>
20    </cffunction>
21
22<!------------------------------------------- PUBLIC ------------------------------------------->
23<cffunction name="getPluginDetails" output="false" access="public" returntype="string" hint="Just for information and to test my first plugin function">
24 <!--- Get Event Context --->
25 <cfset var event = controller.getRequestService().getContext()>
26 <!--- Return the name in the event context --->
27 <cfreturn "#getpluginDescription()#. Have a nice day. #getEnvironment()#">
28</cffunction>
29
30
31<cffunction name="setEnvironment" access="public" hint="Set which gateway ULR's are to be used, simulator, test or live" output="false" returntype="struct">
32<!--- ************************************************************* --->
33<cfargument name="
gateway" type="string" required="true" default="simulator"/>
34<!--- ************************************************************* --->
35<cfset GatewaySettings = StructNew() />

36<cfscript>

37 if (arguments.gateway is "
simulator") {
38 StructInsert(GatewaySettings, "
Verify", "false");
39 StructInsert(GatewaySettings, "
PurchaseURL", "https://test.sagepay.com/Simulator/VSPDirectGateway.asp");
40
StructInsert(GatewaySettings, "RefundURL", "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRefundTx");
41
StructInsert(GatewaySettings, "
ReleaseURL", "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorReleaseTx");
42
StructInsert(GatewaySettings, "RepeatURL", "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRepeatTx");
43
StructInsert(GatewaySettings, "
callbackURL", "https://test.sagepay.com/Simulator/VSPDirectCallback.asp");
44
}
45 if (arguments.gateway is "test") {
46 StructInsert(GatewaySettings, "Verify", "false");
47 StructInsert(GatewaySettings, "PurchaseURL", "https://test.sagepay.com/gateway/service/vspdirect-register.vsp");
48
StructInsert(GatewaySettings, "
RefundURL", "https://test.sagepay.com/gateway/service/refund.vsp");
49
StructInsert(GatewaySettings, "ReleaseURL", "https://test.sagepay.com/gateway/service/release.vsp");
50
StructInsert(GatewaySettings, "
RepeatURL", "https://test.sagepay.com/gateway/service/repeat.vsp");
51
StructInsert(GatewaySettings, "callbackURL", "https://test.sagepay.com/gateway/service/direct3dcallback.vsp");
52
}
53 if (arguments.gateway is "
live") {
54 StructInsert(GatewaySettings, "
Verify", "false");
55 StructInsert(GatewaySettings, "
PurchaseURL", "https://live.sagepay.com/gateway/service/vspdirect-register.vsp");
56
StructInsert(GatewaySettings, "RefundURL", "https://live.sagepay.com/gateway/service/refund.vsp");
57
StructInsert(GatewaySettings, "
ReleaseURL", "https://live.sagepay.com/gateway/service/release.vsp");
58
StructInsert(GatewaySettings, "RepeatURL", "https://live.sagepay.com/gateway/service/repeat.vsp");
59
StructInsert(GatewaySettings, "
callbackURL", "https://live.sagepay.com/gateway/service/direct3dcallback.vsp");
60
}
61
</cfscript>
62 <cfreturn GatewaySettings>
63</cffunction>
64
65
66
67
68
69
70<cffunction name="makeCall" access="public" hint="Make Call" returntype="struct">
71<!--- ************************************************************* --->
72<cfargument name="PurchaseURL" type="string" required="yes">
73<cfargument name="VPSProtocol" type="string" required="yes">
74<cfargument name="vendor" type="string" required="yes">
75<cfargument name="VendorTxCode" type="string" required="yes">
76<cfargument name="DefaultCurrency" type="string" default="GBP" required="no">
77<cfargument name="Amount" type="any" required="yes">
78<cfargument name="CardHolder" type="string" required="yes">
79<cfargument name="CardNumber" type="string" required="yes">
80<cfargument name="DefaultApplyAVSCV2" type="string" required="no" default="0">
81<cfargument name="Basket" type="string" required="no" default="">
82<cfargument name="StartDate" type="string" required="no" default="">
83<cfargument name="ExpiryDate" type="string" required="yes">
84<cfargument name="DeliveryAddress" type="string" required="yes" default="">
85<cfargument name="CardType" type="string" required="yes">
86<cfargument name="BillingPostCode" type="string" required="yes">
87<cfargument name="DeliveryPostCode" type="string" required="yes">
88<cfargument name="CustomerName" type="string" required="yes">
89<cfargument name="ContactNumber" type="string" required="no" default="">
90<cfargument name="ContactFax" type="string" required="no" default="">
91<cfargument name="CustomerEmail" type="string" required="no" default="">
92<cfargument name="ClientIPAddress" type="string" required="no" default="#CGI.REMOTE_ADDR#">
93<cfargument name="CAVV" type="string" required="no" default="">
94<cfargument name="XID" type="string" required="no" default="">
95<cfargument name="ECI" type="string" required="no" default="">
96<cfargument name="DSecureStatus" type="string" required="no" default="">
97<cfargument name="CV2" type="string" required="no">
98<cfargument name="referrerID" type="string" required="no" default="">
99<cfargument name="DefaultDescription" type="string" required="no" default="Payment From #CustomerName#">
100<cfargument name="billfirstName" type="string" required="yes">
101<cfargument name="billlastName" type="string" required="yes">
102<cfargument name="BillingAddress1" type="string" required="yes">
103<cfargument name="billingcity" type="string" required="yes">
104<cfargument name="BillingCountry" type="string" required="no" default="GB">
105<cfargument name="ISSUENUMBER" type="string" required="no" default="">
106<!--- ************************************************************* --->
107<!--- ************************************************************* --->
108 <!---Get the contents of the post from the previous page and split out the variables for sending--->
109 <cfset RequestData = GetHttpRequestData()>
110 <cfset Response = StructNew()>
111 <cfloop list="#RequestData.content#" index="line" delimiters="&">
112 <cfset line = Trim( line )>
113 <cfset StructInsert( Response, Trim( ListFirst( line, "=" ) ), URLDecode(Trim(Mid(line,Find("=",line)+1,len(line)) )) )>
114 </cfloop>
115<!--- ************************************************************* --->
116<!---Set the required outgoing properties for the initial HTTPS post to the VPS--->
117<!--- ************************************************************* --->
118 <!---******************HERE IS WHERE THE ORDER GETS SENT TO PROTX VIA HTTPS*********************** --->
119 <cfhttp url="#PurchaseURL#" method="post" delimiter="," throwonerror="no">
120 <!---to combat IIS's compression scheme incompatible with CFHTTP this issue was fixed in MX7 but is back in CF8--->
121 <cfhttpparam type="Header" name="Accept-Encoding" value="deflate;q=0">
122 <cfhttpparam type="Header" name="TE" value="deflate;q=0">
123 <!---end--->
124 <cfhttpparam name="TxType" value="Payment" type="formfield">
125 <cfhttpparam name="VPSProtocol" value="#arguments.VPSProtocol#" type="formfield">
126 <cfhttpparam name="Vendor" value="#arguments.vendor#" type="formfield">
127 <cfhttpparam name="VendorTxCode" value="#arguments.VendorTxCode#" type="formfield">
128 <cfhttpparam name="referrerID" value="#arguments.referrerID#" type="formfield">
129 <cfhttpparam name="Currency" value="#arguments.DefaultCurrency#" type="formfield">
130 <cfhttpparam name="Description" value="#arguments.DefaultDescription#" type="formfield">
131 <cfhttpparam name="Amount" value="#arguments.Amount#" type="formfield">
132 <cfhttpparam name="CardHolder" value="#arguments.CardHolder#" type="formfield">
133 <cfhttpparam name="CardNumber" value="#arguments.CardNumber#" type="formfield">
134 <cfhttpparam name="GiftAidPayment" value="0" type="formfield">
135 <cfhttpparam name="ApplyAVSCV2" value="#arguments.DefaultApplyAVSCV2#" type="formfield">
136 <cfhttpparam name="BillingSurname" value="#arguments.billlastName#" type="formfield">
137 <cfhttpparam name="BillingFirstnames" value="#arguments.billfirstName#" type="formfield">
138 <cfhttpparam name="BillingCity" value="#arguments.billingcity#" type="formfield">
139 <cfhttpparam name="BillingCountry" value="#arguments.BillingCountry#" type="formfield">
140 <cfhttpparam name="DeliverySurname" value="#arguments.billlastName#" type="formfield">
141 <cfhttpparam name="DeliveryFirstnames" value="#arguments.billfirstName#" type="formfield">
142 <cfhttpparam name="DeliveryAddress1" value="#arguments.BillingAddress1#" type="formfield">
143 <cfhttpparam name="DeliveryCity" value="#arguments.BillingAddress1#" type="formfield">
144 <cfhttpparam name="DeliveryCountry" value="#arguments.BillingCountry#" type="formfield">
145 <cfhttpparam name="Basket" value="#arguments.Basket#" type="formfield">
146    <cfif #arguments.StartDate# is not "">
147 <cfhttpparam name="StartDate" value="#arguments.StartDate#" type="formfield">
148 </cfif>
149 <cfif #arguments.ExpiryDate# is not "">
150 <cfhttpparam name="ExpiryDate" value="#arguments.ExpiryDate#" type="formfield">
151 </cfif>
152 <cfif #arguments.DeliveryAddress# is not "">
153 <cfhttpparam name="DeliveryAddress" value="#arguments.DeliveryAddress#" type="formfield">
154 </cfif>
155 <cfhttpparam name="BillingAddress1" value="#arguments.BillingAddress1#" type="formfield">
156 <cfif #arguments.IssueNumber# is not "">
157 <cfhttpparam name="IssueNumber" value="#arguments.IssueNumber#" type="formfield">
158 </cfif>
159 <cfhttpparam name="CV2" value="#arguments.CV2#" type="formfield">
160 <cfhttpparam name="CardType" value="#arguments.CardType#" type="formfield">
161 <cfhttpparam name="BillingPostCode" value="#arguments.BillingPostCode#" type="formfield">
162 <cfif #arguments.DeliveryPostCode# is not "">
163 <cfhttpparam name="DeliveryPostCode" value="#arguments.DeliveryPostCode#" type="formfield">
164 </cfif>
165 <cfhttpparam name="CustomerName" value="#arguments.CustomerName#" type="formfield">
166    <cfif #arguments.ContactNumber# is not "">
167 <cfhttpparam name="ContactNumber" value="#arguments.ContactNumber#" type="formfield">
168 </cfif>
169 <cfif #arguments.ContactFax# is not "">
170 <cfhttpparam name="ContactFax" value="#arguments.ContactFax#" type="formfield">
171 </cfif>
172 <cfhttpparam name="CustomerEmail" value="#arguments.CustomerEmail#" type="formfield">
173 <cfif #arguments.ClientIPAddress# is not "">
174 <cfhttpparam name="ClientIPAddress" value="#arguments.ClientIPAddress#" type="formfield">
175 </cfif>
176 <cfif #arguments.CAVV# is not "">
177 <cfhttpparam name="CAVV" value="#arguments.CAVV#" type="formfield">
178 </cfif>
179 <cfif #arguments.XID# is not "">
180 <cfhttpparam name="XID" value="#arguments.XID#" type="formfield">
181 </cfif>
182 <cfif #arguments.ECI# is not "">
183 <cfhttpparam name="ECI" value="#arguments.ECI#" type="formfield">
184 </cfif>
185 <cfif #arguments.DSecureStatus# is not "">
186 <cfhttpparam name="3DSecureStatus" value="#arguments.arguments.DSecureStatus#" type="formfield">
187 </cfif>
188 </cfhttp>
189 <!--- ********************************END OF HTTPS POST TO PROTX******************************************--->
190 <cfset Response = StructNew()>
191 <!---if http post was ok--->
192 <cfif #cfhttp.statusCode# is "200 OK">
193 <cfloop list="#CFHTTP.FileContent#" index="line" delimiters="#chr(13)#">
194 <cfset line = Trim( line )>
195 <cfset StructInsert( Response, Trim( ListFirst( line, "=" ) ), Trim(Mid(line,Find("=",line)+1,len(line)) ) )>
196 </cfloop>
197 <!---if could not contact gateway--->
198 <cfelse>
199 <cfset StructInsert(Response, "Status", "timeout")>
200 <cfset StructInsert(Response, "StatusDetail", "Timeout Error: could not contact payment gateway or header code was not 200, please contact website owner.")>
201 </cfif>
202 <!---retrun responce--->
203 <cfreturn Response>
204</cffunction>
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223<!------------------------------------------- PRIVATE ------------------------------------------->
224
225</cfcomponent>

TweetBacks
Comments
Curt Gratz's Gravatar Glyn,

Think of a plugin like any other CFC, so the scopes would be the same. You can put the "SagePayURLStruct"
into the variables scope if you only want to access it inside the CFC, but need it available to other methods
(ie your "makecall" method) inside the CFC. If you need help with understanding the way scopes work in a
CFC, check out this super handy document made by Ray Camden.
<a href="http://www.coldfusionjedi.com/downloads/cfcscopes.... Scopes Reference</a>

Another thing that might be helpful is to look at some of the plugins within ColdBox for reference. Because Luis
has looked at them at all they are documented well so you should be able to follow the flow of the code.

If you haven't already you can read the <a href="http://ortus.svnrepository.com/coldbox/trac.cgi/wi... Plugins Guide</a>

Hope this helps.

Curt Gratz
Computer Know How
ColdBox Allaiance Partner
# Posted By Curt Gratz | 19/06/09 14:45
Glyn Jackson's Gravatar It does help, thanks Curt Gratz. the examples in CB are good its just I need to better understand them.

adding the SagePayURLStruct vars to a scope is an idea but would it be better to have the function created and accessible in the CFC by somehow creating an instance of the function at creation of the object right?

in the example pasted above the URL's that should be available to the object are depeneded on the gatway environment I would set, so something like this would be cool....


getPlugin(plugin="SagePay",customPlugin=true,newInstance=true).init(gateway=test);

then in the CFC all the correct URL's can be called dependant on the gateway mode set in the object creation.
# Posted By Glyn Jackson | 19/06/09 15:21
Curt Gratz's Gravatar Sorry about the links in the first comment.

Here they are corrected.

http://www.coldfusionjedi.com/downloads/cfcscopes....

http://ortus.svnrepository.com/coldbox/trac.cgi/wi...

Take a look at the paging plugin under ColdBox. The Init method looks like this.

<cffunction name="init" access="public" returntype="paging" output="false">
      <cfargument name="controller" type="any" required="true">
      <cfscript>
      super.Init(arguments.controller);
      setpluginName("paging");
      setpluginVersion("1.0");
      setpluginDescription("Paging plugin");

      /* Paging properties */
      setPagingMaxRows( getSetting("PagingMaxRows") );
      setPagingBandGap( getSetting('PagingBandGap') );

      //Return instance
      return this;
      </cfscript>
   </cffunction>

Then the setPagingMaxRows looks like this.

   <cffunction name="setPagingMaxRows" access="public" returntype="void" hint="Set the paging max rows setting" output="false">
      <cfargument name="pagingMaxRows" required="true" type="numeric">
      <cfset instance.pagingMaxRows = arguments.pagingMaxRows>
   </cffunction>



So, you could do the same thing in your case. Just set a setting under the <YourSettings> section of your ColdBox
config file.

Make sense?

Curt Gratz
Computer Know How
Coldbox Alliance Parnter
# Posted By Curt Gratz | 19/06/09 17:24
Glyn Jackson's Gravatar Perfect, thanks. I now see how that would work. I know I am being a pain but seeing as CB helps with OOP how would you define the code above in OO. By this I mean it cannot be a principle of Encapsulation at all, it could sort of Polymorhism in a not so OO way if you know what I mean. Maybe I am looking at this wrong or from a JAVA prospective, another topic I am sure. I can see CB and CF lends itself to Inheritance very well I like the way you can extend the framework/CFCs while however as I try to apply as many OO principles as I can/remember correctly in CB its confusing me. I am not sure if I am approaching this the right way anymore or if I need to change my way of thinking/understanding of CB. anyhow thanks for your help
# Posted By Glyn Jackson | 20/06/09 19:14
 

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