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フィルターでデバッグログを有効化する手順で解決します。

お気軽にご相談ください

お見積りへ お問い合わせへ