Creating a PayPal Transaction in Braintree Using Coldfusion

Creating a PayPal Transaction in Braintree Using Coldfusion

6/2/2019 10:58:38 AM

This post will cover alternate payment methods in Braintree. The example in this post will focus specifically with PayPal, though other payment methods follow similar processes. In this case, at least PayPal, ApplePay, and Google Pay have the following in common:

  • A client token for Braintree that will need to be generated by your server
  • The token will need to be passed into the JavaScript code for the Braintree Client
  • A successful authorization through the payment method interface generates a payment nonce from Braintree
  • That payment nonce is passed into the transaction sale and Braintree handles the rest

The examples provided here will be in two parts, the client interface page and the transaction page. The client interface page has the server generate a client token and is passed into a JavaScript function that generates the PayPal checkout button which brings up the PayPal Checkout Page when clicked on. Also included is a form that contains the payment nonce generated when the PayPal Checkout is authorized. The transaction page then takes the payment nonce and finalizes the transaction.

Basic documentation for the client interface is at https://developers.braintreepayments.com/guides/paypal/checkout-with-paypal/javascript/v3.

You'll need to have a PayPal Merchant ID Account and have that account linked to your Braintree Account which can be done via your Braintree Control Panel. The same would need to be done for your sandbox environments for both PayPal and Braintree as well as get a PayPal sandbox test buyer. After that is setup, you'll be able to set-up your test pages.

To start, the following cfobjects will need to be declared:

<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />

The Briantree Gateway will need to be initialized.

<cfset j = gateway.init(Environment.SANDBOX, '#variables.merchantID#', '#variables.publicKey#', '#variables.privateKey#')>

Remember that when going live to replace 'Environment.SANDBOX' with 'Environment.PRODUCTION' and use the correct merchant ID and keys with those from your Braintree Production Control Panel.

The next step is to generate the client token.

<cfset variables.clientToken = gateway.clientToken().generate() />

Include the Braintree libraries provided in the above documentation.

<!-- Load PayPal's checkout.js Library. -->
<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4 log-level="warn"></script>

<!-- Load the client component. -->
<script src="https://js.braintreegateway.com/web/3.44.2/js/client.min.js"></script>

<!-- Load the PayPal Checkout component. -->
<script src="https://js.braintreegateway.com/web/3.44.2/js/paypal-checkout.min.js"></script>

Here's the code for the PayPal button div tag and the form with the payment nonce and transaction ID that would be submitted to the transaction page.

<div id="paypal-button"></div>

<form id="ppFrm" method="post" action="ppBTFinal.cfm">
    <input type="hidden" id="ppNonce" name="ppNonce" />
    <input type="hidden" id="ppTr" name="ppTr" />
</form>

The following JavaScript code handles the Braintree client for PayPal and is modified to receive the client token generated by the server.

<script>
// Create a client.
braintree.client.create({
authorization: '<cfoutput>#variables.clientToken#</cfoutput>'
}, function (clientErr, clientInstance) {

// Stop if there was a problem creating the client.
// This could happen if there is a network error or if the authorization
// is invalid.
if (clientErr) {
console.error('Error creating client:', clientErr);
return;
}

// Create a PayPal Checkout component.
braintree.paypalCheckout.create({
client: clientInstance
}, function (paypalCheckoutErr, paypalCheckoutInstance) {

// Stop if there was a problem creating PayPal Checkout.
// This could happen if there was a network error or if it's incorrectly
// configured.
if (paypalCheckoutErr) {
console.error('Error creating PayPal Checkout:', paypalCheckoutErr);
return;
}

// Set up PayPal with the checkout.js library
paypal.Button.render({
env: 'sandbox', //'production' when live

payment: function () {
return paypalCheckoutInstance.createPayment({
flow: 'checkout',
amount: '1.99',
currency: 'USD',
intent: 'authorize' // this value must either be `capture` or match the intent passed into the PayPal SDK intent query parameter
});
},

onAuthorize: function (data, actions) {
return paypalCheckoutInstance.tokenizePayment(data, function (err, payload) {
// Submit `payload.nonce` to your server.
document.getElementById("ppNonce").value=payload.nonce;
document.getElementById("ppTr").value=data.orderID;
document.getElementById("ppFrm").submit();

});
},

onCancel: function (data) {
console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));
},

onError: function (err) {
console.error('checkout.js error', err);
}
}, '#paypal-button').then(function () {
// The PayPal button will be rendered in an html element with the id
// `paypal-button`. This function will be called when the PayPal button
// is set up and ready to be used.
});

});

});

</script>

Please note that "intent: 'authorize'" can be used as long as you submit the PayPal transaction for settlement along with the payment nonce.

Here is the code for the client interface in it's entirety (ppTest.cfm):

<!--- DECLARE JAVA OBJECTS --->
<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />

<cfset variables.merchantID = "1z2y3x4w5v" />
<cfset variables.publicKey = "9a8b7c6d5e" />
<cfset variables.privateKey = "1q2w3e4r5t" />

<!--- SANDBOX INITIALIZATION FOR TEST TRANSACTIONS --->
<cfset j = gateway.init(Environment.SANDBOX, '#variables.merchantID#', '#variables.publicKey#', '#variables.privateKey#')>

<cfset variables.clientToken = gateway.clientToken().generate() />

<!-- Load PayPal's checkout.js Library. -->
<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4 log-level="warn"></script>

<!-- Load the client component. -->
<script src="https://js.braintreegateway.com/web/3.44.2/js/client.min.js"></script>

<!-- Load the PayPal Checkout component. -->
<script src="https://js.braintreegateway.com/web/3.44.2/js/paypal-checkout.min.js"></script>

<div id="paypal-button"></div>

<form id="ppFrm" method="post" action="ppBTFinal.cfm">
    <input type="hidden" id="ppNonce" name="ppNonce" />
    <input type="hidden" id="ppTr" name="ppTr" />
</form>
<script>
    // Create a client.
    braintree.client.create({
     authorization: '<cfoutput>#variables.clientToken#</cfoutput>'
    }, function (clientErr, clientInstance) {
    
     // Stop if there was a problem creating the client.
     // This could happen if there is a network error or if the authorization
     // is invalid.
     if (clientErr) {
     console.error('Error creating client:', clientErr);
     return;
     }
    
     // Create a PayPal Checkout component.
     braintree.paypalCheckout.create({
     client: clientInstance
     }, function (paypalCheckoutErr, paypalCheckoutInstance) {
    
    // Stop if there was a problem creating PayPal Checkout.
    // This could happen if there was a network error or if it's incorrectly
    // configured.
    if (paypalCheckoutErr) {
     console.error('Error creating PayPal Checkout:', paypalCheckoutErr);
     return;
    }
    
    // Set up PayPal with the checkout.js library
    paypal.Button.render({
     env: 'sandbox', //'production' when live
    
     payment: function () {
     return paypalCheckoutInstance.createPayment({
     flow: 'checkout',
     amount: '1.99',
     currency: 'USD',
     intent: 'authorize' // this value must either be `capture` or match the intent passed into the PayPal SDK intent query parameter
     });
     },
    
     onAuthorize: function (data, actions) {
     return paypalCheckoutInstance.tokenizePayment(data, function (err, payload) {
     // Submit `payload.nonce` to your server.
     document.getElementById("ppNonce").value=payload.nonce;
     document.getElementById("ppTr").value=data.orderID;
     document.getElementById("ppFrm").submit();
    
     });
     },
    
     onCancel: function (data) {
     console.log('checkout.js payment cancelled', JSON.stringify(data, 0, 2));
     },
    
     onError: function (err) {
     console.error('checkout.js error', err);
     }
    }, '#paypal-button').then(function () {
     // The PayPal button will be rendered in an html element with the id
     // `paypal-button`. This function will be called when the PayPal button
     // is set up and ready to be used.
    });
    
     });
    
    });
    
</script>

Basic documentation for the transaction page is at https://developers.braintreepayments.com/guides/paypal/server-side/java.

The following cfobjects would need to be declared for the transaction page followed by the Environment initialization:

<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.TransactionRequest" name="transactionRequest" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />

<cfset j = gateway.init(Environment.SANDBOX, '#variables.merchantID#', '#variables.publicKey#', '#variables.privateKey#')>

Similar to the credit card transactions, the function process a transaction for PayPal is similar, but all is needed is the payment nonce. The PayPal Transaction/Order ID isn't required but could be useful in storing for reference.

Here's the transaction request followed by the sale provided that the nonce and other fields necessary for the transaction exist:

<cfif structKeyExists(form, 'ppNonce') And structKeyExists(form, 'ppTr') And structKeyExists(Session, 'amt')>
    <cfset variables.request = transactionRequest.amount(JavaCast('bigdecimal','#Session.amt#')).paymentMethodNonce("#form.ppNonce#").orderID('#form.ppTr#').options().submitForSettlement(true).storeInVaultOnSuccess(false).done()>
    <cfset variables.zed = gateway.transaction().sale(variables.request)>
</cfif>

You'll notice that the amount is passed into the function as a Session variable. This would be better so that the user doesn't try to sneak a different amount into the form submission. You won't have to be concerned about the user changing the amount in the javascript as Braintree encodes the amount into the checkout button that it generates.

For 'options()', 'submitForSettlement(true)' will settle the payment at the same time as the sale is processed. ' storeInVaultOnSuccess(false)' keeps that transaction out of the vault since a customer account wasn't created. I'll cover creating a customer account in a future post.

The following code will check the transaction for success and return the Braintree transaction ID. This is useful to store in your database for referencing.

<cfif variables.zed.isSuccess()>
    <cfset variables.TransID = variables.zed.getTarget().getId() />
    <cfoutput>Transaction ID: #variables.TransID#</cfoutput>
</cfif>

Here's the transaction in it's entirety with the amount stored as Session.amt (ppBTFinal.cfm):

<!--- 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.BraintreeGateway" name="gateway" />

<cfset variables.merchantID = "1z2y3x4w5v" />
<cfset variables.publicKey = "9a8b7c6d5e" />
<cfset variables.privateKey = "1q2w3e4r5t" />

<!--- SANDBOX INITIALIZATION FOR TEST TRANSACTIONS --->
<cfset j = gateway.init(Environment.SANDBOX, '#variables.merchantID#', '#variables.publicKey#', '#variables.privateKey#')>

<cfif structKeyExists(form, 'ppNonce') And structKeyExists(form, 'ppTr') And structKeyExists(Session, 'amt')>
    <!--- ADD TRANSACTION --->
    <cfset variables.request = transactionRequest.amount(JavaCast('bigdecimal','#Session.amt#')).paymentMethodNonce("#form.ppNonce#").orderID('#form.ppTr#').options().submitForSettlement(true).storeInVaultOnSuccess(false).done()>
    <cfset variables.zed = gateway.transaction().sale(variables.request)>
    <cfif variables.zed.isSuccess()>
        <cfset variables.TransID = variables.zed.getTarget().getId() />
        <cfoutput>Transaction ID: #variables.TransID#</cfoutput>
    </cfif>
</cfif>

In a future post, I'll go over creating a Customer Account in Braintree using Coldfusion and setting up a recurring payment plan via Braintree Subscription.


Creating a Credit Card Transaction in Braintree Using Coldfusion

6/1/2019 6:05:27 PM

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()>

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.


Implementing Braintree Using Coldfusion

6/1/2019 1:03:41 PM

One of my recent projects was to switch the way the company that I work for does business transactions. For the longest time, it was done via PayPal. Chargebacks, however, were not one of PayPal's best features. The company decided to go a different route with Braintree, which was owned by PayPal, but had lower chargebacks and more flexibility in payment options.

This project was assigned to me at the beginning of April. The company uses an Adobe Coldfusion server with a MySQL backend. To say the least, Braintree was not made to work specifically with Coldfusion. One thing I learned when talking to sales people for tech companies, they'll always say, "Sure, we can get our system to work with your system and we'll walk you through every step of the way." The real truth is, it may work with your system, but you will be doing most, if not all, of the work.

Since I took on the project, Braintree's technical support has been, to say the very least, disappointing. You have to be very specific about what you ask, and 99% of the response is a link to their rather vague documentation; versed only in Java, ASP.NET, Node.js, PHP, or Python.

You'll notice that Coldfusion isn't among those listed. My team and I had a very unpleasant time trying to get Node.js working on our Coldfusion server since the Braintree transaction drop-in in Node.js was considered the most ideal interface.

There were options online on getting Node.js to work in Coldfusion and we did find some old Coldfusion CFC's that work on multiple payment platforms including Braintree, but alas, to not much avail. The CFC used an outdated gateway with Braintree and trying to contact the author for an updated version yielded no response.

After all that, we decided that interfacing Coldfusion with their Java setup was the only option left. On a lighter note, Coldfusion relies a lot on Java libraries, but learning how to work with Java classes using Coldfusion Markup was not a walk in the park, and Braintree's Java documentation didn't make it much easier. After an exchange of not-so-friendly emails between us in programming, Braintree's support, and a few exchanges with our leaders, it was a few weeks until we found a solution.

Since there is little to no documentation on getting Coldfusion to work with Braintree's Java libraries, and getting a root canal is easier than getting good technical support from Braintree; I've put together some examples on how we got our Coldfusion server to successfully communicate with Braintree using their Java Library (JAR File).

Before I continue, please note that this may not be the best solution out there, and there's always room for improvement and code cleanup. That being said, you may look at these examples and come up with a better solution that is very possible; but this setup did work for us.

To start off, this post will cover the basics of setting up and initialize your Coldfusion server to work with Braintree via their Java Class Library JAR file.

Before you begin, make sure that Braintree has set up your Sandbox and Production Dashboards. You'll need to login to access your Merchant ID, Public Key, and Private Key on both dashboards.

Go to Braintree's Developer Documentation to get the latest Java Library JAR File. https://developers.braintreepayments.com/start/hello-server/java

This JAR file will need to be placed in your Coldfusion Library folder (e.g. D:\Coldfusion2016\cfusion\lib)

Restart the Coldfusion Application Server Service.

Now you need to set-up your transaction pages to declare and initialize the necessary Java classes.

(Note: The Braintree Java classes may be viewed non-compiled at https://github.com/braintree/braintree_java/tree/master/src/main/java/com/braintreegateway)

Each Java class needs to be declared on your transaction page or in a CFC if the processing occurs on more than one page.

<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />

The environment object is needed for the initialization. The gateway is needed for the initialization and for all Primary Braintree Java functions.

Following the declaration of objects, you'll be able to initialize the Braintree Gateway. You'll need three variables provided to you by your Braintree Control Panel/Dashboard; your Merchant ID, Public Key, and Private Key. It is recommended that these variables are declared in your Application.cfc file. For this example, we'll declare it on the page followed by the initialization.

<cfset variables.merchantID = "1z2y3x4w5v" />
<cfset variables.publicKey = "9a8b7c6d5e" />
<cfset variables.privateKey = "1q2w3e4r5t" />

<!--- SANDBOX INITIALIZATION FOR TEST TRANSACTIONS --->
<cfset j = gateway.init(Environment.SANDBOX, '#variables.MerchantID#', '#variables.PublicKey#', '#variables.PrivateKey#')>

When you're ready to go live, initialize the gateway with your Braintree Production Credentials. You can't pass 'Environment.PRODUCTION' in as a variable (at least I couldn't), so you'll need to hard-code it into the function.

<!--- PRODUCTION INITIALIZATION FOR LIVE TRANSACTIONS --->
<cfset j = gateway.init(Environment.PRODUCTION, '#variables.MerchantID#', '#variables.PublicKey#', '#variables.PrivateKey#')>

Here it is in it's entirety. This will get the Braintree Gateway setup for you for Sandbox testing.

<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />

<cfset variables.merchantID = "1z2y3x4w5v" />
<cfset variables.publicKey = "9a8b7c6d5e" />
<cfset variables.privateKey = "1q2w3e4r5t" />

<!--- SANDBOX INITIALIZATION FOR TEST TRANSACTIONS --->
<cfset j = gateway.init(Environment.SANDBOX, '#variables.MerchantID#', '#variables.PublicKey#', '#variables.PrivateKey#')>

Next post will go into how to process a simple credit card transaction. It will include the basic initialization code as well as additional 'cfobject' calls necessary for the transaction to run.


END OF LINE.
DISCLAIMER: The recommendations posted here may not be the best solutions. Please feel free to make your own adjustments which may be better than what I posted.