0

I have a form on my WordPress website that collects additional information from customers. I want this information added to an existing record of MyCustomObject. To do this, I will need to make a custom WordPress plugin that sends the data to Salesforce via the cURL PHP library.

How should I go about doing this without having a user logging into Salesforce? I would use Salesforce's Username-Password OAuth flow for this; however, as stated in this forum post, it is not secure and should only be used for development with Sandboxes. Is that true?

At this point, I feel as though I have no other choice but to use the Username-Password OAuth flow; I'm not a Salesforce developer so I have no idea about a good and secure way of going about this. Moreover, what I have right now only works if I send the data to a developer Sandbox. When I try to change it to send it to my Production org, I get errors like cURL 51, HTTP 500, HTTP 501. My thought process is that if I stop using what I have now (the Force.com APEX REST API) and use Username-Password OAuth (or something else), such errors would be resolved.

As stated previously, I currently have a public APEX REST API on a Force.com site (I followed this tutorial). Below is a simplified demonstration of what I've come up with. You'll notice that it is very limited (you can't create new records or delete existing ones; you can only edit a custom field of a record).

Essentially, what the API allows me to do is pass in two parameters: someEmailAddress and theNewFieldVal. someEmailAddress is used to query the records and find all of them that have the supplied email (in other words, it finds records where Email__c is someEmailAddress). I then loop through all of the records and set Some_Field__c to theNewFieldVal.

So, to recap, someEmailAddress is merely a way to find the record(s) I would like to update, and theNewFieldVal is the new value of Some_Field__c.

@RestResource(urlMapping='/myendpoint/*')
global class FooBar {

    @HttpPatch
    global static void doPatch(String someEmailAddress, String theNewFieldVal) {

        // indented so you can clearly see what's going on
        List<MyCustomObject__c> results = [
            SELECT Some_Field__c 
            FROM MyCustomObject__c 
            WHERE Email__c = :someEmailAddress
        ];

        for(MyCustomObject__c o : results){
            o.Some_Field__c = theNewFieldVal;
        }

        update results;
    }

}  

I use the above API with the following PATCH cURL request in my WordPress plugin:

public function patch_salesforce($someEmailAddress, $theNewFieldVal) {
    $url = 'https://<MY_COMPANY>.force.com/<MY_PATH>/services/apexrest/myendpoint';

    $content = json_encode(array(
        'someEmailAddress' => $someEmailAddress,
        'theNewFieldVal' => $theNewFieldVal
    ));

    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json"));
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PATCH");
    curl_setopt($curl, CURLOPT_POSTFIELDS, $content);

    curl_exec($curl);

    $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

    if($status != 200) {
        die("Error: call failed with status $status, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl));
    }

    curl_close($curl);
}

That all works well in development with a Sandbox, but when I changed $url from my Sandbox's Force.com URL to my Production org's Force.com URL, I was greeted with the following error:

Error: call to URL failed with status 0, curl_error SSL: no alternative certificate subject name matches target host name '<MY_INSTANCE>.force.com', curl_errno 51

I then spent some time researching cURL error 51, and came across this post. It suggests to add the following to my cURL settings:

curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);

I tried that and got this error:

Error: call to URL failed with status 501, curl_error , curl_errno 0

If I try using only CURLOPT_SSL_VERIFYHOST, I get the same error.

If I try using only CURLOPT_SSL_VERIFYPEER, I get the original cURL 51 error.

Also, do I need the .secure in $url? Because I tried that and kept getting 500 errors.

@sfdcfox pointed out that one possible solution is to add a new certificate in Salesforce's Certificate and Key Management setup section, but which API client certificate should I use? Self-signed or one issued by a CA?

  • If you are exposing the rest class to a public site you do not need to authenticate at all. Simply post the data to the site URL and let your apexclass handle it – Eric Aug 14 '17 at 3:03
  • @Eric I know, but I'm getting an error when I swap out my developer Sandbox URL with my Production org URL. I get cURL error code 51. Do I need to have a certificate in my production org? – Matthew Aug 14 '17 at 3:05
  • Check your urls. Add a get to you rest class and hit it with your browser to test. At least then u will know if the URL you are trying to access is correct or not. Postman is also a good tool for troubleshooting – Eric Aug 14 '17 at 3:07
  • @Eric, that's a good idea. I'll try it -- thanks! – Matthew Aug 14 '17 at 3:08
  • @Eric, I really don't think the URLs are the problem, though. Here are the URLs I'm using.. (the site label/name and path are the same). I tried it with & without the .secure, too. Question: should Username-Password OAuth flow be only used for development with Sandboxes, or can they be used in Production? – Matthew Aug 14 '17 at 3:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.