I've written a Wordpress Plug-in that interacts with Salesforce via the REST API. It successfully gets an Instance URL and an Authentication Token using a username/password.
I'm able to submit queries and create objects using wp_remote_post with GET and POST respectively.
However, when creating objects, though successfully created in the Salesforce instance, I get the following in response to my POST:
{"message":"HTTP Method 'POST' not allowed. Allowed are HEAD,GET,PATCH,DELETE","errorCode":"METHOD_NOT_ALLOWED"}
Using the same json body content from these requests, I am able to submit and create via the Salesforce Workbench with no problems at all. I get a proper response that looks like this:
{
"id" : "003E000000OubjkIAB",
"success" : true,
"errors" : [ ]
}
Is there something in the Headers that I'm sending that Salesforce only partially disagrees with? Here are some other arguments that are getting sent as a result of using wp_remote_post - http://codex.wordpress.org/HTTP_API#Other_Arguments
Here's the php code that's calling it:
$connInfo['access_token'] = get_transient('npsf_access_token');
$connInfo['instance_url'] = get_transient('npsf_instance_url');
$url = $connInfo['instance_url'] . $service;
$sfResponse = wp_remote_post($url, array(
'method' => $method,
'timeout' => 5,
'redirection' => 5,
'httpversion' => 1.0,
'blocking' => true,
'headers' => array("Authorization" => "OAuth ". $connInfo['access_token'], "Content-type" => "application/json"),
'body' => $content,
'cookies' => array()
)
);
The $content is being encoded via json_encode before it gets to this point.
Update:
It is specific to one of the extra CURL options being sent by the WP_Http_Curl class. I haven't yet narrowed down which one Salesforce is having a problem with.
The solution is disable redirection in the request. You have it as 5 (the default) -- it needs to be set to 0 for this to work.
The initial request works but Salesforce sends a location header as a part of the response (the URL of the newly created object). WordPress thinks it is being told that the URL moved and that it should try again at this new URL. The response you're seeing is the result of that second request to the actual object you just created. That URL doesn't accept POST requests apparently.
It's a bit odd for Salesforce to be sending such a header, but there's also some discussion going on on the WordPress side that WordPress shouldn't follow location headers for non-301/302 responses which would solve this.
Thanks for posting this by the way. You update made me start debugging WP_Http_Curl which made me realize it was actually making a second HTTP request.
Related
I have an application on Yii2.
I have an external vendor i want to redirect. For example, i am encrypting the current user info, and want to send that to the external vendor, so the user information is automatically populated on his website.
Everything works fine if i do that on the front end side using JS.
The problem i have is only my app server is whitelisted to the vendor. So i need to make the redirection happen on the backend.
I tried several method, and even with Guzzle HTTP, and it doesn't redirect.
TO be clear, i am not looking for a simple redirect, it is a form post on external URL.
I went though this post, but the problem remain the same...
Yii2 how to send form request to external url
Does anybody faced this issue?
If I understand you correctly, you want to POST data received from your frontend to the server of a third party company (let's call them ACME). Your webserver is whitelisted by ACME but your clients are not (which is good). You want to show a page on your server and not a page on the ACME server after the POST, right?
You have to send the data with a separate request from your server to the ACME server. You cannot create a HTML <form> and put the ACME server in the action parameter of it, because the request would be sent from the client and not your backend, failing at the whitelist. After you validate your client input, you can send it with guzzle to ACME.
With the status code you can decide if your request was successful or not. You can read more about guzzle here
The code sample below shows how you could POST the $payload (a fictional blog post if you will) as JSON to the ACME server and output a line with the request result.
$payload = [
'username' => 'john.doe',
'postContent' => 'Hello world',
];
$client = new GuzzleHttp\Client();
$response = $client->post('https://acme.example.org/endpoint',['http_errors' => false, 'json' => $payload]);
if($response->getStatusCode() === 200){
echo "Request OK";
}else{
echo "Request failed with status ".$response->getStatusCode();
}
I have been tyring to get this api working for literally hours. I can't even get the try this api part working with api key. I tried to use it with cURL like this:
$submitSite = curl_init($submit_url);
curl_setopt_array($submitSite, [CURLOPT_PUT => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Accept: application/json"]]);
$responseContent = curl_exec($submitSite);
But it returns 0. I url encoded siteUrl and feedpath parts and added the api key at the end. How can I submit my website's sitemap automatically?
You're missing the authorization part. You must have the proper permissions to https://www.googleapis.com/auth/webmasters to add the sitemap.
In your code I don't see any headers for this authorization.
For more info check: https://developers.google.com/webmaster-tools/search-console-api-original/v3/how-tos/authorizing
I am building an application which will eventually reside on the same domain where another application resides; both of which are written in PHP. One is a Laravel application and the other a Magento 1.9 store.
To authenticate the user, the Laravel application requires that a certain cookie be set by the Magento store's response, subsequently retrieved and parsed, all before authentication may continue.
My current strategy is a POST to a custom controller which delivers multiple Set-Cookie headers from the Magento store.
The one I need is something like:
Set-Cookie: auth_token=TheValueWeNeedToContinueAuthenticating; domain='.mydomain'; ...
The server I am testing on is an in-house staging environment. The server's VHost is set to Laravel's public directory, as usual.
The Magento store is on a different server however the TLD is the same .mydomain
I have verified the response in Postman, I am indeed returning the cookie with the correct Set-Cookie in place, however it is not visible in my Laravel application as the other cookies from Magento, are. The other cookies were verified within the response as I dumped Guzzle's CookieJar and still received all but the cookie I am looking for.
I am using PHP's Guzzle HTTP Library to post from a Laravel 5.6 app using PHP 7.1
The Magento1.9 store unfortunately uses PHP/5.6.35
When I dump the HTTP response I am getting the cookies which would normally receive had I actually visited any page within the store.
What else could I check to ensure I am taking to right approach to receiving this cookie? Https is the transmission protocol, and the content-type is x-www-form-urlencoded if that will assist an answer in any way.
Thank you.
UPDATE 1.0 - I was able to get a clean error reading from the request being sent.
{"status":"error","message":"invalid request"}
Here is my Guzzle Post request
$jar = new \GuzzleHttp\Cookie\CookieJar;
// Logging my error output -- I can share this if I must
$debug_file = fopen('../storage/logs/debug.txt', 'a');
try {
$payload = 'Knock, knock';
$url = '/api/for/post';
$client = new Client([
'base_uri'=> 'https://mySubdomain.myDomain.com',
'debug' => $debug_file,
'cookies' => $jar,
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
]
]);
$request = new \GuzzleHttp\Psr7\Request('POST', $url, [], $payload);
$rsp = $client->send($request);
dd($rsp->getBody()->read(1024));
$response->getBody()->read(1024) returns the error message
Use the twitter API to send direct messages, with the following method: "POST direct_messages / new" with php, tmhOAuth library.
Since a few days ago they changed (as indicated in migration documentation
) by the method: "POST direct_messages / events / new", where the structure of the post parameters changes, which are json.
Making the changes that indicate, when testing get response code 415: "Callback URL not approved for this client application. Approved callback URLs can be adjusted in your application settings" (twitter help)
Adding a url callback to the app, keeps giving the same error. Did someone have the same problem when they migrated? any suggestions?
I detail the changes implemented, with some code:
$options = array(
"event" => array(
"type" => 'message_create',
"message_create" => array(
"target" => array('recipient_id' => $id_usuario),
"message_data" => array('text' => $texto),
),
)
);
$json_options = json_encode($options);
$headers_extra = array('Content-Type' => 'application/json');
$code = $this->_tmhOAuth->request('POST', $this->_tmhOAuth->url('1.1/direct_messages/events/new'), $json_options, $headers_extra);
1) In "options" the format is changed, by the requested json,
2) "json_encode" function is used before sending in request method.
3) Headers "Content-Type" are added to be taken by the tmhOAuth library.
Thanks for any comments or help
tmhOauth is too old and hasn't been updated for a while. I lost some time trying to adjust it and finally switched to https://twitteroauth.com/
I was able to send DM in 1 min and 4 lines of codes just following their example in section JSON data.
I have a running workflow which I would like to post fields to via an API call (see below):
$ret = invokeFlowgear(
"https://domain.flowgear.io/salesbooks",
"username",
"password",
30,
array(
'name' => 'Introduction to Data integration with Flowgear',
'isbn' => 'X-XXX-XXXX',
'qis' => 0,
'price' => 250.99,
'author_id' => 3
)
);
Eventually this call should result into the workflow inserting the data onto the table and returning a success message.
What do I need to have this achieved with a workflow via an API?
You need to accept the raw HTTP POST body into the Workflow. To do that, set an appropriate URL ("/salesbooks/") in the workflow detail pane and set the method to POST.
Then drop in a Variable Bar and add the special property FgRequestBody. Optionally also add FgRequestContentType so you can inspect the content type of the message being received.
Create an HTTP POST to that Workflow and you can see what's coming through to the FgRequestBody property (it will show in the Start entry in the activity logs).
If you need to convert between JSON and XML, using JSON Convert.