How to integrate squareUp payments with salesforce

May 16, 2023


 

After completing this module, you'll be able to:

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.

 

  1. Create Auth. Provider
  1. From Setup, enter Auth in the Quick Find box, then select Auth. Providers.
  2. Click New to Create New Auth. Provider
  3. Choose Provider Type = Open ID Connect
  4. Fill the form values like below

 

 

Provide values:

  1. Name = Fill some name
  2. URL Suffix = above name
  3. Consumer Key = SquareUp Sandbox Application Id (in SquareUp OAuth section like below image)
  4. Consumer Secret = SquareUp Sandbox Application secret (in SquareUp OAuth section like below image)

 

 

  1. Authorize Endpoint URL= https://connect.squareupsandbox.com/oauth2/authorize
  2. Token Endpoint URL = https://connect.squareupsandbox.com/oauth2/token

 2. Create Named Credentials

 

 

Provide values:

  1. Label = Square API
  2. Name = Name will auto generate after Label value provided
  3. URL = https://connect.squareupsandbox.com
  4. Identity Type = Named Principal
  5. Authentication Protocol = OAuth 2.0
  6. Authentication Provider = Name of Above created Auth.Provider
  7. Scope = Permission as per your need (Separate values by Space)
  8. Generate Authorization Header = checked

 

  1. SquareUpAccount Important Screen

 

 

 

 

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:

 

 

  1. Make API Call using Apex Code

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;
        else
            locationId = 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;
        else
            locationId = 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 -:

  1. Create Web To Lead form in the Salesforce ORG
  2. When you submit the form Lead Trigger will be invoked.
  3. In the Lead Trigger you need to write below code

Database.executeBatch(new SquareUpAPIBatch(Contact, ContactName, CustomObject_Id , Checkbox_value, Amount));

 

Result:-

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!