• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » How to securely integrate Salesforce CRM endpoints into WordPress custom plugins using REST API Controllers

How to securely integrate Salesforce CRM endpoints into WordPress custom plugins using REST API Controllers

Securing Salesforce REST API Access in WordPress

Integrating Salesforce CRM data into a WordPress site via its REST API offers powerful opportunities for dynamic content and streamlined workflows. However, direct, unauthenticated access is a significant security risk. This guide details how to implement secure authentication and authorization mechanisms within a custom WordPress plugin to interact with Salesforce endpoints, focusing on OAuth 2.0 and best practices for managing credentials.

Prerequisites: Salesforce Connected App Configuration

Before writing any WordPress code, a Salesforce Connected App must be configured to enable API access. This involves obtaining a Consumer Key and Consumer Secret, which will be used for OAuth authentication.

  • Navigate to Setup in Salesforce.
  • Under Apps, select “App Manager”.
  • Click “New Connected App”.
  • Fill in the App Name, API Name, and Contact Email.
  • Enable OAuth Settings.
  • Set the Callback URL to your WordPress site’s endpoint that will handle the OAuth redirect (e.g., https://your-wordpress-site.com/wp-admin/admin-ajax.php?action=salesforce_oauth_callback).
  • Select the appropriate OAuth Scopes (e.g., “Access and manage your data (api)”).
  • Save the Connected App.
  • Once saved, locate the Connected App in the App Manager and click “View” to retrieve the Consumer Key and Consumer Secret. Keep these confidential.

WordPress Plugin Structure and Initialization

We’ll create a basic WordPress plugin structure. The core logic for authentication and API calls will reside within a custom class. We’ll leverage WordPress’s AJAX API for handling redirects and callbacks.

Plugin File Structure

Create a directory for your plugin (e.g., salesforce-integration) within wp-content/plugins/. Inside this directory, create the main plugin file (e.g., salesforce-integration.php).

Main Plugin File: salesforce-integration.php

This file will contain the plugin header and instantiate our main plugin class.

<?php
/**
 * Plugin Name: Salesforce Integration
 * Description: Securely integrates Salesforce REST API endpoints into WordPress.
 * Version: 1.0.0
 * Author: Your Name
 * Author URI: https://your-website.com
 * License: GPL-2.0+
 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain: salesforce-integration
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

// Define constants for Salesforce credentials and endpoints.
// It's highly recommended to store these in wp-config.php or a secure options table.
define( 'SALESFORCE_CONSUMER_KEY', 'YOUR_SALESFORCE_CONSUMER_KEY' );
define( 'SALESFORCE_CONSUMER_SECRET', 'YOUR_SALESFORCE_CONSUMER_SECRET' );
define( 'SALESFORCE_REDIRECT_URI', admin_url( 'admin-ajax.php?action=salesforce_oauth_callback' ) );
define( 'SALESFORCE_AUTH_ENDPOINT', 'https://login.salesforce.com/services/oauth2/authorize' );
define( 'SALESFORCE_TOKEN_ENDPOINT', 'https://login.salesforce.com/services/oauth2/token' );
define( 'SALESFORCE_API_BASE_URL', 'https://your-domain.my.salesforce.com/services/data/v58.0/' ); // Replace with your Salesforce domain and API version

// Include the main plugin class.
require_once plugin_dir_path( __FILE__ ) . 'includes/class-salesforce-integration.php';

/**
 * Begins execution of the plugin.
 */
function run_salesforce_integration() {
    $plugin = new Salesforce_Integration();
    $plugin->run();
}
run_salesforce_integration();
?>

Implementing the Salesforce Integration Class

Create a directory named includes within your plugin directory. Inside includes, create class-salesforce-integration.php.

includes/class-salesforce-integration.php


JavaScript for Admin Interface and AJAX Calls

Create a directory named js within your plugin directory. Inside js, create salesforce-admin.js.

js/salesforce-admin.js

jQuery(document).ready(function($) {

    // Handle Salesforce Authentication Button Click
    $('#authenticate-salesforce').on('click', function(e) {
        e.preventDefault();
        var button = $(this);
        button.text('Redirecting...');
        button.prop('disabled', true);

        $.ajax({
            url: salesforce_ajax_object.ajax_url,
            type: 'POST',
            data: {
                action: 'initiate_salesforce_auth'
            },
            success: function(response) {
                if (response.success) {
                    window.location.href = response.data.redirect_url;
                } else {
                    alert('Error initiating authentication: ' + response.data.message);
                    button.text('Authenticate with Salesforce');
                    button.prop('disabled', false);
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                alert('AJAX Error: ' + textStatus + ' - ' + errorThrown);
                button.text('Authenticate with Salesforce');
                button.prop('disabled', false);
            }
        });
    });

    // Handle Refresh Token Button Click
    $('#refresh-salesforce-token').on('click', function(e) {
        e.preventDefault();
        var button = $(this);
        var originalText = button.text();
        button.text('Refreshing...');
        button.prop('disabled', true);

        $.ajax({
            url: salesforce_ajax_object.ajax_url,
            type: 'POST',
            data: {
                action: 'refresh_salesforce_token' // This action needs to be added to the PHP class
            },
            success: function(response) {
                if (response.success) {
                    $('#salesforce_status_message').html('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>');
                } else {
                    $('#salesforce_status_message').html('<div class="notice notice-error is-dismissible"><p>Error: ' + response.data.message + '</p></div>');
                }
                button.text(originalText);
                button.prop('disabled', false);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                $('#salesforce_status_message').html('<div class="notice notice-error is-dismissible"><p>AJAX Error: ' + textStatus + ' - ' + errorThrown + '</p></div>');
                button.text(originalText);
                button.prop('disabled', false);
            }
        });
    });

    // Handle Disconnect Button Click
    $('#disconnect-salesforce').on('click', function(e) {
        e.preventDefault();
        if (!confirm('Are you sure you want to disconnect Salesforce?')) {
            return;
        }
        var button = $(this);
        var originalText = button.text();
        button.text('Disconnecting...');
        button.prop('disabled', true);

        $.ajax({
            url: salesforce_ajax_object.ajax_url,
            type: 'POST',
            data: {
                action: 'disconnect_salesforce' // This action needs to be added to the PHP class
            },
            success: function(response) {
                if (response.success) {
                    $('#salesforce_status_message').html('<div class="notice notice-success is-dismissible"><p>' + response.data.message + '</p></div>');
                    // Optionally redirect or reload the page
                    location.reload();
                } else {
                    $('#salesforce_status_message').html('<div class="notice notice-error is-dismissible"><p>Error: ' + response.data.message + '</p></div>');
                    button.text(originalText);
                    button.prop('disabled', false);
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                $('#salesforce_status_message').html('<div class="notice notice-error is-dismissible"><p>AJAX Error: ' + textStatus + ' - ' + errorThrown + '</p></div>');
                button.text(originalText);
                button.prop('disabled', false);
            }
        });
    });

    // Handle Test API Call Button Click
    $('#test-salesforce-api').on('click', function(e) {
        e.preventDefault();
        var button = $(this);
        var originalText = button.text();
        button.text('Fetching...');
        button.prop('disabled', true);
        $('#api_response').text('Loading...');

        $.ajax({
            url: salesforce_ajax_object.ajax_url,
            type: 'POST',
            data: {
                action: 'test_salesforce_api_call' // This action needs to be added to the PHP class
            },
            success: function(response) {
                if (response.success) {
                    $('#api_response').text(JSON.stringify(response.data, null, 2));
                } else {
                    $('#api_response').text('Error: ' + response.data.message);
                }
                button.text(originalText);
                button.prop('disabled', false);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                $('#api_response').text('AJAX Error: ' + textStatus + ' - ' + errorThrown);
                button.text(originalText);
                button.prop('disabled', false);
            }
        });
    });

});

Adding AJAX Actions for Refresh, Disconnect, and Test Call

We need to add the refresh_salesforce_token, disconnect_salesforce, and a test API call handler to our Salesforce_Integration class.

First, add the following methods to the Salesforce_Integration class in includes/class-salesforce-integration.php:

    // ... (previous methods in the class) ...

    /**
     * Handles the AJAX request to refresh the Salesforce token.
     */
    public function handle_refresh_salesforce_token() {
        // Ensure this is called via AJAX and user has permissions
        check_ajax_referer( 'salesforce_integration_nonce', 'security' ); // Add nonce for security
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => __( 'Permission denied.', $this->plugin_name ) ) );
        }
        $this->refresh_salesforce_token(); // Call the existing refresh method
        // The refresh_salesforce_token method already handles sending JSON response on error.
        // If it succeeds, it updates options and returns true. We need to send a success response.
        if ( get_option( 'salesforce_access_token' ) ) {
             wp_send_json_success( array( 'message' => __( 'Salesforce token refreshed successfully!', $this->plugin_name ) ) );
        } else {
             wp_send_json_

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Step-by-Step Guide: Offloading high-frequency vendor commission records metadata writes to a Redis KV store
  • Step-by-Step Guide to building a custom XML sitemap generator block for Gutenberg using Vue micro-frontends
  • Step-by-Step Guide to building a custom two-factor authentication block for Gutenberg using Next.js headless configurations
  • WordPress Development Recipe: Implementing a secure lock mechanism for multi-worker Cron tasks with Cron API (wp_schedule_event)
  • How to securely integrate Twilio SMS Gateway endpoints into WordPress custom plugins using Filesystem API

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (644)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (850)
  • PHP (5)
  • PHP Development (37)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (624)
  • SEO & Growth (492)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (274)
  • WordPress Theme Development (357)

Recent Posts

  • Step-by-Step Guide: Offloading high-frequency vendor commission records metadata writes to a Redis KV store
  • Step-by-Step Guide to building a custom XML sitemap generator block for Gutenberg using Vue micro-frontends
  • Step-by-Step Guide to building a custom two-factor authentication block for Gutenberg using Next.js headless configurations

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (850)
  • Debugging & Troubleshooting (644)
  • Security & Compliance (624)
  • SEO & Growth (492)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala