408 lines
No EOL
16 KiB
Text
408 lines
No EOL
16 KiB
Text
<!---
|
|
|
|
Copyright 2009 Joseph Lamoree (http://www.lamoree.com/)
|
|
Copyright 2008 Brian Ghidinelli (http://www.ghidinelli.com/)
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you
|
|
may not use this file except in compliance with the License. You may
|
|
obtain a copy of the License at:
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
|
|
TODO: Add support for API Certificate Security, as well as API Signature Security
|
|
|
|
Configuration
|
|
Username: provided by PayPal in syntax of e-mail address
|
|
Password: provided by PayPal as 16 alphanumeric char string
|
|
APIVersion: 56.0 (default)
|
|
CredentialType: signature (default) or certificate
|
|
Signature: required for signature credential authentication type
|
|
Certificate: required for certificate credential authentication type
|
|
FraudManagement: off (default) or on; Enables robust fraud management, which is an optional PayPal service
|
|
Masking: on (default) or off; Masks account data to comply with PCI DSS
|
|
ReturnURL The URL that PayPal will use to return the customer
|
|
CancelURL The URL that PayPal will use if a customer cancels the order
|
|
|
|
--->
|
|
<cfcomponent extends="cfpayment.api.gateway.base" hint="Name-Value Pair API Gateway for PayPal Website Payments Pro" output="false">
|
|
|
|
<!--- cfpayment structure values override base class --->
|
|
<cfset variables.cfpayment.GATEWAY_NAME = "Name-Value Pair API Gateway for PayPal Website Payments Pro" />
|
|
<cfset variables.cfpayment.GATEWAY_VERSION = "1.0" />
|
|
<cfset variables.cfpayment.GATEWAY_TEST_URL = "https://api-3t.sandbox.paypal.com/nvp" />
|
|
<cfset variables.cfpayment.GATEWAY_LIVE_URL = "https://api-3t.paypal.com/nvp" />
|
|
<cfset variables.cfpayment.GATEWAY_TEST_CLIENT_URL = "https://www.sandbox.paypal.com/cgi-bin/webscr" />
|
|
<cfset variables.cfpayment.GATEWAY_LIVE_CLIENT_URL = "https://www.paypal.com/cgi-bin/webscr" />
|
|
<cfset variables.cfpayment.GATEWAY_API_VERSION = "56.0" />
|
|
<cfset variables.cfpayment.GATEWAY_CREDENTIAL_TYPE = "signature" />
|
|
<cfset variables.cfpayment.GATEWAY_SIGNATURE = "" />
|
|
<cfset variables.cfpayment.GATEWAY_CERTIFICATE = "" />
|
|
<cfset variables.cfpayment.GATEWAY_MASKING = "on" />
|
|
<cfset variables.cfpayment.GATEWAY_FRAUD_MANAGEMENT = "off" />
|
|
<cfset variables.cfpayment.GATEWAY_RETURN_URL = "http://localhost/index.cfm?event=confirmPayPalOrder" />
|
|
<cfset variables.cfpayment.GATEWAY_CANCEL_URL = "http://localhost/index.cfm?event=cancelPayPalOrder" />
|
|
|
|
|
|
<cffunction name="purchase" returntype="any" access="public" output="false">
|
|
<cfargument name="money" type="any" required="true" />
|
|
<cfargument name="account" type="any" required="true" />
|
|
<cfargument name="options" type="struct" required="false" default="#structNew()#" />
|
|
|
|
<cfset var post = structNew() />
|
|
|
|
<cfset post.AMT = arguments.money.getAmount() />
|
|
<cfset post.CURRENCYCODE = arguments.money.getCurrency() />
|
|
<cfset post.METHOD = "DoDirectPayment" />
|
|
<cfset addCustomer(post=post, account=arguments.account, options=arguments.options) />
|
|
<cfset addCreditCard(post=post, account=arguments.account) />
|
|
<cfset addClient(post, arguments.options) />
|
|
|
|
<!--- TODO: Support Sale, Authorization, and Order? --->
|
|
<cfset post.PAYMENTACTION = "Sale" />
|
|
|
|
<cfreturn process(payload=post, options=arguments.options) />
|
|
</cffunction>
|
|
|
|
<cffunction name="setExpressCheckout" returntype="any" access="public" output="false">
|
|
<cfargument name="money" type="any" required="true" />
|
|
<cfargument name="options" type="struct" required="false" default="#structNew()#" />
|
|
|
|
<cfset var post = structNew() />
|
|
|
|
<cfset post.METHOD = "SetExpressCheckout" />
|
|
<cfset post.AMT = arguments.money.getAmount() />
|
|
<cfset post.CURRENCYCODE = arguments.money.getCurrency() />
|
|
<cfset post.RETURNURL = getReturnURL() />
|
|
<cfset post.CANCELURL = getCancelURL() />
|
|
|
|
<!--- TODO: Support Sale, Authorization, and Order? --->
|
|
<cfset post.PAYMENTACTION = "Sale" />
|
|
|
|
<cfreturn process(payload=post, options=arguments.options) />
|
|
</cffunction>
|
|
|
|
<cffunction name="getExpressCheckoutDetails" returntype="any" access="public" output="false">
|
|
<cfargument name="options" type="struct" required="false" default="#structNew()#" />
|
|
|
|
<cfset var post = structNew() />
|
|
|
|
<cfset post.METHOD = "GetExpressCheckoutDetails" />
|
|
<cfset post.TOKEN = arguments.options.tokenId />
|
|
<cfreturn process(payload=post, options=arguments.options) />
|
|
</cffunction>
|
|
|
|
<cffunction name="doExpressCheckoutPayment" returntype="any" access="public" output="false">
|
|
<cfargument name="money" type="any" required="true" />
|
|
<cfargument name="options" type="struct" required="false" default="#structNew()#" />
|
|
|
|
<cfset var post = structNew() />
|
|
|
|
<cfset post.METHOD = "DoExpressCheckoutPayment" />
|
|
<cfset post.AMT = arguments.money.getAmount() />
|
|
<cfset post.CURRENCYCODE = arguments.money.getCurrency() />
|
|
<cfset post.TOKEN = arguments.options.tokenId />
|
|
<cfset post.PAYERID = arguments.options.payerId />
|
|
|
|
<!--- TODO: Support Sale, Authorization, and Order? --->
|
|
<cfset post.PAYMENTACTION = "Sale" />
|
|
|
|
<cfreturn process(payload=post, options=arguments.options) />
|
|
</cffunction>
|
|
|
|
<cffunction name="cancelExpressCheckout" returntype="any" access="public" output="false">
|
|
<cfargument name="options" type="struct" required="false" default="#structNew()#" />
|
|
|
|
<cfset var result = structNew() />
|
|
|
|
<cfreturn result />
|
|
</cffunction>
|
|
|
|
|
|
<cffunction name="getExpressCheckoutForward" returntype="string" access="public" output="false">
|
|
<cfargument name="tokenId" type="string" required="true" />
|
|
|
|
<cfset var u = "" />
|
|
|
|
<cfif getTestMode()>
|
|
<cfset u = variables.cfpayment.GATEWAY_TEST_CLIENT_URL />
|
|
<cfelse>
|
|
<cfset u = variables.cfpayment.GATEWAY_LIVE_CLIENT_URL />
|
|
</cfif>
|
|
<cfset u = u & "?cmd=_express-checkout&token=" & urlEncodedFormat(arguments.tokenId) />
|
|
<cfreturn u />
|
|
</cffunction>
|
|
|
|
|
|
<cffunction name="process" returntype="any" access="private" output="false">
|
|
<cfargument name="payload" type="struct" required="true" />
|
|
<cfargument name="options" type="struct" required="true" />
|
|
|
|
<cfset var response = "null" />
|
|
<cfset var results = structNew() />
|
|
<cfset var rd = "null" />
|
|
<cfset var n = "" />
|
|
|
|
<cfset arguments.payload.VERSION = getAPIVersion() />
|
|
<cfset addCredentials(arguments.payload) />
|
|
<cfset response = createResponse(argumentCollection = super.process(payload=arguments.payload)) />
|
|
|
|
<cfif response.hasError()>
|
|
<!--- Service did not receive an HTTP response --->
|
|
<cfset response.setStatus(getService().getStatusUnknown()) />
|
|
<cfelse>
|
|
<cfset results = parseResponse(response.getResult()) />
|
|
<cfset response.setParsedResult(results) />
|
|
|
|
<cfif arguments.payload.METHOD eq "DoDirectPayment">
|
|
<cfif structKeyExists(results, "AVSCODE")>
|
|
<cfset response.setAVSCode(results.AVSCODE) />
|
|
</cfif>
|
|
<cfif structKeyExists(results, "CVV2MATCH")>
|
|
<cfset response.setCVVCode(results.CVV2MATCH) />
|
|
</cfif>
|
|
</cfif>
|
|
|
|
<cfif results.ACK eq "Failure">
|
|
<cfset response.setStatus(getService().getStatusDeclined()) />
|
|
<cfif structKeyExists(results, "L_LONGMESSAGE0")>
|
|
<cfset response.setMessage(results.L_LONGMESSAGE0) />
|
|
</cfif>
|
|
<cfelseif results.ACK eq "Success">
|
|
<cfset response.setStatus(getService().getStatusSuccessful()) />
|
|
|
|
|
|
|
|
<!--- Credit Cards --->
|
|
<cfif structKeyExists(arguments.payload, "PAYMENTACTION")>
|
|
<cfif arguments.payload.PAYMENTACTION eq "Authorization">
|
|
<cfif structKeyExists(results, "TRANSACTIONID")>
|
|
<cfset response.setAuthorization(results.TRANSACTIONID) />
|
|
</cfif>
|
|
<cfelseif arguments.payload.PAYMENTACTION eq "Sale">
|
|
<cfif structKeyExists(results, "TRANSACTIONID")>
|
|
<cfset response.setTransactionId(results.TRANSACTIONID) />
|
|
</cfif>
|
|
<cfif structKeyExists(results, "TOKEN")>
|
|
<cfset response.setTokenId(results.TOKEN) />
|
|
</cfif>
|
|
</cfif>
|
|
</cfif>
|
|
<cfelse>
|
|
<cfset response.setStatus(getService().getStatusFailure()) />
|
|
</cfif>
|
|
</cfif>
|
|
|
|
<!--- Mask the request data --->
|
|
<cfif getMasking() eq "on">
|
|
<cfset rd = response.getRequestData() />
|
|
<cfif isStruct(rd) AND structKeyExists(rd, "payload")>
|
|
<cfloop collection="#rd.PAYLOAD#" item="n">
|
|
<cfset rd.PAYLOAD[n] = mask(n, rd.PAYLOAD[n]) />
|
|
</cfloop>
|
|
<cfset response.setRequestData(rd) />
|
|
</cfif>
|
|
</cfif>
|
|
<cfreturn response />
|
|
</cffunction>
|
|
|
|
|
|
<cffunction name="parseResponse" returntype="struct" access="private" output="false">
|
|
<cfargument name="data" type="string" required="true" />
|
|
|
|
<cfset var parsed = structNew() />
|
|
<cfset var pair = "" />
|
|
<cfset var name = "" />
|
|
<cfset var value = "" />
|
|
|
|
<cfloop list="#arguments.data#" index="pair" delimiters="&">
|
|
<cfset name = listFirst(pair, "=") />
|
|
<cfif listLen(pair, "=") gt 1>
|
|
<cfset value = urlDecode(listLast(pair, "=")) />
|
|
<cfelse>
|
|
<cfset value = "" />
|
|
</cfif>
|
|
<cfif getMasking() eq "on">
|
|
<cfset parsed[name] = mask(name, value) />
|
|
<cfelse>
|
|
<cfset parsed[name] = value />
|
|
</cfif>
|
|
</cfloop>
|
|
<cfreturn parsed />
|
|
</cffunction>
|
|
|
|
|
|
|
|
<cffunction name="addCredentials" returntype="void" access="private" output="false">
|
|
<cfargument name="payload" type="struct" required="true" />
|
|
|
|
<cfset arguments.payload.USER = getUsername() />
|
|
<cfset arguments.payload.PWD = getPassword() />
|
|
|
|
<cfif getCredentialType() eq "signature">
|
|
<cfset arguments.payload.SIGNATURE = getSignature() />
|
|
<cfelseif getCredentialType() eq "certificate">
|
|
<cfset arguments.payload.CERTIFICATE = getCertificate() />
|
|
<cfelse>
|
|
<cfset createObject("component", "GatewayException").init(type="UnsupportedCredentialTypeException", message="An unsupported credential type was specified.").doThrow() />
|
|
</cfif>
|
|
</cffunction>
|
|
|
|
<cffunction name="addClient" returntype="void" access="private" output="false">
|
|
<cfargument name="payload" type="struct" required="true" />
|
|
<cfargument name="options" type="struct" required="true" />
|
|
|
|
<cfif not structKeyExists(arguments.options, "ipAddress")>
|
|
<cfset createObject("component", "GatewayException").init(type="RequiredParameterMissingException", message="The ipAddress is a required parameter.").doThrow() />
|
|
</cfif>
|
|
<cfset arguments.payload.IPADDRESS = arguments.options.ipAddress />
|
|
</cffunction>
|
|
|
|
<cffunction name="addCustomer" returntype="void" access="private" output="false">
|
|
<cfargument name="post" type="struct" required="true" />
|
|
<cfargument name="account" type="any" required="true" />
|
|
<cfargument name="options" type="struct" required="true" />
|
|
|
|
<cfset var p = arguments.post />
|
|
<cfset var a = arguments.account />
|
|
|
|
<cfset p.UserFirstName = a.getFirstName() />
|
|
<cfset p.LaerFirstName = a.getLastName() />
|
|
<cfset p.STREET = a.getAddress() />
|
|
<cfset p.STREET2 = a.getAddress2() />
|
|
<cfset p.CITY = a.getCity() />
|
|
<cfset p.STATE = a.getRegion() />
|
|
<cfset p.COUNTRYCODE = a.getCountry() />
|
|
<cfset p.ZIP = a.getPostalCode() />
|
|
<cfset p.PHONENUM = a.getPhoneNumber() />
|
|
<cfif structKeyExists(arguments.options, "email") and arguments.options.email neq "">
|
|
<cfset p.EMAIL = arguments.options.email />
|
|
</cfif>
|
|
<cfif structKeyExists(arguments.options, "company") and arguments.options.company neq "">
|
|
<cfset p.BUSINESS = arguments.options.company />
|
|
</cfif>
|
|
</cffunction>
|
|
|
|
<cffunction name="addCreditCard" returntype="void" access="private" output="false">
|
|
<cfargument name="post" type="struct" required="true" />
|
|
<cfargument name="account" type="any" required="true" />
|
|
|
|
<cfset var p = arguments.post />
|
|
<cfset var a = arguments.account />
|
|
|
|
<cfif a.getIsVisa()>
|
|
<cfset p.CREDITCARDTYPE = "Visa" />
|
|
<cfelseif a.getIsMasterCard()>
|
|
<cfset p.CREDITCARDTYPE = "MasterCard" />
|
|
<cfelseif a.getIsAmex()>
|
|
<cfset p.CREDITCARDTYPE = "Amex" />
|
|
<cfelseif a.getIsDiscover()>
|
|
<cfset p.CREDITCARDTYPE = "Discover" />
|
|
<cfelse>
|
|
<cfset createObject("component", "GatewayException").init(type="UnsupportedCardTypeException", message="An unsupported credit card type was specified.").doThrow() />
|
|
</cfif>
|
|
|
|
<cfset p.ACCT = a.getAccount() />
|
|
<cfset p.EXPDATE = a.getMonth() & a.getYear() />
|
|
<cfset p.CVV2 = a.getVerificationValue() />
|
|
</cffunction>
|
|
|
|
<cffunction name="mask" returntype="string" access="private" output="false">
|
|
<cfargument name="name" type="string" required="true" />
|
|
<cfargument name="value" type="string" required="true" />
|
|
|
|
<cfscript>
|
|
var r = "";
|
|
var n = arguments.name;
|
|
var v = arguments.value;
|
|
|
|
// Don't let any exceptions stop the transaction
|
|
try {
|
|
if (compareNoCase("ACCT", n) eq 0) {
|
|
r = repeatString("X", len(v) - 4) + right(v, 4);
|
|
} else if (listContainsNoCase("CVV2,PWD,SIGNATURE", n) gt 0) {
|
|
r = repeatString("X", len(v));
|
|
} else {
|
|
r = v;
|
|
}
|
|
}
|
|
catch(Any e) {
|
|
// Fail without disclosing any data
|
|
r = "MaskingException on #n#";
|
|
}
|
|
return r;
|
|
</cfscript>
|
|
</cffunction>
|
|
|
|
|
|
<cffunction name="getCredentialType" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_CREDENTIAL_TYPE />
|
|
</cffunction>
|
|
<cffunction name="setCredentialType" returntype="void" access="public" output="false">
|
|
<cfargument name="credentialType" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_CREDENTIAL_TYPE = arguments.credentialType />
|
|
</cffunction>
|
|
|
|
<cffunction name="getAPIVersion" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_API_VERSION />
|
|
</cffunction>
|
|
<cffunction name="setAPIVersion" returntype="void" access="public" output="false">
|
|
<cfargument name="apiVersion" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_API_VERSION = arguments.apiVersion />
|
|
</cffunction>
|
|
|
|
<cffunction name="getSignature" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_SIGNATURE />
|
|
</cffunction>
|
|
<cffunction name="setSignature" returntype="void" access="public" output="false">
|
|
<cfargument name="signature" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_SIGNATURE = arguments.signature />
|
|
</cffunction>
|
|
|
|
<cffunction name="getCertificate" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_CERTIFICATE />
|
|
</cffunction>
|
|
<cffunction name="setCertificate" returntype="void" access="public" output="false">
|
|
<cfargument name="certificate" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_CERTIFICATE = arguments.certificate />
|
|
</cffunction>
|
|
|
|
<cffunction name="getFraudManagement" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_FRAUD_MANAGEMENT />
|
|
</cffunction>
|
|
<cffunction name="setFraudManagement" returntype="void" access="public" output="false">
|
|
<cfargument name="fraudManagement" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_FRAUD_MANAGEMENT = arguments.fraudManagement />
|
|
</cffunction>
|
|
|
|
<cffunction name="getMasking" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_MASKING />
|
|
</cffunction>
|
|
<cffunction name="setMasking" returntype="void" access="public" output="false">
|
|
<cfargument name="masking" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_MASKING = arguments.masking />
|
|
</cffunction>
|
|
|
|
<cffunction name="getReturnURL" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_RETURN_URL />
|
|
</cffunction>
|
|
<cffunction name="setReturnURL" returntype="void" access="public" output="false">
|
|
<cfargument name="returnURL" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_RETURN_URL = arguments.returnURL />
|
|
</cffunction>
|
|
|
|
<cffunction name="getCancelURL" returntype="string" access="public" output="false">
|
|
<cfreturn variables.cfpayment.GATEWAY_CANCEL_URL />
|
|
</cffunction>
|
|
<cffunction name="setCancelURL" returntype="void" access="public" output="false">
|
|
<cfargument name="cancelURL" type="string" required="true" />
|
|
<cfset variables.cfpayment.GATEWAY_CANCEL_URL = arguments.cancelURL />
|
|
</cffunction>
|
|
|
|
</cfcomponent> |