Search code examples
phpandroidandroid-c2dm

C2DM Server with PHP 401 Error


I'm building my own C2DM application right now. I first started with a small Android application to test the push feature. And it works if I just call the curl command with the correct settings in my shell.

Now for the server part I wanted to use PHP but as it seems I'm doing something wrong as I always get a 401 error message when I try to send a message to the client. First of all the code consists of two parts. The first curl request asks for the server token. This works I get a real response from google with a working token!

The second curl request ends up with a 401 error message. Any ideas what I'm doing wrong?

  $post_params = array ( "Email" => $MY_GOOGLE_ACC, "Passwd" => $MY_GOOGLE_PWD, "accountType"=>"GOOGLE", "source=" . $MY_GOOGLE_SRC, "service=ac2dm" ); 

  $first = true;
  $data_msg = "";

  foreach ($post_params as $key => $value) { 
    if ($first)
      $first = false;
    else
      $data_msg .= "&";

    $data_msg .= urlencode($key) ."=". urlencode($value); 
  }

  $x = curl_init("https://www.google.com/accounts/ClientLogin"); 

  curl_setopt($x, CURLOPT_HEADER, 1); 
  curl_setopt($x, CURLOPT_POST, 1); 
  curl_setopt($x, CURLOPT_POSTFIELDS, $data_msg); 
  curl_setopt($x, CURLOPT_RETURNTRANSFER, 1); 
  $data = curl_exec($x); 
  curl_close($x); 
  $response = $data;

  $authKey = trim(substr($response, 4+strpos($response, "SID=")));

  echo $authKey;
  $collapse_key = 'something';

  $post_params = array ( "registration_id" => $DEVICE_TOKEN, "collapse_key" => $collapse_key, "data.payload"=>"cakephp" ); 

  $first = true;
  $data_msg = "";

  foreach ($post_params as $key => $value) { 
    if ($first)
      $first = false;
    else
      $data_msg .= "&";

    $data_msg .= urlencode($key) ."=". urlencode($value); 
  }

  $size=strlen($data_msg); 


  $x = curl_init("https://android.apis.google.com/c2dm/send"); 
  curl_setopt($x, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded', 'Content-Length:'. $size, 'Authorization: GoogleLogin auth=' . $authKey)); 
  curl_setopt($x, CURLOPT_HEADER, 1); 
  curl_setopt($x, CURLOPT_POST, 1); 
  curl_setopt($x, CURLOPT_POSTFIELDS, $data_msg); 
  curl_setopt($x, CURLOPT_RETURNTRANSFER, 1); 
  $data = curl_exec($x); 
  curl_close($x); 
  $response = $data;

Solution

  • Example of key'd array use with curl. This is pretty much the exact code I have working (with minor changes for clarity).

    $headers = array('Authorization: GoogleLogin auth=' . $authcode);
    $data = array(
        'registration_id' => $device_registration_id,
        'collapse_key' => 'ck_' . $device_id,
        'data.arg' => 'arrrrghhh'
    );
    
    $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, 0);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    
    curl_exec($ch);
    

    $authcode is the SID returned by ClientLogin. $device_registration_id is the registration ID that the client app on the phone gave us when we did the C2DM_REGISTER.

    Hope that helps.