Adding a Customer to Braintree Using Coldfusion

The COBLOG

Adding a Customer to Braintree Using Coldfusion

8/18/2019 9:44:19 AM

I'll briefly go over adding customers and recurring payment subscriptions in Coldfusion using Java. The basic documentation for Customers can be found at:

https://developers.braintreepayments.com/guides/customers/java

The following objects, including those previously mentioned in earlier posts, are required.

<!--- DECLARE JAVA OBJECTS --->
<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.CustomerRequest" name="customerReq" />
<cfobject type="java" class="com.braintreegateway.PaymentMethodRequest" name="paymentMethod" />
<cfobject type="java" class="com.braintreegateway.SubscriptionRequest" name="subscriptionRequest" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />

The following example shows how to add a customer to the Braintree Vault with a credit card:

<!--- MERCHANT INFO --->
<cfset variables.BTMerchantID = "1q2w3e4r" />
<cfset variables.BTPuclicKey = "0p9o8i7u" />
<cfset variables.BTPrivateKey = "5g6h7j8k" />

<!--- CUSTOMER DATA --->
<cfset variables.firstName = "Gerry" />
<cfset variables.lastName = "Mandering" />
<cfset variables.email = "gerrym@fakedomain.com" />
<cfset variables.phone = "843-555-4444" />
<cfset variables.planType = "Better" />

<!--- CARD 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.city = "Florence" />
<cfset variables.state = "SC" />

<!--- INITIALIZE MERCHANT GATEWAY --->
<cfset j = gateway.init(Environment.SANDBOX, '#variables.BTMerchantID#', '#variables.BTPublicKey#', '#variables.BTPrivateKey#')>

<!--- ADD CUSTOMER AND PAYMENT METHOD --->
<cfset variables.newCustomer = customerReq.firstName("#variables.firstName#").lastName("#variables.lastName#").email("#variables.email#").phone("#variables.phone#").creditCard().number('#variables.tCC#').expirationDate('#variables.tExp#').cvv('#variables.tCVV#').billingAddress().postalCode("#variables.tPostalCode#").streetAddress("#variables.tbillAddr#").locality("#variables.city#").region("#variables.state#").done().done() />

<cfset variables.newCReq = gateway.customer().create(variables.newCustomer) />

A payment nonce is more secure, but there's no reasonable documentation from Braintree for credit card nonce generators. In this example, however, here's how to pass a nonce when creating the customer in the vault:

<!--- ADD CUSTOMER AND PAYMENT METHOD --->
<cfset variables.newCustomer = customerReq.firstName("#variables.firstName#").lastName("#variables.lastName#").email("#variables.email#").phone("#variables.phone#").paymentMethodNonce("#variables.payNonce#") />

For examples on getting a payment nonce with PayPal, visit the previous post at:

http://www.openshawltdpro.com/coblog.aspx?cb=8

Nonces for other payment methods including Apple Pay and Google Pay have similar processes, but different scripts. Luckily, Braintree has decent examples in their documentation and require client tokens similar to how they're generated in examples from the previous post.

Once a customer is created with a payment method, you can get it to return a payment token. This token may be used to attach a subscription. Please note that when a customer is added to the vault with a payment method, the method is saved as a default and can't be overridden when the customer is first added. Here's how to retrieve the payment token:

<!--- VERIFY CUSTOMER AND PAYMENT METHOD IS SUCCESSFULL --->
<cfif variables.newCReq.isSuccess()>
    <cfset variables.custID = variables.newCReq.getTarget().getId() />
    <cfset variables.payToken = variables.newCReq.getTarget().getPaymentMethods() />
    <cfif ArrayIsDefined(variables.payToken,1)>
        <cfset variables.payTokenID = variables.payToken[1].getToken() />
    <cfelse>
        Payment Method Failed.
        <cfabort/>
    </cfif>
    Success, BT Customer ID: <cfoutput>#variables.custID# <br/>
    Payment Token: #variables.payTokenID#<br/>
    </cfoutput>
<cfelse>
    Unable to create customer account.
</cfif>

This method looks at all payment methods and grabs the first. Another process can be used to get the default by substituting getPaymentMethods() with getDefaultPaymentMethod(), which should only return only one value so an array lookup isn't needed. The default payment token can only be removed from default status when another payment method is added. Here's a basic example of adding a credit card to a customer account along with the object required to add the credit card request:

<!--- CC OBJECT --->
<cfobject type="java" class="com.braintreegateway.CreditCard" name="ccReq" />
<cfset variables.addCreditCard = ccreq().customerId("#variables.custID#").cvv("#variables.tCVV#").number("#variables.tCC#").expirationDate("#variables.tExp#") />
<cfset variables.addCC = gateway.creditCard().create(variables.addCreditCard) />

Adding a subscription is very simple once you have the subscription ID and payment token provided. The Braintree Control Panel is the best place to add subscriptions, set up recurring payments, and can get a subscription ID. The final example shows adding a subscription to the customer's account in Coldfusion.

<!--- ADD MEMBERSHIP SUBSCRIPTION --->
<cfif variables.planType IS "Good">
    <cfset variables.planID = "453g" />
<cfelseif variables.planType IS "Better">
    <cfset variables.planID = "dmp2" />
<cfelse>
    <cfset variables.planID = "" />
</cfif>
<cfif Len(variables.planID)>
    <!--- CREATE SUBSCRIPTION USING PLAN ID AND PAYMENT TOKEN ID --->
    <cfset variables.setSubscription = subscriptionRequest.paymentMethodToken("#variables.payTokenID#").planId("#variables.planID#") />
    <cfset variables.setSubResult = gateway.subscription().create(variables.setSubscription) />
    <cfif variables.setSubResult.isSuccess()>
        <cfset variables.getSubInfo = variables.setSubResult.getTarget().getId() />
        Subscription ID: <cfoutput>#variables.getSubInfo#</cfoutput>
    <cfelse>
        Subscription Failed
    </cfif>
</cfif>

That's about it. Feel free to try this code out in your sandbox account. Here's a complete example:

<!--- DECLARE JAVA OBJECTS --->
<cfobject type="java" class="com.braintreegateway.Environment" name="environment" />
<cfobject type="java" class="com.braintreegateway.CustomerRequest" name="customerReq" />
<cfobject type="java" class="com.braintreegateway.PaymentMethodRequest" name="paymentMethod" />
<cfobject type="java" class="com.braintreegateway.SubscriptionRequest" name="subscriptionRequest" />
<cfobject type="java" class="com.braintreegateway.BraintreeGateway" name="gateway" />

<!--- MERCHANT INFO --->
<cfset variables.BTMerchantID = "1q2w3e4r" />
<cfset variables.BTPuclicKey = "0p9o8i7u" />
<cfset variables.BTPrivateKey = "5g6h7j8k" />

<!--- CUSTOMER DATA --->
<cfset variables.firstName = "Gerry" />
<cfset variables.lastName = "Mandering" />
<cfset variables.email = "gerrym@fakedomain.com" />
<cfset variables.phone = "843-555-4444" />
<cfset variables.planType = "Better" />

<!--- CARD 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.city = "Florence" />
<cfset variables.state = "SC" />

<!--- INITIALIZE MERCHANT GATEWAY --->
<cfset j = gateway.init(Environment.SANDBOX, '#variables.BTMerchantID#', '#variables.BTPublicKey#', '#variables.BTPrivateKey#')>

<!--- ADD CUSTOMER AND PAYMENT METHOD --->
<cfset variables.newCustomer = customerReq.firstName("#variables.firstName#").lastName("#variables.lastName#").email("#variables.email#").phone("#variables.phone#").creditCard().number('#variables.tCC#').expirationDate('#variables.tExp#').cvv('#variables.tCVV#').billingAddress().postalCode("#variables.tPostalCode#").streetAddress("#variables.tbillAddr#").locality("#variables.city#").region("#variables.state#").done().done() />

<cfset variables.newCReq = gateway.customer().create(variables.newCustomer) />

<!--- VERIFY CUSTOMER AND PAYMENT METHOD IS SUCCESSFULL --->
<cfif variables.newCReq.isSuccess()>
    <cfset variables.custID = variables.newCReq.getTarget().getId() />
    <cfset variables.payToken = variables.newCReq.getTarget().getPaymentMethods() />
    <cfif ArrayIsDefined(variables.payToken,1)>
        <cfset variables.payTokenID = variables.payToken[1].getToken() />
    <cfelse>
        Payment Method Failed.
        <cfabort/>
    </cfif>
    Success, BT Customer ID: <cfoutput>#variables.custID# <br/>
    Payment Token: #variables.payTokenID#<br/>
    </cfoutput>
    <!--- ADD MEMBERSHIP SUBSCRIPTION --->
    <cfif variables.planType IS "Good">
        <cfset variables.planID = "453g" />
    <cfelseif variables.planType IS "Better">
        <cfset variables.planID = "dmp2" />
    <cfelse>
        <cfset variables.planID = "" />
    </cfif>
    <cfif Len(variables.planID)>
        <!--- CREATE SUBSCRIPTION USING PLAN ID AND PAYMENT TOKEN ID --->
        <cfset variables.setSubscription = subscriptionRequest.paymentMethodToken("#variables.payTokenID#").planId("#variables.planID#") />
        <cfset variables.setSubResult = gateway.subscription().create(variables.setSubscription) />
        <cfif variables.setSubResult.isSuccess()>
            <cfset variables.getSubInfo = variables.setSubResult.getTarget().getId() />
            Subscription ID: <cfoutput>#variables.getSubInfo#</cfoutput>
        <cfelse>
            Subscription Failed
        </cfif>
    </cfif>
<cfelse>
    Unable to create customer account.
</cfif>


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.


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.
© 2019 Openshaw Ltd. Productions