← All changes
|
app/Modules/PaymentMethods/StripeGateway/Stripe.php
+39
-22
1.6.4
→
1.7.1
View file →
| @@ -91,8 +91,9 @@ | ||
| 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 | 93 | 'success_url' => $paymentInstance->transaction->getSuccessUrl(), |
| 94 | 94 | 'gateway_return_url' => Processor::getOnsiteGatewayReturnUrl($paymentInstance->transaction), |
| 95 | + 'trx_hash' => $paymentInstance->transaction->uuid, | |
| 95 | 96 | 'custom_payment_url' => PaymentHelper::getCustomPaymentLink($paymentInstance->order->uuid) |
| 96 | 97 | ); |
| 97 | 98 | |
| 98 | 99 | if ($paymentInstance->subscription) { |
| @@ -480,8 +481,11 @@ | ||
| 480 | 481 | 'redirecting for action' => __('redirecting for action', 'fluent-cart'), |
| 481 | 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'), |
| 482 | 483 | 'Something went wrong' => __('Something went wrong', 'fluent-cart'), |
| 483 | 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'), | |
| 484 | 488 | ] |
| 485 | 489 | ] |
| 486 | 490 | ]; |
| 487 | 491 | } |
| @@ -804,13 +808,11 @@ | ||
| 804 | 808 | ], 422); |
| 805 | 809 | } |
| 806 | 810 | |
| 807 | 811 | $paymentArgs['public_key'] = $publicKey; |
| 812 | + $appearance = $this->getElementsAppearance(); | |
| 813 | + $fonts = $this->getElementsFonts(); | |
| 808 | 814 | |
| 809 | - // Allow filtering the appearance configuration for Stripe Elements | |
| 810 | - $appearance = ['theme' => 'stripe']; | |
| 811 | - $appearance = apply_filters('fluent_cart/stripe_appearance', $appearance); | |
| 812 | - | |
| 813 | 815 | $storeCurrency = CurrencySettings::get('currency'); |
| 814 | 816 | $intentAmount = (int)$totalPrice; |
| 815 | 817 | |
| 816 | 818 | if ($storeCurrency && CurrenciesHelper::isZeroDecimal($storeCurrency)) { |
| @@ -841,11 +843,13 @@ | ||
| 841 | 843 | // mode — a zero-amount payment mode is invalid — and consent becomes a |
| 842 | 844 | // required checkbox: without a saved card the trial can never bill. |
| 843 | 845 | $payableNow = \FluentCart\App\Services\OrderService::getItemsAmountTotal($cart->cart_data ?? [], false, false); |
| 844 | 846 | if ($payableNow <= 0) { |
| 847 | + // Match the SetupIntent usage even when the optional save-card flag is set. | |
| 845 | 848 | $intentData = [ |
| 846 | - 'mode' => 'setup', | |
| 847 | - 'currency' => strtolower($storeCurrency), | |
| 849 | + 'mode' => 'setup', | |
| 850 | + 'currency' => strtolower($storeCurrency), | |
| 851 | + 'setup_future_usage' => 'off_session', | |
| 848 | 852 | ]; |
| 849 | 853 | $consentRequired = true; |
| 850 | 854 | } |
| 851 | 855 | } |
| @@ -856,22 +860,20 @@ | ||
| 856 | 860 | } elseif (empty($intentData['setup_future_usage']) && Arr::get($data, 'save_payment_method') === 'yes') { |
| 857 | 861 | $intentData['setup_future_usage'] = 'on_session'; |
| 858 | 862 | } |
| 859 | 863 | |
| 860 | - // The browser cannot pass setup_future_usage per-request (this endpoint | |
| 861 | - // receives no body), so extensions that vault cards (e.g. saved payment | |
| 862 | - // methods) resolve it here, server-side. Must be matched on the actual | |
| 863 | - // PaymentIntent at place-order (fluent_cart/payments/stripe_onetime_intent_args) | |
| 864 | - // or Stripe rejects the confirmation for a setup_future_usage mismatch. | |
| 865 | - $setupFutureUsage = apply_filters( | |
| 866 | - 'fluent_cart/stripe/client_setup_future_usage', | |
| 867 | - Arr::get($intentData, 'setup_future_usage'), | |
| 868 | - ['data' => $data, 'has_subscription' => $hasSubscription] | |
| 869 | - ); | |
| 870 | - if ($setupFutureUsage) { | |
| 871 | - $intentData['setup_future_usage'] = $setupFutureUsage; | |
| 872 | - } else { | |
| 873 | - unset($intentData['setup_future_usage']); | |
| 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 | + } | |
| 874 | 876 | } |
| 875 | 877 | |
| 876 | 878 | wp_send_json( |
| 877 | 879 | [ |
| @@ -880,8 +882,9 @@ | ||
| 880 | 882 | 'data' => [], |
| 881 | 883 | 'payment_args' => $paymentArgs, |
| 882 | 884 | 'intent' => $intentData, |
| 883 | 885 | 'appearance' => $appearance, |
| 886 | + 'fonts' => $fonts, | |
| 884 | 887 | 'system_consent' => $systemConsent, |
| 885 | 888 | 'consent_required' => $consentRequired, |
| 886 | 889 | ], |
| 887 | 890 | 200 |
| @@ -887,8 +890,22 @@ | ||
| 887 | 890 | 200 |
| 888 | 891 | ); |
| 889 | 892 | } |
| 890 | 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 | + | |
| 891 | 908 | public function getConnectInfo(): array |
| 892 | 909 | { |
| 893 | 910 | return ConnectConfig::getConnectConfig(); |
| 894 | 911 | } |
| @@ -910,9 +927,9 @@ | ||
| 910 | 927 | public function acceptRemoteDispute($transaction, $args = []) |
| 911 | 928 | { |
| 912 | 929 | $disputeId = Arr::get($transaction->meta, 'dispute_id'); |
| 913 | 930 | if (!$disputeId) { |
| 914 | - $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); | |
| 915 | 932 | |
| 916 | 933 | if (is_wp_error($charge) || empty($charge['dispute'])) { |
| 917 | 934 | new \WP_Error('No dispute ID found!', __('Please check stripe if the dispute is already accepted or not!', 'fluent-cart')); |
| 918 | 935 | } |
| @@ -919,9 +936,9 @@ | ||
| 919 | 936 | |
| 920 | 937 | $disputeId = Arr::get($charge, 'dispute', ''); |
| 921 | 938 | } |
| 922 | 939 | |
| 923 | - $closeDispute = (new API())->createStripeObject('disputes/' . $disputeId . '/close'); | |
| 940 | + $closeDispute = (new API())->createStripeObject('disputes/' . $disputeId . '/close', [], $transaction->payment_mode); | |
| 924 | 941 | |
| 925 | 942 | if (is_wp_error($closeDispute)) { |
| 926 | 943 | return $closeDispute; |
| 927 | 944 | } |