*/ private array $captured = []; public function register(): void { add_filter('woocommerce_logger_log_message', [$this, 'capture'], 10, 3); } /** * Capture the provider reason before Stripe replaces it with a generic checkout error. */ public function capture(string $message, string $level, array $context): string { if ('error' !== $level || self::LOGGER_SOURCE !== ($context['source'] ?? '')) { return $message; } if (1 !== preg_match('/^Error when processing payment for order:\s*(\d+)\b/', $message, $matches)) { return $message; } $rawReason = $context['error_message'] ?? null; if (! is_string($rawReason)) { return $message; } $reason = self::sanitizeReason($rawReason); if ('' === $reason) { return $message; } $orderId = absint($matches[1]); $order = wc_get_order($orderId); if (! $order instanceof \WC_Order || ! $this->isStripeOrder($order)) { return $message; } $captureKey = $orderId . ':' . hash('sha256', $reason); if (isset($this->captured[$captureKey])) { return $message; } $this->captured[$captureKey] = true; if ($reason === (string) $order->get_meta(self::META_REASON)) { return $message; } $order->update_meta_data(self::META_REASON, $reason); $order->save_meta_data(); $order->add_order_note(sprintf( /* translators: %s: sanitized payment provider failure reason. */ __('Stripe payment failed: %s', 'aivie-for-woocommerce'), $reason )); return $message; } public static function sanitizeReason(string $reason): string { $reason = sanitize_text_field(wp_strip_all_tags($reason, true)); $patterns = [ '/\b(?:Bearer|Basic)\s+[A-Za-z0-9._~+\/=:-]+/i', '/\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]+\b/i', '/\bwhsec_[A-Za-z0-9]+\b/i', '/\b(?:acct|ba|card|ch|cs|cus|evt|in|link|mandate|pm|pi|price|prod|seti|src|sub|tok|tr)_[A-Za-z0-9_]+\b/i', '/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i', '/https?:\/\/[^\s]+/i', '/(?get_payment_method()); return 'stripe' === $paymentMethod || str_starts_with($paymentMethod, 'stripe_') || str_starts_with($paymentMethod, 'wc_stripe_'); } }