Tuesday 26 March 2013

Sending a Google Voice SMS using PHP


Sending a Google Voice SMS using PHP

If you are interested, I made a tutorial on how to handle incoming SMS from Google Voice. You can also check out the gateway that I have working on, GVoice SMS to Email App and briefly explained in my post: New Email to SMS Gateway. With this app, you can register your Google Voice account/s and new SMS messages will be delivered/sent via email or HTTP POST requests.

The very first thing to do to use GVoice is to login to the service. Now, I tried curling my way to it but it seemed that the curl cookiejar setting on our server at kundiman.net is not working. Then I got to see this code written in Java, google-voice-java. To login to GVoice without emulating a browser, we could use Google’s Client Login API. We just need to post the login credentials to the API’s service endpoint and we will then get an Auth and SID key.
To illustrate this, we will use the xhttp class to post the data:
10
11
12
13
14
15
16
17
18
19
$data = array();
$data['post'] = array(
  'accountType' => 'GOOGLE',
  'Email'       => 'username@gmail.com',
  'Passwd'      => 'mypassword',
  'service'     => 'grandcentral',
  'source'      => 'codecri.me-example-1.0' // Application's name, e.g. companyName-applicationName-versionID
);
 
$response = xhttp::fetch('https://www.google.com/accounts/ClientLogin', $data);
Google will then respond with a status 200 if successful or a 403 if an error occured. There are several other error codes that might be sent. To save up on URL calls and runtime, you can cache the value of these variables for a span of time. I am using 5 minutes before “logging in” again in some of my scripts. But I am not sure just how long before a new authentication call should be made. A better option is to try to send the SMS first with the last auth key then when it fails, get a new auth key and save that for the next call.
If successful, the body of the response will contain 3 lines of the data, the first and last lines, containing the SID and Auth key respectively.
SID=DQAAAGRY5IO78PO8759J5R456NUI766LO87O0O6OT78ITHFTUGGVA7Zg8CTN
LSID=DQAAAG4578JK896J7H8UR67UG5R5HE4YY4VW7MR89KY9UPO8IHsAlk8BBbG
Auth=DQAAAGB5N78OTYRTRYEBYWYUN6R7UYVG4WGYUYTRHT68U45U65GgAdk3fA5
The lines are much longer than the example above. We just need the 3rd line which contains the Auth key and we’ll use preg_match to get the it.
27
28
preg_match('/Auth=(.+)/', $response['body'], $matches);
$auth = $matches[1];
Next thing we need is the value for _rnr_se which is a magic variable assigned by GVoice and is needed with pretty much any request made to Google Voice, sort of an API key. To do this, we just need to fetch the Google Voice homepage and adding an Authorization header for authentication. This authentication method is unofficial and may change without notice. If your script breaks, please let me know by posting a comment below.
36
37
38
39
40
$data['headers'] = array(
    'Authorization' => 'GoogleLogin auth='.$auth
);

$response = xhttp::fetch('https://www.google.com/voice', $data);
Then we just use preg_match again to extract the value for _rnr_se which can be found as a hidden variable on some form of as a javascript json object near the end of your inbox’s source HTML. Well, no worries, the script does this automatically.
48
49
preg_match("/'_rnr_se': '([^']+)'/", $response['body'], $matches);
$rnrse = $matches[1];
Note that the value for _rnr_se for a user does not change so if you want to save on runtime, you can get this value once and store it somewhere for later use. But then again, there is no documentation for this so don’t be too sure. It’s your call.
Now we are ready to send our SMS message through Google Voice! It’s easy, we just need to post the needed variables, and what better way to explain it than to do it in code:
54
55
56
57
58
59
60
61
62
$data['post'] = array (
    '_rnr_se'     => $rnrse,
    'phoneNumber' => '639225970524', // country code + area code + phone number (international notation)
    'text'        => 'This is a test SMS sent from PHP using Google Voice!',
    'id'          => ''  // thread ID of message, GVoice's way of threading the messages like GMail
);

// Send the SMS
$response = xhttp::fetch('https://www.google.com/voice/sms/send/', $data);
If all goes well, the recipient should be getting the message in a few moments after making the call. If not, you could always check the response of the last xhttp call like so:
65
66
67
68
69
70
71
72
$value = json_decode($response['body']);

if($value->ok) {
    echo "SMS message sent! ({$data[post][phoneNumber]}{$data[post][text]})";
} else {
    echo "Unable to send SMS! Error Code ({$value->data->code})\n\n";
    echo 'response: '; print_r($response);
}
I have not tested it thoroughly but the last call may return OK true even if the message was not actually sent, like for example, a wrong number. So be sure to make tests on validity of the number like the format at least or a valid country code. Also check the length of the message because going over 160 characters will generate an error. If script stops working properly, please drop by here again and post a comment so we could find a fix. Thanks!
If you want to access the other GVoice features, the endpoints are listed on posttopic, compiled by Chad Smith.
Finally, the complete PHP code to send an SMS using Google Voice below. If you are to use this code, you just have to put in your Google Voice login info (email address and password) in lines 12 and 13.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<?php

// arvin@codecri.me
// url  : http://codecri.me/case/66/sending-a-google-voice-sms-using-php/
// date: December 28, 2010

require_once 'class.xhttp.php';

// Set account login info
$data = array();
$data['post'] = array(
  'accountType' => 'GOOGLE',
  'Email'       => 'username@gmail.com',
  'Passwd'      => 'mypassword',
  'service'     => 'grandcentral',
  'source'      => 'codecri.me-example-1.0' // Application's name, e.g. companyName-applicationName-versionID
);
 
$response = xhttp::fetch('https://www.google.com/accounts/ClientLogin', $data);

if(!$response['successful']) {
    echo 'response: '; print_r($response);
    die();
}

// Extract Auth
preg_match('/Auth=(.+)/', $response['body'], $matches);
$auth = $matches[1];
// You can also cache this auth value for at least 5+ minutes

// Erase POST variables used on the previous xhttp call
$data['post'] = null;

// Set Authorization for authentication
// There is no official documentation and this might change without notice
$data['headers'] = array(
    'Authorization' => 'GoogleLogin auth='.$auth
);

$response = xhttp::fetch('https://www.google.com/voice', $data);

if(!$response['successful']) {
    echo 'response: '; print_r($response);
    die();
}

// Extract _rnr_se | This value does not change* Cache this value
preg_match("/'_rnr_se': '([^']+)'/", $response['body'], $matches);
$rnrse = $matches[1];

// $data['headers'] still contains Auth for authentication

// Set SMS options
$data['post'] = array (
    '_rnr_se'     => $rnrse,
    'phoneNumber' => '639225970524', // country code + area code + phone number (international notation)
    'text'        => 'This is a test SMS sent from PHP using Google Voice!',
    'id'          => ''  // thread ID of message, GVoice's way of threading the messages like GMail
);

// Send the SMS
$response = xhttp::fetch('https://www.google.com/voice/sms/send/', $data);

// Evaluate the response
$value = json_decode($response['body']);

if($value->ok) {
    echo "SMS message sent! ({$data[post][phoneNumber]}{$data[post][text]})";
} else {
    echo "Unable to send SMS! Error Code ({$value->data->code})\n\n";
    echo 'response: '; print_r($response);
}

?>
See the xhttp class source page for information on how it handles requests.
Using this info, I made an Email to SMS Gateway for easily sending SMS messages for free but is now US-only because of Google Voice restrictions. I have also written a tutorial on how to handle incoming SMS from GVoice. Using both will enable you to use Google Voice as a free SMS gateway for your applications.
You can also check out the gateway that I have working on at gvoicesmstoemail.appspot.comand briefly explained in my post; New Email to SMS Gateway. With this app, you can register your Google Voice account/s and new SMS messages will be delivered/sent via email or HTTP POST requests.

2 comments: