Always getting response as Invalid Session Token in soap client php - php

I have php version 7.1 in my localhost. I have made changes in my php.ini file to run SOAP from my localhost.
I need to generate primary and secondary session token by passing login id and password to SOAP client API.
Once session token is authenticated it will return some rate chart. My code is generating session tokens. But when I am passing that token key to the next method in SOAP Client api its always giving me an error like "Invalid Session Token" or "Invalid Authentication". However the same tokens are working well in SOAP UI exe. I mean I have installed SOAP UI exe and by using wsdl "http://cnx.test.dat.com:9280/wsdl/TfmiFreightMatching.wsdl" and using method "Login" and "LookupRate" its working everything fine. The way i need that.
But whenever i am using that tokens in php localhost its always giving me an authentication error by SOAP Client.
I am sharing my code below.
$wsdl = "http://cnx.test.dat.com:9280/wsdl/TfmiFreightMatching.wsdl";
$client = new SoapClient($wsdl, array('trace' => true));
$params = array('loginOperation'=>array('loginId'=>'ryder_cnx1','password'=>'ryder1','thirdPartyId'=>'dl'));
$client->Login($params);
$data = $client->__getLastResponse();
$p = xml_parser_create();
xml_parse_into_struct($p, $data, $vals, $index);
xml_parser_free($p);
$token = [];
foreach ($vals as $key => $value) {
foreach ($value as $key1 => $value1) {
if($key1 == "value")
$token[] = $value1;
}
}
echo "Primary Token = ".$token[0];
echo "<br> Secondary Token = ".$token[1];
//echo "<br> Expiry Date = ".$token[2];
$params_session = array("sessionToken"=> array("primary"=>$token[0], "secondary"=>$token[1]));
$namespace = 'http://www.tcore.com/TcoreTypes.xsd'; // I am not sure about this namespace. Whether its correct or not.
$header = new SoapHeader($namespace,'sessionHeader',$params_session,true);
$client->__setSoapHeaders($header);
$params_data = array('lookupRateOperations'=> array(
'equipment'=>'Vans',
'origin'=>array('postalCode'=>array('country'=>'US','code'=>'30004')),
'destination'=>array('postalCode'=>array('country'=>'US','code'=>'10001'))
));
try{
$result = $client->LookupRate($params_data);
print_r($result);
}catch (SoapFault $exception){
//or any other handling you like
print_r(get_class($exception));
enter code hereprint_r($exception);
}
if anybody have any idea, please share it with me.
Awaiting any response.
Thanks a lot in advance :)

I know this is very old, and most likely the OP figured it out. But in case anyone else comes along, I was able to get it working with two slight changes.
First,
$namespace = 'http://www.tcore.com/TcoreTypes.xsd';
Should be
$namespace = 'http://www.tcore.com/TcoreHeaders.xsd';
Second,
$params_session = array("sessionToken"=> array("primary"=>$token[0], "secondary"=>$token[1]));
should be
$params_session = array(
"sessionToken"=> array(
"primary"=>base64_decode($token[0]),
"secondary"=>base64_decode($token[1])
)
);
The rest of my code is similar enough that if the above changes are made, it should work. I would also refrain from posting real usernames and passwords, btw.

Related

Why my PHP script does not "see" the webhook from Dialogflow?

I am using DIalogflow (api.ai) to create chat interfaces. I created a webhook from Dialogflow to a simple app containing a php script deployed on Heroku.
Therefore, I placed in the webhook form of Dialogflow the url of my Heroku app which resembles to this: https://my_heroku_app_name.herokuapp.com.
My ultimate goal is to fetch some data from a database (through the php script) and then feed Dialogflow with them. For now, I am only trying to connect the Heroku app (php script) with Dialogflow through a webhook.
The php script of the Heroku app is the following:
<?php
$method = $_SERVER['REQUEST_METHOD'];
if($method == 'GET'){
$requestBody = file_get_contents('php://input');
$json = json_decode($requestBody);
$text = $json->metadata->intentName->text;
switch ($text) {
case 'Name':
$speech = "This question is too personal";
break;
default:
$speech = "Sorry, I didnt get that.";
break;
}
$response = new \stdClass();
$response->speech = $speech;
$response->displayText = $speech;
$response->source = "webhook";
echo json_encode($response);
}
else
{
echo "Method not allowed";
}
?>
Keep in mind the following:
$method is GET for some reason instead of POST as it is supposed to be from Dialogflow.
if you try to echo any of the variables $requestBody, $json or $text then nothing is printed.
I have tested that the if branch is executed and that the default branch is executed at switch.
Why my PHP script cannot "see" the webhook from DIaloflow and fetch the data from it so as to respond appropriately?
P.S. My question is not a duplicate of Valid JSON output but still getting error. The former is about the input of the php script whereas the latter is about the output of the php script. These two things do not necessarily constitute identical problems.
try to do something like this with some modification in your code.
First, I suggest you to use action instead of using intent name for switch case.
index.php
<?php
require 'get_wardinfo.php';
function processMessage($input) {
$action = $input["result"]["action"];
switch($action){
case 'wardinfo':
$param = $input["result"]["parameters"]["number"];
getWardInfo($param);
break;
default :
sendMessage(array(
"source" => "RMC",
"speech" => "I am not able to understand. what do you want ?",
"displayText" => "I am not able to understand. what do you want ?",
"contextOut" => array()
));
}
}
function sendMessage($parameters) {
header('Content-Type: application/json');
$data = str_replace('\/','/',json_encode($parameters));
echo $data;
}
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input["result"]["action"])) {
processMessage($input);
}
?>
get_wardinfo.php
<?php
require 'config.php';
function getWardInfo($param){
$wardinfo="";
$Query="SELECT * FROM public.wardinfo WHERE wardno=$param";
$Result=pg_query($con,$Query);
if(isset($Result) && !empty($Result) && pg_num_rows($Result) > 0){
$row=pg_fetch_assoc($Result);
$wardinfo= "Here is details that you require: Name: " . $row["name"]. " --- Address: " . $row["address"]. " --- MobileNo: " . $row["contact"];
$arr=array(
"source" => "RMC",
"speech" => $wardinfo,
"displayText" => $wardinfo,
);
sendMessage($arr);
}else{
$arr=array(
"source" => "RMC",
"speech" => "Have some problem .",
"displayText" => "Have some problem .",
);
sendMessage($arr);
}
}
?>
It seems you know each parameter and all about dialogflow and how it works with PHP arrays and all still if you have confusion in above code or method kindly put a comment.
And I will suggest you don't go for Heroku directly first try it with ngrok it will make your local server live and put the URL as webhook in dialogflow and you can easily debug the errors and all.
I managed to connect Dialogflow to my php script on Heroku.
I made the following changes on my php script (on Heroku) and on Dialogflow which led to this result:
I replaced the condition if($method == 'GET') with the condition if($method == 'POST') so as to anticipate the POST request of Dialogflow.
Keep in mind that until I solved the whole problem I was not receiving any POST request but I GET request so I thought that the POST request from Dialogflow leads to GET request because of a webpage redirection which I could not really see at that moment.
I replaced $text = $json->metadata->intentName->text; with $text = $json->results->metadata->intentName; which was the right json parsing for retrieving the value of intentName. (I have published here the json request from Dialogflow but nobody noticed my mistake)
I published my bot on Dialogflow through its built-in web demo and on Slack. This may sound quite irrelevant but also one person on the Dialogflow forum stated that: "Maybe it should rementioned somewhere. that api.ai98 is not parsing any parameters/values/data to you service untill you bot is published!!" (See the second post here: https://discuss.api.ai/t/webhook-in-php-example/229).

How to generate a signature for OAuth

I'm currently attempting to generate a signature to make API calls to quickbooks online, however I keep getting authentication errors. I'm sure the signature portion is where I'm going wrong. Is this incorrect:
//method to generate signature
//$this->method = "GET"
//QBO_SANDBOX_URL = 'https://some_url.com/'
//$this->_query = 'something=something'
public function generate_signature()
{
$base = $this->_method.'&'.rawurlencode($this->_url.QBO_SANDBOX_URL.'v3/company/'.$this->_realm_id).'&'
.rawurlencode("oauth_consumer_key=".rawurlencode($this->_consumer_key).'&'
.'&oauth_nonce='.rawurlencode('34604g54654y456546')
.'&oauth_signature_method='.rawurlencode('HMAC-SHA1')
.'&oauth_timestamp='.rawurlencode(time())
.'&oauth_token='.rawurlencode($this->_auth_token)
.'&oauth_version='.rawurlencode('1.0')
.'&'.rawurlencode($this->_query));
$key = rawurlencode($this->_consumer_secret.'&'.$this->_token_secret);
$this->_signature = base64_encode(hash_hmac("sha1", $base, $key, true));
}
Now when I go to send my request, here are the headers:
$this->_headers = array(
'Authorization: '.urlencode('OAuth oauth_token="'.$this->_auth_token.'",oauth_nonce="ea9ec8429b68d6b77cd5600adbbb0456",oauth_consumer_key="'.$this->_consumer_key.'",oauth_signature_method="HMAC-SHA1", oauth_timestamp="'.time().'", oauth_version ="1.0"oauth_signature="'.$this->_signature.'"').''
);
I get a 401 Authorization response. Am I signing incorrectly?
EDIT: All fields not included here (i.e $this->_auth_token) are set.
For anyone that might use this as a basis for their own integration, there is one other issue with the code originally posted:
$key = rawurlencode($this->_consumer_secret.'&'.$this->_token_secret);
should be
$key = rawurlencode($this->_consumer_secret).'&'.rawurlencode($this->_token_secret);
This issue was in the base string:
.rawurlencode("oauth_consumer_key=".rawurlencode($this->_consumer_key).'&'
.'&oauth_nonce='.rawurlencode('34604g54654y456546')
The & after the consumer key and once again before the oauth_nonce.
In the signature creation I think it lacks the call to rawurlencode():
$this->_signature = rawurlencode(base64_encode(hash_hmac("sha1", $base, $key, true)));
instead :
$this->_signature = base64_encode(hash_hmac("sha1", $base, $key, true));

Signing errors from Withings Rest API

all
I have an app that is successfully getting authorized using Withing's api and OAuth.
I get the auth page from whitings, and I get the resulting token and verifier, however I can not make requests with those - I keep getting a 342 error: The signature (using Oauth) is invalid.
Code:
<?
require("include.php");
require_once("OAuth.php");
$domain = "oauth.withings.com";
$base = "/account/";
$base_url = "https://$domain$base";
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
$consumer = new OAuthConsumer("my key goes here :-)", "my key goes here :-)", "http://oauth.corp.withings.com/test.php");
$sig_method = $hmac_method;
$username="mydbusername";
$mySQL=" select * from `healthtokens` where service='WITHINGS' and userid='".$username."'";
$data=mysql_query($mySQL) or die("Died at 2<BR>".mysql_error());
$tokenrow = mysql_fetch_array( $data );
$serviceuserid=$tokenrow['serviceuserid'];
$otoken=$tokenrow['otoken'];
$overifier=$tokenrow['overifier'];
$acc_tok = new OAuthToken($otoken,$overifier);
$req = OAuthRequest::from_consumer_and_token($consumer, $acc_tok, "GET", "http://wbsapi.withings.net/user?action=getbyuserid&userid=".$serviceuserid);
$req->sign_request($sig_method, $consumer, $acc_tok);
$response = file_get_contents($req);
echo $response;
?>
Withings API docs: http://www.withings.com/en/api
An example of my call:
http://wbsapi.withings.net/user?action=getbyuserid&oauth_consumer_key=mybigconsumerkeyishere&oauth_nonce=f57a956d52c7412326fb0577e87addc4&oauth_signature=jiBNvql5r06HysjjVyxCh7C7ZUk%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1381758029&oauth_token=4088d6173b78b71cfd6ddd4245496de4b1f7b3c45bfb49f8e59b1202ccfc&oauth_version=1.0&userid=1234567
I know it sounds silly and it gave me some headaches too, but the "funny" thing with oauth 1 (or at least withings) is, that the order of the parameters is important.
Try using the EXACT order as in the withings oauth sample (http://www.withings.com/en/api/oauthguide):
http://wbsapi.withings.net/measure?
action=getmeas
&oauth_consumer_key=c331c571585e7c518c78656f41582e96fc1c2b926cf77648223dd76424b52b
&oauth_nonce=accbac1b7ee2b86b828e6dc4a5a539b2
&oauth_signature=XfobZMboIg2cRyNKAvyzONHHnKM%3D
&oauth_signature_method=HMAC-SHA1
&oauth_timestamp=1311842514
&oauth_token=887557411788d5120537c6550fbf2df68921f8dd6f8c7e7f9b441941eb10
&oauth_version=1.0
&userid=831

php soapclient returns null but getPreviousResults has proper results

I've ran into trouble with SOAP, I've never had this issue before and can't find any information on line that helps me solve it.
The following code
$wsdl = "path/to/my/wsdl";
$client = new SoapClient($wsdl, array('trace' => true));
//$$textinput is passed in and is a very large string with rows in <item></item> tags
$soapInput = new SoapVar($textinput, XSD_ANYXML);
$res = $client->dataprofilingservice(array("contents" => $soapInput));
$response = $client->__getLastResponse();
var_dump($res);//outputs null
var_dump($response);//provides the proper response as I would expect.
I've tried passing params into the SoapClient constructor to define soap version but that didnt' help. I've also tried it with the trace param set to false and not present which as expected made $response null but $res was still null. I've tried the code on both a linux and windows install running Apache.
The function definition in the WSDL is (xxxx is for security reasons)
<portType name="xxxxServiceSoap">
<operation name="dataprofilingservice">
<input message="tns:dataprofilingserviceSoapIn"/>
<output message="tns:dataprofilingserviceSoapOut"/>
</operation>
</portType>
I have it working using the __getLastResponse() but its annoying me it will not work properly.
I've put together a small testing script, does anyone see any issues here. Do I need a structure for the return type?
//very simplifed dataset that would normally be
//read in from a CSV file of about 1mb
$soapInput = getSoapInput("asdf,qwer\r\nzzxvc,ewrwe\r\n23424,2113");
$wsdl = "path to wsdl";
try {
$client = new SoapClient($wsdl,array('trace' => true,'exceptions' => true));
} catch (SoapFault $fault) {
$error = 1;
var_dump($fault);
}
try {
$res = $client->dataprofilingservice(array("contents" => $soapInput));
$response = $client->__getLastResponse();
echo htmlentities($client->__getLastRequest());//proper request echoed
echo '<hr>';
var_dump($res);//null
echo "<hr>";
echo(htmlentities($response));//proper response echoed
} catch (SoapFault $fault) {
$error = 1;
var_dump($fault);
}
function getSoapInput($input){
$rows = array();
$userInputs = explode("\r\n", $input);
$userInputs = array_filter($userInputs);
//
$inputTemplate = " <contents>%s</contents>";
$rowTemplate = "<Item>%s</Item>";
//
$soapString = "";
foreach ($userInputs as $row) {
// sanitize
$row = htmlspecialchars(addslashes($row));
$xmlStr = sprintf($rowTemplate, $row);
$rows[] = $xmlStr;
}
$textinput = sprintf($inputTemplate, implode(PHP_EOL, $rows));
$soapInput = new SoapVar($textinput, XSD_ANYXML);
return $soapInput;
}
Ok after much digging it is related to relative namespaces, it appears that PHP doesn't handle them well within the WSDL or the SOAP Envelope. So since I don't have control of the SOAP Server I will continue to get the response via __getLastResponse();.
Hopefully this will save some people some time it was hard to find.
You are mixing things here. __getLastResponse() returns the bare XML string response from the server if you make use of the 'trace' => true option. That is for debugging only.
So regardless whether 'trace' => true or not, the method which you would like to call originally returns the same and that is totally normal. Setting tracing to on won't change the behaviour, it just offers an additional feature, the return value for __getLastResponse().
As the SoapClient does not throw any exception I'd say that your call is going okay and NULL is a valid return value.
You might want to provide the actual XML string and/or the WSDL defintion so that one could inspect if that's the case or not.

Help using SOAP for login

I'm designing a website for an organization that's a state chapter of a national organization. The national organization has implemented a member login that I need to use for the state website.
My website is in PHP, and it looks like the server for the national organization is using SOAP and ColdFusion. I'm a total newbie to using SOAP, so I'm probably missing a bunch of things.
The national organization sent me this information:
Fields to collect on a form
mausername
mapassword
Static variables
componenttype Value: Chapter
components Value: NM
authusername Value: NMChap
authpassword Value: USA
authpagealias Value: Login
The webservice is located here:
https://www.apta.org/AM/APTAAPPS/ComponentAuthWebService/aptamemberauthorize.cfc?WSDL
The following fields will be returned:
Email, FirstName, LastName, LoggedIn, Phone_Release, UserName
If LoggedIn returns “true,” the member has been authenticated as a member of the component.
This has been implemented and tested here: http://aptadevisg.apta.org/am/aptaapps/test/NM_Chap_test_form.cfm
Based on this information and reading the SOAP documentation, this is what I came up with:
$apta_server = 'https://www.apta.org/AM/APTAAPPS/ComponentAuthWebService/aptamemberauthorize.cfc?WSDL';
$post_data['mausername'] = '107150';
$post_data['mapassword'] = 'barnes';
$post_data['componenttype'] = 'Chapter';
$post_data['components'] = 'NM';
$post_data['authusername'] = 'NMChap';
$post_data['authpassword'] = 'USA';
$post_data['authpagealias'] = 'Login';
$options = array('trace' => 1, 'exceptions' => 0);
$options['location'] = 'https://www.apta.org/AM/APTAAPPS/ComponentAuthWebService/MemberAuth';
try
{
$client = new soapclient($apta_server, $options);
}
catch (Exception $e)
{
}
$client->debug_flag = 1;
try
{
$result = $client->__soapCall('MemberAuth', array($post_data));
echo '<h1>Soap Result</h1><pre>';
print_r($result);
echo '</pre>';
}
catch (SoapFault $fault)
{
echo '<h1>Soap Fault</h1><pre>';
print_r($fault);
echo '</pre>';
}
echo '<pre>getFunctions<br>';
print_r($client->__getFunctions());
echo '</pre>';
echo '<pre>getTypes<br>';
print_r($client->__getTypes());
echo '</pre>';
echo '<pre>getLastResponseHeaders<br>';
print_r($client->__getLastResponseHeaders());
echo '</pre>';
echo '<pre>getLastResponse<br>';
print_r($client->__getLastResponse());
echo '</pre>';
When I print out the result of the __soapCall(), I get a message of: "looks like we got no XML document."
I really don't know what I'm doing regarding SOAP, so any help would be greatly appreciated. You can view the results of the test login attempt at: http://rc19.info/test_login.php
First, you have the $options['location'] wrong. Try the location of the actual web service:
$options['location'] = 'https://www.apta.org/AM/APTAAPPS/ComponentAuthWebService/aptamemberauthorize.cfc';
Second, though not necessary, you don't have to call $client->__call("MemberAuth"). You can do $client->MemberAuth() and pass the parameters in like so:
$result = $client->MemberAuth($post_data['mausername'],$post_data['mapassword'],$post_data['componenttype'],$post_data['components'],$post_data['authusername'],$post_data['authpassword'],$post_data['authpagealias']);
You've got a superfluous array in there (you could see that with $client->__lastRequest(), so change:
$result = $client->__soapCall('MemberAuth', array($post_data));
To:
$result = $client->__soapCall('MemberAuth', $post_data);
After that, I get either an 'could not connect to host' (if I follow the port of the WSDL, https://aptaweb.apta.org/AM/APTAAPPS/ComponentAuthWebService/aptamemberauthorize.cfc), or a redirect (302) to the website with a bunch of cookies set if I choose yours (https://www.apta.org/AM/APTAAPPS/ComponentAuthWebService/MemberAuth). Use a stream_context with $context = stream_context_create(array('http'=>array('max_redirects'=>1))); and $client->__getLastRequestHeaders(); to see the redirect in action.
Curiously enough, Bob's solution of https://www.apta.org/AM/APTAAPPS/ComponentAuthWebService/aptamemberauthorize.cfc works, but is in no way indicated by the wsdl itself as far as I can tell.

Categories