2020-04-03 02:15:55 +02:00
< ? php
/*
* This file is part of RaspiSMS .
*
* ( c ) Pierre - Lin Bonnemaison < plebwebsas @ gmail . com >
*
* This source file is subject to the GPL - 3.0 license that is bundled
* with this source code in the file LICENSE .
*/
namespace adapters ;
/**
2020-06-23 21:06:13 +02:00
* Octopush SMS service with a shortcode adapter .
2020-04-03 02:15:55 +02:00
*/
class OctopushShortcodeAdapter implements AdapterInterface
{
2021-06-25 02:04:35 +02:00
const SMS_TYPE_LOWCOST = 'sms_low_cost' ;
const SMS_TYPE_PREMIUM = 'sms_premium' ;
2020-04-03 02:15:55 +02:00
/**
2021-01-17 03:16:57 +01:00
* Data used to configure interaction with the implemented service . ( e . g : Api credentials , ports numbers , etc . ) .
2020-04-03 02:15:55 +02:00
*/
2021-01-17 03:16:57 +01:00
private $data ;
2020-04-03 02:15:55 +02:00
/**
2020-06-23 21:06:13 +02:00
* Octopush login .
2020-04-03 02:15:55 +02:00
*/
private $login ;
/**
2020-06-23 21:06:13 +02:00
* Octopush api key .
2020-04-03 02:15:55 +02:00
*/
private $api_key ;
/**
2020-06-23 21:06:13 +02:00
* Sender name to use instead of shortcode .
2020-04-03 02:15:55 +02:00
*/
private $sender ;
2021-07-19 17:32:23 +02:00
2021-06-25 02:04:35 +02:00
/**
2021-07-19 17:32:23 +02:00
* Octopush SMS type .
2021-06-25 02:04:35 +02:00
*/
private $sms_type ;
2020-04-03 02:15:55 +02:00
/**
2020-06-23 21:06:13 +02:00
* Octopush api baseurl .
2020-04-03 02:15:55 +02:00
*/
2021-06-25 02:04:35 +02:00
private $api_url = 'https://api.octopush.com/v1/public' ;
2020-04-03 02:15:55 +02:00
/**
* Adapter constructor , called when instanciated by RaspiSMS .
*
* @ param string $number : Phone number the adapter is used for
2021-02-23 00:31:54 +01:00
* @ param json string $data : JSON string of the data to configure interaction with the implemented service
2020-04-03 02:15:55 +02:00
*/
2021-01-17 03:16:57 +01:00
public function __construct ( string $data )
2020-04-03 02:15:55 +02:00
{
2021-01-17 03:16:57 +01:00
$this -> data = json_decode ( $data , true );
2020-04-03 02:15:55 +02:00
2021-01-17 03:16:57 +01:00
$this -> login = $this -> data [ 'login' ];
$this -> api_key = $this -> data [ 'api_key' ];
2021-06-25 02:04:35 +02:00
$this -> sms_type = self :: SMS_TYPE_LOWCOST ;
2021-07-19 17:32:23 +02:00
if (( $this -> data [ 'sms_type' ] ? ? false ) && 'premium' === $this -> data [ 'sms_type' ])
2021-06-25 02:04:35 +02:00
{
$this -> sms_type = self :: SMS_TYPE_PREMIUM ;
}
2021-01-17 03:16:57 +01:00
$this -> sender = $this -> data [ 'sender' ] ? ? null ;
2020-04-03 02:15:55 +02:00
}
/**
* Classname of the adapter .
*/
public static function meta_classname () : string
{
return __CLASS__ ;
}
/**
* Uniq name of the adapter
2020-06-23 21:06:13 +02:00
* It should be the classname of the adapter un snakecase .
2020-04-03 02:15:55 +02:00
*/
2020-06-23 21:06:13 +02:00
public static function meta_uid () : string
2020-04-03 02:15:55 +02:00
{
return 'octopush_shortcode_adapter' ;
}
2021-02-23 00:31:54 +01:00
2021-01-26 19:27:30 +01:00
/**
* Should this adapter be hidden in user interface for phone creation and
2021-02-23 00:31:54 +01:00
* available to creation through API only .
2021-01-26 19:27:30 +01:00
*/
public static function meta_hidden () : bool
{
return false ;
}
2020-04-03 02:15:55 +02:00
2022-03-28 01:54:38 +02:00
/**
* Should this adapter data be hidden after creation
* this help to prevent API credentials to other service leak if an attacker gain access to RaspiSMS through user credentials .
*/
public static function meta_hide_data () : bool
{
return false ;
}
2020-04-03 02:15:55 +02:00
/**
* Name of the adapter .
* It should probably be the name of the service it adapt ( e . g : Gammu SMSD , OVH SMS , SIM800L , etc . ) .
*/
public static function meta_name () : string
{
return 'Octopush Shortcode' ;
}
/**
* Description of the adapter .
* A short description of the service the adapter implements .
*/
public static function meta_description () : string
{
$credentials_url = 'https://www.octopush-dm.com/api-logins' ;
2020-06-23 21:06:13 +02:00
2020-04-03 02:15:55 +02:00
return '
2020-07-04 21:35:39 +02:00
Envoi de SMS avec un shortcode en utilisant < a target = " _blank " href = " https://www.octopush.com/ " > Octopush </ a >. Pour trouver vos clés API Octopush < a target = " _blank " href = " ' . $credentials_url . ' " > cliquez ici .</ a >< br />
2021-02-04 16:44:13 +01:00
Pour plus d\ ' information sur l\ ' utilisation de ce type de téléphone , reportez - vous à < a href = " https://documentation.raspisms.fr/users/adapters/octopush_shortcode.html " target = " _blank " > la documentation sur le téléphone " Octopush Shortcode " .</ a >
2020-04-03 02:15:55 +02:00
' ;
}
/**
2021-01-17 03:16:57 +01:00
* List of entries we want in data for the adapter .
2020-04-03 02:15:55 +02:00
*
* @ return array : Every line is a field as an array with keys : name , title , description , required
*/
2021-01-17 03:16:57 +01:00
public static function meta_data_fields () : array
2020-04-03 02:15:55 +02:00
{
return [
[
'name' => 'login' ,
'title' => 'Octopush Login' ,
'description' => 'Login du compte Octopush à employer. Trouvable sur la page des identifiants API Octopush.' ,
'required' => true ,
],
[
'name' => 'api_key' ,
'title' => 'API Key' ,
'description' => 'Clef API octopush. Trouvable sur la page des identifiants API Octopush.' ,
'required' => true ,
],
2021-06-25 02:04:35 +02:00
[
'name' => 'sms_type' ,
'title' => 'Type de SMS à employer' ,
'description' => 'Type de SMS à employer coté Octopush, rentrez "low cost" ou "premium" selon le type de SMS que vous souhaitez employer. Laissez vide pour utiliser par défaut des SMS low cost.' ,
'required' => false ,
],
2020-04-03 02:15:55 +02:00
[
'name' => 'sender' ,
'title' => 'Nom de l\'expéditeur' ,
'description' => ' Nom de l\ ' expéditeur à afficher à la place du numéro ( 11 caractères max ) .< br />
< b > Laissez vide pour ne pas utiliser d\ ' expéditeur nommé .</ b >< br />
< b > Si vous utilisez un expéditeur nommé , le destinataire ne pourra pas répondre .</ b > ' ,
'required' => false ,
],
];
}
/**
* Does the implemented service support reading smss .
*/
public static function meta_support_read () : bool
{
return false ;
}
2023-02-18 16:39:07 +01:00
/**
* Does the implemented service support updating phone status .
*/
public static function meta_support_phone_status () : bool
{
return false ;
}
2020-04-03 02:15:55 +02:00
/**
* Does the implemented service support flash smss .
*/
public static function meta_support_flash () : bool
{
return false ;
}
/**
* Does the implemented service support status change .
*/
public static function meta_support_status_change () : bool
{
return true ;
}
/**
* Does the implemented service support reception callback .
*/
public static function meta_support_reception () : bool
{
return true ;
}
2021-06-17 00:51:33 +02:00
2021-03-19 02:45:12 +01:00
/**
2021-06-17 00:51:33 +02:00
* Does the implemented service support mms reception .
2021-03-19 02:45:12 +01:00
*/
public static function meta_support_mms_reception () : bool
{
return false ;
}
2020-04-03 02:15:55 +02:00
/**
2021-06-17 00:51:33 +02:00
* Does the implemented service support mms sending .
2020-04-03 02:15:55 +02:00
*/
2021-03-19 02:45:12 +01:00
public static function meta_support_mms_sending () : bool
{
return false ;
}
2021-06-17 00:51:33 +02:00
2021-03-23 17:39:13 +01:00
public static function meta_support_inbound_call_callback () : bool
{
return false ;
}
2021-06-17 00:51:33 +02:00
2021-03-23 17:39:13 +01:00
public static function meta_support_end_call_callback () : bool
{
return false ;
}
2021-03-19 02:45:12 +01:00
2021-06-17 00:51:33 +02:00
public function send ( string $destination , string $text , bool $flash = false , bool $mms = false , array $medias = []) : array
2020-04-03 02:15:55 +02:00
{
$response = [
'error' => false ,
'error_message' => null ,
'uid' => null ,
];
try
{
2021-06-25 02:04:35 +02:00
$headers = [
'api-login: ' . $this -> login ,
'api-key: ' . $this -> api_key ,
'Content-Type: application/json' ,
];
2021-01-17 03:16:57 +01:00
$data = [
2021-06-25 02:04:35 +02:00
'text' => $text ,
2021-07-19 17:32:23 +02:00
'recipients' => [[ 'phone_number' => $destination ]],
2021-06-25 02:04:35 +02:00
'sms_type' => $this -> sms_type ,
'purpose' => 'alert' ,
2020-04-03 02:15:55 +02:00
];
2021-06-25 02:04:35 +02:00
if ( $this -> sender )
{
$data [ 'sender' ] = $this -> sender ;
}
else
2020-04-03 02:15:55 +02:00
{
2021-07-19 17:32:23 +02:00
$data [ 'with_replies' ] = 'True' ;
2020-04-03 02:15:55 +02:00
}
2021-06-25 02:04:35 +02:00
$data = json_encode ( $data );
$endpoint = $this -> api_url . '/sms-campaign/send' ;
2020-04-03 02:15:55 +02:00
$curl = curl_init ();
curl_setopt ( $curl , CURLOPT_URL , $endpoint );
2021-11-05 23:26:09 +01:00
curl_setopt ( $curl , CURLOPT_PROTOCOLS , CURLPROTO_HTTP | CURLPROTO_HTTPS );
2020-04-03 02:15:55 +02:00
curl_setopt ( $curl , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $curl , CURLOPT_FOLLOWLOCATION , true );
curl_setopt ( $curl , CURLOPT_POST , true );
2021-01-17 03:16:57 +01:00
curl_setopt ( $curl , CURLOPT_POSTFIELDS , $data );
2021-06-25 02:04:35 +02:00
curl_setopt ( $curl , CURLOPT_HTTPHEADER , $headers );
2021-07-19 17:32:23 +02:00
2021-06-25 02:04:35 +02:00
$curl_response = curl_exec ( $curl );
$http_code = ( int ) curl_getinfo ( $curl , CURLINFO_HTTP_CODE );
2020-04-03 02:15:55 +02:00
curl_close ( $curl );
2021-06-25 02:04:35 +02:00
if ( false === $curl_response )
2020-04-03 03:38:35 +02:00
{
$response [ 'error' ] = true ;
$response [ 'error_message' ] = 'HTTP query failed.' ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
}
2021-06-25 02:04:35 +02:00
$response_decode = json_decode ( $curl_response , true );
2020-06-23 21:06:13 +02:00
if ( null === $response_decode )
2020-04-03 03:38:35 +02:00
{
$response [ 'error' ] = true ;
$response [ 'error_message' ] = 'Invalid JSON for response.' ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
}
2021-06-25 02:04:35 +02:00
if ( 200 !== $http_code )
2020-04-03 03:38:35 +02:00
{
$response [ 'error' ] = true ;
2021-06-25 02:04:35 +02:00
$response [ 'error_message' ] = 'Response indicate error code : ' . $response_decode [ 'code' ] . ' -> """' . $response_decode [ 'message' ] . '""" AND HTTP CODE -> ' . $http_code ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
}
2021-06-25 02:04:35 +02:00
$uid = $response_decode [ 'sms_ticket' ] ? ? false ;
2020-04-03 03:38:35 +02:00
if ( ! $uid )
{
$response [ 'error' ] = true ;
$response [ 'error_message' ] = 'Cannot extract SMS uid' ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
}
$response [ 'uid' ] = $uid ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
2020-04-03 02:15:55 +02:00
}
catch ( \Throwable $t )
{
$response [ 'error' ] = true ;
$response [ 'error_message' ] = $t -> getMessage ();
2020-06-23 21:06:13 +02:00
2020-04-03 02:15:55 +02:00
return $response ;
}
}
public function read () : array
{
return [];
}
2023-02-18 16:39:07 +01:00
/**
* Method called to verify phone status
*
* @ return string : Return one phone status among 'available' , 'unavailable' , 'no_credit'
*/
public function check_phone_status () : string
{
return \models\Phone :: STATUS_AVAILABLE ;
}
2020-04-03 02:15:55 +02:00
public function test () : bool
{
try
{
$success = true ;
2021-01-17 03:16:57 +01:00
if ( $this -> data [ 'sender' ] && ( mb_strlen ( $this -> data [ 'sender' ]) < 3 || mb_strlen ( $this -> data [ 'sender' ] > 11 )))
2020-04-03 02:15:55 +02:00
{
return false ;
}
2020-06-23 21:06:13 +02:00
2021-06-25 02:04:35 +02:00
if ( ! empty ( $this -> data [ 'sms_type' ]) && ! in_array ( $this -> data [ 'sms_type' ], [ 'premium' , 'low cost' ]))
{
return false ;
}
2021-07-19 17:32:23 +02:00
2021-06-25 02:04:35 +02:00
$headers = [
'api-login: ' . $this -> login ,
'api-key: ' . $this -> api_key ,
'Content-Type: application/json' ,
2020-04-03 02:15:55 +02:00
];
//Check service name
2021-06-25 02:04:35 +02:00
$endpoint = $this -> api_url . '/wallet/check-balance' ;
2020-04-03 02:15:55 +02:00
$curl = curl_init ();
curl_setopt ( $curl , CURLOPT_URL , $endpoint );
2021-11-05 23:26:09 +01:00
curl_setopt ( $curl , CURLOPT_PROTOCOLS , CURLPROTO_HTTP | CURLPROTO_HTTPS );
2020-04-03 02:15:55 +02:00
curl_setopt ( $curl , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $curl , CURLOPT_FOLLOWLOCATION , true );
2021-06-25 02:04:35 +02:00
curl_setopt ( $curl , CURLOPT_HTTPHEADER , $headers );
2020-04-03 02:15:55 +02:00
$response = curl_exec ( $curl );
2021-06-25 02:04:35 +02:00
$http_code = ( int ) curl_getinfo ( $curl , CURLINFO_HTTP_CODE );
2020-04-03 02:15:55 +02:00
curl_close ( $curl );
2021-07-19 17:32:23 +02:00
if ( 200 !== $http_code )
2020-04-03 02:15:55 +02:00
{
return false ;
}
return true ;
}
catch ( \Throwable $t )
{
return false ;
}
}
public static function status_change_callback ()
{
2020-04-03 03:38:35 +02:00
header ( 'Connection: close' );
header ( 'Content-Encoding: none' );
header ( 'Content-Length: 0' );
2021-06-25 02:04:35 +02:00
$input = file_get_contents ( 'php://input' );
$content = json_decode ( $input , true );
if ( null === $content )
{
return false ;
}
2021-07-19 17:32:23 +02:00
2021-06-25 02:04:35 +02:00
$uid = $content [ 'message_id' ] ? ? false ;
$status = $content [ 'status' ] ? ? false ;
2020-04-03 03:38:35 +02:00
2020-06-23 21:06:13 +02:00
if ( false === $uid || false === $status )
2020-04-03 03:38:35 +02:00
{
return false ;
}
switch ( $status )
{
case 'DELIVERED' :
$status = \models\Sended :: STATUS_DELIVERED ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
break ;
2021-01-14 03:32:17 +01:00
2021-06-25 02:04:35 +02:00
case 'NOT_DELIVERED' :
2020-04-03 03:38:35 +02:00
case 'NOT_ALLOWED' :
case 'BLACKLISTED_NUMBER' :
$status = \models\Sended :: STATUS_FAILED ;
2020-06-23 21:06:13 +02:00
break ;
2021-01-14 03:32:17 +01:00
2020-06-23 21:06:13 +02:00
default :
2020-04-03 03:38:35 +02:00
$status = \models\Sended :: STATUS_UNKNOWN ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
break ;
}
return [ 'uid' => $uid , 'status' => $status ];
2020-04-03 02:15:55 +02:00
}
2020-06-23 21:06:13 +02:00
public static function reception_callback () : array
2020-04-03 02:15:55 +02:00
{
2020-04-03 03:38:35 +02:00
$response = [
'error' => false ,
'error_message' => null ,
2021-01-26 19:27:30 +01:00
'sms' => null ,
2020-04-03 03:38:35 +02:00
];
header ( 'Connection: close' );
header ( 'Content-Encoding: none' );
header ( 'Content-Length: 0' );
2021-07-19 17:32:23 +02:00
2021-06-25 02:04:35 +02:00
$input = file_get_contents ( 'php://input' );
$content = json_decode ( $input , true );
if ( null === $content )
{
$response [ 'error' ] = true ;
$response [ 'error_message' ] = 'Cannot read input data from callback request.' ;
2021-07-19 17:32:23 +02:00
2021-06-25 02:04:35 +02:00
return $response ;
}
2020-04-03 03:38:35 +02:00
2021-06-25 02:04:35 +02:00
$number = $content [ 'number' ] ? ? false ;
$text = $content [ 'text' ] ? ? false ;
$at = $content [ 'reception_date' ] ? ? false ;
2020-04-03 03:38:35 +02:00
if ( ! $number || ! $text || ! $at )
{
$response [ 'error' ] = true ;
$response [ 'error_message' ] = 'One required data of the callback is missing.' ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
}
2021-06-25 02:04:35 +02:00
$origin = \controllers\internals\Tool :: parse_phone ( $number );
2020-04-03 03:38:35 +02:00
if ( ! $origin )
{
$response [ 'error' ] = true ;
2021-06-25 02:04:35 +02:00
$response [ 'error_message' ] = 'Invalid origin number : ' . $number ;
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
}
$response [ 'sms' ] = [
'at' => $at ,
'text' => $text ,
'origin' => $origin ,
];
2020-06-23 21:06:13 +02:00
2020-04-03 03:38:35 +02:00
return $response ;
2020-04-03 02:15:55 +02:00
}
2021-06-17 00:51:33 +02:00
2023-09-22 18:27:17 +02:00
public static function inbound_call_callback () : array
2021-03-23 17:39:13 +01:00
{
return [];
}
2021-06-17 00:51:33 +02:00
2023-09-22 18:27:17 +02:00
public static function end_call_callback () : array
2021-03-23 17:39:13 +01:00
{
return [];
}
2020-04-03 02:15:55 +02:00
}