読者です 読者をやめる 読者になる 読者になる

山田健一のブログ

業務に強いフリーITエンジニア 山田健一のブログです

TwiML生成サービスについて

私はフリーITエンジニアとして、業務分析、業務改善提案を含む設計、製造、受入検査を含む検査、システム運用開始後の運用改善提案など、様々な分野を担当しています。

 

yamadaken1.hatenablog.com

の中で

>===================================================================
>「TwiMLを返すサーバーを用意する必要がある」
>これは、twilio側で対応して欲しいですね。
>通話料金に上乗せするような有料のサービスでも構いません
>(もちろん無料が嬉しいですけど)。
>TwiMLを返すurlにtwilio内部のサービスにアクセスするurlを記述すればよいとなれば、>別途サーバーを用意することなく、クライアントのコードのみでシステムが完成します。
>===================================================================
>この部分、twilio さん、KDDIウェブコミュニケーションズさん、お願いします。

と書きましたが、自分でも作成してみました。プラットフォームは Google Cloud Platform です。

 

Constants.java


package info.yamada_ken1.generate_twiml_no_slim3;

public interface Constants {
    public static final String ILLEGAL_REQUEST = "ILLEGAL_REQUEST";
    
    public static final String XML_START = "<!--?xml version=\"1.0\" encoding=\"UTF-8\"?-->";
    public static final String RESPONSE_START = "<response>";
    public static final String RESPONSE_END = "</response>";
}

GenerateTwiMlServlet.java


package info.yamada_ken1.generate_twiml_no_slim3;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Logger;

import javax.servlet.http.*;
import java.util.ResourceBundle;

@SuppressWarnings("serial")
public class GenerateTwiMlServlet extends HttpServlet {
    private static final Logger logger = Logger.getLogger("Generate_twiml_no_slim3Servlet");
    
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // プロパティ内のgoodPassCode 取得
        String goodPassCode = "";
        try {
            ResourceBundle rb = ResourceBundle.getBundle("generateTwiMlServlet");
            goodPassCode = rb.getString("goodPassCode");
        } catch (Exception e) {
            logger.severe(e.getMessage());
        }
        
        resp.setContentType("text/xml; charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        try{
            String passCode = req.getParameter("pass-code");
            String body = req.getParameter("body");
            logger.info("pass-code = " + passCode + ", body = " + body);
            if (passCode == null || body == null
                    || passCode.length() == 0 || body.length() == 0){
                writer.print(makeResponce(Constants.ILLEGAL_REQUEST));
            } else {
                if (!passCode.equals(goodPassCode)){
                    logger.info("pass-code エラー");
                    writer.print(makeResponce(Constants.ILLEGAL_REQUEST));
                } else {
                    writer.print(makeResponce(body));
                }
            }
        }finally{
            writer.close();
        }
    }

    private String makeResponce(String message) {
        String responce = "";
        responce += Constants.XML_START;
        responce += "\n\r" + Constants.RESPONSE_START;
        responce += "\n\r" + message;
        responce += "\n\r" + Constants.RESPONSE_END;
        return responce;
    }
}

いたずらされても困るので、pass-code で制限をかけています。
generateTwiMlServlet.properties

war\WEB-INF\classes
に配置して


goodPassCode=あなたのパスコード

を記述してください。
※録音された音声再生には対応していません。

このサービスを作っていてハマった点を少し書いておきます。
・twilioはTwiMLを返すurlに POST でアクセスする
Google Cloud Platform を利用する場合、インスタンスが起動していないことを
想定して、スピンアップを考慮する必要がある


このサービスを利用して電話をかける C# のサンプルコードは次のようになります。


private void button1_Click(object sender, EventArgs e)
{
    string AccountSid = "あなたのAccountSid";
    string AuthToken = "あなたのAuthToken";
    string passCode = "あなたのパスコード";
    const string TEL_TO = "宛先電話番号";
    const string TEL_FROM = "あなたのtwilio電話番号";
    const string URL_HOME = "https://あなたのプロジェクト.appspot.com/GenerateTwiMl";
    
    const string URL_MAIN = "?pass-code={0}&body={1}";
    const string VERB_BEGIN = "<say voice="\"woman\"" language="\"ja-JP\"">";
    const string VERB_END = "</say>";
    string verb = VERB_BEGIN + "やまだ けんいち さん、こんにちわ" + VERB_END;
    string verbEncoded = HttpUtility.UrlEncode(verb);

    // AppEngine WarmUp(URL_HOME にアクセスしてインスタンスを起動させる)
    AppEngineWarmUp(URL_HOME);
    
    var twilio = new TwilioRestClient(AccountSid, AuthToken);
    var options = new CallOptions();
    options.Url = URL_HOME + String.Format(URL_MAIN, passCode, verbEncoded);
    options.To = TEL_TO;
    options.From = TEL_FROM;
    var call = twilio.InitiateOutboundCall(options);
}

private void AppEngineWarmUp(string urlHome)
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlHome);
    req.Method = "POST";
    req.ContentLength = 0;

    HttpWebResponse res = (HttpWebResponse)req.GetResponse();            
}

このサービスのソースを希望者に無償で提供します。

お問い合わせ - 山田健一(フリーITエンジニア)

からお問い合わせください。

 

f:id:yamadaken1:20160430090833j:plain