Dans ce tutoriel, nous allons apprendre ensemble comment intégrer l'API SMS d'Orange dans une application web avec le framework PHP Laravel.
Vous aviez été nombreux à me demander comment tu fais pour envoyer les SMS de Kisal? (Oui oui on va faire comme les influenceurs Instagram). Comme l'indique le titre, l'application sera développée en Laravel et je suppose déjà que vous aviez les bases si ce n'est pas le cas ce tutorielpourra vous servir à l'implémenter sur d'autres techno.
Je sais que vous êtes pressés de taper du code mais on va se calmer
Avant de passer aux choses sérieuses, on va créer un projet sur Orange developer pour avoir la possibilité d'utiliser leur API.
Créer un compte sur Orange developer, à la fin de la création vous recevrez un e-mail d'activation (On est tous de grands garçons et de grandes filles donc pas besoin de l'expliquer)
Cliquez sur le bouton "My apps" en haut à droite
Donnez un nom avec application et une petite description
Normalement vous devriez avoir cette page en face de vous. Orange dispose de plusieurs APIs qui sont souvent accessibles selon le pays. Dans notre cas, c'est l'API SMS qui nous intéresse donc pour l'ajouter il faudra cliquer sur le bouton "Add an API", voir la capture ci-dessous.
Maintenant choisissez la bonne API, dans notre cas ça sera "SMS Guinea Conakry(1.1)", après cliquer sur le bouton "Next" puis accepter les conditions d'utilisation (si vous pouvez lire ce qui est dit )
A cet stade, notre projet est prêt parce que nous avions configuré l'API SMS de la Guinée (Au passage Guinée-Conakry n'existe pas mais ça c'est un autre débat).
Juste une petite précision, LES SMS NE SONT PAS GRATUITS.
Euh revenez ne fuyez pas. Je vous assure que ça coûte pas cher non plus:
- 15 SMS à 1 200 GNF
- 100 SMS à 20 000 GNF
- 500 SMS à 100 000 GNF
- 1 000 SMS à 150 000 GNF
- 5 000 SMS à 750 000 GNF
- 10 000 SMS à 1 500 000 GNF
Je vous conseille d'acheter le pack de 15 ou 100 SMS pour faire vos tests, ça sera largement suffisant.
Vous remarquerez qu'il y'a une nouvelle section qui est apparue cliquer sur le bouton "Configure" pour passer à l'achat. (Voir image ci-dessous)
Choisissez le pack qui vous convient, moi j'ai choisi celui de 100 SMS qui coûte 20 000 GNF, après à gauche sélectionnez le mode de paiement et cliquer sur le bouton "Buy".
Vous apercevrez une zone de saisie dans laquelle vous mettrez votre numéro de téléphone. Cliquer sur le bouton "Ok". Patientez un instant vous allez recevoir un SMS contenant un code de confirmation que vous copierez dans la zone de saisie puis cliquer sur le bouton "Continue". Si tout se passe bien, vous aviez été facturé en fonction du pack que vous aviez choisi donc dans mon cas c'est 20 000 GNF (100 SMS).
Bravo on a finit la première étape
Vous êtes prêt là ?
Pour vous faire gagner en temps, j'ai un projet laravel de base que je clone à chaque fois je commence un nouveau. J'ai la gestion des utilisateurs, la gestion des rôles et permissions et l'intégration d'un template admin qui sont déjà faites, vous pouvez le télécharger ici.
Télécharger les librairies nécessaires
$ composer update
Configurer le fichier .env, remplacez les informations de connexion
APP_NAME=Laravel
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=sms_devscom
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Générer la clé
$ php artisan key:generate
N'oubliez pas de configurer la base de donnée et d'exécuter la commande
$ php artisan migrate --seed
Lancer l'application en tapant:
$ php artisan serve
Sur la page d'authentification les identifiants sont les suivants: admin@gmail.com et le mot de passe: password. Lors de la première connexion on vous demandera de modifier le mot de passe.
Normalement vous devriez avoir cette page devant vos yeux.
Super ! jusqu'ici tout va bien, maintenant notre objectif sera d'avoir deux zones de saisie une pour le numéro de téléphone et une autre pour le message à envoyer.
Pour nous faciliter on va utiliser cette librairie, tout ce qui nous intéresse c'est la classe src/Osms.php.
Créer un dossier Helpers dans le répertoire App. Copiez-y la classe Osms.php en la renommant simplement en Sms.php
Sms.php
<?php
namespace App\Helpers;
class Sms {
const BASE_URL = 'https://api.orange.com';
/**
* Client Identifier. Unique ID provided by the Orange backend server to identify
* your application.
*
* @var string
*/
protected $clientId = '';
/**
* Client Secret. Used to sign/crypt the requests.
*
* @var string
*/
protected $clientSecret = '6Av9unjOuAF0mI7F';
/**
* The Token will be used for all further API calls.
*
* @var string
*/
protected $token = '';
/**
* cURL option for whether to verify the peer's certificate or not.
*
* @var bool
*/
protected $verifyPeerSSL = true;
/**
* Creates a new Osms instance. If the user doesn't know his token or doesn't have a
* token yet, he can leave $token empty and retrieve a token with
* getTokenFromConsumerKey() method later.
*
* @param array $config An associative array that can contain clientId, clientSecret,
* token, and verifyPeerSSL
*
* @return void
*/
public function __construct($config = array())
{
if (array_key_exists('clientId', $config)) {
$this->clientId = $config['clientId'];
}
if (array_key_exists('clientSecret', $config)) {
$this->clientSecret = $config['clientSecret'];
}
if (array_key_exists('token', $config)) {
$this->token = $config['token'];
}
if (array_key_exists('verifyPeerSSL', $config)) {
$this->verifyPeerSSL = $config['verifyPeerSSL'];
} else {
$this->verifyPeerSSL = true;
}
}
/**
* Retrieves a token from Orange server, that will be used for all further API calls.
*
* @return array
*/
public function getTokenFromConsumerKey()
{
$url = self::BASE_URL . '/oauth/v3/token';
$credentials = $this->getClientId() . ':' . $this->getClientSecret();
$headers = array('Authorization: Basic ' . base64_encode($credentials));
$args = array('grant_type' => 'client_credentials');
$response = $this->callApi($headers, $args, $url, 'POST', 200);
if (!empty($response['access_token'])) {
$this->setToken($response['access_token']);
}
return $response;
}
/**
* Sends SMS.
*
* @param string $senderAddress The receiver address in this format:
* "tel:+22500000000"
* @param string $receiverAddress The receiver address in this format:
* "tel:+22500000000"
* @param string $message The content of the SMS, must not exceed
* 160 characters
* @param string $senderName The sender name
*
* @return array
*/
public function sendSms(
$senderAddress,
$receiverAddress,
$message,
$senderName
) {
$url = self::BASE_URL . '/smsmessaging/v1/outbound/' . urlencode($senderAddress)
. '/requests';
$headers = array(
'Authorization: Bearer ' . $this->getToken(),
'Content-Type: application/json'
);
if (!empty($senderName)) {
$args = array(
'outboundSMSMessageRequest' => array(
'address' => $receiverAddress,
'senderAddress' => $senderAddress,
'senderName' => urlencode($senderName),
'outboundSMSTextMessage' => array(
'message' => $message
)
)
);
} else {
$args = array(
'outboundSMSMessageRequest' => array(
'address' => $receiverAddress,
'senderAddress' => $senderAddress,
'outboundSMSTextMessage' => array(
'message' => $message
)
)
);
}
return $this->callApi($headers, $args, $url, 'POST', 201, true);
}
/**
* Lists SMS usage statistics per application.
*
* @param array $args An associative array to filter the results, containing
* country (the international 3 digits country code) and/or
* appid (you can retrieve your application ID from your
* dashboard application)
*
* @return array
*/
public function getAdminStats($args = null)
{
$url = self::BASE_URL . '/sms/admin/v1/statistics';
$headers = array('Authorization: Bearer ' . $this->getToken());
return $this->callApi($headers, $args, $url, 'GET', 200);
}
/**
* Displays how many SMS you can still send.
*
* @param string $country The country to filter on (the international 3 digits
* country)
*
* @return array
*/
public function getAdminContracts($country = '')
{
$url = self::BASE_URL . '/sms/admin/v1/contracts';
$headers = array('Authorization: Bearer ' . $this->getToken());
$args = null;
if (!empty($country)) {
$args = array('country' => $country);
}
return $this->callApi($headers, $args, $url, 'GET', 200);
}
/**
* Lists your purchase history.
*
* @param string $country The country to filter on (the international 3 digits
* country)
*
* @return array
*/
public function getAdminPurchasedBundles($country = '')
{
$url = self::BASE_URL . '/sms/admin/v1/purchaseorders';
$headers = array('Authorization: Bearer ' . $this->getToken());
$args = null;
if (!empty($country)) {
$args = array('country' => $country);
}
return $this->callApi($headers, $args, $url, 'GET', 200);
}
/**
* Calls API Endpoints.
*
* @param array $headers An array of HTTP header fields to set
* @param array $args The data to send
* @param string $url The URL to fetch
* @param string $method Whether to do a HTTP POST or a HTTP GET
* @param int $successCode The HTTP code that will be returned on
* success
* @param bool $jsonEncodeArgs Whether or not to json_encode $args
*
* @return array Contains the results returned by the endpoint or an error
* message
*/
public function callApi(
$headers,
$args,
$url,
$method,
$successCode,
$jsonEncodeArgs = false
) {
$ch = curl_init();
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
if (!empty($args)) {
if ($jsonEncodeArgs === true) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($args));
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($args));
}
}
} else /* $method === 'GET' */ {
if (!empty($args)) {
curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($args));
} else {
curl_setopt($ch, CURLOPT_URL, $url);
}
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($this->getVerifyPeerSSL() === false) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
// Make sure we can access the response when we execute the call
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
if ($data === false) {
return array('error' => 'API call failed with cURL error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$response = json_decode($data, true);
$jsonErrorCode = json_last_error();
if ($jsonErrorCode !== JSON_ERROR_NONE) {
return array(
'error' => 'API response not well-formed (json error code: '
. $jsonErrorCode . ')'
);
}
if ($httpCode !== $successCode) {
$errorMessage = '';
if (!empty($response['error_description'])) {
$errorMessage = $response['error_description'];
} elseif (!empty($response['error'])) {
$errorMessage = $response['error'];
} elseif (!empty($response['description'])) {
$errorMessage = $response['description'];
} elseif (!empty($response['message'])) {
$errorMessage = $response['message'];
} elseif (!empty($response['requestError']['serviceException'])) {
$errorMessage = $response['requestError']['serviceException']['text']
. ' ' . $response['requestError']['serviceException']['variables'];
} elseif (!empty($response['requestError']['policyException'])) {
$errorMessage = $response['requestError']['policyException']['text']
. ' ' . $response['requestError']['policyException']['variables'];
}
return array('error' => $errorMessage);
}
return $response;
}
/**
* Gets the Cliend ID.
*
* @return string
*/
public function getClientId()
{
return $this->clientId;
}
/**
* Sets the Client ID.
*
* @param string $clientId the Client ID
*/
public function setClientId($clientId)
{
$this->clientId = $clientId;
}
/**
* Gets the Client Secret.
*
* @return string
*/
public function getClientSecret()
{
return $this->clientSecret;
}
/**
* Sets the Client Secret.
*
* @param string $clientSecret the Client Secret
*/
public function setClientSecret($clientSecret)
{
$this->clientSecret = $clientSecret;
}
/**
* Gets the (local/current) Token.
*
* @return string
*/
public function getToken()
{
return $this->token;
}
/**
* Sets the Token value.
*
* @param string $token the token
*/
public function setToken($token)
{
$this->token = $token;
}
/**
* Gets the CURLOPT_SSL_VERIFYPEER value.
*
* @return bool
*/
public function getVerifyPeerSSL()
{
return $this->verifyPeerSSL;
}
/**
* Sets the CURLOPT_SSL_VERIFYPEER value.
*
* @param bool $verifyPeerSSL FALSE to stop cURL from verifying the
* peer's certificate. TRUE otherwise.
*/
public function setVerifyPeerSSL($verifyPeerSSL)
{
$this->verifyPeerSSL = $verifyPeerSSL;
}
}
Pour envoyer un SMS faudra instancier cette classe en lui donnant les bonnes informations. on va créer une méthode sendSMS
public function sendSMS($phone, $message)
{
$config = array(
'clientId' => config('app.clientId'),
'clientSecret' => config('app.clientSecret'),
);
$osms = new Sms($config);
$data = $osms->getTokenFromConsumerKey();
$token = array(
'token' => $data['access_token']
);
$response = $osms->sendSms(
// sender
'tel:+224620000000',
// receiver
'tel:+224' . $phone,
// message
$message,
'Devscom'
);
}
Cette méthode prend deux paramètres, le premier c'est le numéro de téléphone auquel on envoie le SMS et le deuxième le message qu'on veut lui envoyer.
Pour avoir le clientId et le clientSecret, cliquer sur le bouton "Show" comme indiquer sur la capture suivante. On demandera de retaper votre mot de passe avant que ces informations ne soient visibles.
Ouvrer le fichier config/app.php et remplacer le clientId et le clientSecret par les bonnes informations
'clientId' => '',
'clientSecret' => '',
routes/web.php
/********* ENVOIE SMS ****************/
Route::get('message', 'MessageController@create')->name('message.create');
Route::post('message', 'MessageController@send')->name('message.store');
resources/views/backend/messages/create.blade.php
@extends('backend.base')
@section('content')
<div class="col-sm-8 col-lg-offset-2">
<div class="panel">
<div class="panel-heading">
<h3 class="panel-title">{{ $title }}</h3>
</div>
<!--Horizontal Form-->
<!--===================================================-->
{!! Form::open(['method' => 'POST', 'class' => 'panel-body form-horizontal form-padding', 'url' => route('message.store')]) !!}
<div class="panel-body">
<div class="panel-body">
@include('backend.messages._form')
</div>
<div class="panel-footer text-right">
<button class="btn btn-success" type="submit">Envoyer</button>
</div>
</div>
{!! Form::close() !!}
<!--===================================================-->
<!--End Horizontal Form-->
</div>
</div>
@endsection
resources/views/backend/messages/_form.blade.php
<div class="form-group">
<label class="col-sm-3 control-label" for="email"><b>Numéro de téléphone</b></label>
<div class="col-sm-9">
<input type="text" placeholder="Numéro de téléphone sans le +224" id="phone" name="phone" class="form-control">
{!! $errors->first('phone', '
<small class="help-block ">:message</small>
') !!}
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="email"><b>Message</b></label>
<div class="col-sm-9">
<textarea name="message" id="" cols="63" rows="10"></textarea>
{!! $errors->first('message', '
<small class="help-block ">:message</small>
') !!}
</div>
</div>
app/http/controllers/MessageController.php
<?php
namespace App\Http\Controllers;
use App\Helpers\Sms;
use Illuminate\Http\Request;
class MessageController extends Controller
{
public function create()
{
$title = 'Nouveau message';
return view('backend.messages.create', compact(['title']));
}
public function send(Request $request)
{
$this->validate($request, [
'phone' => 'required|numeric',
'message' => 'required|max:255',
]);
$this->sendSMS($request['phone'], $request['message']);
return redirect(route('message.create'));
}
public function sendSMS($phone, $message)
{
$config = array(
'clientId' => config('app.clientId'),
'clientSecret' => config('app.clientSecret'),
);
$osms = new Sms($config);
$data = $osms->getTokenFromConsumerKey();
$token = array(
'token' => $data['access_token']
);
$response = $osms->sendSms(
// sender
'tel:+224620000000',
// receiver
'tel:+224' . $phone,
// message
$message,
'Devscom'
);
}
}
Je sais pertinemment qu'on a dû laisser certains mais si vous êtes toujours là bravo à vous. Maintenant passons à l'heure de vérité en testant si tout marche bien.
Et bim !
Et voilà notre objectif est atteint. Félicitations ! Le code source est téléchargeable ici.
Participe à la discussion