Contact FormにAPIで送信する

2024-10-17

react
Example Image

WordPress REST API を使ってContact Form 7 にメールを送信できるみたいです。

便利な無料プラグインが、WordPressの外の静的なサイトでも使えるようになります。

なんだかおもしろそう!

送信する

ブラウザからWordPressのエンドポイントにアクセスしてみます。

https://[ドメイン]/wp-json/contact-form-7/v1/

コンタクトフォームのエンドポイント一覧がでてきました。

ここにのってるこのエンドポイントにPOSTするとメールが送れます。

https:/[ドメイン]/wp-json/contact-form-7/v1/contact-forms/(?P<id>\\d+)/feedback

この、idのところには、何を入れるのか。

コンタクトフォームの管理画面にのってる7桁のIDとは異なるようです。

管理画面のurlに入っているIDを入れるとPOSTできました。

https://[ドメイン]/wp/wp-admin/admin.php?page=wpcf7&post=[ここ!]&action=edit

ところが400エラーが返ってきました!

ドキュメントを見にいくと、送信時には適切なユニットタグを入れよとのアドバイスを頂きました。

ユニットタグとは。

ドキュメントには詳しく載っていないので、仮のコンタクトフォームを設置して検証ツールで探してみました。

こいつです。
name: _wpcf7unit_tag value: wpcf7-fxxx-pxx-ox

xのとこにはそれぞれフォームのID、ページのID、ページ内のフォームのオブジェクト番号が入ってます。

コンタクトフォームが各フォームの識別に使うようです。

このユニットタグをフォームのデータと一緒にPOSTします。

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    const API_URL = `${siteUrl}/wp-json/contact-form-7/v1/contact-forms/${formId}/feedback`;

    const formElement = e.target as HTMLFormElement;
    const body = new FormData(formElement);

    try {
      const res = await fetch(API_URL, {
        method: 'POST',
        body: body,
      });
      if (!res.ok) {
        throw new Error('Something went wrong');
      }

      const data: CF7Response = await res.json();
   
    ...

  return (
    ...
          <form onSubmit={handleSubmit} className="space-y-4">
            <input type="hidden" name="_wpcf7_unit_tag" value={formTag} />
            <div className="space-y-2">
              <Label htmlFor="name">名前</Label>
              <Input
                type="text"
                id="name"
                name="yourname"
                value={formData.yourname}
                onChange={handleChange}
                required
              />
    ...

POSTできました!

送信完了画面を表示する

POST時は下記の型のレスが返ってきます。

interface CF7Response {
  contact_form_id: number;
  status: string;
  message: string;
  invalid_fields?: Array<{
    field: string;
    message: string;
    idref: null;
    error_id: string;
  }>;
  posted_data_hash: string;
  into: string;
}

バリデーションにひっかからずに送信できたときは、status: "mail_sent" になっています。

statusとmessageをstateで管理し、値によって条件分岐します。

if (wpMessage && status === 'mail_sent') {
    return (
      <div className="max-w-md mx-auto mt-8">
        <Card>
          <CardHeader>
            <CardTitle>送信完了</CardTitle>
          </CardHeader>
          <CardContent>
            <p className="text-emerald-500">{wpMessage}</p>
          </CardContent>
        </Card>
      </div>
    );
  }

送信完了画面を表示できました!

エラーメッセージを表示する

バリデーションにひっかかったときは、レスポンスにinvalid_fieldsが入っています。

これをstateで管理します。

emailのバリデーションにひっかかった時は、fieldErrors = { your-email : "emailを入力してください" } のような感じです。

これを各フィールドに表示していきます。

type FieldErrors = {
  [key: string]: string;
};
const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
...
<div className="space-y-2">
              <Label htmlFor="name">名前</Label>
              <Input
                type="text"
                id="name"
                name="yourname"
                value={formData.yourname}
                onChange={handleChange}
                required
              />
              {fieldErrors.yourname && (
                <p className="text-sm text-rose-500">{fieldErrors.yourname}</p>
              )}
            </div>
...

これで完成です!

ビルドしたファイルをテーマフォルダに読み込ませればWordPress内でも使用できます。

share