PayPalMX 1.0 User's Guide - Home Page
Introduction
What is PayPalMX?
PayPalMX is a service- based system for ColdFusion development projects, enabling developers to quickly and easily integrate PayPal's Payment Data Transfer (PDT) and Instant Payment Notification (IPN) functionality into web applications. It features a very simple but powerful interface to provide instant synchronous and asynchronous payment verification via PayPal's public services PDT and IPN.
Care and Feeding
PayPalMX is comprised of four ColdFusion classes (or CFC files) and an XML file:
Public Interface Components
-
PayPalService.cfc
PayPalService.cfc is responsible for maintaining the contents of the XML config file in RAM, and for parsing that XML file, as well as for providing the PDT and IPN validation routines. Additionally, it provides the getForm() method, which returns a fully-formatted HTML form generated by the PayPal Button Maker.
- init("mode","relativeXmlPath") returns PayPalService instance
- verifyIpnData(IpnDataStruct) returns PayPalTO instance
- validatePdtData("txToken") returns PayPalTO instance
- getForm("formName") returns String
-
PayPalTO.cfc
PayPalTO.cfc is responsible for transferring the results of a call to one of the validation routines (verifyIpnData() and validatePdtData()) to the calling code. Applications must use the syntax myVar = payPalService.validatePdtData(), and after that call myVar will contain an instance of PayPalTO.cfc. It is used to provide a common interface to the results of PDT and IPN payment validation.
- getInstance() returns struct
- getParameterList() returns string
- getParameterArray() returns array
- getParameter("paramName") returns param
- paramExists("paramName") returns boolean
- paymentReceived() returns boolean
- getStatus() returns string
- getServiceMessage() returns string
Private Interface Components
- xmlHandler.cfc
- fileHandler.cfc
XML File Elements
- paypal
- pdt
- sandbox - contains the sandbox seller token
- live - contains the live seller token
- urls
- sandbox - contains the sandbox PayPal URL
- live - contains the live PayPal URL
- buynow
- sandbox
- These sub-elements are named by the user, named to match the argument to getForm("formName") in sandbox mode
- live
- These sub-elements are named by the user, named to match the argument to getForm("formName") in live mode
- sandbox
- pdt
To use PayPalMX
Simply instantiate PayPalService.cfc in a shared scope or into the page-local variables scope and call verifyIpnData(formScope) or validatePdtData("transactionToken") to process the incoming data from PayPal. This will cause PayPalMX to interact with PayPal and return a transfer object containing the results.
If you wish to use PayPal.xml to store your BuyNow buttons, you should save them to the XML file as shown in the next section, then call getForm("productName") against the PayPalMX instance. It returns a simple string containing the HTML text defined in your XML file.
Since the product is delivered without masking the source, you're free to modify it if you wish. Please remember, however, that support for modified implementations of the PayPalMX is not free.
Usage Examples
Form Retrieval
To retrieve a form from PayPalMX, code your application as follows:
<!--- for a single request call --->
<cfset myForm = createObject("component","payPalPDT").init("sandbox","paypal.xml").getForm("productOfMine")>
<cfoutput>#myForm#</cfoutput>
<!--- alternatively --->
<cfset application["PayPalSVC"] = createObject("component","payPalPDT").init("sandbox","paypal.xml").getForm("productOfMine")>
<!--- later in the application --->
<cfoutput>#application.PayPalSVC.getForm("productOfMine")#</cfoutput>
This functionality allows you to define a form in the XML file and then recall it by name. PayPalMX will throw an error if there's no form defined by that name and under the current mode. Therefore you must define your forms in pairs, one under live and one under sandbox, and be careful to use the same name for each one.
For this example, the form was created using the buttom generator in PayPal's live and sandbox sites and certain values have been truncated for the sake of brevity.
The XML involved looks like this:
<paypal>
<buynow>
<sandbox>
<productOfMine><![CDATA[
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="image" src="{imageURL}" border="0" name="submit">
<input type="hidden" name="encrypted" value="{encrypted form data}">
</form>]]>
</productOfMine>
</sandbox>
<live>
<productOfMine><![CDATA[
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="image" src="{imageURL}" border="0" name="submit">
<input type="hidden" name="encrypted" value="{encrypted form data}">
</form>]]>
</productOfMine>
</live>
</buynow>
</paypal>
You'll probably notice that the form itself is simply an HTML form. For now, it will be best to continue using the Button Generator at PayPal.com to create the BuyNow buttons for your applications. Future versions of PayPalMX will incorporate a wider variety of existing PayPal options.
Once you have the text of the BuyNow button, you can simply copy/paste it into the XML file, being careful to leave the <![CDATA[...]]> block wrapped around the form contents. The CDATA wrapper tells xmlParse() to render its contents as-is and not parse them, effectively treating XML-invalid characters as valid.
Payment Processing
Note: It is STRONGLY recommended that your paypal.xml file reside in a folder NOT web-accessible. Failing to do so exposes your XML file, along with your PayPal tokens, to clever but malicious persons hoping to cash in on ignorance or negligence.
For handling payments via the web, the code in your application is going to look something like this:
<!--- In your application logic, i.e. in a fuseaction or event/broadcast --->
<cfset PayPalSVC = createObject("component","PayPalService").init("sandbox","paypal.xml")>
<!--- or --->
<cfset server.PayPalSVC = createObject("component","PayPalService").init("sandbox","paypal.xml")>
<!--- or --->
<cfset application.PayPalSVC = createObject("component","PayPalService").init("sandbox","paypal.xml")>
<!--- in the app, be it event, fuseaction, broadcast, or inline; whereever you actually want to do the validation --->
<cfset MyPayPalTO = PayPalSVC.validatePdtData(url.tx)> <!--- could also capture form.tx --->
<!--- or --->
<cfset MyPayPalTO = PayPalSVC.verifyIpnData(form)> <!--- could also capture URL --->
The XML looks like this:
<paypal>
<pdt>
<sandbox>j89KJ2jK_P2jKS8fsdKtxHYj89KJ2jKY5E1PM0j89KJ2jKv6z1HDpkjMcy</sandbox>
<live>j89KJ2jKwxn7udF1j89KJ2jKAdUaAn8kM_tcuBj89KJ2jKeLHXj89KJ2jKG</live>
</pdt>
<urls>
<sandbox>https://www.sandbox.paypal.com/cgi-bin/webscr</sandbox>
<live>https://www.paypal.com/cgi-bin/webscr</live>
</urls>
<paypal>
These values are used to provide the tokens needed for PDT validation and the URLs used by both PDT and IPN. Each value is read into PayPalMX's instance data based on the "mode" argument passed to init(). If you're using this system with a framework like Model-glue, Fusebox, or MachII it's recommended that you tie the PayPalMX mode to the application's status (production vs. development). This way you can provide an automatic switch from PayPal's sandbox system to their production system when you put the application into production or development mode.
Links and References
Other documentation in this package: