August 16, 2018, 09:19:45 am *
Welcome, Guest. Please login or register.
News:
 
   Forum Home   Search Login Register OBiTALK  
Pages: [1]
  Print  
Author Topic: GoogleVoice solution for OBi100  (Read 810 times)
azrobert
Hero Member & Beta Tester
*****
Posts: 3524


« on: July 30, 2018, 02:53:14 pm »

Get a SIP DID and define it as a forwarding number to the OBi100. This will allow inbound GV calls to the OBi100.

To support outbound calls you can run a PHP GV callback script on a web server. I have the PHP script running under XAMPP on a Windows 7 machine. The XAMPP setup is fast and easy and only takes a few minutes.
Download XAMPP link:
https://www.apachefriends.org/index.html

After installation start Apache from the XAMPP Control Panel.

Here is an XAMPP tutorial. Ignore the WordPress stuff.
https://undsgn.com/xampp-tutorial/

Copy and paste the script below into Notepad. At the end of the script change Name to your GV name, change password to your pw and change 1201xxxxxxx to your DID number (No + sign)

Save the file as gvcallback.php Do NOT save it as a txt file, use type ALL FILES. Move the gvcallback.php file to folder XAMPP/htdocs. That's it!

To test the script, just enter the following in a web browser:
http://192.168.1.xx/gvcallback.PHP?dialnum=6235941000

192.168.1.xx is the IP address of the computer running XAMPP Web Server.
6235941000 is the outbound number.
Your DID number will ring. After you answer, GV will call the number.


Here is an OBi hack to initiate a GV call:

System Management -> Auto Provisioning -> ITSP Provisioning
Method: System Start
ConfigURL:
SET TPRM1 = $UDM0; @loop IF ( $TPRM1 != $UDM0 ) SYNC http://192.168.1.xx/gvcallback.PHP?dialnum=$UDM0; SET UDM0 = "xx"; SET TPRM1 = "xx"; WAIT 2; GOTO loop;

Replace 192.168.1.xx with the IP address of the computer running XAMPP

System Management -> Auto Provisioning -> User Defined Macro 0
Value: $SpeedDial.99
ExpandIn: ANY

Define a Star Code:
*(1xxxxxxxxxx|xxxxxxxxxx|<480>xxxxxxx), Set Speed Dial99, set($Spd[99],$code)
Replace 480 with your local area code

Dial a star followed by 7, 10 or 11 digits. This will set Speed Dial 99 to the number after the star. The ConfigURL script will look for a speed dial 99 change. A call will be initiated when it detects a change.

gvcallback.php
Code:
<?php

class GoogleVoice {
// Google account credentials.
private $_login;
private $_pass;

// Special string that Google Voice requires in our POST requests.
private $_rnr_se;

// File handle for PHP-Curl.
private $_ch;

// The location of our cookies.
private $_cookieFile;

// Are we logged in already?
private $_loggedIn FALSE;

public function __construct($login$pass) {
$this->_login $login;
$this->_pass $pass;
$this->_cookieFile '/tmp/gvCookies.txt';

$this->_ch curl_init();
curl_setopt($this->_chCURLOPT_COOKIEJAR$this->_cookieFile);
curl_setopt($this->_chCURLOPT_FOLLOWLOCATIONTRUE);
curl_setopt($this->_chCURLOPT_RETURNTRANSFERTRUE);
curl_setopt($this->_chCURLOPT_USERAGENT"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");  //was "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
}

private function _logIn() {
global $conf;

if($this->_loggedIn)
return TRUE;

// Fetch the Google Voice login page input fields
$URL='https://accounts.google.com/ServiceLogin?service=grandcentral&passive=1209600&continue=https://www.google.com/voice/b/0/redirection/voice&followup=https://www.google.com/voice/b/0/redirection/voice#inbox';  //adding login to GET prefills with username "&Email=$this->_login"
curl_setopt($this->_chCURLOPT_URL$URL);
$html curl_exec($this->_ch);

// Send HTTP POST service login request using captured input information.
$URL='https://accounts.google.com/signin/challenge/sl/password';  // This is the second page of the two page signin
curl_setopt($this->_chCURLOPT_URL$URL);
$postarray $this->dom_get_input_tags($html);  // Using DOM keeps the order of the name/value from breaking the code.

// Parse the returned webpage for the "GALX" token, needed for POST requests.
if((!isset($postarray['GALX']) || $postarray['GALX']=='') && (!isset($postarray['gxf']) || $postarray['gxf']=='')){
$pi1 var_export($postarrayTRUE);
error_log("Could not parse for GALX or gxf token. Inputs from page:\n" $pi1 "\n\nHTML from page:" $html);
throw new Exception("Could not parse for GALX or gxf token. Inputs from page:\n" $pi1);
}

$postarray['Email'] = $this->_login;  //Add login to POST array
$postarray['Passwd'] = $this->_pass;  //Add password to POST array
curl_setopt($this->_chCURLOPT_POSTTRUE);
curl_setopt($this->_chCURLOPT_POSTFIELDS$postarray);
$html curl_exec($this->_ch);

// Test if the service login was successful.
$postarray $this->dom_get_input_tags($html);  // Using DOM keeps the order of the name/value from breaking the code.
if(isset($postarray['_rnr_se']) && $postarray['_rnr_se']!='') {
$this->_rnr_se $postarray['_rnr_se'];
$this->_loggedIn TRUE;
} else {
$pi2 var_export($postarrayTRUE);
error_log("Could not log in to Google Voice with username: " $this->_login .
  "\n\nMay need to change scraping.  Here are the inputs from the page:\n"$pi2
 );  //add POST action information from DOM.  May help hunt down single or dual sign on page changes.
throw new Exception("Could not log in to Google Voice with username: " $this->_login "\nLook at error log for detailed input information.\n");
}
}

/**
 * Place a call to $number connecting first to $fromNumber.
 * @param $number The 10-digit phone number to call (formatted with parens and hyphens or none).
 * @param $fromNumber The 10-digit number on your account to connect the call (no hyphens or spaces).
 * @param $phoneType (mobile, work, home) The type of phone the $fromNumber is. The call will not be connected without this value.
 */
public function callNumber($number$from_number$phone_type 'mobile') {
$types = array(
'mobile' => 2,
'work' => 3,
'home' => 1
);

// Make sure phone type is set properly.
if(!array_key_exists($phone_type$types))
throw new Exception('Phone type must be mobile, work, or home');

// Login to the service if not already done.
$this->_logIn();

// Send HTTP POST request.
curl_setopt($this->_chCURLOPT_URL'https://www.google.com/voice/call/connect/');
curl_setopt($this->_chCURLOPT_POSTTRUE);
curl_setopt($this->_chCURLOPT_POSTFIELDS, array(
'_rnr_se' => $this->_rnr_se,
'forwardingNumber' => '+1'.$from_number,
'outgoingNumber' => $number,
'phoneType' => $types[$phone_type],
'remember' => 0,
'subscriberNumber' => 'undefined'
));
curl_exec($this->_ch);
}

/**
 * Cancel a call to $number connecting first to $fromNumber.
 * @param $number The 10-digit phone number to call (formatted with parens and hyphens or none).
 * @param $fromNumber The 10-digit number on your account to connect the call (no hyphens or spaces).
 * @param $phoneType (mobile, work, home) The type of phone the $fromNumber is. The call will not be connected without this value.
 */
public function cancelCall($number$from_number$phone_type 'mobile') {
$types = array(
'mobile' => 2,
'work' => 3,
'home' => 1
);

// Make sure phone type is set properly.
if(!array_key_exists($phone_type$types))
throw new Exception('Phone type must be mobile, work, or home');

// Login to the service if not already done.
$this->_logIn();

// Send HTTP POST request.
curl_setopt($this->_chCURLOPT_URL'https://www.google.com/voice/call/cancel/');
curl_setopt($this->_chCURLOPT_POSTTRUE);
curl_setopt($this->_chCURLOPT_POSTFIELDS, array(
'_rnr_se' => $this->_rnr_se,
'forwardingNumber' => '+1'.$from_number,
'outgoingNumber' => $number,
'phoneType' => $types[$phone_type],
'remember' => 0,
'subscriberNumber' => 'undefined'
));
curl_exec($this->_ch);
}

/**
 * Source from http://www.binarytides.com/php-get-name-and-value-of-all-input-tags-on-a-page-with-domdocument/
 * Generic function to fetch all input tags (name and value) on a page
 * Useful when writing automatic login bots/scrapers
 */
private function dom_get_input_tags($html)
{
    $post_data = array();

    // a new dom object
    $dom = new DomDocument;

    //load the html into the object
    @$dom->loadHTML($html);  //@suppresses warnings
    //discard white space
    $dom->preserveWhiteSpace FALSE;

    //all input tags as a list
    $input_tags $dom->getElementsByTagName('input');

    //get all rows from the table
    for ($i 0$i $input_tags->length$i++)
    {
        if( is_object($input_tags->item($i)) )
        {
            $name $value '';
            $name_o $input_tags->item($i)->attributes->getNamedItem('name');
            if(is_object($name_o))
            {
                $name $name_o->value;

                $value_o $input_tags->item($i)->attributes->getNamedItem('value');
                if(is_object($value_o))
                {
                    $value $input_tags->item($i)->attributes->getNamedItem('value')->value;
                }

                $post_data[$name] = $value;
            }
        }
    }

    return $post_data;
}

}

// NOTE: Full email address required.

$gv = new GoogleVoice('Name@gmail.com''password');

// Call a phone from one of your forwarding phones.

$dialnum $_GET["dialnum"];

$gv->callNumber($dialnum'1201xxxxxxx''home');

?>

« Last Edit: August 01, 2018, 07:19:01 am by azrobert » Logged
dannymo
Newbie
*
Posts: 1


« Reply #1 on: August 03, 2018, 11:55:27 am »

How do you forward SIP DID to GV on OBI110? Where do I get a free SIP DID? Thanks!
Logged
azrobert
Hero Member & Beta Tester
*****
Posts: 3524


« Reply #2 on: August 06, 2018, 07:49:19 am »

You register the SIP DID on your OBi100 then setup that number as a forwarding number on your GV account.

In the new GV interface it's called a linked number.
Click New Linked Number
Click Verify by Phone
Click Call
GV will prompt you for a code.
GV will then call your number and give you the code.

Callcentric has free numbers, but will change for e911. You can lie and say the number is only used for international calls and you won't be required to get e911.
https://www.callcentric.com/products/

IPComms has free numbers
https://www.facebook.com/ipcomms/app/128953167177144/?ref=page_internal
Logged
A_Friend
Full Member
***
Posts: 144


« Reply #3 on: August 06, 2018, 09:23:22 am »

To support outbound calls you can run a PHP GV callback script on a web server.

Azrobert, that is a VERY neat hack.   Although I don't specifically need it, thanks for posting it.  I learn a lot here.  I've bookmarked it for future reference, especially how the Obi can call routines on a server.

Speaking of that callback ability, though...  When we were first invited to Google Voice, way back before Obihai existed, and when telcos ruled the world, using the callback feature from a browser to make free calls on a POTS line was thrillingly magical. 

It's important to note that that capability never went away and that any GV user with a browser open to https://voice.google.com still has that "Make a call" button which works to their linked phone, ready to use.  Definitely not as neat as your Apache/PHP/Obi hack, which is decidedly elegant, but it's there.
Logged
PA345NH
Newbie
*
Posts: 8


« Reply #4 on: August 06, 2018, 10:25:00 am »

"Could not log in to Google Voice with username:..."

Tried:
* Allow less secure apps: ON: https://myaccount.google.com/lesssecureapps
* Unlock Captcha: https://accounts.google.com/DisplayUnlockCaptcha
* Enabled 2 factor authentication and generated app password.
Logged
azrobert
Hero Member & Beta Tester
*****
Posts: 3524


« Reply #5 on: August 06, 2018, 10:35:36 am »

I forgot about GV access. I have less secure apps enabled, but not 2 factor authentication. I never used 2 factor auth and don't think you can use it, but not sure.
Logged
PA345NH
Newbie
*
Posts: 8


« Reply #6 on: August 06, 2018, 10:39:53 am »

I forgot about GV access. I have less secure apps enabled, but not 2 factor authentication. I never used 2 factor auth and don't think you can use it, but not sure.

I tried both with and without 2 factor authentication.

If anyone else gets it to work, please advise.

References:
* https://github.com/aaronpk/Google-Voice-PHP-API
* https://github.com/DanielMarquard/Google-Voice-PHP-API
« Last Edit: August 06, 2018, 10:44:10 am by PA345NH » Logged
azrobert
Hero Member & Beta Tester
*****
Posts: 3524


« Reply #7 on: August 06, 2018, 02:25:31 pm »

I originally did this setup about 4 years ago. If I remember correctly, this is the procedure I used:
Enabled less secure apps.
Tried a call and it failed.
In my Google account page under Signin and Security clicked on Device Activity and Security Events.
There was a security event and it asked if this was me.
I selected it was me.
I then signed into the GoogleCaptcha.
Now the calls worked.

This whole setup was designed by giqcass.
Here is the original thread:
http://www.obitalk.com/forum/index.php?topic=6892.0

We used aaronpk's version of GoogleVoice.php.
My small contribution was the refinement of the ITSP Auto Provisioning script.

I recently checked aaronpk's Github page and saw the script was updated a few months ago, so I tried and it worked. I did make a few changes and deletions.
Logged
azrobert
Hero Member & Beta Tester
*****
Posts: 3524


« Reply #8 on: August 06, 2018, 02:31:11 pm »

If anyone else gets it to work, please advise.

Here's another happy customer.
http://www.obitalk.com/forum/index.php?topic=14706.msg93278#msg93278
Logged
PA345NH
Newbie
*
Posts: 8


« Reply #9 on: August 06, 2018, 06:28:49 pm »

Thank you very much, @azrobert.  I will troubleshoot further.  I appreciate your very clever solution.  Hopefully, I will be able to get it to work.

ETA: Working!
« Last Edit: August 07, 2018, 09:36:32 am by PA345NH » Logged
PA345NH
Newbie
*
Posts: 8


« Reply #10 on: August 07, 2018, 03:14:19 pm »

Can this be deployed on Google Cloud Platform (free tier)?

https://cloud.google.com/free/

https://cloud.google.com/php/
« Last Edit: August 07, 2018, 03:16:40 pm by PA345NH » Logged
azrobert
Hero Member & Beta Tester
*****
Posts: 3524


« Reply #11 on: August 07, 2018, 04:36:00 pm »

The Tropo service can run PHP scripts and you can initiate the script via SIP. This would be the ideal service to run this app, but I couldn't get it to work. The free development account doesn't allow file system writes. Google requires cookies for access and the script stores the cookies in a temp file, so the script fails with a permission error when it tries to setup the temp file.

Don't use the IE browser.
https://www.tropo.com/

It looks like Google's free PHP tier will have the same problem.
https://cloud.google.com/php/quickstarts

I did create a Tropo script to initiate a call on the XAMPP server.

The negative compared to the OBi100 hack:
It's noticeable slower.

The positive:
The hack requires you to hang-up and the GV rings your phone,
Using the Tropo app you don't hang up
You wait to hear the Call Waiting tone and then you press Flash.
I'll have to test this to make sure it still works like this.

I also did the same with SipSorcery (free accounts are no longer available).
Logged
PA345NH
Newbie
*
Posts: 8


« Reply #12 on: August 07, 2018, 06:46:34 pm »

FYI, I modified your PHP script, as per:
https://stackoverflow.com/questions/1486099/any-way-to-keep-curls-cookies-in-memory-and-not-on-disk

Code:
curl_setopt($this->_ch, CURLOPT_COOKIEFILE, "");
instead of:
Code:
curl_setopt($this->_ch, CURLOPT_COOKIEJAR, $this->_cookieFile);

It works.

I received this reply after filling form for Tropo account:

"Thank you for submitting your application for a Tropo Developer account. In the three years since Cisco acquired Tropo, we had the opportunity to expose Tropo’s capabilities to a variety of groups within Cisco, adding phone and messaging functionality to a large set of products, services and partner-created solutions. Due to the success of these offerings, we chose to focus the Tropo platform on supporting Cisco and its ISV (Independent Software Vendor) community. To that end, we are limiting new Tropo accounts to partners building solutions that can be resold, and include other Cisco components such as Webex, Meraki, Contact Centers, etc."
Logged
azrobert
Hero Member & Beta Tester
*****
Posts: 3524


« Reply #13 on: August 07, 2018, 07:56:08 pm »

I'm confused. Did you get a free Tropo account? Did you test the cookie change in Tropo or XAMPP?
I saw that link, but it didn't work for me in Tropo. I received an unknown error. I had the 1st line coded like yours and commented the 2nd line.

Do you think it will work in the Google Cloud with that change?
Logged
PA345NH
Newbie
*
Posts: 8


« Reply #14 on: August 07, 2018, 08:21:02 pm »

I'm confused. Did you get a free Tropo account? Did you test the cookie change in Tropo or XAMPP?
I saw that link, but it didn't work for me in Tropo. I received an unknown error. I had the 1st line coded like yours and commented the 2nd line.

Do you think it will work in the Google Cloud with that change?


Sorry, I meant working with XAMPP. I am not sure if it would work with Google Cloud, etc.
Logged
PA345NH
Newbie
*
Posts: 8


« Reply #15 on: August 09, 2018, 10:25:43 pm »

Simple PHP TCP Server to receive SIP request and trigger gvcallback with phone# parsed from SIP request:
http://www.dslreports.com/forum/r32074641-
Logged
SteveInUS
Newbie
*
Posts: 4



« Reply #16 on: August 12, 2018, 08:53:45 am »

pbxes.com virtual PBX supports SIP based googlevoice trunks which can be configured with your googlevoice account.
Extensions can be created and configured on OBi100 and OBi110.
However they have a monthly traffic consumption limit of 2000 minutes for free accounts.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC