In the last post, we showed you the architecture of the Prowork notifications app which comprises the GCM, Prowork push API, the android app and the proxy server. In this part of the series, we are going to zoom in on the server part of the app.

Please not that the example codes below have been modified for brevity and simplicity. The full source code of the server (PHP) is available at github.com/kehers/Android-Push-Server. It uses MongoDB for datastore and the Prowork PHP API library.

So what does the server do?

1. Receives registration notifications from the android app and subscribes the user to Prowork’s push.

When the android app is registered with GCM, it is assigned a registration id. Any time we need to send a push notification to the phone, we do that using this id. But as Prowork push API only requires the user id and url to push to (and verifier key), we need to map the registration id from the device with the user’s id. And this is what this part of the server does. (See register.php)

$token = $_POST['token'];
$reg_id = $_POST['reg_id'];

...

try {
  $db = new Mongo();
     
  // Register for prowork's push
  if ($prowork->pushSubscribe($push_url, $verifier_key)) {
    // Successful
    // Map reg_id and user_id together
    $db->push->android->update(array(
        'user' => $user_id,
        'id' => $reg_id
      ), array(
        'user' => $user_id,
        'id' => $reg_id
      ), array('upsert' => true));
  }
}
catch(MongoConnectionException $e) {
  // Db error
}

2. Receives push messages from Prowork, processes them and sends to the app via GCM server.

Now that we’ve mapped the user id with the registration id of the device and subscribed for push, Prowork sends notifications to the push url ($push_url). Here is how the url handler (push.php) processes message and sends them to the app via GCM.

// Verify post is from prowork
if ($_POST['verifier'] != $verifier_key)
  exit;

$user = $_POST['receiver_id'];
try {
    // Get the reg id this user id is mapped to
	$db = new Mongo();
	$r = $db->push->android->findOne(array('user' => $user));
	$regids[] = $r['id'];
	
	// Process message from prowork push here
	// .....
	// So that now we have a title and message
	$payload = json_encode(array(
				'data' => array('title'=>$title, 'message'=>$message),
				'registration_ids' => $regids
			)
		);
		
	// Send to GCM server
	// (GCM sends it to our app)
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $google_gcm_server);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_HTTPHEADER, array(
			'Content-Type: application/json',
			'Authorization: key='.$authkey
	)); 
	curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
	$response = curl_exec($ch);
	$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	curl_close($ch);
	
	// Process response here...
	// See full source code for more
}
catch(MongoConnectionException $e) {
	// Db error
}

3. Unregisters the user from Prowork push. (unregister.php)

This is the simple part. It simply removes the details from the db and unsubscribes from Prowork push.

try {
  $db = new Mongo();
		
	// Unregister for prowork's push
	if ($prowork->pushUnsubscribe($apikey)) {
		// Successful
		$db->push->android->remove(array('id' => $reg_id));
	}
}
catch(MongoConnectionException $e) {
	// DB error
}

It is that simple. And that concludes this part of the series. In the next part, we will be building a bug tracking system on the Prowork API. Till then, have fun hacking the Prowork API.