PHP CURL - Apple push notification servers - php

I am writing code to send notifications to the Apple push notification servers (APNs) using PHP Laravel. It says in the documents that it requires HTTP/ HPACK header compression.
I've tried using cURL
$cURLConnection = curl_init();
if(strcmp(env('APP_ENV'), 'production') == 0) {
curl_setopt($cURLConnection, CURLOPT_URL, 'api.push.apple.com:443');
} else {
curl_setopt($cURLConnection, CURLOPT_URL, 'api.development.push.apple.com:443');
}
curl_setopt_array($cURLConnection, [
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_HTTP_VERSION =>CURL_HTTP_VERSION_2_0,
]);
curl_setopt($cURLConnection, CURLOPT_HTTPHEADER, array(
'path: /3/device/<devicetoken>',
'authorization: bearer ' . $token,
'Content-Type: application/json'
));
curl_setopt($cURLConnection, CURLOPT_POSTFIELDS, $postRequest);
curl_setopt ($cURLConnection, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
$apiResponse = curl_exec($cURLConnection);
but the APNS server always returning 'Empty reply from server'

I see a few things that could be problematic.
Try adding the following to actually turn your request into a POST request.
curl_setopt($c, CURLOPT_POST, 1);
Your 'path' should also be part of the main URL instead of being added as a header.
curl_setopt($c, CURLOPT_URL, "https://api.push.apple.com:443/3/device/<devicetoken>");

In addition to the previous suggestion, we should also be able to use certificate bases auth system.
Example snippet below:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://path-to-auth-example.com/token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_cert");
curl_setopt($ch, CURLOPT_SSLCERT, "path/to/your/pem-file.pem");
curl_setopt($ch, CURLOPT_SSLCERTTYPE, "PEM");
$headers = [];
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
//catch your error wisely
}
curl_close($ch);
$result = json_decode($result);
print_r($result);
?>

Related

PhP cURL - 403 Error With API Key In Header

I'm relatively new to cURL in PHP, and I'm looking to cURL against an API where where the API Key is in the header. Here's what I have thus far:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://publicapi.ohgo.com/api/v1/reported-conditions?region=ne-ohio');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Authorization: APIKEY 016c348e-58fe-486f-ad72-9b2f41c55a56';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
Unfortunately, after running this script, I get a 403 error printed to the screen after a few seconds:
Error:Failed connect to publicapi.ohgo.com:443; Connection timed out
How can I get these API results? Worth noting:
1) I have changed a few characters from my actual API key to make the one above
2) API documentation is here: https://publicapi.ohgo.com/docs/v1/swagger/index#/Reported32Conditions
It's failed to connect to API server. Try to increase connect timeout for that.
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); // value in seconds
Try to skip ssl verification this will solve your issue
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://publicapi.ohgo.com/api/v1/reported-conditions?region=ne-ohio');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // Skip SSL Verification
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Authorization: APIKEY 016c348e-58fe-486f-ad72-9b2f41c55a56';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);

Curl to test Sabre REST API Authentication Failing

I'm creating the authentication and getting an access token fine but the problem arises when I try to send a request. I'm creating the headers using PHP
<?php
define("POST", "POST");
**$environment=' https://api-crt.cert.havail.sabre.com';**
$userId='XXXXXXX';
$domain='AA';
$Group='XXXXXXXXXX';
$formatVersion='V1';
$clientSecret=base64_encode('XXXXXXXXXXX');
$client_id=base64_encode($formatVersion.":".$userId.":".$Group.":".$domain);
$bulid_credential=base64_encode($client_id.":".$clientSecret);
######################## Step 1: Get Token #############################
**$ch =curl_init("https://api-crt.cert.havail.sabre.com/v2/auth/token");**
$vars ="grant_type=client_credentials";
$header =array(
'Authorization: Basic '.$bulid_credential,
'Accept: */*',
'Content-Type: application/x-www-form-urlencoded'
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res= curl_exec($ch);
$result=json_decode($res);
$token=$result->access_token;
########################## Step 2: Call the REST API###################
**$url="https://api.test.sabre.com/v3.3.0/shop/flights?mode=live";**
$header = array(
'Authorization: Bearer'. $token,
'Content-Type: application/json'
);
$calltype='POST';
$ch = curl_init();
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $calltype);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonrequest);//Request
array_push($header, 'Content-Type: application/json');
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$result=curl_exec($ch);
$result1=json_decode($result);
curl_close($ch);
?>
The Sabre Response :
{"status":"Incomplete","type":"Application","errorCode":"ERR.2SG.PROVIDER_ERROR","timeStamp":"2017-10-11T06:02:08.658-05:00","message":"Error occurred while invoking service rest:readMetadata:1.13.7.SNAPSHOT"}
1) Did you ensure that $token is a string and not an object?
I use this:
$result=json_decode($res, TRUE);
$token=$result['access_token'];
Instead of this:
$result=json_decode($res);
$token=$result->access_token;
2) Did you ensure that the content of $jsonrequest is valid?
Maybe it's not the PHP code that is incorrect, but your JSON query.

Do PHP cURL options CURLOPT_HEADER and CURLOPT_RETURNTRANSFER conflict

I am using cURL with php to authenticate to an API.
Like this:
$ch = curl_init();
$headers = [];
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode( $this->body ));
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$this->response = json_decode( curl_exec($ch) );
curl_close ($ch);
The body of the request response contains status code and if request has been successfull the user object. This is an anonymous request and it returns the token in the response headers.
My problem:
The script's above response is null.
If I comment out the CURLOPT_RETURNTRANSFER option, then I get what I need, but it gets echoed out and the response is 1.
If I comment out the CURLOPT_HEADER option, then I get only the body of the response.
I've tried switching between http and https.
I am using PHP-5.5.27.
You're decoding without being sure that what you're getting is JSON. It most likely is not JSON, at least not all of the response. When you use CURLOPT_HTTPHEADER the response consists of text which starts with the response headers and then may have some JSON after them.
Do something like:
$ch = curl_init();
$headers = [];
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode( $this->body ));
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
$actualResponseHeaders = (isset($info["header_size"]))?substr($response,0,$info["header_size"]):"";
$actualResponse = (isset($info["header_size"]))?substr($response,$info["header_size"]):"";
$this->response = json_decode( $actualResponse );
curl_close ($ch);

when CURLOPT_HTTPHEADER need 'Content-Length'

I have this code in the client side of my application:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length:0 ' )
);
$body = curl_exec($ch);
while in the server files:
$ch = curl_init($this->modelAddress);
$data = array("params"=>array("resource" => "artist","operation" => $operation,"params"=>$params));
$data_string = json_encode($data);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string))
);
They are made from 2 different people and I want to ask what is the most correct.
When the use of 'Content-Length:0' instead of 'Content-Length:'.strlen($data_string) is better.
It's only question of POST/GET method?
I've searched explanations of this in the web but I've found nothing
If you use http PUT with curl then you have to specify the Content-Length header. Otherwise it is automatically handled by the curl for both GET and POST.
For example if you are posting the following data with curl with CURLOPT_POSTFIELDS. Then curl will automatically add the length of the data with the header.
$data = "name=alex&email=none!";
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
For better understand, run your curl code using verbose mode and you'll see how its handling the requests and responses.
curl_setopt($ch, CURLOPT_VERBOSE, true);

Push Notification in android c2dm

I'am developing a sample push notification app in android using c2dm. Here is my PHP code to send the message from server to device.
function sendMessageToPhone($authCode, $deviceRegistrationId, $msgType, $messageText) {
$headers = array('Authorization: GoogleLogin auth=' . $authCode);
$data = array(
'registration_id' => $deviceRegistrationId,
'collapse_key' => $msgType,
'data.message' => $messageText //TODO Add more params with just simple data instead
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://android.apis.google.com/c2dm/send");
if ($headers)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
curl_close($ch);
}
sendMessageToPhone("my application server auth token ","my device id","UTF-8","hello");
But i'am getting "No info." notification on my emulator. Where i'am going wrong ? Please help me.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://android.apis.google.com/c2dm/send");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: GoogleLogin auth=$token", "Content-Length: $len", "Content-Type: application/x-www-form-urlencoded"));
echo curl_exec($ch);
curl_close($ch);
This is the php code that my app uses to send C2DM messages where $data is your data array. Please note that the Content-Length is necessary and is is the length of your data.
EDIT: Something you may also find useful a class for php that makes sending messages a little nicer.

Categories