GiveWPアップデート後にStripeの寄付が完了しない原因と直し方

GiveWPアップデート後にStripeの寄付が完了しない原因と直し方

GiveWPアップデート後にStripeの寄付が完了しない原因と直し方

Stripeの決済は成功しているのにGiveWPで寄付が「完了」にならない。管理画面に寄付データが作成されず、Webhookだけが延々と失敗し続ける。この症状は、GiveWP 4.16のアップデート後にStripeから送られてくるWebhookの中身が空(null)になっていることが原因だ。PHPの致命的エラー「array_keys(): Argument #1 ($array) must be of type array, null given」が記録されているならなおさらで、GiveWPがイベントデータを正しく読み取れていない。

対処の核心はGiveWPとStripeの接続を完全に再確立し、Webhookの登録から正しくやり直すことにある。加えて、サーバー側のキャッシュがWebhookの受信を阻害しているケースも多いため、キャッシュの全削除とWebhookエンドポイントの除外設定が必要だ。

なぜStripeの決済は成功するのにGiveWPの寄付は未完了になるのか

なぜStripeの決済は成功するのにGiveWPの寄付は未完了になるのか

この問題のややこしい点は、Stripe上では決済が正常に完了して見えることだ。PaymentIntentのステータスは「succeeded」になり、クレジットカードの引き落としも問題なく行われる。しかしGiveWP側では寄付レコードが作成されず、寄付者にも完了メールが届かない。

仕組みをたどると、GiveWPは次の流れで寄付を確定させている。

① 寄付者がフォームで決済を実行
Stripeがクレジットカード情報を処理し、PaymentIntentが作成される
② StripeがWebhookをGiveWPのエンドポイントに送信
エンドポイントURLの例 https://example.com/?give-listener=stripe
③ GiveWPがWebhookを受け取り、署名を検証
署名検証に成功するとイベントデータを内部処理に回す
④ GiveWPが寄付レコードを作成し、ステータスを「完了」に変更
寄付者に完了メールが送信される

この流れのうち、手順③の段階でコケているのが今回の症状だ。StripeからのWebhookはGiveWPのエンドポイントに届いているのに、GiveWPがその中身を処理できない。結果として手順④に進めず、寄付は永遠に「処理中」のまま取り残される。

「array_keys null given」エラーが示す根本原因

「array_keys null given」エラーが示す根本原因

GiveWPのデバッグログに次のような致命的エラーが記録されている場合、原因の特定はかなり絞り込める。

Uncaught TypeError: array_keys(): Argument #1 ($array) must be of type array, null given
in vendor/stripe/stripe-php/lib/StripeObject.php

このエラーは、GiveWPがStripeの公式PHPライブラリ(stripe-php)を使ってWebhookイベントのデータを読み取ろうとしたとき、肝心のイベントオブジェクトの中身がnullになっていることを意味する。本来なら配列として渡されるべきデータが空っぽなのだ。

なぜデータが空になるのか。主な原因は次の3つに集約される。

  • GiveWPのアップデートで内部のWebhook処理ロジックが変わり、既存の接続設定との整合性が崩れた
  • サーバーレベルのキャッシュ(LiteSpeedやホスティング側のキャッシュ)がWebhookリクエストを変形させている
  • StripeダッシュボードのWebhook設定とGiveWPが自動管理する署名シークレットとの間にずれが生じている

4.16より前のバージョンではWebhookのデータ取得方法が異なっていた可能性があり、アップデートによって従来の接続状態に不整合が発生したと見るのが自然だ。事実、GiveWP 4.16がリリースされる直前の6月23日までは正常に動作していたという報告は、この仮説を裏付けている。

GiveWPとStripeの接続を完全に再確立する手順

GiveWPとStripeの接続を完全に再確立する手順

部分的な修正では直らない。GiveWPとStripeの間の信頼関係をゼロから組み直すつもりで、以下の手順を上から順に実行する。

STEP 1 GiveWPを最新バージョンに更新する
4.16.0で問題が発生した場合も、まず4.16.1以降への更新を試みる。GiveWPは不具合修正を迅速にリリースすることが多い。
STEP 2 GiveWP管理画面でStripeとの接続を解除する
「寄付」→「設定」→「支払いゲートウェイ」→「Stripe」から「接続を解除」を実行する。
STEP 3 StripeダッシュボードのWebhookを完全に削除する
Stripeダッシュボードの「開発者」→「Webhook」から、GiveWP用のエンドポイントをすべて削除する。古いものや重複しているものも含めて、すべて消す。
STEP 4 WordPressのキャッシュをすべて削除する
プラグインキャッシュ、サーバーキャッシュ(LiteSpeed等)、ホスティングキャッシュの3層すべてをクリアする。キャッシュ系プラグインを一時的に無効化してもよい。
STEP 5 GiveWPでStripeに再接続する
「寄付」→「設定」→「支払いゲートウェイ」→「Stripe」から「Stripeと接続」を実行し、Stripeの認証画面で許可する。
STEP 6 Webhookが自動再作成されるのを確認する
GiveWPが再接続時にStripeへWebhookエンドポイントを自動登録する。StripeダッシュボードのWebhook一覧を開き、新しいエンドポイントが作成されていること、必要なイベントが有効になっていることを確認する。

GiveWP管理画面でのStripe接続解除と再接続の落とし穴

接続解除ボタンを押しても、内部的に完全にクリーンアップされるとは限らない。GiveWPは接続情報をデータベースのoptionsテーブルに保存しているため、万が一解除がうまくいかない場合は、データベースを直接確認する方法も検討する。

再接続時は必ず本番モードで認証を通すこと。テストモードで接続したあとに本番モードに切り替えても、Webhookエンドポイントはテスト用のものが残ったままになり、本番決済のWebhookが正しく処理されない原因になる。

Stripe Webhookエンドポイントに必要なイベントを確認する

GiveWPが自動登録するWebhookには、以下の8つのイベントが最低限有効になっている必要がある。Stripeダッシュボードでエンドポイントを開き、「受信イベント」欄を目視で確認する。

  • charge.refunded(返金処理)
  • checkout.session.completed(チェックアウトセッション完了)
  • customer.subscription.created(定期寄付の作成)
  • customer.subscription.deleted(定期寄付の削除)
  • invoice.payment_failed(請求書の支払い失敗)
  • invoice.payment_succeeded(請求書の支払い成功)
  • payment_intent.payment_failed(支払い意図の失敗)
  • payment_intent.succeeded(支払い意図の成功)

いずれかが欠けている場合は手動で追加する。GiveWPがイベントを自動追加する仕様はバージョンによって変わるため、再接続後に必ず確認する習慣をつけるとよい。

キャッシュがWebhookを壊す仕組みと確実な対処

キャッシュがWebhookを壊す仕組みと確実な対処

Webhookはサーバー間のHTTP POSTリクエストだ。ところが一部のキャッシュプラグインやホスティング側のキャッシュ機構は、このPOSTリクエストに対して予期せぬ挙動を示す。具体的には、リクエストボディを空にしたり、ヘッダー情報を削除したり、レスポンスをキャッシュしてしまったりする。

GiveWPが正しく署名を検証し、イベントデータを読み取るためには、StripeからのPOSTリクエストが一切加工されずに届かなければならない。次の対応を必ず実施する。

Before(キャッシュがWebhookを加工している状態)
Stripe → キャッシュを通過リクエストボディが変形・空になる → GiveWPが処理失敗
After(キャッシュからWebhookエンドポイントを除外した状態)
Stripe → キャッシュをバイパスリクエストボディが完全なまま届く → GiveWPが正常に処理
キャッシュがリクエストを加工している状態  キャッシュから除外した状態

LiteSpeedキャッシュが原因のケース

LiteSpeedサーバー環境では、LiteSpeed Cacheプラグインの設定画面から「キャッシュ」→「除外」タブを開き、「URLの除外」にGiveWPのWebhookエンドポイントパスを追加する。具体的には「give-listener=stripe」を含むURLパターンを指定する。正規表現が使える場合は次のように記述する。

give-listener=stripe

また、LiteSpeedの「オブジェクトキャッシュ」や「ブラウザキャッシュ」も合わせて無効化した状態でテストすることを推奨する。テストが終わったら再度有効化しても問題はないが、少なくともWebhookエンドポイントだけは常にキャッシュの対象外にしておく。

ホスティング側のキャッシュが原因のケース

一部の共用サーバーやマネージドホスティングでは、サーバーレベルでリバースプロキシキャッシュが動作している。管理パネルからキャッシュを手動でクリアしたあと、一時的にキャッシュ機能を停止してWebhookが正常に処理されるかテストする。

恒常的な解決策としては、ホスティングのサポートに依頼して「https://example.com/?give-listener=stripe」をキャッシュの除外リストに追加してもらう必要がある。

署名シークレットの誤設定が引き起こす症状と修正

署名シークレットの誤設定が引き起こす症状と修正

GiveWP 4.16以降、署名シークレットの管理方法が変わり、手動での設定が不要になった。GiveWPがStripeに接続する際、自動的にWebhookエンドポイントを作成し、署名シークレットもGiveWP内部で管理する。そのため、Stripeダッシュボードから取得した署名シークレットをGiveWPの設定画面に入力する欄は存在しない。

もし過去に手動でWebhookを作成し、その署名シークレットを何らかの方法でGiveWPに設定していた場合、バージョンアップ後にその情報が無視されるか、あるいは競合を起こす可能性がある。そのため、手順としては次のように徹底する。

  1. Stripeダッシュボードから古いWebhookをすべて削除する(手動で作成したものも含む)
  2. GiveWP管理画面でStripeとの接続を完全に解除する
  3. GiveWP管理画面でStripeに再接続する(このとき新しいWebhookと署名シークレットが自動作成される)

署名シークレットに関するエラーがStripeダッシュボードに表示されている場合、ほぼ間違いなく新旧のWebhookが混在しているか、手動設定の名残が残っている。上記の手順で完全にリセットすれば、署名検証エラーは解消する。

それでも直らないときの最終確認リスト

それでも直らないときの最終確認リスト

上記の手順をすべて実行しても症状が改善しない場合、以下のポイントを順に再チェックする。

チェック1 サーバーの時刻が大幅にずれていないか
SSL証明書の評価がAランクでもNTPの同期が外れていると署名検証に失敗する。ホスティングに確認する。
チェック2 .htaccessやNginx設定にWebhookを妨害するルールが入っていないか
特定のクエリ文字列をブロックする設定や、POSTリクエストをGETに変換するリダイレクトルールがないか確認する。
チェック3 セキュリティプラグインがWebhookエンドポイントをブロックしていないか
WordfenceやSucuriなどのWAFがStripeのIPを遮断しているケースがある。一時的に無効化してテストする。
チェック4 StripeのAPIバージョンが極端に新しくなっていないか
Stripeダッシュボードの「開発者」→「APIのバージョン管理」で、使用中のAPIバージョンがGiveWPの対応範囲内か確認する。

よくある質問

GiveWPを最新版に更新したあとにStripeのWebhookが失敗し始めた。ロールバックするべきか

ロールバックは推奨しない。4.16系にはWebhook処理まわりの重要な変更が含まれており、古いバージョンに戻すと将来的にStripe APIの更新に追随できず、より深刻な不具合を引き起こす。まずは本記事の再接続手順を試し、それでも解決しない場合はGiveWPのサポートにシステムレポートを送って調査を依頼するほうが安全だ。

StripeのダッシュボードでWebhookが「失敗」と表示されるが、GiveWP側にエラーログが出ない

GiveWPのデバッグモードが有効になっていない可能性が高い。「寄付」→「設定」→「詳細」→「デバッグモード」を有効にすると、Webhook処理のエラーログが記録されるようになる。ログは「寄付」→「ツール」→「ログ」で確認できる。

再接続してもWebhookがStripeダッシュボードに自動作成されない

GiveWPの接続プロセスの中で、WordPressのREST APIが正しく動作していない可能性がある。パーマリンク設定を「基本」以外に変更して保存し直す。また、セキュリティプラグインがREST APIを制限していないか確認する。

WebhookエンドポイントのURLは手動で変更してもよいか

原則として不要であり、変更すべきではない。GiveWPが自動生成するエンドポイントURLは「https://(サイトURL)/?give-listener=stripe」で固定されており、これをStripeに正しく登録している。URLを手動で変更すると、署名の不一致が発生してすべてのWebhookが失敗する。

GiveWPのシステムレポートはどこで確認できるか

WordPress管理画面の「寄付」→「ツール」→「システム情報」タブを開き、「システムレポートを取得」ボタンをクリックすると、サーバー環境やGiveWPの設定情報がテキスト形式で表示される。サポートに問い合わせる際はこのレポートを添付するとスムーズに調査が進む。

この記事のポイント

  • Stripe決済成功後に寄付が未完了になるのは、Webhook処理の段階でGiveWPがイベントデータを読み取れていないから
  • 致命的エラー「array_keys null given」はWebhookの中身が空であることを示す決定的な手がかり
  • GiveWPとStripeの接続解除からWebhook全削除、再接続までを一気に行い、署名シークレットを完全に再生成する
  • LiteSpeedやホスティングのキャッシュからWebhookエンドポイントを除外し、POSTリクエストが加工されないようにする
  • 署名シークレットはGiveWPが自動管理するため、手動設定は不要であり、むしろ競合の原因になる
佐々木 太陽

・ Reddit、Stack Overflow、WordPress.org フォーラムを日々巡回し、現場の悩みを拾い上げて記事化 ・ WordPress、WooCommerce、Next.js などモダンWeb制作領域のトラブルシューティングが専門 ・ 「検索しても答えが見つからなかった」を一つでも減らすことが目標 ・ エラーメッセージから根本原因にたどり着く粘り強い調査が得意 ・ 初心者がつまずきやすい箇所を先回りで解決する記事作りを心がけている

メッセージを残す