Previously, I went over how to implement Braintree using Coldfusion using their Java JAR file. Now it's time to create a simple credit card transaction into that will show up in your Sandbox Environment. Many other payment methods that Braintree works with requires client tokens and payment nonces. That will be posted later. For now, let's go with the most common method which are credit cards.
To start, make sure the page initializes the Braintree Java Objects. This may be reviewed in the previous post which can be viewed here.
Additional objects will need to be declared, including TransactionRequest.java and TransactionSearchRequest.java.
<cfobject type="java" class="com.braintreegateway.TransactionRequest" name="transactionRequest" />
<cfobject type="java" class="com.braintreegateway.TransactionSearchRequest" name="transactionSearchRequest" />
Basic Java documentation for creating a credit card transaction sale is at https://developers.braintreepayments.com/reference/request/transaction/sale/java
For this example, we'll set some variables for a test credit card that works in the Braintree Sandbox for transactions.
<!--- TRANSACTION DATA --->
<cfset variables.tempID = CreateUUID() />
<cfset variables.tAmount = 0.11 />
<cfset variables.tCC = 4111111111111111 />
<cfset variables.tExp = "09/2020" />
<cfset variables.tCVV = 400 />
<cfset variables.tbillAddr = "1234 Wallaby Way" />
<cfset variables.tPostalCode = 40000 />
<cfset variables.tFirstName = "Gerry" />
<cfset variables.tLastName = "Mandering" />
<cfset variables.tCity = "Charleston" />
<cfset variables.tState = "SC" />
The actual transaction sale starts with a transaction request function followed by a sale function with the request passed into it. This is one method and there are simpler methods in this process; some of which I'll explain. That being said, these are just some examples and there may be better or more simpler ways to handle these transactions.
Here's a code example to pass the variables listed above into a transaction request followed by the sale.
<!--- RUN TRANSACTION --->
<cfset variables.request = transactionRequest.amount(JavaCast('bigdecimal','#variables.tAmount#')).orderID('#variables.tempID#').creditCard().number('#variables.tCC#').expirationDate('#variables.tExp#').cvv('#variables.tCVV#').done().billingAddress().streetAddress('#variables.tBillAddr#').postalCode('#variables.tPostalCode#').firstName("#variables.tFirstName#").lastName("#variables.tLastName#").locality("#variables.tCity#").region("#variables.tState#").done()>
<cfset variables.zed = gateway.transaction().sale(variables.request).getTarget()>
Important Note: As with any server transaction processing, always make sure your server is up to the latest PCI server security compliance standards.
You'll notice that Braintree refers to city as 'locality' and state as 'region.' Obviously, zip code is also referred to as 'Postal Code.' The variables.zed function call processes the sale and gets information from the transaction. This isn't necessary, but helpful. Also, Braintree is picky about the number of characters to be passed into the transaction's 'orderId' field and could result in a failed transaction. Using the Coldfusion CreateUUID function resolves this as it always creates a unique and lenghty alphanumeric string based on date and time.
The transaction amount has to be passed as a 'BigDecimal' format. Coldfusion can resolve this by calling the JavaCast function to convert the value passed into the appropriate format.
You may omit the '.getTarget()' suffix to the function and just verify the sale went through. For example:
<cfset variables.zed = gateway.transaction().sale(variables.request)>
<cfif variables.zed.isSuccess()>
Transaction successful!
<cfelse>
Transaction Failed!
</cfif>
In the earlier example, adding '.getTarget()' can be verified by checking if the variable assigned to the function is defined. The next example checks the variable and then gets the Transaction ID; followed by submitting the transaction for settlement which will post the transaction to your account.
<cfif structKeyExists(variables, 'zed') And isDefined("variables.zed")>
<cfset variables.tID = variables.zed.getId() />
Transaction Successful! Braintree Transaction ID is <cfoutput>#variables.tID# <br/>
<!--- SUBMIT FOR SETTLEMENT --->
<cfset variables.SResult = gateway.transaction().submitForSettlement("#variables.tID#") />
<cfif variables.SResult.isSuccess()>
<cfset variables.FinalizePayment = variables.SResult.getTarget() />
Payment Submitted For Settlement.
<cfelse>
Unable to settle payment. #variables.SResult.getErrors()#
</cfif>
</cfif>
You may add a section so that if the transaction fails to find out the error number from the failed transaction. A list of error numbers may be found at https://developers.braintreepayments.com/reference/general/processor-responses/authorization-responses
Here's an example of getting the error code from the failed transaction:
<cfif not structKeyExists(variables, 'zed') or Not isDefined("variables.zed")>
<!--- GET REASON FOR FAILED TRANSACTION FROM TEMP ORDER ID --->
<cfset variables.srchA = transactionSearchRequest.init().orderId().endsWith(variables.tempID) />
<cfset variables.getTrans = gateway.transaction().search(variables.srchA).getIds()/>
<cfif ArrayIsDefined(variables.getTrans,1)>
<cfset variables.getTransInfo = gateway.transaction().find("#variables.getTrans[1]#")/>
<cfset variables.failReason = variables.getTransInfo.getProcessorResponseCode() />
Transaction Failed.<br/>
<cfif variables.FailReason GTE 2000>
We're sorry! There was a problem charging this credit card. Please try another card.
</cfif>
<cfelse>
<!--- USER INPUT ERROR, CVV MISMATCH TO CARD OR OTHERWISE --->
Transaction failed due to likely user error. Please check your address or Credit Card CVV number.
</cfif>
</cfif>
Here's the entirety of a test transaction in Coldfusion.
<!--- DECLARE JAVA OBJECTS --->
<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.TransactionRequest" name="transactionRequest" />
<cfobject type="java" class="com.braintreegateway.TransactionSearchRequest" name="transactionSearchRequest" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />
<!--- DECLARE MERCHANT VARIABLES --->
<cfset variables.merchantID = "1z2y3x4w5v" />
<cfset variables.publicKey = "9a8b7c6d5e" />
<cfset variables.privateKey = "1q2w3e4r5t" />
<!--- TRANSACTION DATA --->
<cfset variables.tempID = CreateUUID() />
<cfset variables.tAmount = 0.11 />
<cfset variables.tCC = 4111111111111111 />
<cfset variables.tExp = "09/2020" />
<cfset variables.tCVV = 400 />
<cfset variables.tbillAddr = "1234 Wallaby Way" />
<cfset variables.tPostalCode = 40000 />
<cfset variables.tFirstName = "Gerry" />
<cfset variables.tLastName = "Mandering" />
<cfset variables.tCity = "Charleston" />
<cfset variables.tState = "SC" />
<!--- INITIALIZE MERCHANT GATEWAY --->
<cfset j = gateway.init(Environment.SANDBOX, '#variables.merchantID#', '#variables.publicKey#', '#variables.privateKey#')>
<!--- RUN TRANSACTION --->
<cfset variables.request = transactionRequest.amount(JavaCast('bigdecimal','#variables.tAmount#')).orderID('#variables.tempID#').creditCard().number('#variables.tCC#').expirationDate('#variables.tExp#').cvv('#variables.tCVV#').done().billingAddress().streetAddress('#variables.tBillAddr#').postalCode('#variables.tPostalCode#').firstName("#variables.tFirstName#").lastName("#variables.tLastName#").locality("#variables.tCity#").region("#variables.tState#").done()>
<cfset variables.zed = gateway.transaction().sale(variables.request).getTarget()>
<!--- VERIFY TRANSACTION OR RETURN AN ERROR --->
<cfif structKeyExists(variables, 'zed') And isDefined("variables.zed")>
<cfset variables.tID = variables.zed.getId() />
Transaction Successful! Braintree Transaction ID is <cfoutput>#variables.tID# <br/>
<!--- SUBMIT FOR SETTLEMENT --->
<cfset variables.SResult = gateway.transaction().submitForSettlement("#variables.tID#") />
<cfif variables.SResult.isSuccess()>
<cfset variables.FinalizePayment = variables.SResult.getTarget() />
Payment Submitted For Settlement.
<cfelse>
Unable to settle payment. #variables.SResult.getErrors()#
</cfif>
<cfelse>
<!--- GET REASON FOR FAILED TRANSACTION FROM TEMP ORDER ID --->
<cfset variables.srchA = transactionSearchRequest.init().orderId().endsWith(variables.tempID) />
<cfset variables.getTrans = gateway.transaction().search(variables.srchA).getIds()/>
<cfif ArrayIsDefined(variables.getTrans,1)>
<cfset variables.getTransInfo = gateway.transaction().find("#variables.getTrans[1]#")/>
<cfset variables.failReason = variables.getTransInfo.getProcessorResponseCode() />
Transaction Failed.<br/>
<cfif variables.FailReason GTE 2000>
We're sorry! There was a problem charging this credit card. Please try another card.
</cfif>
<cfelse>
<!--- USER INPUT ERROR, CVV MISMATCH TO CARD OR OTHERWISE --->
Transaction failed due to likely user error. Please check your address or Credit Card CVV number.
</cfif>
</cfif>
Upcoming posts will cover alternate payment methods and customer subscriptions/recurring payments.