概要
- Nuxt.jsベースでJamstackなECサイトのサンプル実装しているときに、PAY.JPの初期化でエラーが出ることがあったのでメモ
- PAY.JPを実装するにあたり、payjp(2.0.5)のnode moduleを利用
- 画面側では
payjp
のCardElement
を生成し、トークンを作成して決済用のAPI呼び出す流れで実装
エラーとなる実装
- PAY.JPを利用する画面の
mounted
でpayjp
のインスタンス生成していた
<template>
<div id="payjp-form"></div>
</template>
<script>
mounted() {
const payjp = window.Payjp(process.env.PAY_JP_PK)
const elements = this.payjp.elements()
const cardElement = elements.create('card')
cardElement.mount('#payjp-form')
cardElement.on('change', async (event) => {
if (event.complete) {
const res = await this.$payjp.createToken(cardElement)
this.payjpToken = res.id
this.isValidCard = true
}
})
},
</script>
- 画面初期表示時は問題なくカードレイアウトが表示されていたが、画面遷移後、再び画面を開くと「Error: 既にインスタンス化されています」というエラーが発生。
複数回の初期化処理はNGとのこと。
対応策(Pluginを作成し初期化を1度に制御する)
import Vue from 'vue';
export default ({store, isHMR}) => {
if (isHMR) return
if (process.client) {
Vue.prototype.$payjp = window.Payjp(process.env.PAY_JP_PK)
}
}
- nuxt.config.jsにPlugin定義追加
plugins: [
'~/plugins/payjp.js',
],
<template>
<div id="payjp-form"></div>
</template>
<script>
mounted() {
const elements = this.$payjp.elements()
const cardElement = elements.create('card')
cardElement.mount('#payjp-form')
cardElement.on('change', async (event) => {
if (event.complete) {
const res = await this.$payjp.createToken(cardElement)
this.payjpToken = res.id
this.isValidCard = true
}
})
},
</script>