WordPressお問合せフォームをAPIで【Contact Form 7 REST API】

# WordPressでお問合せフォーム
お問合せフォームを作る需要はよくあります。
WordPressでお問合せフォームを作るプラグインは色々ありますが、WordPress REST APIをやってきているのでお問合せフォームもなんとかREST APIで実装したい。
調べた所、[Contact Form 7](https://ja.wordpress.org/plugins/contact-form-7/)はREST APIに対応していましたので、これを使ってみます。
![contact form 7](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128044/4fba3328-1f09-8ca3-5bff-44768bedf9ec.png)

# Contact Form 7
> Contact Form 7 は複数のコンタクトフォームを管理できてその上フォームとメールの内容を簡単なマークアップで柔軟にカスタマイズしたりもできます。Ajax によるフォーム送信、CAPTCHA、Akismet スパムフィルタリング等々サポートしています。

Contact Form 7でお問合せフォームの作り方はここでは触れません。
ぱぱっと作れる前提でREST APIのことについてのみ触れます。

## REST API全般
Contact Form 7はREST APIに対応しているもののドキュメントがありません。
なのでソースコードを読みます。
https://github.com/ohze/wp-contact-form-7/blob/master/includes/rest-api.php
これをざっと見ると、APIでお問合せフォームの取得と、お問合せの投稿ができそうです。

## 試す
フォームを1つ作った状態で、
`/wp-json/contact-form-7/v1/contact-forms`を`GET`メソッドでAPIを叩いてみましょう。
そうすると、以下のようなレスポンスが返ってきます。

```json:レスポンス
{
    "code": "wpcf7_forbidden",
    "message": "リクエストしたコンタクトフォームにアクセスする権限がありません。",
    "data": {
        "status": 403
    }
}
```

Contact Form 7はAPIによって認証が必要みたいです。
なのでそういったものにはアプリケーションパスワードをリクエストヘッダーにいれてAPIを再度叩いてみましょう。

```json:レスポンス
[
    {
        "id": 13,
        "slug": "%e3%82%b3%e3%83%b3%e3%82%bf%e3%82%af%e3%83%88%e3%83%95%e3%82%a9%e3%83%bc%e3%83%a0-1",
        "title": "コンタクトフォーム 1",
        "locale": "ja"
    }
]
```

なにやらフォームの一覧っぽいものが返ってきました。

 * ドキュメントないからソースコードをみよう
 * Contact Form 7のAPIの一部は認証が必要

この2つを抑えておきましょう。

## フォームの取得
`/wp-json/contact-form-7/v1/contact-forms/<id>`を`GET`メソッドでAPIを叩いてみましょう。（認証が必要です）

```json:レスポンス
{
    "id": 13,
    "slug": "%e3%82%b3%e3%83%b3%e3%82%bf%e3%82%af%e3%83%88%e3%83%95%e3%82%a9%e3%83%bc%e3%83%a0-1",
    "title": "コンタクトフォーム 1",
    "locale": "ja",
    "properties": {
        "form": "<label> お名前 (必須)\n    [text* your-name] </label>\n\n<label> メールアドレス (必須)\n    [email* your-email] </label>\n\n<label> 題名\n    [text your-subject] </label>\n\n<label> メッセージ本文\n    [textarea your-message] </label>\n\n[submit \"送信\"]",
        "mail": {
            "subject": "test \"[your-subject]\"",
            "sender": "test <xxx@example.co.jp>",
            "body": "差出人: [your-name] <[your-email]>\n題名: [your-subject]\n\nメッセージ本文:\n[your-message]\n\n-- \nこのメールは test (http://localhost:8000) のお問い合わせフォームから送信されました",
            "recipient": "xxx@example.co.jp,
            "additional_headers": "Reply-To: [your-email]",
            "attachments": "",
            "use_html": 0,
            "exclude_blank": 0
        },
        "mail_2": {
            "active": false,
            "subject": "test \"[your-subject]\"",
            "sender": "test <xxx@example.co.jp>",
            "body": "メッセージ本文:\n[your-message]\n\n-- \nこのメールは test (http://localhost:8000) のお問い合わせフォームから送信されました",
            "recipient": "[your-email]",
            "additional_headers": "Reply-To: xxx@example.co.jp",
            "attachments": "",
            "use_html": 0,
            "exclude_blank": 0
        },
        "messages": {
            "mail_sent_ok": "ありがとうございます。メッセージは送信されました。",
            "mail_sent_ng": "メッセージの送信に失敗しました。後でまたお試しください。",
            "validation_error": "入力内容に問題があります。確認して再度お試しください。",
            "spam": "メッセージの送信に失敗しました。後でまたお試しください。",
            "accept_terms": "メッセージを送信する前に承諾確認が必要です。",
            "invalid_required": "必須項目に入力してください。",
            "invalid_too_long": "入力されたテキストが長すぎます。",
            "invalid_too_short": "入力されたテキストが短すぎます。",
            "invalid_date": "日付の形式が正しくありません。",
            "date_too_early": "選択された日付は早すぎます。",
            "date_too_late": "選択された日付は遅すぎます。",
            "upload_failed": "ファイルのアップロード時に不明なエラーが発生しました。",
            "upload_file_type_invalid": "この形式のファイルはアップロードできません。",
            "upload_file_too_large": "ファイルが大きすぎます。",
            "upload_failed_php_error": "ファイルのアップロード中にエラーが発生しました。",
            "invalid_number": "数値の形式に間違いがあります。",
            "number_too_small": "入力された数値が小さすぎます。",
            "number_too_large": "数値が最大許容値を超えています。",
            "quiz_answer_not_correct": "クイズの答えが正しくありません。",
            "captcha_not_match": "入力されたコードが正しくありません。",
            "invalid_email": "入力されたメールアドレスに間違いがあります。",
            "invalid_url": "URL に間違いがあります。",
            "invalid_tel": "電話番号に間違いがあります。"
        },
        "additional_settings": null
    }
}
```
かなり色々なのが返ってきますが、`properties.form`のhtmlを埋め込みつつ、[text* your-name]とかは独自でパースしてinputタグにしてやる必要がありそうです。
ただこのAPIは認証が必要です。
なのでアプリケーションパスワードを発行してそれをエンドユーザーが使うAPIで利用する必要があります。
エンドユーザー側が扱うAPIを想定しているので、認証に必要な文字列がバレてしまうのでこれを使われるとWordPressの投稿もエンドユーザーからされてしまうことになり大変危険です。
Contact Form 7だけ利用できる権限のユーザを作ればと思いましたが、「購読者」の権限ではContact Form 7のAPIは利用できませんでした。
ソースをいじればいけそうですが、htmlのパースもしないといけないことを考えるとContact Form 7で作ったフォームと完全連動してフロントに埋め込むのは少々骨が折れそうです。

## お問合せ投稿
ここでの投稿はエンドユーザーがお問合せフォームにデータを入れて登録することを指します。
`/wp-json/contact-form-7/v1/contact-forms/<id>/feedback`を`POST`メソッドでAPIを叩きます。
このAPIは認証がいりません。
バリデーションを通らないとエラーが返ります。

```json:レスポンス
{
    "into": "#",
    "status": "validation_failed",
    "message": "入力内容に問題があります。確認して再度お試しください。",
    "invalidFields": [
        {
            "into": "span.wpcf7-form-control-wrap.your-email",
            "message": "必須項目に入力してください。",
            "idref": null
        }
    ]
}
```

また、content-typeを`multipart/form-data`にしてあげる必要があります。
バリデーションが通ると以下のようなレスポンスが返ります。

```json:レスポンス
{
    "into": "#",
    "status": "mail_sent",
    "message": "ありがとうございます。メッセージは送信されました。"
}
```

dockerなどでメールの設定をしていない場合以下のようなメッセージが返ってきます。

```json:レスポンス
{
    "into": "#",
    "status": "mail_failed",
    "message": "メッセージの送信に失敗しました。後でまたお試しください。"
}
```

これを回避するには、Contact Form 7のその他の設定で

```
skip_mail: on
```

としてやるとOKです。
(※設定については https://contactform7.com/ja/additional-settings/ を参照）

# まとめ
Contact Form 7 REST APIでお問合せが出来ることを確認しました。
管理画面で作ったフォームをAPIで取得してフロントに埋め込むのは少々大変そうです。
ここも機会があればチャレンジしてみようと思います。