Omise.js で支払額を動的に変更する方法



![image.png](https://qiita-image-store.s3.amazonaws.com/0/138674/5243e14d-b8ce-1b9e-7961-7db74d458a58.png)

## はじめに

カード決済をする際、カード番号を取り扱うため、一般的に以下のようなプロトコルが使われている

![image.png](https://qiita-image-store.s3.amazonaws.com/0/138674/ad3f95c4-6fb9-5849-2166-c4d4aa3940fe.png)

[前回](https://qiita.com/vascoosx/items/80e76861141d80765f0c)サーバーサイドでOmiseのAPIを使う話をした時、クレジットカード情報を受け渡すときはクライアントサイドから行ったほうが良いという話をした。今回はクライアントサイドのトークン送受信の部分を実装してみた。

クライアントサイドを実装するにはOmise.jsを使うかOmise のjavascriptクライアントを使うかの2通りの方法がある。javascript クライアントを使う場合はクレジットカードを入力するフォームを一から作らないといけないが、自由にカスタマイズできる。Omise.jsを使う場合はカスタマイズがやや難しいこともあるが、あまりこだわらなければ簡単に使うことができる。今回はOmise.jsをVue.jsで実装してみたが、**値段の変更**をダイナミックに行えるようにした。

## コード

まず omise.js を使えるように omise.js の cdn を `script` タグで囲みます。順番としては omise.js を使っている入ってる `main.js` の前に書く。

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vuex shopping cart example</title>
  </head>
  <body>
    <script src="https://cdn.omise.co/omise.js"></script>
    <div id="app"></div>
    <script src="main.js"></script>
  </body>
</html>
```

omise.js は以下のように使う。

```html
<template>
  <div class="cart">
    <h2>Your Cart</h2>
    <p v-show="!products.length"><i>Please add some products to cart.</i></p>
    <ul>
      <li v-for="product in products">
        {{ product.title }} - {{ "¥" + product.price  }} x {{ product.quantity }}
      </li>
    </ul>
    <p>Total: {{ "¥" + total }}</p>

    <p><button :disabled="!products.length" @click.prevent="checkout(total)">Checkout</button></p>

    <form action="https://postman-echo.com/post" id="my-custom-checkout-form" method="POST">
      <input type="hidden" :value="total" name="total">
      <input type="hidden" value="" name="omiseToken">
      <input v-for="product in products" type="hidden" :value="product.quantity" :name="product.id">
    </form>
    <p v-show="checkoutStatus">Checkout {{ checkoutStatus }}.</p>
  </div>
</template>

<script>
import { mapGetters, mapState } from "vuex"

export default {
  computed: {
    ...mapState({
      checkoutStatus: state => state.cart.checkoutStatus
    }),
    ...mapGetters("cart", {
      products: "cartProducts",
      total: "cartTotalPrice"
    })
  },
  methods: {
    checkout(total) {
      OmiseCard.open({
        frameLabel: "Merchant",
        submitLabel: "PAY RIGHT NOW !",
        amount: total
      })
    }
  },

  mounted() {
    OmiseCard.configure({
      publicKey: "pkey_test_???", // 公開鍵。ダッシュボードから取得できます
      image: "https://cdn.omise.co/assets/dashboard/images/omise-logo.png", 
      currency: "JPY",
      onCreateTokenSuccess: token => {
        const form = document.querySelector("#my-custom-checkout-form")
        form.omiseToken.value = token;
        form.submit()
      }
    })
    OmiseCard.attach()
  }
}
</script>
```
   
## 解説
1. トークンを送るフォームの作成。ここではテスト用に `https://postman-echo.com/post` を使っているが本来はマーチャントのサーバーがここに来る

       ```html
           <form action="https://postman-echo.com/post" id="my-custom-checkout-form" method="POST">
             <input type="hidden" :value="total" name="total">
             <input type="hidden" value="" name="omiseToken">
             <input v-for="product in products" type="hidden" :value="product.quantity" :name="product.id">
           </form>
       ```

2. トークンを取得したら呼び出すコールバックの作成。カード情報等が間違っていなければ次に呼び出される。ここでは 1で作成したフォームをサブミットするようにしている。こちらはページが最初にロードされたときにのみ実行される

       ```javascript
         mounted() {
           OmiseCard.configure({
             publicKey: "pkey_test_???", // 公開鍵。ダッシュボードから取得できます
             image: "https://cdn.omise.co/assets/dashboard/images/omise-logo.png", 
             currency: "JPY",
             onCreateTokenSuccess: token => {
               const form = document.querySelector("#my-custom-checkout-form")
               form.omiseToken.value = token;
               form.submit()
             }
           })
           OmiseCard.attach()
         }
       ```
3. omise.jsのカード情報入力するためのフォームを呼び出す関数。こちらは値段 (`amount`) が渡されるパラメータによって動的に変わるようになっている。

      ```javascript
      methods: {
          checkout(total) {
            OmiseCard.open({
              frameLabel: "Merchant",
              submitLabel: "PAY RIGHT NOW !",
              amount: total
            })
          }
      ```


### レポジトリ

https://github.com/vascoosx/omisejs-sample

マーチャントと言えばヴェニスの商人。
![merchant of venice](https://ia800603.us.archive.org/zipview.php?zip=/31/items/olcovers13/olcovers13-L.zip&file=130497-L.jpg)