Hello friends, today we are going to discuss Authorize.net Payment Gateway Integration in Salesforce. Authorize.net is a very common Payment Gateway. Transaction data can be quick, reliable, and securely transmitted due to its complex infrastructure and security.
Also, Check this: DropBox Integration with Apex Salesforce
We use a payment gateway so customers can do when they purchase products on an online store. You can advantage this payment processing platform by integrating it with Salesforce.
In Authorize.net payment Gateway there are multiple payments methods like ACH, Credit Card, Debit Card & Wallet. In Salesforce many clients have online Portals so they need such type of Payment Gateway.
Today we will create an Apex class for API Call Out and for the UI part, we will create Lightning Web Component. For testing purposes, we will create an Authorize.net Sandbox Account so we do testing with dummy cards.
Highlight Points:
- Easy to integrate.
- Use Basic Authentication.
- Low Cost, High Secure.
- Use HTTP CallOut for Post/GET
- Many payment options available
- Recurring billing
- It store custome informations
Keys Steps
Step 1: First we create Authorize.net developer Account. Click here.
Fill in the all details for the account. After creating an account on the next page show details of the transaction Key and API key, you can save it anywhere or we will get it on a sandbox account.
Step 2: In this step, we will get API Client Key and Password and Setup Sandbox Account. link.
Click on Account Tab and search API Credentials & Keys, check the below image.
Hit this and on the next page API key is there, you should need to generate a transaction key by choosing options at bottom of the page. Save these keys.
Code Samples :
Step 1: In the coding part, first of all, we create an Apex class for calling REST API to GET/POST Transaction.
AuthurizePaymentGatewayCtrl.cls :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | public class AuthurizePaymentGatewayCtrl { @AuraEnabled public static String payByAuthrizePayment(String firstName, String lastName, String cardNumber, String amount, String cardMonth, String cardYear, String cvv, String country, String state, String zip, String street, String city){ String email = 'test@g.com' ; //you can also feed this in LWC Form String fullName = firstName + ' ' + lastName; String phone = '9999999999' ; //you can also feed this in LWC Form String loginId = 'xxxxx' ; // these get from authurize.net sandbox account tab String transactionKey = 'xxxxx' ; // these get from authurize.net sandbox account tab //create JSON body JSON Genertor JSONGenerator payBody = JSON.createGenerator( true ); payBody.writeStartObject(); //1 payBody.writeFieldName( 'createTransactionRequest' ); payBody.writeStartObject(); //2 payBody.writeFieldName( 'merchantAuthentication' ); payBody.writeStartObject(); //3 payBody.writeStringField( 'name' , loginId); payBody.writeStringField( 'transactionKey' , transactionKey); payBody.writeEndObject(); payBody.writeStringField( 'refId' , '123456' ); payBody.writeFieldName( 'transactionRequest' ); payBody.writeStartObject(); //4 payBody.writeStringField( 'transactionType' , 'authCaptureTransaction' ); payBody.writeStringField( 'amount' , amount); payBody.writeFieldName( 'payment' ); payBody.writeStartObject(); //5 payBody.writeFieldName( 'creditCard' ); payBody.writeStartObject(); //6 payBody.writeStringField( 'cardNumber' , cardNumber); payBody.writeStringField( 'expirationDate' , cardYear + '-' + cardMonth); payBody.writeStringField( 'cardCode' , cvv); payBody.writeEndObject(); payBody.writeEndObject(); payBody.writeFieldName( 'customer' ); payBody.writeStartObject(); if (String.isNotBlank(email)){ payBody.writeStringField( 'email' , email); } payBody.writeEndObject(); payBody.writeFieldName( 'billTo' ); payBody.writeStartObject(); if (String.isNotBlank(firstName)){ payBody.writeStringField( 'firstName' , firstName); } if (String.isNotBlank(lastName)){ payBody.writeStringField( 'lastName' , lastName); } if (string.isNotBlank(fullName)){ payBody.writeStringField( 'company' , fullName); } if (string.isNotBlank(street)){ payBody.writeStringField( 'address' , street); } if (String.isNotBlank(city)){ payBody.writeStringField( 'city' , city); } if (String.isNotBlank(state)){ payBody.writeStringField( 'state' , state); } if (String.isNotBlank(zip)){ payBody.writeStringField( 'zip' , zip); } if (String.isNotBlank(phone)){ payBody.writeStringField( 'phoneNumber' , phone); } payBody.writeEndObject(); payBody.writeEndObject(); payBody.writeEndObject(); payBody.writeEndObject(); // Instantiate a new http object Http h = new Http(); // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint HttpRequest req = new HttpRequest(); req.setHeader( 'Content-Type' , 'application/json' ); req.setMethod( 'POST' ); req.setBody(payBody.getAsString()); System.debug(payBody.getAsString()); // Send the request, and return a response HttpResponse res = new HttpResponse(); res = h.send(req); String responseBody = res.getBody(); if (String.IsNotBlank(res.getBody())){ System.debug(res.getBody()); if (responseBody.contains( '"description":"This transaction has been approved."' ) || responseBody.contains( '"description":"Your order has been received. Thank you for your business!"' )){ return 'This transaction has been approved.' ; } else { string error = responseBody.substringBetween( '"errorText":"' , '"' ); throw newMessageException( 'Error encountered: ' + error); } } else { throw newMessageException( 'Error encountered. Status Code: ' + res.getStatus()); } } private static AuraHandledException newMessageException(String message) { AuraHandledException e = new AuraHandledException(message); e.setMessage(message); return e; } public static void payByEcheck(){ String email = 'test@g.com' ; //you can also feed this in LWC Form String phone = '9999999999' ; //you can also feed this in LWC Form String loginId = 'xxxxx' ; String transactionKey = 'xxxxx' ; JSONGenerator payBody = JSON.createGenerator( true ); payBody.writeStartObject(); //1 payBody.writeFieldName( 'createTransactionRequest' ); payBody.writeStartObject(); //2 payBody.writeFieldName( 'merchantAuthentication' ); payBody.writeStartObject(); //3 payBody.writeStringField( 'name' , loginId); payBody.writeStringField( 'transactionKey' , transactionKey); payBody.writeEndObject(); payBody.writeStringField( 'refId' , '123456' ); payBody.writeFieldName( 'transactionRequest' ); payBody.writeStartObject(); //4 payBody.writeStringField( 'transactionType' , 'authCaptureTransaction' ); payBody.writeStringField( 'amount' , '100' ); payBody.writeFieldName( 'payment' ); payBody.writeStartObject(); //5 payBody.writeFieldName( 'bankAccount' ); payBody.writeStartObject(); //6 payBody.writeStringField( 'accountType' , 'accountType' ); payBody.writeStringField( 'routingNumber' , 'Routing_Number' ); payBody.writeStringField( 'accountNumber' , 'Account_Number' ); payBody.writeStringField( 'nameOnAccount' , 'name on account' ); payBody.writeStringField( 'bankName' , '' ); payBody.writeStringField( 'checkNumber' , '' ); payBody.writeEndObject(); payBody.writeEndObject(); payBody.writeFieldName( 'customer' ); payBody.writeStartObject(); if (String.isNotBlank(email)){ payBody.writeStringField( 'email' , email); } payBody.writeEndObject(); payBody.writeFieldName( 'billTo' ); payBody.writeStartObject(); payBody.writeStringField( 'firstName' , '' ); payBody.writeStringField( 'lastName' , '' ); payBody.writeStringField( 'company' , '' ); payBody.writeStringField( 'address' , '' ); payBody.writeStringField( 'city' , '' ); payBody.writeStringField( 'state' , '' ); payBody.writeStringField( 'zip' , '' ); payBody.writeStringField( 'country' , '' ); payBody.writeStringField( 'phoneNumber' , '' ); payBody.writeEndObject(); payBody.writeEndObject(); payBody.writeEndObject(); payBody.writeEndObject(); // Instantiate a new http object Http h = new Http(); // Instantiate a new HTTP request, specify the method (GET) as well as the endpoint HttpRequest req = new HttpRequest(); req.setHeader( 'Content-Type' , 'application/json' ); req.setMethod( 'POST' ); req.setBody(payBody.getAsString()); // Send the request, and return a response HttpResponse res = new HttpResponse(); res = h.send(req); if (String.IsNotBlank(res.getBody())){ system.debug(res.getBody()); } } } |
Step 2: In this step, we will create Lightning Web Component(LWC) for the UI part, so the user can feed data and run the process by hitting submit button.
AuthorizeNetPaymentGatwayLWC.Html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | < template > <!-- loader --> < div if:true={showSpinner}> < lightning-spinner alternative-text = "Loading..." variant = "brand" class = "slds-is-fixed" > </ lightning-spinner > </ div > <!-----/loader--------> <!--- Header --> < div class = "slds-tabs_card" > < div class = "slds-page-header" > < div class = "slds-page-header__row" > < div class = "slds-page-header__col-title" > < div class = "slds-media" > < div class = "slds-media__figure" > < span class = "slds-icon_container slds-icon-standard-opportunity" > < lightning-icon icon-name = "standard:recipe" alternative-text = "recipe" title = "recipe" ></ lightning-icon > </ span > </ div > < div class = "slds-media__body" > < div class = "slds-page-header__name" > < div class = "slds-page-header__name-title" > < h1 > < span >Authorize.net Payment Gateway Integration in Salesforce</ span > < span class = "slds-page-header__title slds-truncate" title = "Recently Viewed" >TechDicer</ span > </ h1 > </ div > </ div > </ div > </ div > </ div > </ div > </ div > </ div > < br /> <!--- /Header --> <!--- payment gatway inputs form --> < lightning-card variant = "Narrow" title = "Credit Card Forms" icon-name = "standard:payment_gateway" > < div class = "slds-var-p-around_small" > < lightning-layout multiple-rows> < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "6" large-device-size = "6" > < lightning-input name = "firstName" class = "fieldvalidate" type = "text" label = "First Name" required onchange={handleChange}> </ lightning-input > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "6" large-device-size = "6" > < lightning-input name = "lastName" class = "fieldvalidate" type = "text" label = "Last Name" required onchange={handleChange}> </ lightning-input > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "9" large-device-size = "9" > < lightning-input name = "cardNumber" class = "fieldvalidate" type = "tel" label = "Card Number" required onchange={handleChange} maxlength = "16" minlength = "12" > </ lightning-input > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "3" large-device-size = "3" > < lightning-input type = "number" label = "Amount" value = "150" formatter = "currency" name = "amount" required onchange={handleChange} > </ lightning-input > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "3" large-device-size = "3" > < lightning-combobox name = "month" options={monthOptions} placeholder = "Choose a month" label = "Month" value={cardmMonth} required onchange={handleChange}> </ lightning-combobox > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "3" large-device-size = "3" > < lightning-combobox name = "year" options={yearOptions} placeholder = "Choose a year" label = "Year" value={cardYear} required onchange={handleChange}> </ lightning-combobox > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "6" large-device-size = "6" > < lightning-input name = "cvv" class = "fieldvalidate" type = "password" maxlength = "4" label = "CVV/CVC" required onchange={handleChange}> </ lightning-input > </ lightning-layout-item > <!-- address inputs --> < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "6" large-device-size = "6" > < lightning-combobox name = "country" options={countries} placeholder = "Choose a country" label = "Country" value={country} required onchange={handleChange}> </ lightning-combobox > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "6" large-device-size = "6" > < lightning-input name = "state" class = "fieldvalidate" type = "text" label = "State/Province" required onchange={handleChange}> </ lightning-input > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "4" large-device-size = "4" > < lightning-input name = "street" class = "fieldvalidate" type = "text" label = "Street" required onchange={handleChange}> </ lightning-input > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "4" large-device-size = "4" > < lightning-input name = "city" class = "fieldvalidate" type = "text" label = "City" required onchange={handleChange}> </ lightning-input > </ lightning-layout-item > < lightning-layout-item padding = "around-small" size = "12" medium-device-size = "4" large-device-size = "4" > < lightning-input label = "Postal Code" value={zipcode} type = "tel" name = "zip" required onchange={handleChange}> </ lightning-input > </ lightning-layout-item > <!--/address inputs--> < lightning-layout-item size = "12" class = "slds-var-p-top_small" > < lightning-button class = "slds-align_absolute-center" variant = "brand" label = "Pay Amount" onclick={handlePayment}> </ lightning-button > </ lightning-layout-item > </ lightning-layout > </ div > </ lightning-card > <!--- /payment gatway inputs form --> </ template > |
AuthurizeLWCPaymentGateway.JS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | import { LightningElement, track } from 'lwc'; //Import our Apex method import payByAuthrizePayment from "@salesforce/apex/AuthurizePaymentGatewayCtrl.payByAuthrizePayment"; import {ShowToastEvent} from 'lightning/platformShowToastEvent'; export default class AuthurizeLWCPaymentGateway extends LightningElement { monthOptions = [ { value: "01", label: "January" }, { value: "02", label: "February" }, { value: "03", label: "March" }, { value: "04", label: "April" }, { value: "05", label: "May" }, { value: "06", label: "June" }, { value: "07", label: "July" }, { value: "08", label: "August" }, { value: "09", label: "September" }, { value: "10", label: "October" }, { value: "11", label: "November" }, { value: "12", label: "December" } ]; yearOptions = [ { value: "2023", label: "2023" }, { value: "2024", label: "2024" }, { value: "2025", label: "2025" }, { value: "2026", label: "2026" }, { value: "2027", label: "2027" }, { value: "2028", label: "2028" }, { value: "2029", label: "2029" }, { value: "2030", label: "2030" } ]; countries = [ { value: "India", label: "India" }, { value: "USA", label: "USA" }, { value: "United Kingdom", label: "United Kingdom" }, ]; @track firstName; @track lastName; @track cardNumber; @track cvv; @track cardMonth; @track cardYear; @track amount; @track country; @track state; @track zip; @track street; @track city; @track amount = 150; @track showSpinner = false; handleChange(event) { if(event.target.name == 'firstName'){ this.firstName = event.detail.value; } else if(event.target.name == 'lastName'){ this.lastName = event.detail.value; } else if(event.target.name == 'cardNumber'){ this.cardNumber = event.detail.value; } else if(event.target.name == 'amount'){ this.amount = event.detail.value; } else if(event.target.name == 'month'){ this.cardMonth = event.detail.value; } else if(event.target.name == 'year'){ this.cardYear = event.detail.value; } else if(event.target.name == 'cvv'){ this.cvv = event.detail.value; } else if(event.target.name == 'country'){ this.country = event.detail.value; } else if(event.target.name == 'state'){ this.state = event.detail.value; } else if(event.target.name == 'street'){ this.street = event.detail.value; } else if(event.target.name == 'city'){ this.city = event.detail.value; } else if(event.target.name == 'zip'){ this.zip = event.detail.value; } } handlePayment(){ console.log(this.cardNumber); this.handleSpinner(); payByAuthrizePayment({firstName : this.firstName, lastName : this.lastName, cardNumber : this.cardNumber, amount : this.amount, cardMonth : this.cardMonth, cardYear : this.cardYear, cvv : this.cvv, country : this.country, state : this.state, zip : this.zip, street : this.street, city : this.city }) .then(res=>{ let title = res; this.ShowToast('Success!', title, 'success', 'dismissable'); }).catch(err=>{ this.ShowToast('Error!!', err.body.message, 'error', 'dismissable'); }).finally(() => { this.handleSpinner(); }) } handleSpinner(){ this.showSpinner = !this.showSpinner; } ShowToast(title, message, variant, mode){ const evt = new ShowToastEvent({ title: title, message:message, variant: variant, mode: mode }); this.dispatchEvent(evt); } } |
OutPut :
Test Card :
- Card No : 4111111111111111
- first name and last name : whatever you want
- Month and Year should be future’
- Address according to you