SMS Gateways
The SMS gateways for VikBooking can be extended by creating a PHP file containing the VikSmsApi class.
The generated file should be uploaded via FTP onto the following directory:
/wp-content/plugins/vikbooking/admin/smsapi/
Follow the schema below to see the structure of the Class File:
<?php
defined('ABSPATH') OR die('Restricted Area');
class VikSmsApi {
private $order_info;
private $params;
private $log = '';
public static function getAdminParameters() {
return array();
}
public function __construct($order, $params=array()) {
$this->order_info=$order;
$this->params = ( !empty($params) ) ? $params : $this->params;
}
public function sendMessage( $phone_number, $msg_text ) {
/** See the code below to build this method */
return new stdClass;
}
public function estimate( $phone_number, $msg_text ) {
/** See the code below to build this method */
return new stdClass;
}
public function validateResponse($response_obj) {
/** See the code below to build this method */
return true;
}
public function getLog() {
return $this->log;
}
}
?>
The parameters form for the administrator can be built through the getAdminParameters() static method, to fill in private data required to the creation and validation of the API, like API Key and API Secret.
The parameters of the form are returned as an array with the following structure:
[
"param_1" : [
"label" : "Label 1",
"type" : "text",
],
"param_2" : [
"label" : "Label 2",
"type" : "select",
],
]
- param_1 is the key of the array and have to be unique (required).
It represents the name of the parameter to use. - label indicates the text to assign for the parameter in the administrator section (optional).
By placing a double slash (//) after the label, the next text will be displayed as a tip near the field of the parameter (like "Sender//max 11 characters"). - type is used to render the right type of input in the administrator section (required).
The assumed value can be only one of the followings: custom, select, text. - html will be used only when the type of the parameter is custom (optional).
- options is an array containing all the possible values to use in the dropdown (required only when the type is select).
public static function getAdminParameters() {
return array(
'apikey' => array(
'label' => 'API Key',
'type' => 'text'
),
'apisecret' => array(
'label' => 'API Secret',
'type' => 'text'
),
'sender' => array(
'label' => 'Sender Name//max 11 characters',
'type' => 'text'
),
'sandbox' => array(
'label' => 'Sandbox',
'type' => 'select',
'options' => array('NO', 'YES')
)
);
}
The code above will generate a parameters form in the administrator section as follows.
If your form doesn't show up, then you probably have a syntax error in your file.
After filling in the Gateway parameters, they will be available in the array $params and you will be able to access these values through the code below:
$api_key = $this->params['apikey']; /* returns "TS8KJSGV20E7SG2K" */
$api_secret = $this->params['apisecret']; /* returns "ks03bsoaqsdlew83hdswlsn2ie7d2hndmwq" */
$sender_name = $this->params['sender']; /* returns "e4j.com" */
$sandbox = $this->params['sandbox']; /* returns "NO" */
The method sendMessage($phone_number, $msg_text) of the object VikSmsApi is invoked every time an order becomes CONFIRMED, like after a payment.Through this function, you should submit via POST (probably) all the necessary variables for the authentication on the Gateway and the content of the message, including the recipient phone number. Generally, cURL is the safest method to submit variables to a remote Gateway but this depends on the requirements of the gateway you are working on.
The sendMessage function requires 2 arguments:
- $phone_number - (string) the phone number of the recipient. This value must be validated before sending the message, as it could be missing the prefix or it could contain invalid characters (like @ or /)
- $msg_text - (string) the full text to send to the customer. A lot of providers allow to send max 160 characters per message, please keep this limit in mind.
The code below is just an example of how a cURL Request could establish the connection with the SMS gateway and send the message.
public function sendMessage($phone_number, $msg_text) {
$phone_number = $this->sanitizePhoneNumber($phone_number);
if( $this->params['sandbox'] == "NO" ) {
$this->params['sandbox'] = 0;
} else {
$this->params['sandbox'] = 1;
}
$request = array(
"apikey" => $this->params['apikey'],
"apisecret" => $this->params['apisecret'],
"from" => $this->params['sender'],
"to" => $phone_number,
"msg" => $msg_text,
"sandbox" => $this->params['sandbox']
);
$json = json_encode($request);
$curl_opts = array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Content-Type: application/json;charset=UTF-8',
'Content-Length: '.strlen($json)
),
CURLOPT_VERBOSE => true,
);
$ch = curl_init('https://secure.sms.fakeprovider.com/send');
curl_setopt_array($ch, $curl_opts);
$response = curl_exec($ch);
return json_decode($response);
}
The sanitizePhoneNumber function used above is not a native function of the VikSmsApi class, so you would have to write this method on your own code.
This is just an example to see how a phone number could be parsed and sanitized:
protected function sanitizePhoneNumber($phone_number) {
$str = '';
for( $i = 0; $i < strlen($phone_number); $i++ ) {
if( ($phone_number[$i] >= '0' && $phone_number[$i] <= '9') || $phone_number[$i] == '+' ) {
$str .= $phone_number[$i]; // copy only numbers and plus character
}
}
$default_prefix = '+1'; // US, Canada phone prefix
if( $phone_number[0] != '+' ) {
// $phone_number doesn't contain the phone prefix. Checking if it starts with 00 would be smart as well
$str = $default_prefix.$str;
}
return $str;
}
The validateResponse($response_obj) method is used to validate the object returned by the gateway during the sending of the message. Some gateways return an object containing a short error message and the http status code.
{
"httpcode" : 200,
"errmsg" : "",
}
{
"httpcode" : 401,
"errmsg" : "BAD_CREDENTIALS",
}
{
"httpcode" : 402,
"errmsg" : "BAD_CREDIT",
}
While, sometimes, the object returned is a simple boolean value (true/false).
In this method you have to return only a boolean value (true/false) to tell the framework whether the message was sent. By returning TRUE, no errors will be raised or notified, the error will be sent via e-mail to the administrator otherwise. Please notice that the errors to be returned, must be placed in the $log attribute.
//in this example, the method requires an object as first and only argument
public function validateResponse($response_obj) {
if( $response_obj->httpcode == 200 ) {
return true;
}
$this->log .= $response_obj->errmsg;
return false;
}
The estimate($phone_number, $msg_text) is an optional method used to retrieve the remaining credit from the back-end of the plugin. It is not a mandatory method and the class could not have it. Not every provider (SMS Gateway) allows such a request.
$phone_number and $msg_text are only used as example from the gateway.
The returned value of this function must be a string that will be displayed in the back-end.
Most of the times, the structure of the estimate function is similar to the sendMessage method, it usually makes a call with some different variables to the SMS Gateway of the provider.
public function estimate($phone_number, $msg_text) {
$fixedResponse = '----';
$phone_number = $this->sanitizePhoneNumber($phone_number);
$request = array(
"apikey" => $this->params['apikey'],
"apisecret" => $this->params['apisecret'],
"from" => $this->params['sender'],
"to" => $phone_number,
"msg" => $msg_text,
);
$json = json_encode($request);
$curl_opts = array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Content-Type: application/json;charset=UTF-8',
'Content-Length: '.strlen($json)
),
CURLOPT_VERBOSE => true,
);
$ch = curl_init('https://secure.sms.fakeprovider.com/estimate');
curl_setopt_array($ch, $curl_opts);
$response = curl_exec($ch);
$response = json_decode($response);
if(is_object($response)) {
$fixedResponse = (float)$response->credit;
}
return $fixedResponse;
}