2026年8月26日
2026年8月26日
WooCommerce Stripeのエラーを解決する方法
はじめに
WooCommerce Stripeで「カードが拒否されました」以外の理由で決済が失敗する・StripeダッシュボードにWebhookイベントが届かない・3Dセキュア(SCA)認証後に注文が完了しない・管理画面から返金しても実際には返金されないといった問題は、APIキーの環境設定ミス・Webhook署名の不一致・HTTPSの設定が原因です。
症状・原因
- テストモードで決済するとStripeダッシュボードに決済が記録されない
- 本番環境でのみ「Your card was declined」エラーが出る(テストでは問題ない)
- Webhook受信ログにイベントが記録されるが注文ステータスが更新されない
- 3Dセキュア認証ページで「戻る」を押すと注文が「処理中」のまま残る
解決手順
ステップ1:Stripe設定の状態を確認する
# WooCommerce Stripe設定を確認
wp eval "
\$stripe_settings = get_option('woocommerce_stripe_settings', []);
echo 'Stripe enabled: ' . (\$stripe_settings['enabled'] ?? 'no') . PHP_EOL;
echo 'Test mode: ' . (\$stripe_settings['testmode'] ?? 'no') . PHP_EOL;
echo 'API key set: ' . (!empty(\$stripe_settings['secret_key']) ? 'YES' : 'NO') . PHP_EOL;
echo 'Webhook secret set: ' . (!empty(\$stripe_settings['webhook_secret']) ? 'YES' : 'NO') . PHP_EOL;
// Webhook URLを確認
\$webhook_url = WC()->api_request_url('wc_stripe');
echo 'Webhook URL: ' . \$webhook_url . PHP_EOL;
"
# Webhook URLにアクセステスト
wp eval "
\$webhook_url = WC()->api_request_url('wc_stripe');
\$response = wp_remote_post(\$webhook_url, [
'headers' => ['Content-Type' => 'application/json'],
'body' => '{}',
'timeout' => 10,
]);
echo 'Webhook endpoint status: ' . wp_remote_retrieve_response_code(\$response) . PHP_EOL;
"
ステップ2:Webhook処理を修正する
// functions.php: Stripe Webhook処理のカスタマイズ
// ① Webhookイベントを手動でデバッグ
add_action('wc_gateway_stripe_process_webhook', function(string $event_type, object $event): void {
error_log(sprintf('[Stripe] Webhook received: %s | ID: %s',
$event_type,
$event->id
));
}, 10, 2);
// ② payment_intent.succeeded イベントの補完処理
add_action('wc_gateway_stripe_payment_intent_succeeded', function(object $intent, object $order): void {
if (!$order) return;
// 注文が「処理中」のままの場合は強制完了
if ($order->get_status() === 'pending') {
$order->payment_complete($intent->id);
$order->add_order_note(sprintf(
'Stripe Payment Intent 成功: %s (Webhook補完)',
$intent->id
));
error_log(sprintf('[Stripe] Order %d completed via webhook: %s',
$order->get_id(), $intent->id));
}
}, 10, 2);
// ③ 3Dセキュア(SCA)認証後のリダイレクト
add_filter('wc_stripe_return_url', function(string $url, \WC_Order $order): string {
// 認証完了後は注文確認ページに遷移
if ($order->get_status() === 'pending') {
return $order->get_checkout_payment_url();
}
return $url;
}, 10, 2);
ステップ3:APIキーとセキュリティを設定する
// functions.php: Stripe APIキー管理
// ① 環境別にAPIキーを切り替え
add_filter('wc_stripe_secret_key', function(string $key): string {
// ステージング環境ではテストキーを強制使用
if (defined('WP_ENVIRONMENT_TYPE') && WP_ENVIRONMENT_TYPE === 'staging') {
return defined('STRIPE_TEST_SECRET_KEY') ? STRIPE_TEST_SECRET_KEY : $key;
}
return $key;
});
// ② Stripe決済の追加バリデーション
add_action('woocommerce_checkout_process', function(): void {
// 日本の郵便番号バリデーション
$billing_postcode = WC()->checkout()->get_posted_data()['billing_postcode'] ?? '';
if (!preg_match('/^\d{3}-?\d{4}$/', $billing_postcode)) {
wc_add_notice('郵便番号の形式が正しくありません(例: 123-4567)', 'error');
}
});
// ③ 決済失敗時のカスタムエラーメッセージ
add_filter('wc_stripe_payment_failed_message', function(string $message, string $error_code): string {
$messages = [
'card_declined' => 'カードが拒否されました。別のカードをお試しください。',
'insufficient_funds' => '残高が不足しています。',
'expired_card' => 'カードの有効期限が切れています。',
'incorrect_cvc' => 'セキュリティコードが正しくありません。',
'processing_error' => '決済処理中にエラーが発生しました。しばらくしてから再試行してください。',
'do_not_honor' => 'カード会社により決済が承認されませんでした。',
];
return $messages[$error_code] ?? $message;
}, 10, 2);
ステップ4:返金処理を修正する
// functions.php: Stripe返金処理
// ① 返金を手動でトリガー
function stripe_refund_order(int $order_id, float $amount, string $reason = ''): bool {
$order = wc_get_order($order_id);
if (!$order) return false;
$charge_id = $order->get_transaction_id();
if (!$charge_id) {
error_log('[Stripe] No charge ID for order ' . $order_id);
return false;
}
$gateway = WC()->payment_gateways()->payment_gateways()['stripe'] ?? null;
if (!$gateway) return false;
$result = $gateway->process_refund($order_id, $amount, $reason);
if (is_wp_error($result)) {
error_log('[Stripe] Refund failed: ' . $result->get_error_message());
return false;
}
return true;
}
// ② 返金完了時の通知
add_action('woocommerce_order_refunded', function(int $order_id, int $refund_id): void {
$order = wc_get_order($order_id);
$refund = wc_get_order($refund_id);
if (!$order || !$refund) return;
error_log(sprintf('[Stripe] Refund processed: Order %d | Amount: %s | Refund ID: %d',
$order_id,
wc_price($refund->get_amount()),
$refund_id
));
}, 10, 2);
ステップ5:テストとデバッグ
# Stripeのログを確認
wp eval "
\$logs = WC_Log_Handler_File::get_log_files();
foreach (\$logs as \$log) {
if (str_contains(\$log, 'stripe')) {
echo 'Stripe log: ' . \$log . PHP_EOL;
}
}
// 最新ログ(50行)を表示
\$log_file = WC_LOG_DIR . 'stripe-' . sanitize_file_name(wp_hash('stripe')) . '.log';
if (file_exists(\$log_file)) {
\$lines = file(\$log_file);
echo implode('', array_slice(\$lines, -50));
}
"
// functions.php: Stripeデバッグ設定
// ① 詳細ログを有効化
add_filter('wc_stripe_log_level', function(): string {
return 'debug'; // 'debug' | 'info' | 'warning' | 'error'
});
// ② Stripe決済の前後でデバッグ情報を記録
add_action('wc_gateway_stripe_before_process_payment', function(\WC_Order $order): void {
error_log(sprintf('[Stripe] Processing payment for order %d | Total: %s',
$order->get_id(), $order->get_total()));
});
注意事項
- テストモードと本番モードではAPIキーが異なります。
sk_test_で始まるキーはテスト用、sk_live_で始まるキーは本番用です。本番環境でテストキーを使用すると決済は記録されません - StripeのWebhook署名検証に失敗する場合は「WooCommerce → 設定 → 支払い → Stripe → Webhook」でWebhook Secretを再設定してください。StripeダッシュボードのWebhookエンドポイント設定から署名シークレットを取得できます
- 3Dセキュア認証後に注文が完了しない場合は、サイトのSSL証明書が正しく設定されているか確認してください。Stripeは本番環境でHTTPSが必須です
まとめ
WooCommerce Stripe修復は①woocommerce_stripe_settingsオプション確認・Webhook URL疎通テスト、②wc_gateway_stripe_payment_intent_succeededフックで注文ステータスをWebhook補完・wc_stripe_return_urlフィルターで3Dセキュア後のリダイレクトを修正、③wc_stripe_secret_keyフィルターで環境別APIキーを管理・wc_stripe_payment_failed_messageフィルターでエラーメッセージを日本語化、④gateway->process_refund()で返金を手動実行・woocommerce_order_refundedフックで返金ログを記録、⑤wc_stripe_log_levelフィルターでデバッグログを有効化する手順で解決します。