Step-by-Step Salesforce Third-Party Integration: Real-Time Example

Step-by-Step Salesforce Third-Party Integration: Real-Time Example

In this article, we will learn how to integrate Salesforce with a third-party system using a real-time business example.

Real-Time Example: Salesforce + Payment Gateway Integration

Business Scenario

Imagine a company uses Salesforce Sales Cloud to manage customers and Opportunities.

When an Opportunity is marked as Closed Won, the company wants to:

  1. Create a customer in a third-party payment system.
  2. Create a payment or invoice link.
  3. Receive the payment status.
  4. Automatically update Salesforce when the payment is successful.

Integration Flow

Salesforce Opportunity
        |
        | Opportunity = Closed Won
        v
Salesforce Apex
        |
        | REST API Callout
        v
Third-Party Payment API
        |
        | Customer/Payment Created
        v
Salesforce
        |
        | Payment Status = Pending
        v
Customer Makes Payment
        |
        v
Third-Party Webhook
        |
        v
Salesforce Apex REST Endpoint
        |
        v
Update Opportunity = Payment Received

Step 1: Create a Third-Party API

Assume the third-party payment provider provides the following API.

API Endpoint

POST https://api.paymentprovider.com/v1/payments

Request


{
  "customerName": "John Smith",
  "email": "john@example.com",
  "amount": 5000
}

Response


{
  "paymentId": "PAY-12345",
  "paymentUrl": "https://paymentprovider.com/pay/PAY-12345",
  "status": "PENDING"
}

Step 2: Create a Named Credential in Salesforce

Instead of hardcoding the third-party URL directly in Apex, we should use Named Credentials.

Go to:

Setup
→ Named Credentials
→ New

Example Configuration

Name: Payment_API

URL: https://api.paymentprovider.com

Named Credentials provide a more secure way to manage external endpoints and authentication.


Step 3: Trigger the Integration When Opportunity Is Closed Won

When the Opportunity stage changes to Closed Won, we start the integration process.

We should not perform the HTTP callout directly inside the trigger.

Recommended Architecture

Trigger
   |
   v
Handler / Service
   |
   v
Queueable Apex
   |
   v
HTTP Callout

Opportunity Trigger


trigger OpportunityTrigger on Opportunity (after update) {

    List<Id> closedWonOppIds = new List<Id>();

    for (Opportunity opp : Trigger.new) {

        Opportunity oldOpp = Trigger.oldMap.get(opp.Id);

        if (
            opp.StageName == 'Closed Won' &&
            oldOpp.StageName != 'Closed Won'
        ) {
            closedWonOppIds.add(opp.Id);
        }
    }

    if (!closedWonOppIds.isEmpty()) {

        PaymentIntegrationService.sendPaymentRequest(
            closedWonOppIds
        );
    }
}

Step 4: Create the Service Class

The trigger calls a service class that starts the asynchronous Queueable Apex job.


public with sharing class PaymentIntegrationService {

    public static void sendPaymentRequest(
        List<Id> opportunityIds
    ) {

        System.enqueueJob(
            new PaymentQueueable(opportunityIds)
        );
    }
}

Why Use Queueable Apex?

Queueable Apex allows the Salesforce transaction to complete before making the external API call.

User changes Opportunity
        ↓
Salesforce saves Opportunity
        ↓
Queueable job starts
        ↓
Call third-party API

This approach is more scalable and suitable for real-time integrations.


Step 5: Create the Queueable Apex Callout

The Queueable class will send Opportunity information to the third-party payment API.


public class PaymentQueueable
    implements Queueable, Database.AllowsCallouts {

    private List<Id> opportunityIds;

    public PaymentQueueable(
        List<Id> opportunityIds
    ) {
        this.opportunityIds = opportunityIds;
    }

    public void execute(QueueableContext context) {

        List<Opportunity> opportunities = [
            SELECT Id,
                   Name,
                   Amount,
                   Account.Name,
                   Account.PersonEmail
            FROM Opportunity
            WHERE Id IN :opportunityIds
        ];

        for (Opportunity opp : opportunities) {

            Map<String, Object> requestData =
                new Map<String, Object>();

            requestData.put(
                'customerName',
                opp.Account.Name
            );

            requestData.put(
                'email',
                opp.Account.PersonEmail
            );

            requestData.put(
                'amount',
                opp.Amount
            );

            HttpRequest request = new HttpRequest();

            request.setEndpoint(
                'callout:Payment_API/v1/payments'
            );

            request.setMethod('POST');

            request.setHeader(
                'Content-Type',
                'application/json'
            );

            request.setBody(
                JSON.serialize(requestData)
            );

            Http http = new Http();

            HttpResponse response = http.send(request);

            if (
                response.getStatusCode() == 200 ||
                response.getStatusCode() == 201
            ) {

                Map<String, Object> responseData =
                    (Map<String, Object>)
                    JSON.deserializeUntyped(
                        response.getBody()
                    );

                update new Opportunity(
                    Id = opp.Id,
                    Payment_Status__c = 'Pending',
                    Payment_Id__c =
                        (String) responseData.get('paymentId'),
                    Payment_URL__c =
                        (String) responseData.get('paymentUrl')
                );

            } else {

                System.debug(
                    'Payment API Error: ' +
                    response.getBody()
                );
            }
        }
    }
}

Step 6: What Happens in Real Time?

Let's say a Salesforce user changes the following Opportunity:

Opportunity: ABC Software Deal

Stage: Closed Won

Amount: $5,000

Salesforce automatically sends the following request to the third-party API.

Salesforce Sends


{
  "customerName": "ABC Technologies",
  "email": "customer@example.com",
  "amount": 5000
}

Third-Party System Responds


{
  "paymentId": "PAY-98765",
  "paymentUrl": "https://payment.com/pay/PAY-98765",
  "status": "PENDING"
}

Salesforce Updates the Opportunity

Stage = Closed Won

Payment Status = Pending

Payment ID = PAY-98765

Payment URL =
https://payment.com/pay/PAY-98765

Step 7: Customer Completes the Payment

The customer receives the payment link and completes the payment.

After the payment is successful, the third-party payment provider sends a Webhook to Salesforce.

Webhook Endpoint

POST

https://yourSalesforceDomain.my.salesforce.com
/services/apexrest/payment/webhook

Webhook Request


{
  "paymentId": "PAY-98765",
  "status": "SUCCESS"
}

Step 8: Create a Salesforce Apex REST Webhook Endpoint

Salesforce exposes an Apex REST endpoint that receives the real-time payment notification.


@RestResource(
    urlMapping='/payment/webhook/*'
)
global with sharing class PaymentWebhookService {

    @HttpPost
    global static void paymentWebhook() {

        RestRequest request =
            RestContext.request;

        String requestBody =
            request.requestBody.toString();

        Map<String, Object> requestData =
            (Map<String, Object>)
            JSON.deserializeUntyped(
                requestBody
            );

        String paymentId =
            (String) requestData.get(
                'paymentId'
            );

        String status =
            (String) requestData.get(
                'status'
            );

        List<Opportunity> opportunities = [
            SELECT Id,
                   Payment_Status__c
            FROM Opportunity
            WHERE Payment_Id__c = :paymentId
            LIMIT 1
        ];

        if (!opportunities.isEmpty()) {

            Opportunity opp =
                opportunities[0];

            opp.Payment_Status__c =
                status;

            if (status == 'SUCCESS') {

                opp.Payment_Received__c =
                    true;
            }

            update opp;
        }
    }
}

Step 9: Complete Real-Time Integration Flow

┌─────────────────────────────┐
│ Salesforce User             │
│ Changes Opportunity         │
│ to Closed Won               │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Opportunity Trigger         │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Service Class               │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Queueable Apex              │
│ REST API Callout            │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Third-Party Payment API     │
└──────────────┬──────────────┘
               │
               ▼
        Payment Created
               │
               ▼
┌─────────────────────────────┐
│ Customer Makes Payment      │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Third-Party Webhook         │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Salesforce Apex REST API    │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Opportunity Updated         │
│ Payment = SUCCESS           │
└─────────────────────────────┘

Important Salesforce Integration Concepts

Concept Purpose
Named Credential Securely manage external API endpoints and authentication.
REST API Communicate with third-party systems.
HTTP Callout Send data from Salesforce to an external system.
Queueable Apex Perform asynchronous processing and callouts.
Webhook Receive real-time notifications from external systems.
Apex REST Create an API endpoint in Salesforce.
JSON Exchange structured data between systems.
Opportunity The Salesforce business record used in this integration.

Other Real-World Salesforce Integration Examples

  • Salesforce to SAP: Send a Closed Won Opportunity to create a sales order.
  • Salesforce to Stripe or Razorpay: Create payment requests and receive payment status.
  • Salesforce to Shipping API: Create a shipment after an order is confirmed.
  • Twilio to Salesforce: Update Salesforce when an SMS is delivered.
  • WhatsApp API to Salesforce: Create Cases when customers send messages.
  • Salesforce to ERP System: Send customer, product, order, and invoice information to an external ERP application.

Conclusion

This example demonstrates a common real-time Salesforce integration pattern. When an Opportunity changes to Closed Won, Salesforce sends information to an external payment system using an asynchronous REST API callout.

The external system later sends a webhook back to Salesforce after the customer completes the payment.

This creates a two-way integration:

Salesforce
    ↓
REST API Callout
    ↓
Third-Party System
    ↓
Webhook
    ↓
Salesforce

This architecture is commonly used in enterprise Salesforce applications and can be adapted for payment systems, ERP systems, shipping platforms, messaging services, banking applications, and AI-powered applications.

```

Post a Comment

Post a Comment (0)

Previous Post Next Post