PHP Soap Client to handle multipart/related - php

I am developing an application that needs to access a SOAP api. The soap API should return a base64 encoded zip file, and it does so when being fired from SOAPUI. However I am trying to read this result programatically therefore I would need to get the file with a request fired from PHP.
$client = new MTOMSoapClient($url, array("soap_version" => SOAP_1_1,"trace" => 1));
$user_param = array (
'DealerCode' => "1234",
'Hash' => "asjdfasjda1231231231",
'Password' => "somerandompassword",
'UserName' => "somerandomusername"
);
var_dump(
$client->__soapCall(
"DownloadOffer",
array($user_param)
)
);
var_dump($client->__getLastRequest());
I also extended PHP's soap client like shown here without the proper results: https://gist.github.com/pkmishra/2243055
The same error is shown in postman:
SoapFault: Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'multipart/related; type="application/xop+xml"'. in file /app/app/Http/Middleware/MTOMSoapClient.php on line 8
Any advice, library, way to get the response or at least the reason behind the error is greatly apreciated.

Related

POST with guzzle returns 417

I created an API to post JSON data to another API, but for some JSON it returns 417 error code.
I checked these JSONs and tried to re-post them, but i got the 417 again, the post is only working if i delete some values from the JSON.
The JSONs is always valid and it's around 1.5KB of data, but i cant figure it out why it's happening.
Guzzle version: 7.0, PHP version: 7.4
$guzzle = new \GuzzleHttp\Client([
'verify' => false,
'expect' => false
]);
$request = null;
$request = $guzzle->post(
$request_url,
[
'auth' => [self::$API_USERNAME, self::$API_PASSWORD],
'json' => [$request_body]
]
);
I've created a postman request and send the invalid JSON to the API direct without the middleware, now i can see the full error related to the invalid email address format.

"Empty Payload. JSON content expected" error calling Microsoft Graph (Guzzle & PHP)

I am trying to call the Microsoft Graph API to reset a passcode on a device registered with Intune. Unfortunately when I go to make the call, I receive an error stating that the JSON Payload is empty. The specific endpoint does not require a JSON payload, in fact it says to not include a body at all.
I attempted to add some JSON to see if that would satisfy the error, and I still receive the same error message.
Here is the call I am making:
$client = new Client();
try{
$client->post('https://graph.microsoft.com/beta/managedDevices/12345resetPasscode', [
'headers' => [
'Authorization' => 'Bearer 12345',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'json' => json_encode(['hello' => 'world']),
]
]);
} catch (\GuzzleHttp\Exception\ClientException $e) {
dd($e->getResponse()->getBody()->getContents());
}
Here is the error I am receiving:
"Bad Request: Empty Payload. JSON content expected."
https://i.stack.imgur.com/gwwtJ.png
Here is the API Documentation I am working off: https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/intune_devicefe_manageddevice_resetpasscode
Using PHP 7 & Guzzle 6
Any help is appreciated!
I'm an engineer on the Microsoft Intune team, working on the integration between Microsoft Graph and Intune.
It looks like there is an error in the documentation (I will make sure that is fixed). The correct URL You should be using is:
https://graph.microsoft.com/beta/managedDevices/12345/resetPasscode
Where 12345 is a the id of the device.
Hope that resolves your issue
Peter

Using PHP SOAP client in non-WSDL mode

I am working on an api for a client. I have received the following information:
API Url: http://xyz-crm.example/WebAPI/Custom/project_name/XML/
Username: foobar
password: spameggs
I need to configure the PHP SOAP client for the same in non-WSDL mode. I have written the following but it does not seem to work:
$wsdl = null;
$options = array(
'uri' => 'http://xyz-crm.example/WebAPI/Custom/project_name/XML/',
'location' => 'http://xyz-crm.exmaple.com/WebAPI/Custom/project_name/XML/',
'login' => 'foobar',
'password' => 'spameggs'
);
$client = new SoapCLient($wsdl, $options);
I just want to make a successful ping to the api at first. See if things are working fine. What am I doing wrong here?
Update 1
I made the following changes:
$wsdl = null;
$options = array(
'uri' => "http://xyz-crm.example/WebAPI/Custom/project_name/XML/",
'location' => "http://xyz-crm.example/",
'Username' => "foobar",
'Password' => "spameggs",
'soap_version' => '1.2'
);
$client = new SoapClient($wsdl, $options);
$client = $client->getListings();
I get the error: looks like we got no XML document
[Edit by me, hakre: This update was done as feedback to answer #1. It changes the location option using a shortened URL (reason not given by OP) and it adds the soap_version option (as suggested in answer #1, but not as constant but as string (containing an invalid value), so there should be no wonder this creates an error, a correct option value is given in answer #1 (the SOAP_1_1 constant) and by intention, the correct value would be the SOAP_1_2 constant for this example). Error message as commented by OP was "SOAP Fault: Wrong version."]
Update 2
I tried the following but it still fails:
$listing = $client->getListings();
$request = $client->__getLastRequest();
The execution stops at the first line itself without ever going to the second one.
[Edit by me, hakre: As review has shown wrong configuration options in Update 1 already which are not addressed in Update 2 it would be a miracle if it still wouldn't fail. The execution stops because an Exception is thrown and no error/exception handling is done]
Die URI or file ending does not matter, it could even be .jpg, there is no default.
Have a look at similiar questions: Does this SOAP Fault mean what I think it means?
It would be helpful if you put the error message into the question, aswell as the XML output of your request.
try setting the SOAP Version in the array of your SoapClient instance to one of the constants (try different ones):
new SoapClient($url, array("soap_version" => SOAP_1_1,.......
or SOAP_1_2 ...
To debug the XML try the answer from Inspect XML created by PHP SoapClient call before/without sending the request
The error message of your updated question does not look like it coming from PHP, looks more like an answer from the webservice, means your request is actually working.

Twitter api 1.1 update_with_media

i'm changing my php code to be compatible with new API and i'm stuck with update_with_media.
This is my code:
$image = constant('PATH_UPLOAD').$db_data['post_image'];
$connection = new TwitterOAuth(constant('CONSUMER_KEY'), constant('CONSUMER_SECRET'), $db_data['tw_oauth_token'], $db_data['tw_oauth_secret']);
$content = $connection->OAuthRequest('https://api.twitter.com/1.1/account/verify_credentials.json', 'GET', array());
$twitterInfo = json_decode($content);
$resp_tw = $connection->OAuthRequest('https://api.twitter.com/1.1/statuses/update_with_media.json', 'POST',
array(
'status' => html_entity_decode($db_data['post_text'],ENT_QUOTES,'UTF-8'),
'media[]' => "#{$image}"
)
);
And it returns
{"errors":[{"code":189,"message":"Error creating status"}]}
What might be the problem / what i'm doing wrong?
you can try like this :
$tmhOAuth = new tmhOAuth(array(
'consumer_key' => 'abc',
'consumer_secret' => 'abc',
'user_token' => 'abc',
'user_secret' => 'abc',
));
$response = $tmhOAuth->request('POST', $tmhOAuth->url('1.1/statuses/update_with_media'),
array(
'status' => $message,
'media[]' => file_get_contents($image)
));
if ($response != 200) {
//Do something if the request was unsuccessful
}
there is my code test https://twitter.com/wallapps/status/357137553691906048
Though the question is a few months old, I thought I'd answer it since I spent several hours on making update_with_media work and could not find satisfactory answers online.
Twitter API error messages unfortunately are not that specific. I was able to figure out the foll twitter errors:
"error could not authenticate you" - probably means your OAuth signature base string is not correct
"error incorrect or missing uri" - probably means you are not strictly following the format expected by Twitter in the request body. Could be something as simple as missing a \n in your request body
"error creating status - probably means your status text is encoded when it should not be in the request body of a multipart / form-data request
"Error internal error" - this one indicates nothing useful. It probably means that you have some data that is not encoded when twitter expects it to be or vice versa. It could also mean that you have not included the encoding type in the request body
To make update_with_media work, these tips may help:
The request should have content-type of multipart/form-data
The request body should contain the two elements twitter expects media[] and status in the correct format (RFC 2388)
In addition Twitter server expects \r\n (CR LF) after each portion of the request body. Skipping this causes Twitter to return an error
The media[] data should be base64 encoded and the content-disposition section in the request body should have Content-Transfer-Encoding
OAuth signature base string should be: (see OAuth 1.0A spec for signature) &All oauth_ parameters(name=value) in the Auth header of your request object in alphabetic order, separated by & and encoded

Salesforce creates record but responds with a 405

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.

Categories