Envoyer des sms depuis le google app engine

Description

Cet article expose une (mini) web application dont le principe consiste à récupérer un numéro de mobile et lui envoyé un lien vers un site mobile sous forme d un SMS si celui-ci est identifié comme un numéro SFR. En parallèle, on conserve l ensemble des numéros saisis dans la base de données de Google.

Vous pouvez directement tester cette webapp en ligne sur http://appliscopepromo.appspot.com

Il s agit d un prototype qui peut surement être largement amélioré et dont le but principal est uniquement d illustrer l usage des API SFR en mode REST depuis le cloud.

Techniquement, le serveur est héberge dans le Google App Engine (GAE). L interface, reduite au minimum, est realisee avec le Google Web Toolkit (GWT) sur la base de l exemple standard proposé à la création du projet sous Eclipse. On s appuie sur la base de données du GAE (Big Table) à travers le Framework Objectify (très simple à mettre en œuvre) pour stocker les numéros de mobiles.

L appartenance du numéro de mobile à SFR et l envoi du SMS depuis le serveur sont assurés par SFR API. Une classe réduite au minimum permet d encapsuler les méthodes REST construites via l API Test Tool. L instanciation de cette classe nécessite de disposer d un Token valide, obtenu par une simple inscription à SFR API.

L algorithme est simple. A la suite du déclenchement du bouton « Envoyer », on invoque la methode sendNumberToServer(). Cette méthode côté client verifie le format du numéro puis instancie la classe GreetingServiceImpl cote serveur contenant l essentiel du traitement.

Depuis cette classe :
- on enregistre le numéro saisie la base de donnees Google
- on ouvre le service SFR API avec le token (qui reste caché puisque sur le serveur)
- on identifie l operateur du numero (methode isSFR : https://api.sfr.fr/api/sis)
- on envoi le SMS contenant le message principal si l operateur est bien SFR (méthode SendSMS : https://api.sfr.fr/api/sms)

Vous pouvez trouver ci-dessous quelques éléments du code (les deux principales classes) ainsi que le projet réalisé sous Eclipse en attache (avec les librairies en moins pour limiter la taille de l'archive)

Source / Exemple :


package com.promo.appliscope.client;

import com.promo.appliscope.shared.FieldVerifier;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;

/**

  • Entry point classes define <code>onModuleLoad()
.
  • /

  • public class PromoAppliScope implements EntryPoint {
    /**
    • Create a remote service proxy to talk to the server-side Greeting service.
    • /

    private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);

    /**
    • This is the entry point method.
    • /

    public void onModuleLoad() {
    final Button sendButton = new Button("Envoyer");
    final TextBox nameField = new TextBox();
    final Label errorLabel = new Label();
    final Timer timer=new Timer() {
    public void run() {
    //Le timer permet de laisser le temps de lire le message
    //avant de l'effacer de l'interface
    errorLabel.setText("");
    }
    };

    // We can add style names to widgets
    sendButton.addStyleName("sendButton");

    // Add the nameField and sendButton to the RootPanel
    // Use RootPanel.get() to get the entire body element
    RootPanel.get("nameFieldContainer").add(nameField);
    RootPanel.get("sendButtonContainer").add(sendButton);
    RootPanel.get("errorLabelContainer").add(errorLabel);

    // Focus the cursor on the name field when the app loads
    nameField.setText("06");
    nameField.setFocus(true);

    // Create the popup dialog box
    final Label textToServerLabel = new Label();

    // Create a handler for the sendButton and nameField
    class MyHandler implements ClickHandler, KeyUpHandler {
    /**
    • Fired when the user clicks on the sendButton.
    • /

    public void onClick(ClickEvent event) {
    sendNumberToServer();
    }

    /**
    • Fired when the user types in the nameField.
    • /

    public void onKeyUp(KeyUpEvent event) {
    if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
    sendNumberToServer();
    }
    }

    /**
    • Send the number from the nameField to the server and wait for a response.
    • /

    private void sendNumberToServer() {
    // First, we validate the input.
    errorLabel.setText("Envoi en cours ...");

    String textToServer = nameField.getText();
    if (!FieldVerifier.isMobileNumber(textToServer)) {
    errorLabel.setText("Numero non valide");
    return;
    }

    sendButton.setEnabled(false);
    textToServerLabel.setText(textToServer);

    greetingService.greetServer(textToServer,
    new AsyncCallback<String>() {
    public void onFailure(Throwable caught) {
    // Show the RPC error message to the user
    errorLabel.setText(caught.getMessage());
    sendButton.setEnabled(true);
    timer.schedule(4000);
    }

    //result contient les informations sur le numéro de mobile
    public void onSuccess(String result) {
    errorLabel.setText(result);
    sendButton.setEnabled(true);
    nameField.setText("06");
    nameField.setFocus(true);
    timer.schedule(4000);
    }
    });
    }
    }

    // Add a handler to send the name to the server
    MyHandler handler = new MyHandler();
    sendButton.addClickHandler(handler);
    nameField.addKeyUpHandler(handler);
    }
    }

    //Classe principales contenant l'essentiel des traitements sur le serveur

    package com.promo.appliscope.server;

    import com.promo.appliscope.client.GreetingService;
    import com.google.gwt.user.server.rpc.RemoteServiceServlet;
    import com.googlecode.objectify.Objectify;
    import com.googlecode.objectify.ObjectifyService;

    /**
    • The server side implementation of the RPC service.
    • /

    @SuppressWarnings("serial")
    public class GreetingServiceImpl extends RemoteServiceServlet implements
    GreetingService {

    public String greetServer(String input) throws IllegalArgumentException {
    //Ouvre une instance vers la base de données Google
    try {
    ObjectifyService.register(mobilenumber.class);
    } catch(Exception e) {
    e.printStackTrace();
    };


    //Stocke systématiquement le numéro dans la base de donnée de GAE
    Objectify ofy = ObjectifyService.begin();
    ofy.put(new mobilenumber(input));

    //Crée une instance d'SFR API avec un token obtenu sur api.sfr.fr
    //Ici le token à été supprimé.
    SFRAPI sfrapi=new SFRAPI("<mettre ici votre propre token>");

    // Verify que le numero est un numéro SFR
    if (!sfrapi.isSFR(input)) {
    // If the input is not valid, throw an IllegalArgumentException back to
    // the client.
    throw new IllegalArgumentException("Ce numéro n'est pas un numéro SFR");
    }


    // Escape data from the client to avoid cross-site script vulnerabilities.
    input = escapeHtml(input);

    //Envoi du SMS à l'aide de l'API SMS d'SFR (http://api.sfr.fr/)
    if(sfrapi.SendSMS(input,"Retrouver les meilleures applis sur SFR AppliScope en cliquant sur http://appliscope.m.sfr.fr/"))
    return("Le lien vers l'appliscope a été envoyé sur votre mobile");
    else
    return("Problème technique. Veuillez recommencer");
    }

    /**
    • Escape an html string. Escaping data received from the client helps to
    • prevent cross-site script vulnerabilities.
    • @param html the html string to escape
    • @return the escaped string
    • /

    private String escapeHtml(String html) {
    if (html == null) {
    return null;
    }
    return html.replaceAll("&", "&").replaceAll("<", "<")
    .replaceAll(">", ">");
    }
    }
    </code>

    Conclusion :


    Quelques références / liens utiles

    Hervé Hoareau
    Resp Développement SFR API

    Références :
    - Consommer des services REST dans Google App Engine http://code.google.com/intl/fr/appengine/docs/java/urlfetch/overview.html

    - Framework Objectify : http://code.google.com/p/objectify-appengine/

    - SFR API (envoi de SMS et détection de l opérateur) : http://api.sfr.fr

    Codes Sources

    A voir également

    Vous n'êtes pas encore membre ?

    inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

    Les membres obtiennent plus de réponses que les utilisateurs anonymes.

    Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

    Le fait d'être membre vous permet d'avoir des options supplémentaires.