php code igniter using curl for ios push notifications - php

I've made web-service to send push notifications to ios using curl,
i have the ck.pem file for development which contain both cert & RSA private key, and referring to it correctly.
but every time i call the web-service i get the same error
Curl failed: unable to use client certificate (no key found or wrong pass phrase?)
All related solutions not working, except alternatives using "stream_context_create", But I want to do it with curl and idk where's the problem is.
find below my code :
function test_push_to_ios() {
$url = 'https://gateway.sandbox.push.apple.com:2195';
$cert = base_url() . 'backend_includes/ios_cert/ck.pem';
$gcm_ids = array("xxxxxx");
$passphrase = "passphrase";
$message = 'nbad_notification';
$aps = array('alert' => $message, 'sound' => 'default');
$fields = array('device_tokens' => $gcm_ids, 'data' => $message, 'aps' => $aps);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SSLCERT, $cert);
//curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $passphrase);
curl_setopt($ch, CURLOPT_SSLKEY, $cert);
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $passphrase);
curl_setopt($ch, CURLOPT_CERTINFO, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
echo json_encode($result);
}

I didn't read your question carefully.
You are trying to send push notifications to Apple via an HTTPS request. That can't work. Apple Push Notifications only work with a specific binary format over TCP protocol.
As a provider you communicate with Apple Push Notification service over a binary interface. This interface is a high-speed, high-capacity interface for providers; it uses a streaming TCP socket design in conjunction with binary content. The binary interface is asynchronous.
There are many problems with your code :
You seem to mix GCM code with APNS code.
$fields = array('device_tokens' => $gcm_ids, 'data' => $message, 'aps' => $aps); looks similar to what you would do when sending a message to Google Cloud Messaging server. But GCM is completely different than APNS, so why did you think that would work?
You are sending a JSON body, which is what works with GCM, but APNS use a binary format. While the payload within the binary message to APNS contains an encoded JSON String (which looks similar to your $aps JSON), you can't package it within another JSON and expect it to work.
And adding https:// in front of the APNS server can't make it support HTTPS, since it wasn't implemented to support HTTPS (nor HTTP).
I suggest you use stream_context, which works.

Related

Unable to access Flask web app from php curl

I have a Flask app, with a basic function, where I have exposed app.run() to a public ip, so that it is accessible from an external server;[ using Flask - Externally Visible Dev Server ]
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(host = '0.0.0.0', port = 8080)
The curl request I have written in my php code is:
$signed_url = "http://my-ip-address:8080/";
$ch = curl_init($signed_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
$data= curl_exec($ch);
echo $data;
I can do a curl request :
curl http://my-ip-address:8080/
from command line. However, when the curl request is embedded within my PHP code, it gives me an error "Connection refused".
Kindly help!
If the PHP code is on another server, but your command line cURL request is on the same server, then you aren't comparing apples to apples.
Two things that might be wrong:
Your Flask server has a firewall that doesn't allow external connections.
You are connecting using an private network IP address rather than a public IP address.
For now your PHP code looks correct, so I would narrow down the problem a little bit. Ignore that PHP code and try to connect using cURL on the command line from the same server you are running your PHP code on.
try to set your port with curl options like this:
curl_setopt($ch, CURLOPT_PORT, 8080);
so your signed url will be:
$signed_url = "http://my-ip-address";
I use this code for my work and worked :)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:5000/spmi/api/1');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"teks_analysis\":\"tidak ada skor nol\"}");
curl_setopt($ch, CURLOPT_POST, 1);
$headers = array();
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
the key is CURLOPT_POSTFIELDS

how to listen for new event on server

I need to create a Listener for new events on server in android.
I was using a request to the server cyclically for new events before.
But this is not a suitable way because of performances and internet traffic.
Another way could be using a listener, but I don't know HOW TO ?
Please guide me!
Polling the server may drain the battery
You can take advantage of Google Cloud Messaging for Android
Google Cloud Messaging (GCM) for Android is a service that allows you
to send data from your server to your users' Android-powered device,
and also to receive messages from devices on the same connection. The
GCM service handles all aspects of queueing of messages and delivery
to the target Android application running on the target device, and it
is completely free.
It will work on Android >= 2.2 (on phones that have the Play Store)
Here is the link to official documentation
Here is a sample php code that sends push notification
<?php
function sendPushNotification($registration_ids, $message) {
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $registration_ids,
'data' => $message,
);
define('GOOGLE_API_KEY', 'AIzaSyCjctNK2valabAWL7rWUTcoRA-UAXI_3ro');
$headers = array(
'Authorization:key=' . GOOGLE_API_KEY,
'Content-Type: application/json'
);
echo json_encode($fields);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if($result === false)
die('Curl failed ' . curl_error());
curl_close($ch);
return $result;
}
?>
Here is a good article on android push notifications

Get Response from GCM

How can i get Response if the Message was sent or Not, using Php Script, Then i want to use the Response to Determine If the Device is Online or Not,
Here is my Php Script to Send a Message :
function send_push_notification($registration_ids, $message) {
$regId=$registration_ids;
$msg=$message;
$message = array("message" => $msg);
$regArray[]=$registration_ids;
$url = 'https://android.googleapis.com/gcm/send';
$fields = array('registration_ids' => $regArray, 'data' => $message,);
$headers = array( 'Authorization: key=API_KEY','Content-Type: application/json');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result=curl_exec($ch);
echo $result;
if($result==FALSE)
{
die('Curl Failed');
}
curl_close($ch);
}
Thanks
The response your server gets from GCM server doesn't tell you if the message was sent or not. It only tells you if the message was accepted by the GCM server or rejected. If it's accepted, GCM server will try to deliver it, but there's no guarantee it would succeed. If it's rejected, you get an error message (such as InvalidRegistration, MissingRegistration, etc...).
If you want an acknowledgment of delivery, you must have code in your Android app that upon receiving of the message makes a call to your server, to acknowledge the message was received.
You don't get response from the app; you can only get response from the GCM system itself. When the CURL call completes, $result contains a JSON-encoded object; its id property contains a message ID upon success.

Android Push Notification unauthorized error 401

I have created an Android app with Googles' OAuth 2.0 (from developer console) and has an API key for Android application (it use Google Maps, which works by the way).
However, my problem is that I'm using Push Notifications and it works on the android application though (I get the registration ID), but on the server it doesn't work at all.
I'm using PHP and the problem seems to be the API key which is the same as the one I've for the Android application.
So what key am I supposed to use? And how do I retrieve it?
Code:
<?php
function send_push_notification($registatoin_ids, $message) {
// Set POST variables
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $registatoin_ids,
'data' => $message,
);
$headers = array(
'Authorization: key=An_Api_Key',
'Content-Type: application/json'
);
//print_r($headers);
// Open connection
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
// Execute post
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
// Close connection
curl_close($ch);
echo $result;
}?>
Please check allowed IP addresses in your Google API. You can restrict API access to certain IP addresses and by default one IP address is set when you create new API project.
Remove that IP address so that any IP address (Including your local machine's server) can connect and access the API.
I have implemented similar kind of code and got 401 error. Above fix worked for me. Hope that helps you as well.

Use GCM with PHP

I've seen several posts about how to send GCM messages from my PHP server, but I can't get it working. This is my code:
public function test_gcm($id_user){
// Search user's RegIds and stores them in $regids
if(count($regids) == 0){
echo "This user has no registered device.";
return;
}
$ch = curl_init();
$data = array(
'data' => array('message'=>'my message', 'title'=>'message title'),
'registration_ids' => $regids
);
curl_setopt($ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// WRITE JSON HEADERS
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization:key=' . $apiKey)
);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
}
I'm using the browser key. I tried the server key too, but none of them work, the curl_exec always return false. Does anybody know why is it?
EDIT: I just used 'netstat -tuanc | grep 173' on my server and performed the server call. I'm using grep 173 because if I ping android.googleapis.com I ping this ip address. The netstat didn't show any connection to that ip address when I use the curl_exec. Does that mean I'm not connecting to android.googleapis.com? Or what I'm doing is wrong?
Thanks!
Check the "message" content are same or not in android code. 'message'=>'my message' should match with the message from IntentService class in android.
I've managed to fix it. It was a firewall issue, my firewall was blocking the connection. I've added the rules to accept these messages and now it works.
Thanks to all the people that tried to help :)
Try to change it from https to http
curl_setopt($ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
to
curl_setopt($ch, CURLOPT_URL, 'http://android.googleapis.com/gcm/send');
try this http://2mecode.blogspot.hk/2013/01/google-cloud-messaging-php.html
hope it can help you

Categories