vue-stripe-elementsを使っていて困ったこと
最初下記を使っていて、すごく使いやすかったのですが、複数ヶ所でstripe-elementを表示させようとするとエラーになってうまくできませんでした。
vue-stripe-elementsのissue
同じようなことで困ってる人がいるようで、issueみても解決してないみたいだったので、自作しました。
自作したやつ
ボタンが、vuetify仕様になっております。まだ、カード番号入力中に支払いボタンが一瞬アクティブになったりするし、ボタンクリック時にローディングまでのタイムラグが若干あったりと、改善点がありますが、上記問題は解決できました。
<template>
<div>
<div :class="stripeElementClass"></div>
<div :class="errorClass">{{ errorMessage }}</div>
<v-btn
:color="btnColor"
:large="btnSize === 'large'"
class="stripe-element-btn"
@click.prevent="createToken"
:disabled="!complete"
:loading="btnLoading"
>
<slot></slot>
</v-btn>
</div>
</template>
<script>
export default {
props: [
'stripeKey', 'stripeOptions', 'btnColor',
'btnSize', 'cardClass', 'errorClass',
'btnLoading'
],
data: () => ({
stripe: null,
stripeElement: null,
token: null,
complete: false,
errorMessage: '',
newCardClass: null,
}),
created() {
this.stripe = Stripe(this.stripeKey)
this.newCardClass = this.cardClass + this._randomString(20)
},
mounted() {
this.createStripeElement()
},
computed: {
stripeElementClass: function() {
return [this.cardClass, this.newCardClass]
}
},
methods: {
async createToken() {
try {
if (!this.complete) return
const result = await this.stripe.createToken(this.stripeElement)
if (result.error) {
this.errorMessage = result.error.message
} else {
this.$emit('token', result.token.id)
}
} catch (err) {
this.errorMessage = err.message
}
},
createStripeElement() {
const elements = this.stripe.elements();
this.stripeElement = elements.create('card', {style: this.stripeOptions, hidePostalCode: true});
this.stripeElement.mount('.' + this.newCardClass)
this.stripeElement.addEventListener('change', event => {
if (event.error) {
this.complete = false
this.errorMessage = event.error.message
} else {
this.errorMessage = ''
this.complete = true
}
})
},
_randomString(len) {
const str = "abcdefghijklmnopqrstuvwxyz0123456789";
let r = '';
for (let i = 0; i < len; i++) {
r += str[Math.floor(Math.random() * str.length)];
}
return r
}
}
}
</script>