380 lines
No EOL
17 KiB
Text
380 lines
No EOL
17 KiB
Text
<!---
|
||
$Id$
|
||
|
||
Copyright 2011 Shawn Mckee (http://www.clinicapps.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.
|
||
--->
|
||
<cfcomponent displayname="GoEMerchant Gateway" extends="cfpayment.api.gateway.base" output="false" hint="Provides credit card process for GoEMerchant">
|
||
|
||
<!--- gateway specific variables --->
|
||
<cfset variables.cfpayment.GATEWAYID = "1" />
|
||
<cfset variables.cfpayment.GATEWAY_NAME = "GoEmerchant Gateway" />
|
||
<cfset variables.cfpayment.GATEWAY_VERSION = "1" />
|
||
<cfset variables.cfpayment.GATEWAY_LIVE_URL = "https://secure.goemerchant.com/secure/gateway/xmlgateway.aspx" />
|
||
<cfset variables.cfpayment.GATEWAY_TEST_URL = variables.cfpayment.GATEWAY_LIVE_URL /> <!--- test mode determined by processor, mid, and tid --->
|
||
<cfset variables.cfpayment.MerchantAccount = "" />
|
||
<cfset variables.cfpayment.Username = "" />
|
||
<cfset variables.cfpayment.Password = "" />
|
||
<cfset variables.cfpayment.TestMode = true />
|
||
<cfset variables.cfpayment.processor = "">
|
||
<cfset variables.cfpayment.mid = "" />
|
||
<cfset variables.cfpayment.tid = "" />
|
||
|
||
|
||
<cffunction name="init" access="public" output="false" returntype="any">
|
||
<cfset super.init(argumentCollection = arguments) />
|
||
|
||
<cfif variables.cfpayment.TestMode>
|
||
<cfset variables.cfpayment.processor = "sandbox">
|
||
<cfset variables.cfpayment.mid = arguments.config.mid />
|
||
<cfset variables.cfpayment.tid = arguments.config.tid />
|
||
</cfif>
|
||
|
||
<cfreturn this />
|
||
</cffunction>
|
||
|
||
|
||
<!--- implemented functions --->
|
||
<cffunction name="process" access="private" returntype="struct" output="true">
|
||
<cfargument name="payload" type="string" required="true" />
|
||
<cfargument name="options" type="struct" required="true" />
|
||
|
||
<cfset var local = structNew() />
|
||
<cfoutput>
|
||
<cfsavecontent variable="local.strXML">
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<TRANSACTION>
|
||
<FIELDS>
|
||
<FIELD KEY="transaction_center_id">#variables.cfpayment.userName#</FIELD>
|
||
<FIELD KEY="gateway_id">#variables.cfpayment.MerchantAccount#</FIELD>
|
||
<FIELD KEY="mid">#variables.cfpayment.mid#</FIELD>
|
||
<FIELD KEY="tid">#variables.cfpayment.tid#</FIELD>
|
||
<FIELD KEY="processor">#variables.cfpayment.processor#</FIELD>
|
||
<FIELD KEY="operation_type">#arguments.options.operationType#</FIELD>
|
||
<cfoutput>
|
||
#arguments.payload#
|
||
</cfoutput>
|
||
<cfif !find("::1", cgi.REMOTE_ADDR)>
|
||
<FIELD KEY="remote_ip_address">#cgi.REMOTE_ADDR#</FIELD>
|
||
<cfelse>
|
||
<FIELD KEY="remote_ip_address">127.0.0.1</FIELD>
|
||
</cfif>
|
||
</FIELDS>
|
||
</TRANSACTION>
|
||
</cfsavecontent>
|
||
</cfoutput>
|
||
|
||
<cfset local.h = { "Content-Type" = "text/xml" } />
|
||
<cfset local.p = local.strXML.trim()>
|
||
<cfset local.processorData = createResponse(argumentCollection = super.process(payload = local.p, headers=local.h)) />
|
||
|
||
|
||
<cfif !local.processorData.hasError()>
|
||
<cfset local.processorXMLData = XmlParse(local.processorData.getResult())>
|
||
|
||
<cfset local.fieldNodes = xmlSearch(local.processorXMLData,'/RESPONSE/FIELDS/FIELD')>
|
||
|
||
<cfloop index="local.field" array="#local.fieldNodes#">
|
||
<cfset local.response[field.XmlAttributes.Key] = field.XmlText />
|
||
</cfloop>
|
||
<cfif structKeyExists(local.response, "status")>
|
||
<cfif local.response.status EQ 0>
|
||
<cfset local.processorData.setStatus(getService().getStatusUnprocessed()) />
|
||
<cfset local.processorData.setAuthorization(local.response.auth_code) />
|
||
<cfset local.processorData.setTransactionID(local.response.reference_number) /> <!--- generated by GoEMerchant --->
|
||
<cfset local.processorData.setTokenID(local.response.order_id) /> <!--- your order ID sent to GoEMerchant --->
|
||
<cfset local.processorData.setMessage(local.response.error) />
|
||
|
||
<cfelseif local.response.status EQ 1>
|
||
|
||
<cfset local.processorData.setStatus(getService().getStatusSuccessful()) />
|
||
<cfset local.processorData.setAuthorization(local.response.auth_code) />
|
||
<cfset local.processorData.setTransactionID(local.response.reference_number) /> <!--- generated by GoEMerchant --->
|
||
<cfset local.processorData.setTokenID(local.response.order_id) /> <!--- your order ID sent to GoEMerchant --->
|
||
|
||
<!--- leave avs response blank if no answer is returned --->
|
||
<cfif len(trim(local.response.avs_code))>
|
||
<cfset local.processorData.setAVSCode(local.response.avs_code) />
|
||
</cfif>
|
||
|
||
<!--- leave cvv2 response blank if no answer is returned --->
|
||
<cfif len(trim(local.response.cvv2_code))>
|
||
<cfset local.processorData.setCVVCode(local.response.cvv2_code) />
|
||
</cfif>
|
||
|
||
<cfset local.processorData.setMessage(local.response.auth_response) />
|
||
|
||
<cfelseif local.response.status EQ 2>
|
||
<cfif trim(local.response.auth_code) EQ "">
|
||
<cfset local.processorData.setStatus(getService().getStatusDeclined()) />
|
||
<cfset local.processorData.setAuthorization(local.response.auth_code) />
|
||
<cfset local.processorData.setTransactionID(local.response.reference_number) /> <!--- generated by GoEMerchant --->
|
||
<cfset local.processorData.setTokenID(local.response.order_id) /> <!--- your order ID sent to GoEMerchant --->
|
||
<cfset local.processorData.setMessage("Declined") />
|
||
<cfelse>
|
||
<cfset local.processorData.setStatus(getService().getStatusFailure()) />
|
||
<cfset local.processorData.setAuthorization(local.response.auth_code) />
|
||
<cfset local.processorData.setTransactionID(local.response.reference_number) /> <!--- generated by GoEMerchant --->
|
||
<cfset local.processorData.setTokenID(local.response.order_id) /> <!--- your order ID sent to GoEMerchant --->
|
||
<cfset local.processorData.setMessage("Auth Code: '#local.response.auth_code#' - Auth Response: '#local.response.auth_response#' - Error: '#local.response.error#'") />
|
||
</cfif>
|
||
<cfelse>
|
||
<cfset local.processorData.setStatus(getService().getStatusUnknown()) />
|
||
<cfset local.processorData.setTokenID(arguments.options.order_ID) />
|
||
<cfset local.processorData.setMessage("GoEMerchant status unrecognized: #local.response.status# ERROR: #local.response.error#") />
|
||
</cfif>
|
||
<cfelseif structKeyExists(local.response, "status1")> <!--- void, credit or settle --->
|
||
<cfif local.response.status1 EQ 1>
|
||
<cfset local.processorData.setStatus(getService().getStatusSuccessful()) />
|
||
<cfif structKeyExists(local.response, "batch_number1")>
|
||
<cfset local.processorData.setTransactionID(local.response.batch_number1) /> <!--- generated by GoEMerchant for settle --->
|
||
</cfif>
|
||
<cfset local.processorData.setTokenID(arguments.options.order_ID) /> <!--- your order ID sent to GoEMerchant --->
|
||
<cfelseif local.response.status1 EQ 2>
|
||
<cfset local.processorData.setStatus(getService().getStatusFailure()) />
|
||
<cfset local.processorData.setTransactionID(local.response.reference_number1) /> <!--- generated by GoEMerchant --->
|
||
<cfset local.processorData.setTokenID(arguments.options.order_ID) /> <!--- your order ID sent to GoEMerchant --->
|
||
<cfset local.processorData.setMessage(local.response.response1) />
|
||
<cfelse>
|
||
<cfset local.processorData.setStatus(getService().getStatusUnknown()) />
|
||
<cfset local.processorData.setTokenID(arguments.options.order_ID) />
|
||
<cfset local.processorData.setMessage("Error: '#local.response.error1#' - Response: 'local.response.response1'") />
|
||
</cfif>
|
||
<cfelse>
|
||
<cfset local.processorData.setStatus(getService().getStatusUnknown()) />
|
||
<cfset local.processorData.setTransactionID(arguments.options.order_ID) />
|
||
<cfset local.processorData.setMessage("GoEMerchant failed to return status") />
|
||
</cfif>
|
||
|
||
<cfelse>
|
||
|
||
<cfset local.processorData.setStatus(getService().getStatusUnknown()) />
|
||
<cfset local.processorData.setTransactionID(arguments.options.order_ID) />
|
||
<cfset local.processorData.setMessage("System error") />
|
||
|
||
</cfif>
|
||
|
||
<cfreturn local.processorData>
|
||
|
||
</cffunction>
|
||
|
||
|
||
<cffunction name="purchase" output="false" access="public" returntype="any" hint="Perform an authorization immediately followed by a capture">
|
||
<cfargument name="money" type="struct" required="true" />
|
||
<cfargument name="account" type="struct" required="true" />
|
||
<cfargument name="options" type="struct" required="true" />
|
||
|
||
<cfset var local = structNew() />
|
||
<cfset arguments.options.operationType = "sale" /> <!--- used in process method --->
|
||
<cfset local.ccNum = arguments.account.getAccount() />
|
||
<cfset local.payload = '<FIELD KEY="order_id">#arguments.options.order_ID#</FIELD>
|
||
<FIELD KEY="total">#numberFormat(arguments.money.getAmount(),'9999.99')#</FIELD>
|
||
<FIELD KEY="card_name">#getCardType(local.ccNum).shortName#</FIELD>
|
||
<FIELD KEY="card_number">#local.ccNum#</FIELD>
|
||
<FIELD KEY="card_exp"> #numberFormat(arguments.account.getMonth(), "00")##right(arguments.account.getYear(), 2)#</FIELD>
|
||
<FIELD KEY="owner_name">#arguments.account.getFirstName()# #arguments.account.getLastName()#</FIELD>
|
||
<FIELD KEY="owner_street"></FIELD>
|
||
<FIELD KEY="owner_city"></FIELD>
|
||
<FIELD KEY="owner_state"></FIELD>
|
||
<FIELD KEY="owner_zip">#arguments.account.getPostalCode()#</FIELD>
|
||
<FIELD KEY="owner_country"></FIELD>
|
||
<FIELD KEY="owner_email"></FIELD>
|
||
<FIELD KEY="owner_phone"></FIELD>' />
|
||
|
||
<cfif trim(arguments.account.getVerificationValue()) NEQ "">
|
||
<cfset local.payload = local.payload & '<FIELD KEY="cvv2">#arguments.account.getVerificationValue()#</FIELD>' />
|
||
</cfif>
|
||
|
||
<cfset local.response = process(local.payload, options) />
|
||
|
||
<cfreturn local.response />
|
||
|
||
</cffunction>
|
||
|
||
|
||
<cffunction name="authorize" output="false" access="public" returntype="any" hint="Verifies payment details with merchant bank">
|
||
<cfargument name="money" type="struct" required="true" />
|
||
<cfargument name="account" type="struct" required="true" />
|
||
<cfargument name="options" type="struct" required="true" />
|
||
|
||
<cfset var local = structNew() />
|
||
<cfset arguments.options.operationType = "auth" /> <!--- used in process method --->
|
||
<cfset local.ccNum = arguments.account.getAccount() />
|
||
<cfset local.payload = '<FIELD KEY="order_id">#arguments.options.order_ID#</FIELD>
|
||
<FIELD KEY="total">#numberFormat(arguments.money.getAmount(),'9999.99')#</FIELD>
|
||
<FIELD KEY="card_name">#getCardType(local.ccNum).shortName#</FIELD>
|
||
<FIELD KEY="card_number">#local.ccNum#</FIELD>
|
||
<FIELD KEY="card_exp"> #numberFormat(arguments.account.getMonth(), "00")##right(arguments.account.getYear(), 2)#</FIELD>
|
||
<FIELD KEY="owner_name">#arguments.account.getFirstName()# #arguments.account.getLastName()#</FIELD>
|
||
<FIELD KEY="owner_street"></FIELD>
|
||
<FIELD KEY="owner_city"></FIELD>
|
||
<FIELD KEY="owner_state"></FIELD>
|
||
<FIELD KEY="owner_zip">#arguments.account.getPostalCode()#</FIELD>
|
||
<FIELD KEY="owner_country"></FIELD>
|
||
<FIELD KEY="owner_email"></FIELD>
|
||
<FIELD KEY="owner_phone"></FIELD>' />
|
||
<cfif trim(arguments.account.getVerificationValue()) NEQ "">
|
||
<cfset local.payload = local.payload & '<FIELD KEY="cvv2">#arguments.account.getVerificationValue()#</FIELD>' />
|
||
</cfif>
|
||
<cfset local.response = process(local.payload, options) />
|
||
|
||
<cfreturn local.response />
|
||
</cffunction>
|
||
|
||
|
||
<!--- based on the assumption that credits and captures (settles) are done as singletons. The GoEMerchant interface can process mutliple
|
||
credits and captures in a single transaction but this code does not support that. --->
|
||
<cffunction name="capture" output="false" access="public" returntype="any" hint="Confirms an authorization with direction to charge the account">
|
||
<cfargument name="money" type="struct" required="true" />
|
||
<cfargument name="authorization" type="numeric" required="true" hint="Transaction ID" />
|
||
<cfargument name="options" type="struct" required="true" hint="Must include order_id" />
|
||
|
||
<cfset var local = structNew() />
|
||
<cfset arguments.options.operationType = "settle" /> <!--- used in process method --->
|
||
<cfset local.payload = '<FIELD KEY="total_number_transactions">1</FIELD><FIELD KEY="reference_number1">#arguments.authorization#</FIELD><FIELD KEY="settle_amount1">#numberFormat(arguments.money.getAmount(),'9999.99')#</FIELD>'>
|
||
<cfset local.response = process(local.payload, arguments.options) />
|
||
|
||
<cfreturn local.response />
|
||
|
||
</cffunction>
|
||
|
||
|
||
<cffunction name="credit" output="false" access="public" returntype="any" hint="">
|
||
<cfargument name="money" type="struct" required="true" />
|
||
<cfargument name="transactionid" type="numeric" required="true" />
|
||
<cfargument name="options" type="struct" required="true" hint="Must include order_id" />
|
||
|
||
<cfset var local = structNew() />
|
||
<cfset arguments.options.operationType = "credit" /> <!--- used in process method --->
|
||
<cfset local.payload = '<FIELD KEY="total_number_transactions">1</FIELD><FIELD KEY="reference_number1">#arguments.transactionid#</FIELD><FIELD KEY="credit_amount1">#numberFormat(arguments.money.getAmount(),'9999.99')#</FIELD>' />
|
||
<cfset local.response = process(local.payload, arguments.options) />
|
||
|
||
<cfreturn local.response />
|
||
|
||
</cffunction>
|
||
|
||
|
||
<cffunction name="void" output="false" access="public" returntype="any" hint="">
|
||
<cfargument name="transactionid" type="numeric" required="true" />
|
||
<cfargument name="options" type="struct" required="true" hint="Must include order_id" />
|
||
|
||
<cfset var local = structNew() />
|
||
<cfset arguments.options.operationType = "void" /> <!--- used in process method --->
|
||
<cfset local.payload = '<FIELD KEY="total_number_transactions">1</FIELD><FIELD KEY="reference_number1">#arguments.transactionid#</FIELD>' />
|
||
<cfset local.response = process(local.payload, arguments.options) />
|
||
|
||
<cfreturn local.response />
|
||
|
||
</cffunction>
|
||
|
||
<!--- this is a credit card gateway --->
|
||
<cffunction name="getIsCCEnabled" output="false" access="public" returntype="boolean" hint="determine whether or not this gateway can accept credit card transactions">
|
||
<cfreturn true />
|
||
</cffunction>
|
||
|
||
<!---
|
||
// CardTypes Prefix Width
|
||
// American Express 34, 37 15
|
||
// Diners Club 300 to 305, 36 14
|
||
// Carte Blanche 38 14
|
||
// Discover 6011 16
|
||
// EnRoute 2014, 2149 15
|
||
// JCB 3 16
|
||
// JCB 2131, 1800 15
|
||
// Master Card 51 to 55 16
|
||
// Visa 4 13, 16
|
||
// http://www.beachnet.com/~hstiles/cardtype.html
|
||
// http://www.ros-soft.net/otros/cakephp_blog/creditcard.php.txt
|
||
// http://www.rgagnon.com/javadetails/java-0034.html
|
||
|
||
// Most comprehensive seems to be Wikipedia: http://en.wikipedia.org/wiki/Credit_card_number
|
||
--->
|
||
<cffunction name="getCardType" access="private" returntype="struct" output="false" hint="Card Type short/long name required by GoEmerchant gateway">
|
||
<cfargument name="ccNum" type="numeric" required="true" />
|
||
|
||
<cfscript>
|
||
var local = structNew();
|
||
|
||
switch(len(arguments.ccNum))
|
||
{
|
||
case 16:
|
||
if(left(arguments.ccNum, 1) == 4)
|
||
{
|
||
local.returnStruct.shortName = "Visa";
|
||
local.returnStruct.longName = "Visa";
|
||
}
|
||
else if(listFind("51,52,53,54,55", left(arguments.ccNum, 2)))
|
||
{
|
||
local.returnStruct.shortName = "MasterCard";
|
||
local.returnStruct.longName = "Master Card";
|
||
}
|
||
else if(left(arguments.ccNum, 4) == 6011)
|
||
{
|
||
local.returnStruct.shortName = "JCB";
|
||
local.returnStruct.longName = "JCB";
|
||
}
|
||
else if(left(arguments.ccNum, 1) == 3)
|
||
{
|
||
local.returnStruct.shortName = "JCB";
|
||
local.returnStruct.longName = "JCB";
|
||
}
|
||
break;
|
||
|
||
case 15:
|
||
if(listFind("34,37", left(arguments.ccNum, 2)))
|
||
{
|
||
local.returnStruct.shortName = "Amex";
|
||
local.returnStruct.longName = "American Express";
|
||
}
|
||
else if(listFind("2131,1800", left(arguments.ccNum, 4)))
|
||
{
|
||
local.returnStruct.shortName = "JCB";
|
||
local.returnStruct.longName = "JCB";
|
||
}
|
||
else if(listFind("2014,2149", left(arguments.ccNum, 4)))
|
||
{
|
||
local.returnStruct.shortName = "EnRoute";
|
||
local.returnStruct.longName = "EnRoute";
|
||
}
|
||
break;
|
||
|
||
case 14:
|
||
if(left(arguments.ccNum, 2) == 36 OR listFind("301,302,303,304,305", left(arguments.ccNum, 3)))
|
||
{
|
||
local.returnStruct.shortName = "DinersClub";
|
||
local.returnStruct.longName = "Diners Club";
|
||
}
|
||
else if(left(arguments.ccNum, 2) == 38)
|
||
{
|
||
local.returnStruct.shortName = "CarteBlanche";
|
||
local.returnStruct.longName = "Carte Blanche";
|
||
}
|
||
break;
|
||
|
||
case 13:
|
||
if(left(arguments.ccNum, 1) == 4)
|
||
{
|
||
local.returnStruct.shortName = "Visa";
|
||
local.returnStruct.longName = "Visa";
|
||
}
|
||
break;
|
||
}
|
||
|
||
return local.returnStruct;
|
||
|
||
</cfscript>
|
||
|
||
</cffunction>
|
||
|
||
</cfcomponent> |