Vue.jsでreCAPTCHA v2を使用

Vue.jsで作成したフォームにreCAPTCHAを組み込みたいと考えました。

組み込むといっても普通のフォームであれば難なくできたのでさして難しく考えていませんでした。動作としては下記のような挙動を実装したいです。

  • ページの描画時にreCAPTCHAのウィジェットを表示
    • Vue Router等で遷移して戻ってきたときにも描画(何も考えずに埋め込むとこの時描画されない)
  • 他の項目もバリデーションが全てOKであれば、reCAPTCHAのチェックボックスにチェックを入れてレスポンスのトークンを取得した時点でsubmitボタンを有効化する(「レスポンスでトークンを取得」というイベントにどうやってフックし、Vue.js側のメソッドを発火させるのか……)
  • 2分ほど放置してreCAPTCHAがexpired(タイムアウト)したら、そのタイミングでフォームデータにセットしたトークンをリセットし、submitボタンをdisabledにする(これもイベントへのフックと発火がどうすれば良いのやら)

どれも直感的・自然に「そうあってほしい」という挙動だと思います。が、そのためにはGoogleの外部スクリプトを読み込み、それとVue.jsを連携させる必要があり、そこで四苦八苦。どうにも上手く行く見通しが立ちませんでした。

エラーコードなどでググったり外部スクリプトの読み込み関係を調べたりしていて行き詰ったとき、そもそもとして世の開発者達はどうやっているのかと「Vue.js reCAPTCHA」とググってみたところ……

ライブラリがある……だと……?!

早速今までのコードを投げ捨ててnpm install vue-recaptchaして試してみることに。

結果。あっけなくできてしまいました。ライブラリ製作者に感謝🙏😇

index.html

<script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer>
</script>

HTMLはサンプル通り。

Vueコンポーネント

<template>
    <form @submit.prevent="send">
        <vue-recaptcha :sitekey="this.procenv.sitekey" @verify="onVerify" @expired="onExpired"></vue-recaptcha>
        <button type="submit" :disabled="this.disabled ? true : false">送信</button>
    </form>
</template>

<script>
import VueRecaptcha from 'vue-recaptcha'

export default {
    name: 'Form',
    components: {
        VueRecaptcha
    },
    data() {
        return {
            sendflag: null,
            recaptcha: {
                useflag: false, //reCAPTCHAを使用するかどうするか
                setflag: false, //reCAPTCHAに値が入ったかどうか
                response: '' //レスポンスのトークン
            }
        }
    },
    methods: {
        submitEnable() {
//略

                if(this.recaptcha.useflag) { //reCAPTCHAあり
                    if(this.recaptcha.responce !== null && this.recaptcha.responce !== undefined && this.recaptcha.responce.length > 0) { //値がセットされればフラグセット
                        this.recaptcha.setflag = true
                    }
                }

                if(/* 他のバリデーションがOKというフラグ */ && this.recaptcha.setflag) { //全項目がバリデーションOK、かつreCAPTCHAがセット(未使用の場合は最初からtrue)されていれば
                    this.disabled = false //submitボタンのdisabledを外す
                    //送信用の値セット
                }
                else {
                    this.disabled = true //disabledを付け直す
                    //送信用の値リセット
                }
            }
        },
        onVerify(response) {
            this.recaptcha.responce = response //レスポンスのトークンをセット
            this.submitEnable() //バリデーションとsubmitボタンを有効にするメソッドを発火
        },
        onExpired() {
            this.recaptcha.responce = '' //レスポンスのトークンを空に戻す
            this.recaptcha.setflag = false //フラグを下す
            this.disabled = true //submitボタンをdisabledに
        },
        resetRecaptcha() {
            this.$refs.recaptcha.reset() // Direct call reset method
        }
}

reCAPTCHA周りのコードを抜き出すとこんな感じ。すごく楽にできました🎉

この記事を書いた人

アバター

アルム=バンド

フルスタックエンジニアっぽい何か。LAMPやNodeからWP、gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。