May 16, 2023
In this blog we will integrate Salesforce with SquareUp and we will generate an invoice link of SquareUp for a customer, using this link the customer can make the payment.
Provide values:
2. Create Named Credentials
Provide values:
● After Clicking on Developer Dashboard screen will look like this:
● In SquareUp you can get Secret key and Consumer key from OAuth Section And Set Callback URL in Redirect URL from Salesforce Org Auth.Provider which you created like above:
● You also can monitor which API call is successful or not from API logs Section like this:
Create Apex classes in your developer org like below:
SquareUpAPIBatch.apxc
public class SquareUpAPIBatch implements Database.Batchable<sObject>, Database.AllowsCallouts, database.stateful {
public String conId = '';public String serviceId = '';public String contactName ='';public String conEmail = '';public String conEmail_C='';public String customerId = '';public String publicURL='';public String invoiceId='';public Boolean isSendInvoice=false;String orderId = '';Decimal totalSaleAmount = null;String phoneNumber = null;Boolean isSandbox = null;public SquareUpAPIBatch(Contact con, String name, String serviceId, Boolean isSendInvoice, Decimal totalSaleAmount){this.conId = con.Id;this.serviceId = serviceId;this.contactName = name;this.conEmail = con.Email;this.conEmail_C = con.Email__C;this.isSendInvoice = isSendInvoice;this.totalSaleAmount = totalSaleAmount;this.phoneNumber = con.MobilePhone != null ? con.MobilePhone : con.Phone;isSandbox = [select id , IsSandbox from Organization limit 1].IsSandbox;}public Iterable<sObject> start(Database.BatchableContext cntx){return Database.getQueryLocator('SELECT Id FROM Contact limit 1');}public void execute(Database.BatchableContext bc, List<sobject> scope){System.debug('inside execute method');this.customerId = SquareUpAPICall.searchCustomer(this.conEmail);//System.debug('customerFound = '+customerFound);if(this.customerId =='' || this.customerId == null){System.debug('inside execute method If condition');System.debug(this.contactName+'--'+ this.conEmail +'--'+ this.phoneNumber);if(!Test.isRunningTest())this.customerId = SquareUpAPICall.createCustomer(this.contactName, this.conEmail, this.phoneNumber);}if(this.customerId !='' || this.customerId != null){if(!Test.isRunningTest())orderId = SquareUpAPICall.createOrder(this.customerId, this.totalSaleAmount*100, isSandbox);}}public void finish(Database.BatchableContext bc){if(orderId != '' && orderId != null && !Test.isRunningTest()) {System.debug( this.customerId+'--'+orderId +'--'+isSandbox);invoiceId = SquareUpAPICall.createInvoice(this.customerId, orderId, isSandbox);}if(orderId != '' && orderId != null && invoiceId != '' && invoiceId != null && !Test.isRunningTest()) {System.debug( 'invoiceId ' + invoiceId);publicURL = SquareUpAPICall.publishInvoice(0, invoiceId);System.debug('publicURL >>> '+publicURL);}if(this.isSendInvoice == true){System.debug(this.conId+'--'+this.serviceId +'--'+ this.conEmail +'--'+ this.conEmail_C +'--'+this.publicURL);ID jobID = System.enqueueJob(new SquareUpQueuable(this.conId, this.serviceId, this.conEmail, this.conEmail_C, this.publicURL));}}}
SquareUpAPICall.apxc
public class SquareUpAPICall {public static String searchCustomer(String email){String customerId='';Map<String, String> exactMap = new Map<String, String>();exactMap.put('exact', email);Map<String, Object> emailAddressMap = new Map<String, Object>();emailAddressMap.put('email_address', exactMap);Map<String, Object> filterMap = new Map<String, Object>();filterMap.put('filter', emailAddressMap);Map<String, Object> queryMap = new Map<String, Object>();queryMap.put('query', filterMap);String reqBody = JSON.Serialize(queryMap);Boolean isCustomerFound=false;HttpRequest req = new HttpRequest();req.setHeader('Content-Type', 'application/json');req.setHeader('accept','application/json');req.setEndpoint('callout:Square_API/v2/customers/search');req.setMethod('POST');req.setBody(reqBody);Http http = new Http();HttpResponse res = http.send(req);if(res.getStatusCode() == 200){System.debug('res.getBody() >> '+res.getBody());Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());List<Object> customersList = (List<Object>)result.get('customers');Map<String, Object> customersMap = new Map<String, Object>();if(customersList != null && customersList.size() > 0)customersMap = (Map<String, Object>)customersList[0];if(result.isEmpty()){System.debug('Reponse Body is Empty');customerId='';}else{System.debug('Reponse Body is not Empty');customerId = String.valueOf(customersMap.get('id'));}}else{System.debug('Error >> '+res.getBody()+ ' Status Code >> ' +res.getStatusCode());}return customerId;}public static String createCustomer(String name, String emailAddress, String phoneNumber){Map<String, String> reqBodyMap = new Map<String, String>();reqBodyMap.put('given_name', name);reqBodyMap.put('email_address', emailAddress);reqBodyMap.put('phone_number', phoneNumber);String reqBody = JSON.Serialize(reqBodyMap);HttpRequest req = new HttpRequest();req.setHeader('Content-Type', 'application/json');req.setHeader('accept','application/json');req.setEndpoint('callout:Square_API/v2/customers');req.setMethod('POST');req.setBody(reqBody);Http http = new Http();HttpResponse res = http.send(req);String customerId='';if(res.getStatusCode() == 200){System.debug('res.getBody() >> '+res.getBody());Map<String, Object> mapRes = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());Map<String, Object> mapInvoice = (Map<String, Object>)mapRes.get('customer');customerId = (String)mapInvoice.get('id');}else{System.debug('Error >> '+res.getBody()+ ' Status Code >> ' +res.getStatusCode());}return customerId;}public static String createOrder(String customerId, Decimal totalSaleAmount, Boolean isSandbox){String locationId;if(isSandbox)locationId = System.Label.SquareUpLocationIdSandbox;elselocationId = System.Label.SquareUpLocationIdProduction;List<Map<String, Object>> lineItemsList = new List<Map<String, Object>>();Map<String, Object> basePriceMoneyMap = new Map<String, Object>();basePriceMoneyMap.put('amount', totalSaleAmount);basePriceMoneyMap.put('currency', 'USD');Map<String, Object> lineItemsMap = new Map<String, Object>();lineItemsMap.put('quantity', '1');lineItemsMap.put('item_type', 'ITEM');lineItemsMap.put('base_price_money', basePriceMoneyMap);lineItemsMap.put('name', 'Water System Service');lineItemsList.add(lineItemsMap);Map<String, Object> orderMap = new Map<String, Object>();orderMap.put('location_id', locationId);orderMap.put('customer_id', customerId);orderMap.put('line_items', lineItemsList);Map<String, Object> reqBodyMap = new Map<String, Object>();reqBodyMap.put('order', orderMap);String reqBody = JSON.Serialize(reqBodyMap);HttpRequest req = new HttpRequest();req.setHeader('Content-Type', 'application/json');req.setHeader('accept','application/json');req.setEndpoint('callout:Square_API/v2/orders');req.setMethod('POST');req.setbody(reqBody);Http http = new Http();HttpResponse res = http.send(req);String orderId='';if(res.getStatusCode() == 200){System.debug('res.getBody() >> '+res.getBody());Map<String, Object> mapRes = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());Map<String, Object> mapInvoice = (Map<String, Object>)mapRes.get('order');orderId = (String)mapInvoice.get('id');}else{System.debug('Error >> '+res.getBody()+ ' Status >> ' +res.getStatus());}return orderId;}public static String createInvoice(String customerId, String orderId, Boolean isSandbox){String locationId;if(isSandbox)locationId = System.Label.SquareUpLocationIdSandbox;elselocationId = System.Label.SquareUpLocationIdProduction;String dueDate = String.valueOf(Date.today()).removeEnd(' 00:00:00');Map<String, object> primaryRecipientMap = new Map<String, Object>();primaryRecipientMap.put('customer_id', customerId);Map<String, Object> paymentRequestsMap = new Map<String, Object>();paymentRequestsMap.put('request_type', 'BALANCE');paymentRequestsMap.put('due_date', dueDate);paymentRequestsMap.put('tipping_enabled', true);paymentRequestsMap.put('automatic_payment_source', 'NONE');List<Map<String, Object>> paymentRequestsList = new List<Map<String, Object>>();paymentRequestsList.add(paymentRequestsMap);Map<String, object> acceptedPaymentMethodsMap = new Map<String, Object>();acceptedPaymentMethodsMap.put('card', true);Map<String, object> invoiceMap = new Map<String, Object>();invoiceMap.put('location_id', locationId);invoiceMap.put('delivery_method', 'SHARE_MANUALLY');invoiceMap.put('accepted_payment_methods', acceptedPaymentMethodsMap);invoiceMap.put('payment_requests', paymentRequestsList);invoiceMap.put('primary_recipient', primaryRecipientMap);invoiceMap.put('order_id', orderId);invoiceMap.put('description', 'Water System Service');Map<String, Object> reqBodyMap = new Map<String, Object>();reqBodyMap.put('invoice', invoiceMap);String reqBody = JSON.Serialize(reqBodyMap);HttpRequest req = new HttpRequest();req.setHeader('Content-Type', 'application/json');req.setHeader('accept','application/json');req.setEndpoint('callout:Square_API/v2/invoices');req.setMethod('POST');req.setBody(reqBody);Http http = new Http();HttpResponse res = http.send(req);String invoiceId='';if(res.getStatusCode() == 200){System.debug('res.getBody() >> '+res.getBody());Map<String, Object> mapRes = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());Map<String, Object> mapInvoice = (Map<String, Object>)mapRes.get('invoice');invoiceId = (String)mapInvoice.get('id');}else{System.debug('Error >> '+res.getBody()+ ' Status >> ' +res.getStatus());}return invoiceId;}public static String publishInvoice(Integer versionValue, String invoiceId){Map<String, Object> reqBodyMap = new Map<String, Object>();reqBodyMap.put('version', versionValue);String reqBody = JSON.Serialize(reqBodyMap);HttpRequest req = new HttpRequest();req.setHeader('Content-Type', 'application/json');req.setHeader('accept','application/json');req.setEndpoint('callout:Square_API/v2/invoices/'+invoiceId+'/publish');req.setMethod('POST');req.setBody(reqBody);Http http = new Http();HttpResponse res = http.send(req);String invoicePublishURL='';if(res.getStatusCode() == 200){System.debug('res.getBody() >> '+res.getBody());Map<String, Object> mapRes = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());Map<String, Object> mapInvoice = (Map<String, Object>)mapRes.get('invoice');invoicePublishURL = (String)mapInvoice.get('public_url');System.debug('invoicePublishURL >> '+invoicePublishURL);}else{System.debug('Error >> '+res.getBody()+ ' Status >> ' +res.getStatus());}return invoicePublishURL;}}
SquareUpQueuable.apxc
public class SquareUpQueuable implements Queueable{
public String conId = '';public String serviceId = '';public String contactEmail = '';public String contactEmail_C='';public String publicURL='';public SquareUpQueuable(String conId, String serviceId, String contactEmail, String contactEmail_C, String publicURL){this.conId = conId;this.serviceId = serviceId;this.contactEmail = contactEmail;this.contactEmail_C = contactEmail_C;this.publicURL = publicURL;}public void execute(QueueableContext context) {if(this.contactEmail != null){SendEmailController.sendEmail(this.conId, this.serviceId , this.contactEmail, this.publicURL);}else{if(this.contactEmail_C != null){SendEmailController.sendEmail(this.conId, this.serviceId , this.contactEmail_C, this.publicURL);}}}}
SendEmailController.apxc
public class SendEmailController {@Future(callout=true)public static void sendEmail(String conId, String serviceId, String toAddress, String invoicePublicURL){String squareUpPaymentLink = '';if(invoicePublicURL != null && invoicePublicURL != '')squareUpPaymentLink = '<br/><br/>Payment Link - ' + invoicePublicURL;Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();string[] to = new string[] {toAddress};email.setToAddresses(to);email.setTreatTargetObjectAsRecipient(false);email.setTargetObjectId(conId);email.setSubject('Demo invoice');email.setSaveAsActivity(true);email.setHtmlBody(squareUpPaymentLink);Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });}}
How to Execute -:
Database.executeBatch(new SquareUpAPIBatch(Contact, ContactName, CustomObject_Id , Checkbox_value, Amount));
After making API calls in this case an email will be sent to the Salesforce contact email address and using that link we can make payment.
Email link look like this:
After click on Payment Link the page will look like this:
You can make payment by providing card details.
I hope this blog helped you!