LoginSignup
0
1

More than 5 years have passed since last update.

Monaca + Movable Type で記事投稿スマホアプリを作ってみる

Last updated at Posted at 2017-07-31

前回の続きです。
今回は、Movable Type のData APIから認証機能を呼び出し

  • Monaca で作成したスマホアプリから Movable Type へサインインする
  • スマホアプリから投稿する

までを作ってみます。

UIには、前回同様 Onsen UIを使います。

新しいプロジェクトの作成

前回の「Monaca プロジェクト作成」と同様に、記事投稿アプリ用のプロジェクトを作成します。

monaca_post_1.png

投稿用インデックスファイルの作成

プロジェクトの作成が終わったら、inde.htmlを以下のファイルに差し替えます。
こちらの記事で作成した投稿用のスクリプトを、一部 Monaca 用にアレンジして書き換えました。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>autheticationを使った投稿サンプル</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script src="components/loader.js"></script>
  <script src="lib/onsenui/js/onsenui.min.js"></script>

  <link rel="stylesheet" href="components/loader.css">
  <link rel="stylesheet" href="lib/onsenui/css/onsenui.css">
  <link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css">
  <link rel="stylesheet" href="css/style.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>

<body>

<ons-page>
  <ons-toolbar>
    <div class="center">MT投稿アプリ</div>
  </ons-toolbar>

  <div style="text-align: center; margin-top: 30px;" id="content">
    <p>
      <ons-input id="username" modifier="underbar" placeholder="Username" float></ons-input>
    </p>
    <p>
      <ons-input id="password" modifier="underbar" type="password" placeholder="Password" float></ons-input>
    </p>
    <p style="margin-top: 30px;">
      <ons-button id="signin">サインイン</ons-button>
    </p>
  </div>
</ons-page>

<script> 

$(function() {
  const clientId = 'smartphone_post_sample';
  const currentSession = 'mt_session_' + clientId;
  const currentToken = 'mt_token_' + clientId;
  const nowTime = Math.floor(new Date().getTime() / 1000);

  const apiUrl = 'http://your-mt/mt-data-api.cgi';
      const siteId = 'ブログIDの数字';


  if (sessionStorage.getItem(currentSession)) {
    haveSignedIn();
  }

  $('#signin').on('click', function() {
    signIn();
  });

  $('#submit').on('click', function() {
    var promise = Promise.resolve(checkToken());
    promise.then(function() {
      PostEntry();
    });
  });

  $('#signout').on('click', function() {
    revokeSession();
  });

  function haveSignedIn() {
    const displayData = `
        <h3>投稿する</h3>
        <form class="col-sm-8">
        <div class="form-group">
          <input id="title" name="title" placeholder="タイトル" type="text"  class="form-control">
        </div>
        <div class="form-group">
          <textarea id="body" maxlength="140" placeholder="本文" rows="7"  class="form-control"></textarea>
        </div>
        <div class="form-group">
          <ons-button id="submit" name="submit" type="button">投稿する</ons-button>
        </div>
        <div class="form-group">
          <ons-button id="signout" name="signout" type="button">サインアウト</ons-button>
        </div>
        </form>
        `
    $("#content").empty();
    $("#content").append(displayData);
  }

  function signIn() {
    const username = $('#username').val();
    const password = $('#password').val();
    $.ajax({
      url: apiUrl + '/v3/authentication',
      type: 'POST',
      dataType: 'json',
      data: {
        'username': username,
        'password': password,
        'clientId': clientId,
      }
    }).done(function(data) {
      sessionStorage.setItem(currentSession, data.sessionId);
      let TokenData = {
        'accessToken': data.accessToken,
        'expiresIn': data.expiresIn,
        'gotTokenTime': nowTime,
      }
      sessionStorage.setItem(currentToken, JSON.stringify(TokenData));
      alert("サインインしました。");
      location.reload();
    }).fail(function(data) {
      alert("サインイン時にエラーが発生しました。再度サインインをお試しください。");
    });
  }

  function PostEntry() {
    const entry = {};
    entry.title = $('#title').val();
    entry.body = $('#body').val();
    $.ajax({
      url: apiUrl + '/v3/sites/' + siteId + '/entries',
      type: 'POST',
      dataType: 'json',
      headers: {
        'X-MT-Authorization': 'MTAuth accessToken=' + JSON.parse(sessionStorage.getItem(currentToken)).accessToken,
      },
      data: {
        'entry': JSON.stringify(entry)
      },
    }).done(function() {
      alert("データを投稿しました。");
    }).fail(function(data) {
      alert("投稿時にエラーが発生しました。");
    });
  }

  function revokeSession() {
    $.ajax({
      url: apiUrl + '/v3/token',
      type: "DELETE",
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'X-MT-Authorization': 'MTAuth accessToken=' + JSON.parse(sessionStorage.getItem(currentToken)).accessToken,
      }
    }).done(function() {
      $.ajax({
        url: apiUrl + "/v3/authentication",
        type: "DELETE",
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'X-MT-Authorization': 'MTAuth sessionId=' + sessionStorage.getItem(currentSession),
        }
      })
    }).done(function() {
      sessionStorage.removeItem(currentSession);
      sessionStorage.removeItem(currentToken);
      alert("サインアウトしました。");
      location.reload();
    }).fail(function(data) {
      alert("サインアウト中にエラーが発生しました。もう一度サインインし直してください。");
      sessionStorage.removeItem(currentSession);
      sessionStorage.removeItem(currentToken);
      location.reload();
    });
  }

  function checkToken() {
    const expiresIn = JSON.parse(sessionStorage.getItem(currentToken)).expiresIn;
    const gotTokenTime = JSON.parse(sessionStorage.getItem(currentToken)).gotTokenTime;
    if (nowTime >= expiresIn + gotTokenTime) {
      refreshToken();
    }
  }

  function refreshToken() {
    $.ajax({
      url: apiUrl + '/v3/token',
      type: "DELETE",
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'X-MT-Authorization': 'MTAuth accessToken=' + JSON.parse(sessionStorage.getItem(currentToken)).accessToken,
      }
    }).done(function() {
      $.ajax({
        url: apiUrl + '/v3/token',
        type: "POST",
        dataType: "json",
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'X-MT-Authorization': 'MTAuth sessionId=' + sessionStorage.getItem(currentSession),
        }
      }).done(function(data) {
        let TokenData = {
          'accessToken': data.accessToken,
          'expiresIn': data.expiresIn,
          'gotTokenTime': nowTime,
        }
        sessionStorage.setItem(currentToken, JSON.stringify(TokenData));
      }).fail(function(data) {
        alert("アクセストークンのリフレッシュ中にエラーが発生しました。サインし直してください。");
        sessionStorage.removeItem(currentSession);
        sessionStorage.removeItem(currentToken);
        location.reload();

      });
    });
  }
});


</script>
</body>
</html>

このアプリでは、以下の機能を実装しています。

  • サインイン画面を表示
  • ユーザー名、パスワードを入力後、「サインイン」ボタンを押すと、Movable Type のData APIを利用した認証を行う
  • ユーザー情報が正しい場合、サインイン画面を消去して記事投稿用のフォームを表示する。
  • 今回は「タイトル」と「本文」を入力できるようにする。
  • データ入力後「投稿する」ボタンを押すと、Movable Type にデータを投稿する。
  • 「サインアウト」ボタンを押すと、サインアウト処理を行い、初期画面に戻る

詳細は元記事を参照ください。

Onsen UI を使うために、header内でOnsen UI の各ライブラリを読み込んでいます。
サインイン用の初期画面、および投稿用画面のボタンを、Onsen UI のタグに書き換え、スマホアプリっぽい見栄えに変えてみました。

保存したら、Monaca デバッガーで確認します。

monaca_post_2.png

monaca_post_3.png

免責

今回のサンプルは、十分なテストを行っていないため、実際に利用する際は、作成したコードのテスト・チェックを十分に行った上で実装ください。

※何かお気づきの点などありましたら、どうぞお知らせください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1