function tratar_hotmail(){
$client_id = '0xxxxxxxxxxxxxxxx2';
$client_secret = 'Wyyyyyyyyyyyyyyyyyp';
$redirect_uri = 'http://example.com/';
$auth_code = $_GET["code"];
$fields=array(
'code'=> urlencode($auth_code),
'client_id'=> urlencode($client_id),
'client_secret'=> urlencode($client_secret),
'redirect_uri'=> urlencode($redirect_uri),
'grant_type'=> urlencode('authorization_code')
);
$post = '';
foreach($fields as $key=>$value) { $post .= $key.'='.$value.'&'; }
$post = rtrim($post,'&');
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,'https://login.live.com/oauth20_token.srf');
curl_setopt($curl,CURLOPT_POST,5);
curl_setopt($curl,CURLOPT_POSTFIELDS,$post);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
$result = curl_exec($curl);
curl_close($curl);
$response = json_decode($result);
$accesstoken = $response->access_token;
$url = 'https://apis.live.net/v5.0/me/contacts?access_token='.$accesstoken.'';
$xmlresponse = curl_file_get_contents($url);
echo $xmlresponse;
$xml = json_decode($xmlresponse, true);
foreach($xml['data'] as $emails)
{
echo $emails['name'];
}
}
which outputs:
{ "error": { "code": "request_token_invalid", "message": "The access token isn't valid." } }
How can I get the request_access_token?
-EDIT-
Forgot the curl function
function curl_file_get_contents($url)
{
$curl = curl_init();
$userAgent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)';
curl_setopt($curl,CURLOPT_URL,$url); //The URL to fetch. This can also be set when initializing a session with curl_init().
curl_setopt($curl,CURLOPT_RETURNTRANSFER,TRUE); //TRUE to return the transfer as a string of the return value of curl_exec() instead of outputting it out directly.
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,5); //The number of seconds to wait while trying to connect.
curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); //The contents of the "User-Agent: " header to be used in a HTTP request.
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE); //To follow any "Location: " header that the server sends as part of the HTTP header.
curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE); //To automatically set the Referer: field in requests where it follows a Location: redirect.
curl_setopt($curl, CURLOPT_TIMEOUT, 10); //The maximum number of seconds to allow cURL functions to execute.
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); //To stop cURL from verifying the peer's certificate.
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
$contents = curl_exec($curl);
curl_close($curl);
return $contents;
}
Here's a class I've just thrown together for talking to the API:
<?php
// Note: the test script below assumes this is in a
// file called class.liverestapiconsumer.php
class LiveRESTAPIConsumer {
protected $accessTokenURI = 'https://login.live.com/oauth20_token.srf';
protected $restAPIBaseURI = 'https://apis.live.net/v5.0';
protected $appId;
protected $appSecret;
protected $accessToken;
protected $accessTokenExpires;
public function __construct($appId = NULL, $appSecret = NULL, $accessToken = NULL, $accessTokenExpires = NULL) {
$this->setAppId($appId);
$this->setAppSecret($appSecret);
$this->setAccessToken($accessToken);
$this->setAccessTokenExpires($accessTokenExpires);
}
public function getAppId() {
return $this->appId;
}
public function setAppId($appId) {
$this->appId = $appId;
}
public function getAppSecret() {
return $this->appSecret;
}
public function setAppSecret($appSecret) {
$this->appSecret = $appSecret;
}
public function getAccessToken() {
return $this->accessToken;
}
public function setAccessToken($accessToken) {
$this->accessToken = $accessToken;
}
public function getAccessTokenExpires() {
return $this->accessTokenExpires;
}
public function setAccessTokenExpires($accessTokenExpires) {
$this->accessTokenExpires = $accessTokenExpires;
}
public function accessTokenIsExpired() {
return $this->accessTokenExpires <= time();
}
public function fetchAccessToken($code, $redirectURI) {
if (!isset($code, $redirectURI, $this->appId, $this->appSecret)) {
throw new \Exception('Cannot fetch access token without an authorization code, redirect URI, application id and application secret');
}
$postFields = array(
'client_id' => $this->appId,
'client_secret' => $this->appSecret,
'code' => $code,
'redirect_uri' => $redirectURI,
'grant_type' => 'authorization_code'
);
$bodyData = http_build_query($postFields);
$headers = array(
'Content-Type: application/x-www-form-urlencoded'
);
$ch = curl_init($this->accessTokenURI);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyData);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if (!$response = curl_exec($ch)) {
throw new \Exception('cURL request failed');
} else if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) {
throw new \Exception('Live API returned an error response code: '.curl_getinfo($ch, CURLINFO_HTTP_CODE));
} else if (!$responseObj = json_decode($response)) {
throw new \Exception('Cannot decode API response as JSON; data: '.$response);
} else if (!isset($responseObj->access_token)) {
throw new \Exception('Live API did not return an access token; error: '.$responseObj->error_description);
}
$this->setAccessToken($responseObj->access_token);
$this->setAccessTokenExpires(time() + $responseObj->expires_in);
}
protected function normalizeAPIPath($path) {
return $path[0] == '/' ? $path : '/'.$path;
}
public function apiCall($method, $path, array $params = array(), $data = NULL) {
if (!isset($this->accessToken)) {
throw new \Exception('Cannot make API requests without an access token');
} else if ($this->accessTokenIsExpired()) {
throw new \Exception('The currently defined access token has expired');
}
$ch = curl_init();
$url = $this->restAPIBaseURI.$this->normalizeAPIPath($path);
if ($params) {
$url .= '?'.http_build_query($params);
}
curl_setopt($ch, CURLOPT_URL, $url);
$method = trim(strtoupper($method));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
$headers = array();
$headers[] = 'Authorization: Bearer '.$this->accessToken;
if ((array) $data) {
$bodyData = json_encode($data);
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyData);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if (!$response = curl_exec($ch)) {
throw new \Exception('cURL request failed');
} else if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) {
throw new \Exception('Live API returned an error response code: '.curl_getinfo($ch, CURLINFO_HTTP_CODE));
} else if (!$responseObj = json_decode($response)) {
throw new \Exception('Cannot decode API response as JSON; data: '.$response);
}
return $responseObj;
}
}
...and the test script (yes, I am fully aware that my HTML skills are terrible - I don't write very much of it):
<?php
session_start();
require 'class.liverestapiconsumer.php';
// Your details as assigned by Microsoft
$appId = '<your client id>';
$appSecret = '<your client secret>';
// The public (internet) URL of this script
$localUrl = 'http://example.com/path/to/file.php';
// Work out whether we have a valid access token or not
$haveAccessToken = FALSE;
$accessTokenExpiresIn = 'N/A';
if (isset($_SESSION['accessToken'])) {
$now = time();
$haveAccessToken = $now < $_SESSION['accessTokenExpires'];
$accessTokenExpiresIn = ($_SESSION['accessTokenExpires'] - $now).' seconds';
if (!$haveAccessToken || isset($_GET['destroy'])) {
unset($_SESSION['accessToken'], $_SESSION['accessTokenExpires']);
}
if (isset($_GET['destroy'])) {
header('HTTP/1.1 302 Found');
header('Location: '.$localUrl);
}
}
function parse_body_data($str) {
$result = array();
$items = preg_split('/[\r\n]+/', $str, -1, PREG_SPLIT_NO_EMPTY);
foreach ($items as $item) {
$item = explode(':', $item, 2);
if (count($item) !== 2) {
return FALSE;
}
$result[trim($item[0])] = trim($item[1]);
}
return $result;
}
?>
<html>
<head>
<title>Live API Test</title>
<style>
div.label {
margin-top: 10px;
}
</style>
</head>
<body>
<div>Do we have an access token? <b><?php echo $haveAccessToken ? 'Yes <sup>(destroy)</sup>' : 'No'; ?></b> (Expires: <?php echo $accessTokenExpiresIn; ?>)</div>
<?php
if (isset($_POST['path'])) { // get something from the API
do { // do-while so we can easily break out of it on error
$client = new LiveRESTAPIConsumer($appId, $appSecret, $_SESSION['accessToken'], $_SESSION['accessTokenExpires']);
$path = $_POST['path'];
$method = $_POST['method'];
$paramStr = trim($_POST['params']);
$params = array();
if (!empty($paramStr)) {
parse_str($paramStr, $params);
}
if (($body = parse_body_data($_POST['body'])) === FALSE) {
echo "<div>Error: Body data invalid</div>";
break;
}
try {
$result = $client->apiCall($method, $path, $params, $body);
// The class returns the response data decoded to an object, so json_encode() it again for display
echo '
Result:
<pre>'.json_encode($result, JSON_PRETTY_PRINT).'</pre>
';
} catch (\Exception $e) {
echo "<div>Exception: ".$e->getMessage()."</div>";
break;
}
} while(FALSE);
echo '<div>Back</div>';
} else if (isset($_GET['code'])) { // handle redirect from live API
try {
$client = new LiveRESTAPIConsumer($appId, $appSecret);
$client->fetchAccessToken($_GET['code'], $localUrl);
$_SESSION['accessToken'] = $client->getAccessToken();
$_SESSION['accessTokenExpires'] = $client->getAccessTokenExpires();
echo '
<div>Successfully retrieved access token: '.$_SESSION['accessToken'].'</div>
<div>Go to form</div>
';
} catch (\Exception $e) {
echo '
<div>Exception: '.$e->getMessage().'</div>
<div>Back</div>
';
}
} else if ($haveAccessToken) { // Output form
echo '
<form action="'.$localUrl.'" method="post">
<div>
<div class="label">API Path</div>
<div><input name="path" type="text"></div>
</div>
<div>
<div class="label">Parameters (query string)</div>
<div><input name="params" type="text"></div>
</div>
<div>
<div class="label">Method</div>
<div>
<select name="method">
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
<option value="MOVE">MOVE</option>
<option value="COPY">COPY</option>
</select>
</div>
</div>
<div>
<div class="label">Body Data (key: value, newline separated)</div>
<div><textarea name="body" rows="10" cols="40"></textarea></div>
</div>
<input type="submit" value="Send Request">
</form>
API Reference
';
} else { // Don't have access token yet
$opts = array(
'client_id' => $appId,
'scope' => 'wl.basic',
'response_type' => 'code',
'redirect_uri' => $localUrl
);
echo '<div>Get access token</div>';
}
?>
</body>
</html>
All the parts that I think need explanation are commented. If you have any questions let me know.
Note that I haven't extensively tested the class, and it may be lacking when it comes to the more advanced API functionality. Seems to work fairly well for simple contact manipulation though.
In addition to the answer of DaveRandom and the comment of saveATcode: You should submit the redirect url given in $localUrl as a valid redirect url at account live application. They must be exactly the same or else you will get the 'The provided value for the input parameter 'redirect_uri' is not valid....' message. I just mentioned it because mine had a typo and i experienced the same error.
Related
I'm trying to generate a token to sign my requests to the iTunes Connect API. That's my PHP file:
function encode($data)
{
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
}
function sign($data)
{
if (!$key = openssl_pkey_get_private('file://AuthKey_qwerty.p8')) {
throw new \Exception('Failed to read PEM');
}
if (!openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA256)) {
throw new \Exception('Claims signing failed');
}
return $signature;
}
function create()
{
$header = encode(
json_encode([
'kid' => 'frfc343r4',
'alg' => 'ES256',
'typ' => 'JWT',
])
);
$claims = encode(
json_encode([
'iss' => 'ddd-aaa-bbbb-cccc-ddddd',
'exp' => time() + (20 * 60),
'aud' => 'appstoreconnect-v1',
])
);
$signature = encode(
sign("$header.$claims")
);
return $header . '.' . $claims . '.' . $signature;
}
echo create();
which gives an error, "Authentication credentials are missing or invalid.",App Store Connect API must be signed with ES256 encryption
require_once '../vendor/autoload.php';
use Curl\Curl;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
$signer = new Sha256();
$privateKey = new Key('file://AuthKey_ed2erd424.p8');
$time = time();
$Issuer_ID = "3455355-3535-4f8g-8x2r-3dcfrr43ed33";
$Key_ID = "4DD3R45DT45";
$token = (new Builder())->issuedBy($Issuer_ID)// Configures the issuer (iss claim)
->permittedFor("appstoreconnect-v1")// Configures the audience (aud claim)
//->identifiedBy('XXYYZZ', true)// Configures the id (jti claim), replicating as a header item
->withHeader('kid', $Key_ID)
->withHeader('type', 'JWT')
->withHeader('alg', 'ES256')
->issuedAt($time)// Configures the time that the token was issue (iat claim)
->expiresAt($time + 1200)// Configures the expiration time of the token (exp claim)
->withClaim('uid', 1)// Configures a new claim, called "uid"
->getToken($signer, $privateKey); // Retrieves the generated token
$token->getHeaders(); // Retrieves the token headers
$token->getClaims(); // Retrieves the token claims
$date = $_GET['date'];
$url ='https://api.appstoreconnect.apple.com/v1/salesReports';
$dataArray = array(
'filter[frequency]'=>'DAILY',
'filter[reportDate]'=>$date,
'filter[reportSubType]'=>'SUMMARY',
'filter[reportType]'=>'SALES',
'filter[vendorNumber]'=>'345434463',
'filter[version]'=>'1_0'
);
$ch = curl_init();
$data = http_build_query($dataArray);
$getUrl = $url."?".$data;
$authorization = "Authorization: Bearer ".$token; // Prepare the authorisation token
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json' , $authorization )); // Inject the token into the header
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, $getUrl);
curl_setopt($ch, CURLOPT_TIMEOUT, 80);
$response = curl_exec($ch);
if(curl_error($ch)){
echo 'Request Error:' . curl_error($ch);
}
else
{
// if(!gzdecode($response)){ echo $response; exit; }
$uncompressed = $fp = #gzdecode($response);
if ($uncompressed === false) {
// do something related to error here
echo $response; exit;
}
;
$fp1 = array();
$myArray = [];
$lines = explode(PHP_EOL, $uncompressed);
$l = 0;
foreach($lines as $line) {
if($line == ''){continue;}
if($l == 0){ $myArray[$l] = explode("\t", $line); $l++; continue;}
//explode("\t", $line);
$key =0;
foreach(explode("\t", $line) as $value){
$myArray[$l][$myArray[0][$key]] = $value;
$key++;
}
$fp1[] = $myArray[$l];
$l++;
}
echo json_encode($fp1);
//echo $response;
}
curl_close($ch);
I've trying to integrate my Laravel PASSPORT API with my another website.
Login route "https://api.myapi.com/login"
I created website where I want use API route for login.
I think I've done wrongly it, I dont know how to check it if logged in and use correct way bearer token in header.
Api class where is login function and curl post method
class Api {
private $errors = array(); // array to hold validation errors
private $data = array(); // array to pass back data
private $cookies;
private $headers = [];
private $token;
private $user_agent;
private $compression;
private $proxy;
function __construct($cookies = true, $cookie = "cookie.c", $compression = 'gzip', $proxy = '') {
$this->headers[] = 'Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg';
$this->headers[] = 'Connection: Keep-Alive';
$this->headers[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8';
$this->token = $this->checkAuth();
if ($this->token !== null) { $this->headers[] = 'Authorization: Bearer ' . $token; }
$this->user_agent = $this->http_user_agent();
$this->compression = $compression;
$this->proxy = $proxy;
$this->cookies = $cookies;
if ($this->cookies == true) $this->cookie($cookie);
}
//this function is done wrongly..
public function checkAuth () {
$auth = json_decode($this->login());
if ($auth->success === true) {
return $auth->token;
}
return null;
}
public function login($vars) {
if (empty($vars['email'])) $this->errors[$vars['email']] = 'Email field is required.';
if (empty($vars['password'])) $this->errors[$vars['password']] = 'Password field is required.';
if ( ! empty($this->errors)) {
$this->data['success'] = false;
$this->data['errors'] = $this->errors;
} else {
$email = $vars['email'];
$password = $vars['password'];
$fields = array(
"email" => $email,
"password" => $password
);
$fields_string = http_build_query($fields);
$res = $this->post("http://kris.dev/apify/public/stylist/login", $fields_string);
$logPost = json_decode($res);
if (isset($logPost->error)) {
$this->data['success'] = false;
$this->data['errors'] = $logPost->error;
return json_encode($this->data);
} elseif (isset($logPost->token)) {
$this->data['success'] = true;
$this->data['token'] = $logPost->token;
return json_encode($this->data);
}
}
// return all our data to an AJAX call
return json_encode($this->data);
}
private function cookie($cookie_file) {
if (file_exists($cookie_file)) {
$this->cookie_file = $cookie_file;
} else {
fopen($cookie_file, 'w') or $this->error('The cookie file could not be opened. Make sure this directory has the correct permissions');
$this->cookie_file = $cookie_file;
fclose($this->cookie_file);
}
}
public static function http_user_agent() {
return ((isset($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT'] : NULL);
}
public function post($url, $data) {
$process = curl_init($url);
curl_setopt($process, CURLOPT_HTTPHEADER, $this->headers);
curl_setopt($process, CURLOPT_HEADER, 1);
curl_setopt($process, CURLOPT_USERAGENT, $this->user_agent);
if ($this->cookies == true) curl_setopt($process, CURLOPT_COOKIEFILE, $this->cookie_file);
if ($this->cookies == true) curl_setopt($process, CURLOPT_COOKIEJAR, $this->cookie_file);
curl_setopt($process, CURLOPT_ENCODING, $this->compression);
curl_setopt($process, CURLOPT_TIMEOUT, 30);
if ($this->proxy) curl_setopt($process, CURLOPT_PROXY, $this->proxy);
curl_setopt($process, CURLOPT_POST, 1);
curl_setopt($process, CURLOPT_POSTFIELDS, $data);
curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($process, CURLOPT_FOLLOWLOCATION, 1);
$response = curl_exec($process);
$header_size = curl_getinfo($process, CURLINFO_HEADER_SIZE);
$return = substr($response, $header_size);
curl_close($process);
return $return;
}
login function what passes form parameters to Api class.
require __DIR__ . 'api.php';
$api = new Api();
if (isset($_POST)) {
$vars = array("email" => $_POST['email'], "password" => $_POST['password']);
$api->login($vars);
}
ajax passes form data to login function
$(document).ready(function() {
// process the form
$('#subButton').click(function(e) {
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
var email = $('#email').val();
var password = $('#password').val();
// process the form
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : 'functions/login.php', // the url where we want to POST
data: {
'email' : email,
'password' : password
},
dataType:'JSON',
success: function(data) {
console.log(data);
// here we will handle errors and validation messages
if ( ! data.success) {
// handle errors for email ---------------
if (data.errors.email) {
$('#email').addClass('has-error'); // add the error class to show red input
$('#email').append('<div class="help-block">' + data.errors.email + '</div>'); // add the actual error message under our input
}
// handle errors for email ---------------
if (data.errors.password) {
$('#password').addClass('has-error'); // add the error class to show red input
$('#password').append('<div class="help-block">' + data.errors.password + '</div>'); // add the actual error message under our input
}
} else {
// ALL GOOD! just show the success message!
$('form').append('<div class="alert alert-success">' + data.message + '</div>');
$('#token').append('<div class="alert alert-success">' + data.token + '</div>');
// usually after form submission, you'll want to redirect
// window.location = '/thank-you'; // redirect a user to another page
alert('success'); // for now we'll just alert the user
}
}
});
// stop the form from submitting the normal way and refreshing the page
e.preventDefault();
});
});
Laravel passport api login controller is simple if user email and password correct then creates accessToken, if password or email is wrong it throws http_code 422 and response text "Email or Password incorrect.
I want to use mediawiki api to retrieve some informations with a symfony project, i want tu use curl to fo api calls,
I tried with
$ch=curl_init();
$postfield = "action=query&titles=Watch&prop=langlinks&lllimit=20";
$url = "https://en.wikipedia.org/w/api.php"; //url to wiki's api
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfield);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
var_dump($output);
curl_close($ch);
but it does not work, it gives me boolean false as result
Here's a good example of using the PHP API using cURL from WikiMedia itself.
First, logging in:
/**
* Configuration
* -------------------------------------------------
*/
// Start session
session_start();
// Login
$app['username'] = "Example";
$app['password'] = "mypassword";
// Version
$app["version"] = "0.0.1-dev";
// Last modified
date_default_timezone_set("UTC");
$app["lastmod"] = date("Y-m-d H:i", getlastmod()) . " UTC"; // Example: 2010-04-15 18:09 UTC
// User-Agent used for loading external resources
$app["useragent"] = "My First Tool " . $app["version"] . " (LastModified: " . $app["lastmod"] . ") Contact: myfirsttool (at) example (.) com";
// Cookie file for the session
$app["cookiefile"] = tempnam("/tmp", "CURLCOOKIE");
// cURL to avoid repeating ourselfs
$app["curloptions"] =
array(
CURLOPT_COOKIEFILE => $app["cookiefile"],
CURLOPT_COOKIEJAR => $app["cookiefile"],
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_USERAGENT => $app["useragent"],
CURLOPT_POST => true
);
$app["apiURL"] = "http://www.mediawiki.org/w/api.php";
Then to do the login using cookies:
/**
* Login
* -------------------------------------------------
*/
// Info: http://www.mediawiki.org/wiki/API:Login
$postdata = http_build_query([
"action" => "login",
"format" => "php",
"lgname" => $app["username"],
"lgpassword" => $app["password"],
]);
$ch = curl_init();
curl_setopt_array($ch, $app["curloptions"]);
curl_setopt($ch, CURLOPT_URL, $app["apiURL"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
$result = unserialize(curl_exec($ch));
if(curl_errno($ch)){
$curl_error = "Error 003: " . curl_error($ch);
}
curl_close($ch);
//print_r($result);//die;//DEBUG
// Basic error check + Confirm token
if ($curl_error){
$domain_error = $curl_error;
} else if ($result["login"]["result"] == "NeedToken") {
if (!empty($result["login"]["token"])) {
$_SESSION["logintoken"] = $result["login"]["token"];
$postdata = http_build_query([
"action" => "login",
"format" => "php",
"lgname" => $app["username"],
"lgpassword" => $app["password"],
"lgtoken" => $_SESSION["logintoken"],
]);
$ch = curl_init();
curl_setopt_array($ch, $app["curloptions"]);
curl_setopt($ch, CURLOPT_URL, $app["apiURL"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
$result = unserialize(curl_exec($ch));
if(curl_errno($ch)){
$curl_error = "Error 004: " . curl_error($ch);
}
curl_close($ch);
//print_r($result);//die;//DEBUG
} else {
$other_error = "Error 006: Token error.";
}
}
// Check for all documented errors
// Source: http://www.mediawiki.org/wiki/API:Login#Errors
// Date: 2010-04-17
if ($curl_error){
$domain_error = $curl_error;
} else if ($result["login"]["result"] == "Success") {
$_SESSION["login_result"] = $result["login"]["result"];
$_SESSION["login_lguserid"] = $result["login"]["lguserid"];
$_SESSION["login_lgusername"] = $result["login"]["lgusername"];
} else if ($result["login"]["result"] == "NeedToken") {
$other_error = "Error 005: Token error.";
} else if ($result["login"]["result"] == "NoName") {
$username_error = "The username can not be blank";
} else if ($result["login"]["result"] == "Illegal") {
$username_error = "You provided an illegal username";
} else if ($result["login"]["result"] == "NotExists") {
$username_error = "The username you provided doesn't exist";
} else if ($result["login"]["result"] == "EmptyPass") {
$password_error = "The password can not be blank";
} else if ($result["login"]["result"] == "WrongPass" || $result["login"]["result"] == "WrongPluginPass") {
$password_error = "The password you provided is incorrect";
} else if ($result["login"]["result"] == "CreateBlocked") {
$username_error = "Autocreation was blocked from this IP address";
} else if ($result["login"]["result"] == "Throttled") {
$other_error = "You've logged in too many times in a short time. Try again later.";
} else if ($result["login"]["result"] == "mustbeposted") {
$other_error = "Error 004: Logindata was not send correctly";
} else if ($result["login"]["result"] == "Blocked") {
$username_error = "This account is blocked.";
} else if ($result["login"]["result"]){
$other_error = "Error 001: An unknown event occurred.";
} else {
$other_error = "Error 002: An unknown event occurred.";
}
// The tool you use may log or display the variables:
// $other_error, $username_error and $password_error in the appropiate place
// Such as near a login form, or in a specific debug/logfile
// by default the errors are not outputted
if($_SESSION["login_result"] !== "Success"){
die("Login error. Have you defined app[username] and app[password] ?");
}
Example of building a query:
/**
* Get userinfo
* -------------------------------------------------
*/
$postdata = http_build_query([
"action" => "query",
"format" => "php",
"meta" => "userinfo",
"uiprop" => "rights|hasmsg",
]);
$ch = curl_init();
curl_setopt_array($ch, $app["curloptions"]);
curl_setopt($ch, CURLOPT_URL, $app["apiURL"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
$result = unserialize(curl_exec($ch));
if(curl_errno($ch)){
Death("Error 003: " . curl_error($ch),"API connection failed.");
}
curl_close($ch);
//print_r($result);//die;//DEBUG
// Check for usermessages
if (isset($result['query']['userinfo']['messages'])) {
$api['hasmsg'] = true;
$api['hasmsghtml'] = '<div class="usermessage">You have new messages !</div>';
} else {
// User does not have new messages
}
And finally, how to clean up the session:
// Delete the cookie file
unlink($app["cookiefile"]);
// Destroy the session
session_destroy();
// End this file
die($output);
I tried that, and it works either
public function callWiki($url)
{
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2
));
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
public function getAllCategories()
{
$api = 'https://en.wikipedia.org/w/api.php? action=query&titles=watch&prop=categories&format=json';
//get query result
$api_response = $this->callWiki($api);
$results = json_decode($api_response, true);
}
I'm trying to send notifications to my Windows Phone 8 app using an authenticated server, but I'm getting a 401 error whenever a notification is tried to be sent.
I've been following the instructions on the MSDN pages, namely http://msdn.microsoft.com/library/windows/apps/ff941099(v=vs.105).aspx where it says The Key-Usage value of the TLS certificate must be set to include client authentication. I've no idea what this means though and searching online doesn't give me any clues either.
It could be that, that is incorrect or it could be my code so that is shown below.
VB.NET CODE:
Private Async Sub ApplicationBarPin_Click(sender As Object, e As EventArgs)
' Holds the push channel that is created or found.
Dim pushChannel As HttpNotificationChannel
' The name of our push channel.
Dim channelName As String = "WindowsPhoneTrainTileNotification"
' Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName)
' If the channel was not found, then create a new connection to the push service.
If pushChannel Is Nothing Then
pushChannel = New HttpNotificationChannel(channelName, "redsquirrelsoftware.co.uk")
uri_timer = New DispatcherTimer
uri_timer.Interval = TimeSpan.FromSeconds(5)
AddHandler uri_timer.Tick, AddressOf UriTimerTick
uri_timer.Start()
' Register for all the events before attempting to open the channel.
AddHandler pushChannel.ChannelUriUpdated, AddressOf PushChannel_TileChannelUriUpdated
AddHandler pushChannel.ErrorOccurred, AddressOf PushChannel_TileErrorOccurred
pushChannel.Open()
pushChannel.BindToShellTile()
Else
' The channel was already open, so just register for all the events.
AddHandler pushChannel.ChannelUriUpdated, AddressOf PushChannel_TileChannelUriUpdated
AddHandler pushChannel.ErrorOccurred, AddressOf PushChannel_TileErrorOccurred
Dim form As New MultipartFormDataContent()
form.Add(New StringContent(Statics.getUserID), "userId")
form.Add(New StringContent(pushChannel.ChannelUri.ToString()), "uri")
form.Add(New StringContent(Statics.CurrentScheduleId), "scheduleId")
Dim httpClient As HttpClient = New HttpClient()
Dim response As HttpResponseMessage = Await httpClient.PostAsync("http://redsquirrelsoftware.co.uk/trains/push/WPTileSubscribe.php", form)
End If
ShellTile.Create(New Uri("/Route.xaml?scheduleId=" & scheduleId, UriKind.Relative), secondaryTile, True) 'Create SecondaryTile and pass querystring to navigation url.
Catch ex As Exception
End Try
End If
End Sub
Private Async Sub PushChannel_TileChannelUriUpdated(sender As Object, e As NotificationChannelUriEventArgs)
Dim form As New MultipartFormDataContent()
form.Add(New StringContent(Statics.getUserID), "userId")
form.Add(New StringContent(e.ChannelUri.ToString()), "uri")
form.Add(New StringContent(Statics.CurrentScheduleId), "scheduleId")
Dim httpClient As HttpClient = New HttpClient()
Dim response As HttpResponseMessage = Await httpClient.PostAsync("http://redsquirrelsoftware.co.uk/trains/push/WPTileSubscribe.php", form)
End Sub
Private Sub PushChannel_TileErrorOccurred(sender As Object, e As NotificationChannelErrorEventArgs)
MessageBox.Show("Error creating live tile, please try again")
End Sub
Private Async Sub UriTimerTick(sender As Object, e As EventArgs)
Try
If pushChannel.ChannelUri IsNot Nothing Then
Dim form As New MultipartFormDataContent()
form.Add(New StringContent(Statics.getUserID), "userId")
form.Add(New StringContent(pushChannel.ChannelUri.ToString()), "uri")
form.Add(New StringContent(Statics.CurrentScheduleId), "scheduleId")
Dim httpClient As HttpClient = New HttpClient()
Dim response As HttpResponseMessage = Await httpClient.PostAsync("http://redsquirrelsoftware.co.uk/trains/push/WPTileSubscribe.php", form)
uri_timer.Stop()
End If
Catch ex As Exception
End Try
End Sub
That works as expected and the URI is stored in my database (starting with HTTPS, and doesn't contain throttledthirdparty in the URI either, suggesting that this code works).
train_movements.php:
<?php
include 'WindowsPhoneTilePush.php';
$WPN = new WPN($packageSID, $clientSecret);
$xml_data = $WPN->build_tile_xml($sched_id, strtoupper($loc), "$eventTypeStr $dt (". strtolower($variation_status) . ")");
$WPNResponse = $WPN->post_tile($uri, $xml_data);
if($WPNResponse->error == true) {
$my_file = $logFile;
$handle = fopen($my_file, 'a') or die('Cannot open file: '.$my_file);
$data = $WPNResponse->httpCode . ":" . $WPNResponse->message . "\n";
fwrite($handle, $data);
}
?>
WindowsPhoneTilePush.php: (adapted from here)
<?php
class WPNTypesEnum{
const Toast = 'wns/toast';
const Badge = 'wns/badge';
const Tile = 'wns/tile';
const Raw = 'wns/raw';
}
class WPNResponse{
public $message = '';
public $error = false;
public $httpCode = '';
function __construct($message, $httpCode, $error = false){
$this->message = $message;
$this->httpCode = $httpCode;
$this->error = $error;
}
}
class WPN{
private $access_token = '';
private $sid = '';
private $secret = '';
function __construct($sid, $secret){
$this->sid = $sid;
$this->secret = $secret;
}
private function get_access_token(){
if($this->access_token != ''){
return;
}
$str = "grant_type=client_credentials&client_id=$this->sid&client_secret=$this->secret&scope=notify.windows.com";
$url = "https://login.live.com/accesstoken.srf";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, "$str");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output);
if(isset($output->error)){
throw new Exception($output->error_description);
}
$this->access_token = $output->access_token;
}
public function build_tile_xml($tile_nav_uri, $wide2, $wide3){
$msg = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" .
"<wp:Notification xmlns:wp=\"WPNotification\" Version=\"2.0\">" .
"<wp:Tile Id=\"/Route.xaml?scheduleId=$tile_nav_uri\" Template=\"IconicTile\">" .
//"<wp:SmallIconImage>$image_url_small</wp:SmallIconImage>" .
//"<wp:IconImage>$image_url_large</wp:IconImage>" .
//"<wp:WideContent1>$wide1</wp:WideContent1>" .
"<wp:WideContent2>$wide2</wp:WideContent2>" .
"<wp:WideContent3>$wide3</wp:WideContent3>" .
//"<wp:Count>$count</wp:Count>" .
//"<wp:Title>$title</wp:Title>" .
//"<wp:BackgroundColor>#00FFFFFF</wp:BackgroundColor>" .
"</wp:Tile>" .
"</wp:Notification>";
return $msg;
}
public function post_tile($uri, $xml_data, $type = WPNTypesEnum::Tile, $tileTag = '', $count = 0){
if($this->access_token == ''){
$this->get_access_token();
}
$headers = array('Content-Type: text/xml', "Content-Length: " . strlen($xml_data), "X-WNS-Type: $type", "Authorization: Bearer $this->access_token");
if($tileTag != ''){
array_push($headers, "X-WNS-Tag: $tileTag");
}
$ch = curl_init($uri);
# Tiles: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868263.aspx
# http://msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx
curl_setopt($ch, CURLOPT_CAPATH, "/var/www/clients/client1/web1/ssl/");
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data");
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$response = curl_getinfo( $ch );
curl_close($ch);
$code = $response['http_code'];
if($code == 200){
return new WPNResponse('Successfully sent message', $code);
}
else if($code == 401){
$my_file = '/var/log/WPNotify.txt';
$handle = fopen($my_file, 'a') or die('Cannot open file: '.$my_file);
$data = date("d-M-y H:i:s:") . "401 Authorisation Error:" . $this->access_token . "\n";
fwrite($handle, $data);
if($count == 10) {
exit;
}
$this->access_token = '';
return $this->post_tile($uri, $xml_data, $type, $tileTag, $count++);
}
else if($code == 410 || $code == 404){
return new WPNResponse('Expired or invalid URI', $code, true);
}
else{
return new WPNResponse('Unknown error while sending message', $code, true);
}
}
}
?>
There could be an error in my code, or it could be that I'm not setting up the backend stuff correctly (most of the MSDN docs are aimed at Windows Servers and .aspx, so I've tried to replicate those instructions but could have gone wrong somewhere along the line!).
If anyone can help in either fixing errors in the code, or with the client authentication for the SSL certificate it would be much appreciated!
Thanks,
Jake
take a look at
Windows Notifications Service: 401 Invalid Token when trying to create a Toast notification in PHP
invalid-token-when-trying-to-create-a-toast-n
make sure you're sending package SID of your app as the 'client_id' parameter instead of your app's client_id when requesting access token.
This is really confusing ,doing both are able to get access_token from Microsoft's server, but only the token requested with you package SID won't give you 401 error when sending toast notification.
I am currently writing an C# windows service, which integrates with a PHP page. I have an example of code making the request in PHP which is below however I have never developed in PHP and don't understand how the cURL function performs the request.
Is there anyway to retrieve the request which is being sent? Or can anyone provide an example of how the request would look and how the request is sent so I can replicate the request in C#.
Thank you for any help.
public function api(/* polymorphic */) {
$args = func_get_args();
if (is_array($args[0])) {
$serviceId = $this->getApiServiceId($args[0]["method"]);
unset($args[0]["method"]);
$args[0]["serviceId"] = $serviceId;
$args[0]["dealerId"] = $this->dealerId;
$args[0]["username"] = $this->username;
$args[0]["password"] = $this->password;
$args[0]["baseDomain"] = $this->baseDomain;
return json_decode($this->makeRequest($args[0]));
} else {
throw Exception("API call failed. Improper call.");
}
}
protected function makeRequest($params, $ch=null) {
if (!$ch) {
$ch = curl_init();
}
$opts = self::$CURL_OPTS;
if ($this->useFileUploadSupport()) {
$opts[CURLOPT_POSTFIELDS] = $params;
} else {
$opts[CURLOPT_POSTFIELDS] = http_build_query($params, null, '&');
}
// disable the 'Expect: 100-continue' behaviour. This causes CURL to wait
// for 2 seconds if the server does not support this header.
if (isset($opts[CURLOPT_HTTPHEADER])) {
$existing_headers = $opts[CURLOPT_HTTPHEADER];
$existing_headers[] = 'Expect:';
$opts[CURLOPT_HTTPHEADER] = $existing_headers;
} else {
$opts[CURLOPT_HTTPHEADER] = array('Expect:');
}
curl_setopt_array($ch, $opts);
$result = curl_exec($ch);
if ($result === false) {
$e = new WPSApiException(array(
'error_code' => curl_errno($ch),
'error' => array(
'message' => curl_error($ch),
'type' => 'CurlException',
),
));
curl_close($ch);
throw $e;
}
curl_close($ch);
return $result;
}
Add the option CURLINFO_HEADER_OUT to curl handle, then call curl_getinfo on it after execing.
As in:
//...
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
//...
curl_exec($ch);
//...
$header = curl_getinfo(CURLINFO_HEADER_OUT);
echo $header;