LoginSignup
10
9

More than 1 year has passed since last update.

初音ミクが、残高を教えてくれたり振込の手続きをしてくれる銀行アプリのプロトタイプを作ってみた

Last updated at Posted at 2021-11-06


GMOあおぞらネット銀行のsunabarというサンドボックス環境を使って、初音ミクの銀行アプリのプロトタイプを作ってみました。
なお、sunabarを利用するためにはGMOあおぞらネット銀行の口座が必要です。(口座開設は面倒な書類のやりとりは無く、ネットだけで完結します。

動作環境

OS: Windows10

使用ソフト:Unity
 ・Text Mesh Pro をインストール
  ※Window > Package Manager
 ・JSON Object アセットをインストール
  https://assetstore.unity.com/packages/tools/input-management/json-object-710?locale=ja-JP

必要アカウント
・sunabar(あおぞら銀行のAPI環境)

sunabar について

API開発者ポータルでアカウント作成
https://api.gmo-aozora.com/ganb/developer/api-docs/#/STOP0101

GMOあおぞら銀行の口座開設
https://gmo-aozora.com/

銀行口座を作成すると、
サンドボックス環境であるsunabarポータルへのログインが可能になります。

ログインID,パスワードは、リアル口座画面から確認できます。
「お客さま情報(申込・設定)」タブ  >  「開発者向け」
※パスワードは定期的に変更されています。

sunabarポータルへのログイン
https://portal.sunabar.gmo-aozora.com/

こんな画面です。
Image from Gyazo

自分のサンドボックス口座は、
左側をクリック

スクリーンショット 2021-09-08 18.50.35.png

すでに個人・法人の2つの口座ができてます。
Image from Gyazo

ログインすると
本物のGMOあおぞら銀行のインターネットバンキングと同じUIです。
開発中に本物かsunabarか混乱したことあるほど。
なお、この画像では残高1万円ですが、デフォルトでは残高はゼロです。
Image from Gyazo

では、どうやって入金するかというと、先ほどの画面の右側から入金できます。
仮想的なセブン銀行のATMという設定です。
Image from Gyazo

Unity

Live2DのキャラをUnity へ

まずは、Unityで "2D" のプロジェクトを新規作成し、
2次元のイラストを自由に動かすことができるLive2DのSDKである「Cubism SDK for Unity」をプロジェクトにインポートします。
https://www.live2d.com/download/cubism-sdk/download-unity/

こんなエラーでたけど

ArgumentNullException: Value cannot be null.
Parameter name: shader

ほっといても、よさげ



Live2Dのウェブサイトのサンプルデータを見に行きます。
https://www.live2d.com/download/sample-data/

こんなに種類が豊富です。
Image from Gyazo



今回は初音ミクを選択

ダウンロードした初音ミクを
Unity の Project のどっかにフォルダをそのままドラッグします。

Prefab が生成されるので、Sceneに適当においてみます。
Image from Gyazo

アニメーション設定

笑顔、怒り、悲しみという3感情を設定。
通常の返答は「笑顔」、残高少ないのに出金しようとしたら「怒り」、間違った操作をしたら「悲しみ」というふうに設定。

左側のParameters も忘れずに
Image from Gyazo

Idleの設定
Image from Gyazo

表情の設定
smileを例にする
Image from Gyazo

Idle -> Smile
Has Exit Time のチェックをはずす
Conditions
Image from Gyazo

Smile -> Idle
Has Exit Time のチェックをする。
Conditions は何も入れない
Image from Gyazo

UI設定

この画像のように残高照会ボタン、振込ボタン、メッセージ欄をつくる
Image from Gyazo

残高照会ボタン、振込ボタン

クリックしたらスクリプトanswer.cs を呼び出すために
onClick の設定とスクリプトanswer.csをアタッチする
Image from Gyazo

スクリプトanswer.csはこちら

answer.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
using TMPro; //UIテキストにハイパーリンク表示

public class answer : MonoBehaviour
{
    private Animator animator;
    public GameObject TransferInputObject;
    public Button button;

    public GameObject BankCodeInputField;
    public GameObject BranchCodeInputField;
    public GameObject AccountNumberInputField;
    public GameObject NameInputField;
    public GameObject TransferAmountInputField;

    [SerializeField]
    private TextMeshProUGUI LinkText;

    [Serializable]
    public class body
    {
        public string accountId;
        public string transferDesignatedDate;
        public Transfers[] transfers;    
    }

    [Serializable]
    public class Transfers
    {
        public string transferAmount;
        public string beneficiaryBankCode;
        public string beneficiaryBranchCode;
        public string accountTypeCode;
        public string accountNumber;
        public string beneficiaryName;
    }

    public void OnClick()
    {
        animator = GameObject.Find("miku").GetComponent<Animator>();
        string order = this.gameObject.name;

        //残高照会ボタンが押された場合
        if (order == "BalanceButton")
        {         
            string url = "https://api.sunabar.gmo-aozora.com/personal/v1/accounts/balances";

            StartCoroutine(get(url, order));
        }

        //振込ボタンが押された場合
        else if (order == "TransferButton")
        {         
            TransferInputObject.SetActive(true);
        }

        //振込OKボタンが押された場合
        else if (order == "TransferOkButton") {
            string transferAmount = TransferAmountInputField.GetComponent<Text>().text;
            string bankCode = BankCodeInputField.GetComponent<Text>().text;
            string branchCode = BranchCodeInputField.GetComponent<Text>().text;
            string accountNumber = AccountNumberInputField.GetComponent<Text>().text;
            string name = NameInputField.GetComponent<Text>().text;

            var url = "https://api.sunabar.gmo-aozora.com/personal/v1/transfer/request";

            string date = DateTime.Now.ToString("yyyy-MM-dd");

            string itemJson = "{ \"accountId\":\"301010003162\", \"transferDesignatedDate\":\"" + date + "\", " +
                "\"transfers\":[{ \"transferAmount\" :\""+ transferAmount + "\", \"beneficiaryBankCode\": \""+ bankCode + "\" , \"beneficiaryBranchCode\": \"" + branchCode + "\", " +
                "\"accountTypeCode\": \"1\", \"accountNumber\": \""+ accountNumber + "\", \"beneficiaryName\": \"" + name + "\" }] }";

            body item = JsonUtility.FromJson<body>(itemJson);

            string serialisedItemJson = JsonUtility.ToJson(item);
            Debug.Log("serialisedItemJson " + serialisedItemJson);

            StartCoroutine(post(url, serialisedItemJson));
        }
    }

    private IEnumerator get(string url, string order)
    {
        UnityWebRequest request = UnityWebRequest.Get(url);
        request.SetRequestHeader("x-access-token", "GMOあおぞらネット銀行のトークン");
        yield return request.SendWebRequest();

        // 通信エラーチェック
        if (request.isNetworkError)
        {       
            Debug.Log(request.error);
        }
        else
        {
            Debug.Log(request.responseCode);
            if (request.responseCode == 200)
            {
                // UTF8文字列として取得する
                string text = request.downloadHandler.text;
                Debug.Log(text);
                JSONObject json = new JSONObject(text);

                if (order == "BalanceButton")
                {    
                    JSONObject balances = json.GetField("balances");                    
                    string balance = balances[0].GetField("balance").str;
                    int balanceInt = int.Parse(balance);

                    if (balanceInt < 10000)
                    {
                        animator.SetBool("angry", true);
                        string mes = "今の残高は" + balanceInt.ToString("N0") + "円しかないよー\n無駄使いしたらダメだよ";
                        GameObject MesObj = GameObject.Find("MessageText");
                        MesObj.GetComponent<Text>().text = mes;

                        //アニメーションが終わる時間にもとにもどす
                        yield return new WaitForSeconds(0.8f);
                        animator.SetBool("angry", false);
                    }
                    else
                    {
                        animator.SetBool("smile", true);
                        string mes = "今の残高は" + balanceInt.ToString("N0") + "円だよー";
                        GameObject MesObj = GameObject.Find("MessageText");
                        MesObj.GetComponent<Text>().text = mes;

                        //アニメーションが終わる時間にもとにもどす
                        yield return new WaitForSeconds(0.8f);
                        animator.SetBool("smile", false);
                    }
                }
            }
        }
    }

    private IEnumerator post(string url,string body)
    {
        var request = new UnityWebRequest(url, "POST");
        byte[] postData = System.Text.Encoding.UTF8.GetBytes(body);

        request.uploadHandler = new UploadHandlerRaw(postData);
        request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");
        request.SetRequestHeader("x-access-token", "GMOあおぞらネット銀行のトークン");

        yield return request.SendWebRequest();

        // 通信エラーチェック
        if (request.isNetworkError)
        {
            Debug.Log(request.error);
            animator.SetBool("sad", true);
            yield return new WaitForSeconds(0.8f);
            animator.SetBool("sad", false);
        }
        else
        {           
            Debug.Log(request.responseCode);
            if (request.responseCode == 200 || request.responseCode == 201)
                           
                TransferInputObject.SetActive(false);
                animator.SetBool("smile", true);
                GameObject MesObj = GameObject.Find("MessageText");
                MesObj.GetComponent<Text>().text = "受け付けました。\nあとはこのリンク先から振込承認してね";
                GameObject LinkObj = GameObject.Find("LinkText_TMP");
                string LinkURL = "https://bank.sunabar.gmo-aozora.com/bank/notices/important";
                string mes = "<link=\"" + LinkURL + "\">" + LinkURL + "</link>";
                LinkText.text = mes;
                yield return new WaitForSeconds(3.0f);
                animator.SetBool("smile", false);
            }
            else
            {
                animator.SetBool("angry", true);
                GameObject MesObj = GameObject.Find("MessageText");
                MesObj.GetComponent<Text>().text = request.responseCode+ "エラーだよ!!\nどこかが間違ってるよ。";

                yield return new WaitForSeconds(0.8f);
                animator.SetBool("angry", false);
                yield return new WaitForSeconds(3.0f);
                MesObj.GetComponent<Text>().text = "";
            }
        }
    }
}



これで残高照会ボタンで残高を教えてくれる。
Image from Gyazo

振込ボタンが押されたら表示する振込情報のUIを作っておく

Image from Gyazo

これは通常は非表示にしておく
Image from Gyazo

Message 欄

Image from Gyazo

振込を受付後に 振込承認の画面に誘導するため、ハイパーリンクを表示する必要がある。
冒頭の準備でTextMesh Pro をインストールしたのはこのため
Image from Gyazo

スクリプト HyperlinkUI.cs をアタッチする
Image from Gyazo

このサイトのスクリプトを拝借した
https://baba-s.hatenablog.com/entry/2019/09/03/075000

HyperlinkUI.cs
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

[RequireComponent(typeof(TextMeshProUGUI))]
public class HyperlinkUI : MonoBehaviour, IPointerClickHandler
{
    public void OnPointerClick(PointerEventData e)
    {
        var text = GetComponent<TextMeshProUGUI>();
        var pos = Input.mousePosition;
        var canvas = text.canvas;
        var camera = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
        var index = TMP_TextUtilities.FindIntersectingLink(text, pos, camera);

        if (index == -1) return;

        var linkInfo = text.textInfo.linkInfo[index];
        var url = linkInfo.GetLinkID();

        Application.OpenURL(url);
    }
}




以上、自分好みの銀行アプリを作ることは技術的には可能です。



参考サイト

10
9
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
10
9