PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.1
1.7.1 1.7.0 1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 All 51 releases
← All changes | app/Modules/PaymentMethods/StripeGateway/Stripe.php +62 -15 1.6.0 → 1.7.1 View file →
@@ -28,9 +28,9 @@
28 28 private $methodSlug = 'stripe';
29 29
30 30 public array $supportedFeatures = ['payment', 'refund', 'webhook', 'custom_payment', 'card_update', 'switch_payment_method' => [
31 31 'supported_gateways' => ['stripe', 'paypal'],
32 - ], 'dispute_handler', 'subscriptions', 'zero_recurring', 'system_subscription', 'manual_subscription'];
32 + ], 'dispute_handler', 'subscriptions', 'zero_recurring', 'system_subscription', 'manual_subscription', 'verify_vendor_ids'];
33 33
34 34 public BaseGatewaySettings $settings;
35 35
36 36 public function __construct()
@@ -55,9 +55,9 @@
55 55
56 56 public function meta(): array
57 57 {
58 58 return [
59 - 'title' => 'Card',
59 + 'title' => __('Card', 'fluent-cart'),
60 60 'route' => 'stripe',
61 61 'slug' => 'stripe',
62 62 'label' => 'Stripe',
63 63 'admin_title' => 'Stripe',
@@ -89,9 +89,11 @@
89 89 'amount' => $chargeAmount,
90 90 'currency' => strtolower($transactionCurrency),
91 91 'description' => $storeName . ' #' . $order->invoice_no, // @todo: We will replace with order summary with item names later
92 92 'customer_email' => $paymentInstance->order->email,
93 - 'success_url' => $this->getSuccessUrl($paymentInstance->transaction),
93 + 'success_url' => $paymentInstance->transaction->getSuccessUrl(),
94 + 'gateway_return_url' => Processor::getOnsiteGatewayReturnUrl($paymentInstance->transaction),
95 + 'trx_hash' => $paymentInstance->transaction->uuid,
94 96 'custom_payment_url' => PaymentHelper::getCustomPaymentLink($paymentInstance->order->uuid)
95 97 );
96 98
97 99 if ($paymentInstance->subscription) {
@@ -254,9 +256,9 @@
254 256
255 257 $attempt = max(1, (int) Arr::get($args, 'attempt', 1));
256 258
257 259 $intent = (new API())->createStripeObject('payment_intents', $intentData, $order->mode, [
258 - 'Idempotency-Key' => 'fct_system_charge_' . $order->id . '_' . $attempt,
260 + 'Idempotency-Key' => 'fct_system_charge_' . $order->uuid . '_' . $attempt,
259 261 ]);
260 262
261 263 if (is_wp_error($intent)) {
262 264 return $intent;
@@ -479,8 +481,11 @@
479 481 'redirecting for action' => __('redirecting for action', 'fluent-cart'),
480 482 'You will be redirected to Stripe to complete your payment securely.' => __('You will be redirected to Stripe to complete your payment securely.', 'fluent-cart'),
481 483 'Something went wrong' => __('Something went wrong', 'fluent-cart'),
482 484 'Payment confirmation failed' => __('Payment confirmation failed', 'fluent-cart'),
485 + 'Payment failed. Please try again.' => __('Payment failed. Please try again.', 'fluent-cart'),
486 + 'We could not record that failed attempt. Please reload the page before trying again.' => __('We could not record that failed attempt. Please reload the page before trying again.', 'fluent-cart'),
487 + 'We could not verify your payment status. Please do not pay again. Contact the store to check your order status.' => __('We could not verify your payment status. Please do not pay again. Contact the store to check your order status.', 'fluent-cart'),
483 488 ]
484 489 ]
485 490 ];
486 491 }
@@ -578,9 +583,9 @@
578 583 }
579 584
580 585 public function fields(): array
581 586 {
582 - $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. It will be removed in v1.4.3.');
587 + $disabled = false;
583 588 $providerValue = apply_filters('fluent_cart/form_disable_stripe_connect', $disabled, []) ? 'api_keys' : 'connect';
584 589
585 590 return array(
586 591 'notice' => [
@@ -634,8 +639,23 @@
634 639 ],
635 640 'tooltip' => __('Choose between Embedded and Hosted checkout modes. Embedded mode is recommended for most use cases. For Bank transfers, use Hosted mode. (checkout.session.completed webhook event will be triggered only for hosted mode)', 'fluent-cart'),
636 641 'description' => __("Embedded checkout is recommended for most use cases. For Bank transfers , or if any payment methods are not showing up on embedded checkout, try Hosted checkout. ('checkout.session.completed' webhook event will be triggered only for hosted checkout)", 'fluent-cart')
637 642 ),
643 + 'submit_type' => array(
644 + 'value' => 'auto',
645 + 'label' => __('Submit Button Label', 'fluent-cart'),
646 + 'type' => 'select',
647 + 'filterable' => false,
648 + 'options' => [
649 + ['value' => 'auto', 'label' => __('Automatic (Pay / Subscribe)', 'fluent-cart')],
650 + ['value' => 'pay', 'label' => __('Pay', 'fluent-cart')],
651 + ['value' => 'book', 'label' => __('Book', 'fluent-cart')],
652 + ['value' => 'donate', 'label' => __('Donate', 'fluent-cart')],
653 + ['value' => 'subscribe', 'label' => __('Subscribe', 'fluent-cart')],
654 + ],
655 + 'tooltip' => __('Stripe customises the submit button and surrounding copy from this. Applies to Stripe Hosted Checkout only.', 'fluent-cart'),
656 + 'description' => __('Applies to Stripe Hosted Checkout only, and is ignored when a card is being saved without a charge. Automatic gives one-time orders the "Buy" button and subscriptions the "Subscribe" button.', 'fluent-cart')
657 + ),
638 658 'webhook_desc' => array(
639 659 'value' => Webhook::webhookInstruction(),
640 660 'label' => __('Webhook URL', 'fluent-cart'),
641 661 'type' => 'html_attr'
@@ -788,15 +808,11 @@
788 808 ], 422);
789 809 }
790 810
791 811 $paymentArgs['public_key'] = $publicKey;
812 + $appearance = $this->getElementsAppearance();
813 + $fonts = $this->getElementsFonts();
792 814
793 - // Allow filtering the appearance configuration for Stripe Elements
794 - $appearance = apply_filters_deprecated('fluent_cart_stripe_appearance', [
795 - ['theme' => 'stripe']
796 - ], '1.3.16', 'fluent_cart/stripe_appearance', 'Use fluent_cart/stripe_appearance instead of fluent_cart_stripe_appearance. It will be removed in v1.4.3.');
797 - $appearance = apply_filters('fluent_cart/stripe_appearance', $appearance);
798 -
799 815 $storeCurrency = CurrencySettings::get('currency');
800 816 $intentAmount = (int)$totalPrice;
801 817
802 818 if ($storeCurrency && CurrenciesHelper::isZeroDecimal($storeCurrency)) {
@@ -827,11 +843,13 @@
827 843 // mode — a zero-amount payment mode is invalid — and consent becomes a
828 844 // required checkbox: without a saved card the trial can never bill.
829 845 $payableNow = \FluentCart\App\Services\OrderService::getItemsAmountTotal($cart->cart_data ?? [], false, false);
830 846 if ($payableNow <= 0) {
847 + // Match the SetupIntent usage even when the optional save-card flag is set.
831 848 $intentData = [
832 - 'mode' => 'setup',
833 - 'currency' => strtolower($storeCurrency),
849 + 'mode' => 'setup',
850 + 'currency' => strtolower($storeCurrency),
851 + 'setup_future_usage' => 'off_session',
834 852 ];
835 853 $consentRequired = true;
836 854 }
837 855 }
@@ -842,8 +860,22 @@
842 860 } elseif (empty($intentData['setup_future_usage']) && Arr::get($data, 'save_payment_method') === 'yes') {
843 861 $intentData['setup_future_usage'] = 'on_session';
844 862 }
845 863
864 + // a one-time payment may be changed here.
865 + if ($intentData['mode'] === 'payment') {
866 + $setupFutureUsage = apply_filters(
867 + 'fluent_cart/stripe/client_setup_future_usage',
868 + Arr::get($intentData, 'setup_future_usage'),
869 + ['data' => $data, 'has_subscription' => $hasSubscription]
870 + );
871 + if ($setupFutureUsage) {
872 + $intentData['setup_future_usage'] = $setupFutureUsage;
873 + } else {
874 + unset($intentData['setup_future_usage']);
875 + }
876 + }
877 +
846 878 wp_send_json(
847 879 [
848 880 'status' => 'success',
849 881 'message' => __('Order info retrieved!', 'fluent-cart'),
@@ -850,8 +882,9 @@
850 882 'data' => [],
851 883 'payment_args' => $paymentArgs,
852 884 'intent' => $intentData,
853 885 'appearance' => $appearance,
886 + 'fonts' => $fonts,
854 887 'system_consent' => $systemConsent,
855 888 'consent_required' => $consentRequired,
856 889 ],
857 890 200
@@ -857,8 +890,22 @@
857 890 200
858 891 );
859 892 }
860 893
894 + public function getElementsAppearance(): array
895 + {
896 + $appearance = ['theme' => 'stripe'];
897 +
898 + return (array) apply_filters('fluent_cart/stripe_appearance', $appearance);
899 + }
900 +
901 + public function getElementsFonts(): array
902 + {
903 + $fonts = (array) apply_filters('fluent_cart/stripe_elements_fonts', []);
904 +
905 + return array_values(array_filter($fonts, 'is_array'));
906 + }
907 +
861 908 public function getConnectInfo(): array
862 909 {
863 910 return ConnectConfig::getConnectConfig();
864 911 }
@@ -880,9 +927,9 @@
880 927 public function acceptRemoteDispute($transaction, $args = [])
881 928 {
882 929 $disputeId = Arr::get($transaction->meta, 'dispute_id');
883 930 if (!$disputeId) {
884 - $charge = (new API())->getStripeObject('payment_intents/' . $transaction->vendor_charge_id, ['expand' => ['latest_charge']]);
931 + $charge = (new API())->getStripeObject('payment_intents/' . $transaction->vendor_charge_id, ['expand' => ['latest_charge']], $transaction->payment_mode);
885 932
886 933 if (is_wp_error($charge) || empty($charge['dispute'])) {
887 934 new \WP_Error('No dispute ID found!', __('Please check stripe if the dispute is already accepted or not!', 'fluent-cart'));
888 935 }
@@ -889,9 +936,9 @@
889 936
890 937 $disputeId = Arr::get($charge, 'dispute', '');
891 938 }
892 939
893 - $closeDispute = (new API())->createStripeObject('disputes/' . $disputeId . '/close');
940 + $closeDispute = (new API())->createStripeObject('disputes/' . $disputeId . '/close', [], $transaction->payment_mode);
894 941
895 942 if (is_wp_error($closeDispute)) {
896 943 return $closeDispute;
897 944 }