[ 'supported_gateways' => ['stripe', 'paypal'], ], 'dispute_handler', 'subscriptions', 'zero_recurring']; public BaseGatewaySettings $settings; public function __construct() { parent::__construct( new StripeSettingsBase(), new StripeSubscriptions() ); add_action('fluent_cart_action_stripe_connect', function ($data) { ConnectConfig::handleConnect($data); }); } public function boot() { (new IPN)->init(); (new Confirmations)->init(); add_filter('fluent_cart/payment_methods/stripe_pub_key', [$this, 'getPublicKey'], 10); } public function meta(): array { return [ 'title' => 'Card', 'route' => 'stripe', 'slug' => 'stripe', 'label' => 'Stripe', 'admin_title' => 'Stripe', 'description' => __("Stripe's payments platform lets you accept credit cards, debit cards, and popular payment methods around the world all with a single integration.", "fluent-cart"), 'logo' => Vite::getAssetUrl('images/payment-methods/card.svg'), 'icon' => Vite::getAssetUrl('images/payment-methods/stripe-icon.svg'), 'status' => $this->settings->get('is_active') === 'yes', 'brand_color' => '#136196', 'upcoming' => false, 'supported_features' => $this->supportedFeatures ]; } public function makePaymentFromPaymentInstance(PaymentInstance $paymentInstance) { $order = $paymentInstance->order; $storeName = (new StoreSettings())->get('store_name'); $transactionCurrency = $paymentInstance->transaction->currency; $chargeAmount = (int)$paymentInstance->transaction->total; if ($transactionCurrency && CurrenciesHelper::isZeroDecimal($transactionCurrency)) { $chargeAmount = (int)round($chargeAmount / 100); } $paymentArgs = array( 'client_reference_id' => $order->uuid, 'amount' => $chargeAmount, 'currency' => strtolower($transactionCurrency), 'description' => $storeName . ' #' . $order->invoice_no, // @todo: We will replace with order summary with item names later 'customer_email' => $paymentInstance->order->email, 'success_url' => $this->getSuccessUrl($paymentInstance->transaction), 'custom_payment_url' => PaymentHelper::getCustomPaymentLink($paymentInstance->order->uuid) ); if ($paymentInstance->subscription) { return (new Processor())->handleSubscription($paymentInstance, $paymentArgs); } return (new Processor())->handleSinglePayment($paymentInstance, $paymentArgs); } public function processRefund($transaction, $amount, $args) { if (!$amount) { return new \WP_Error( 'fluent_cart_stripe_refund_error', __('Refund amount is required.', 'fluent-cart') ); } return \FluentCart\App\Modules\PaymentMethods\StripeGateway\StripeHelper::processRemoteRefund($transaction, $amount, $args); } public function webHookPaymentMethodName() { return $this->getMeta('route'); } public function handleIPN(): void { (new IPN($this))->verifyAndProcess(); } public function getEnqueueScriptSrc($hasSubscription = 'no'): array { $checkoutMode = $this->settings->get('checkout_mode') ?? 'onsite'; if ($checkoutMode == 'hosted') { return [ [ 'handle' => 'fluent-cart-checkout-handler-stripe-hosted', 'src' => Vite::getEnqueuePath('public/payment-methods/stripe-hosted-checkout.js'), ] ]; } // For embedded/onsite mode, load Stripe SDK and full handler return [ [ 'handle' => 'fluent-cart-checkout-sdk-stripe', 'src' => 'https://js.stripe.com/v3/', ], [ 'handle' => 'fluent-cart-checkout-handler-stripe', 'src' => Vite::getEnqueuePath('public/payment-methods/stripe-checkout.js'), 'deps' => ['fluent-cart-checkout-sdk-stripe'] ] ]; } private function getStripeLocale(): string { $parts = explode('_', get_locale()); $lang = strtolower($parts[0]); $region = isset($parts[1]) ? strtoupper($parts[1]) : ''; if ($region) { $full = $lang . '-' . $region; if (in_array($full, ['en-GB', 'fr-CA', 'zh-HK', 'zh-TW', 'pt-BR', 'es-419'])) { return $full; } } return $lang ?: 'auto'; } public function getLocalizeData(): array { return [ 'fct_stripe_data' => [ 'locale' => $this->getStripeLocale(), 'translations' => [ 'Payment module not available to checkout! Please reload again, or contact admin!' => __('Payment module not available to checkout! Please reload again, or contact admin!', 'fluent-cart'), 'See Errors' => __('See Errors', 'fluent-cart'), 'Pay Now' => __('Pay Now', 'fluent-cart'), 'Place Order' => __('Place Order', 'fluent-cart'), 'Card details are not valid!' => __('Card details are not valid!', 'fluent-cart'), 'Total amount is not valid, please add some items to cart!' => __('Total amount is not valid, please add some items to cart!', 'fluent-cart'), 'An error occurred while parsing the response.' => __('An error occurred while parsing the response.', 'fluent-cart'), 'An error occurred while loading the payment method.' => __('An error occurred while loading the payment method.', 'fluent-cart'), 'Loading Payment Processor...' => __('Loading Payment Processor...', 'fluent-cart'), 'redirecting for action' => __('redirecting for action', 'fluent-cart'), 'You will be redirected to Stripe to complete your payment securely.' => __('You will be redirected to Stripe to complete your payment securely.', 'fluent-cart'), 'Something went wrong' => __('Something went wrong', 'fluent-cart'), 'Payment confirmation failed' => __('Payment confirmation failed', 'fluent-cart'), ] ] ]; } public static function beforeSettingsUpdate($data, $oldSettings): array { $provider = Arr::get($data, 'provider', 'connect'); $mode = Arr::get($data, 'payment_mode', 'test'); if ('connect' == $provider) { $currentKey = Arr::get($data, $mode . '_secret_key', ''); $oldKey = Arr::get($oldSettings, $mode . '_secret_key', ''); if ($currentKey !== $oldKey) { $data[$mode . '_secret_key'] = Helper::encryptKey($currentKey); } } if (Arr::get($data, 'provider') === 'api_keys') { $data['test_publishable_key'] = ''; $data['live_publishable_key'] = ''; $data['test_secret_key'] = ''; $data['live_secret_key'] = ''; } return $data; } public static function validateSettings($data): array { $mode = Arr::get($data, 'payment_mode', 'test'); $provider = Arr::get($data, 'provider', 'connect'); if ($provider === 'api_keys') { if ($mode === 'live') { $sk = defined('FCT_STRIPE_LIVE_SECRET_KEY') ? FCT_STRIPE_LIVE_SECRET_KEY : Arr::get($data, 'live_secret_key'); } else { $sk = defined('FCT_STRIPE_TEST_SECRET_KEY') ? FCT_STRIPE_TEST_SECRET_KEY : Arr::get($data, 'test_secret_key'); } } else { $sk = $mode === 'live' ? Arr::get($data, 'live_secret_key') : Arr::get($data, 'test_secret_key'); if (empty($sk)) { $errorMessage = $mode === 'live' ? __('Stripe not connected in live mode!', 'fluent-cart') : __('Stripe not connected in test mode!', 'fluent-cart'); return [ 'status' => 'failed', 'message' => $errorMessage ]; } else { return [ 'status' => 'success', 'message' => __('Stripe account already verified!', 'fluent-cart') ]; } } if (empty($sk)) { return [ 'status' => 'failed', 'message' => __('Please provide a valid secret key!', 'fluent-cart') ]; } if ($mode === 'live' && !str_contains($sk, 'sk_live')) { return [ 'status' => 'failed', 'message' => __('Please provide a valid LIVE secret key!', 'fluent-cart') ]; } else if ($mode === 'test' && !str_contains($sk, 'sk_test')) { return [ 'status' => 'failed', 'message' => __('Please provide a valid TEST secret key!', 'fluent-cart') ]; } $response = (new API)->remoteRequest('account', [], $sk, 'GET'); if (isset($response['error'])) { return [ 'status' => 'failed', 'message' => $response['error']['message'] ? $response['error']['message'] : __('Invalid credentials!', 'fluent-cart') ]; } if (!isset($response['id'])) { return [ 'status' => 'failed', 'message' => $response['error']['message'] ? $response['error']['message'] : __('Invalid credentials!', 'fluent-cart') ]; } return [ 'status' => 'success', 'message' => __('Stripe account verified!', 'fluent-cart') ]; } public function fields(): array { $disabled = apply_filters_deprecated('fluent_cart_form_disable_stripe_connect', [false, []], '1.3.16', 'fluent_cart/form_disable_stripe_connect', 'Use fluent_cart/form_disable_stripe_connect instead of fluent_cart_form_disable_stripe_connect.'); $providerValue = apply_filters('fluent_cart/form_disable_stripe_connect', $disabled, []) ? 'api_keys' : 'connect'; return array( 'notice' => [ 'value' => $this->renderStoreModeNotice(), 'label' => __('Store Mode notice', 'fluent-cart'), 'type' => 'notice' ], 'payment_mode' => [ 'type' => 'tabs', 'schema' => [ [ 'type' => 'tab', 'label' => __('Live credentials', 'fluent-cart'), 'value' => 'live', 'schema' => [] ], [ 'type' => 'tab', 'label' => __('Test credentials', 'fluent-cart'), 'value' => 'test', 'schema' => [], ] ] ], 'provider' => array( 'value' => $providerValue, 'label' => __('Provider', 'fluent-cart'), 'type' => 'provider' ), 'setup_guide' => array( 'value' => '