[Javascript] クライアントからサーバーサイドにトークン情報を送信 ※メモです

#はじめに
コードの意味を個人的に解釈したメモです。
誤りがありましたら、ご指摘いただけますと幸いです。

---

```app/javascript/card.js
const pay = () => {
  const form = document.getElementById("charge-form");
  form.addEventListener("submit", (e) => {
    e.preventDefault();
    console.log("フォーム送信時にイベント発火")
  })
}

window.addEventListener("load", pay);
```

window.addEventListener("load", pay);
ブラウザをリロードすると"pay"という関数が動く

const pay = (　) =>
(　) =>はアロー関数のfunction( )の省略形

const form = document.getElementById("charge-form");
getElementByIdで("charge-form")というHTMLタグ内で指定したidにマッチするドキュメント要素を取得する。

addEventListener("submit", (e)
addEventListenerは指定の処理を発火させるメソッド
`対象要素.addEventListener( 種類, 関数, false )`
※今回だと"submit"を(e)という**変数**に代入している


e.preventDefault();は、submitイベントの発生元であるフォームが持つデフォルトの動作をキャンセルするメソッド
e(submit)の動作をストップしている

console.log("フォーム送信時にイベント発火")
form.addEventListener("submit", (e) =>の出力結果

----


```app/javascript/card.js
const pay = () => {
  Payjp.setPublicKey("pk_test_******************"); // PAY.JPテスト公開鍵
  const form = document.getElementById("charge-form");
  form.addEventListener("submit", (e) => {
    e.preventDefault();

    const formResult = document.getElementById("charge-form");
    const formData = new FormData(formResult);

    const card = {
      number: formData.get("order[number]"),
      cvc: formData.get("order[cvc]"),
      exp_month: formData.get("order[exp_month]"),
      exp_year: `20${formData.get("order[exp_year]")}`,
    };

Payjp.createToken(card, (status, response) => {
      if (status == 200) {
        const token = response.id;
        const renderDom = document.getElementById("charge-form");
        const tokenObj = `<input value=${token} name='token' type="hidden">`;
        renderDom.insertAdjacentHTML("beforeend", tokenObj);
      }

      document.getElementById("order_number").removeAttribute("name");
      document.getElementById("order_cvc").removeAttribute("name");
      document.getElementById("order_exp_month").removeAttribute("name");
      document.getElementById("order_exp_year").removeAttribute("name");

      document.getElementById("charge-form").submit();
    });
  });
};

window.addEventListener("load", pay);
```

FormDataは、フォームに入力された値を取得できるオブジェクト
new FormData(フォームの要素);のように、オブジェクトを生成し、引数にフォームの要素を渡すことで、そのフォームに入力された値を取得できる

new FormDataでからの箱を用意し、その中に引数・formResult(クライアントが入力した情報)をいれる


number, cvc, exp_month, exp_year 
この４つは決まった書き方のものなので、変更はできない

定数formDataにはクライアントが入力したデータが入っているので、
そこからgetで値を取得
どんな値か？
検証ツールでHTMLの中身を確認し、その中のname属性を取得


exp_year：　`20${ ~  の
20$のついては、クレカの有効期限〇月　〇年の、
○年の方、いつも24とか書きますよね？
あれって正しくは2024年じゃないですか
その頭の20のことです。

**Payjp.createToken(card, callback)**
pay.jsが提供するPayjpオブジェクトとcreateTokenメソッド
これはワンセットで覚えましょう

第一引数のcardは、PAY.JP側に送るカードの情報で、直前のステップで定義したカード情報のオブジェクトが入る

第二引数のcallbackには、PAY.JP側からトークンが送付された後に実行する処理を記述する

Payjp.createToken(card, (status, response) =>
cardは直前のステップで定義したカード情報
status, responseは
status　  = HTTPステータスコード
response = トークン
どちらかを受け取るみたいな書き方です
トークンは許可証みたいなものなので、もし許可が降りなかったら、トークンではなくHTTPステータスコードを受け取って何がダメだったかとかを確認するのでしょう(おそらく)

if (status == 200)は、
HTTPステータスコードが200だったら~

const token = response.id;
tokenにトークンを代入

const renderDom = document.getElementById("charge-form");
DOMはHTMLのAPIのこと(オブジェクトっていうイメージでいいと思う)
特徴は３つ
・ツリー構造と呼ばれる階層構造を持つ
・それぞれノードで説明される
・WEBページとJSなどのプログラミング言語をつなぐ

DOM = document
documentの:id charge-form を持った要素を取得

 input value=${token} name='token' type="idden";
HTML の input 要素
ユーザーから受け取ったデータを、サーバーサイドのフォームに挿入するために使用する
value=${token} はトークン
name='token' は変数名みたいにしているだけ
type="idden はブラウザ上で非表示にしている


renderDom.insertAdjacentHTML("beforeend", tokenObj);
**element.insertAdjacentHTML(position, text);**は、
要素をHTMLに挿入するメソッド
positionには挿入位置を、textには挿入することが可能な文字列を引数として指定


document.getElementById("order_number").removeAttribute("name");
**removeAttribute**は、
要素ノードから指定された属性名の属性を除去するメソッド
"order_number"はどこから来たか？
結論：HTMLドキュメントの中のname属性
検証ツールのElementsのHTMLドキュメントです

document.getElementById("charge-form").submit();
フォームの情報をサーバーサイドに送信