← All changes
|
app/Modules/PaymentMethods/PayPalGateway/PayPal.php
+36
-10
1.6.0
→
1.6.6
View file →
| @@ -24,9 +24,9 @@ | ||
| 24 | 24 | private $methodSlug = 'paypal'; |
| 25 | 25 | |
| 26 | 26 | public array $supportedFeatures = ['payment', 'refund', 'webhook', 'custom_payment', 'card_update', 'switch_payment_method' => [ |
| 27 | 27 | 'supported_gateways' => ['stripe', 'paypal'], |
| 28 | - ], 'dispute_handler', 'subscriptions', 'resume_subscription', 'system_subscription', 'manual_subscription']; | |
| 28 | + ], 'dispute_handler', 'subscriptions', 'resume_subscription', 'system_subscription', 'manual_subscription', 'verify_vendor_ids']; | |
| 29 | 29 | |
| 30 | 30 | private $vaultUserIdToken = ''; |
| 31 | 31 | |
| 32 | 32 | private $vaultSetupUnavailable = false; |
| @@ -65,8 +65,10 @@ | ||
| 65 | 65 | public function boot() |
| 66 | 66 | { |
| 67 | 67 | (new IPN())->init(); |
| 68 | 68 | |
| 69 | + add_action('fluent_cart_action_paypal_connect', [ConnectConfig::class, 'handleConnect']); | |
| 70 | + | |
| 69 | 71 | add_action('wp_ajax_nopriv_fluent_cart_confirm_paypal_payment', [$this, 'confirmPayPalSinglePayment']); |
| 70 | 72 | add_action('wp_ajax_fluent_cart_confirm_paypal_payment', [$this, 'confirmPayPalSinglePayment']); |
| 71 | 73 | |
| 72 | 74 | add_action('wp_ajax_nopriv_fluent_cart_confirm_paypal_subscription', [$this, 'confirmPayPalSubscription']); |
| @@ -393,15 +395,17 @@ | ||
| 393 | 395 | $paidCurrency = strtoupper(Arr::get($unit, 'amount.currency_code', '')); |
| 394 | 396 | } |
| 395 | 397 | } |
| 396 | 398 | |
| 397 | - if ($paidAmount != $transaction->total) { | |
| 399 | + $expectedAmount = PayPalHelper::wireCents($transaction->total, $transaction->currency); | |
| 400 | + | |
| 401 | + if ($paidAmount != $expectedAmount) { | |
| 398 | 402 | fluent_cart_warning_log( |
| 399 | 403 | __('PayPal Amount Mismatch Attempt', 'fluent-cart'), |
| 400 | 404 | sprintf( |
| 401 | 405 | /* translators: %1$s: expected amount, %2$s: received amount */ |
| 402 | 406 | __('Payment amount mismatch detected. Expected: %1$s, Received: %2$s. This may indicate payment tampering.', 'fluent-cart'), |
| 403 | - Helper::toDecimal($transaction->total), | |
| 407 | + Helper::toDecimal($expectedAmount), | |
| 404 | 408 | Helper::toDecimal($paidAmount) |
| 405 | 409 | ), |
| 406 | 410 | [ |
| 407 | 411 | 'module_name' => 'order', |
| @@ -453,9 +457,9 @@ | ||
| 453 | 457 | } |
| 454 | 458 | |
| 455 | 459 | wp_send_json([ |
| 456 | 460 | 'status' => 'pending', |
| 457 | - 'redirect_url' => $transaction->getReceiptPageUrl(true), | |
| 461 | + 'redirect_url' => $this->getConfirmRedirectUrl($transaction), | |
| 458 | 462 | 'order' => [ |
| 459 | 463 | 'uuid' => $transaction->order->uuid |
| 460 | 464 | ], |
| 461 | 465 | 'message' => __('Your payment is being reviewed by PayPal. Your order will be confirmed once the payment is completed.', 'fluent-cart') |
| @@ -515,9 +519,9 @@ | ||
| 515 | 519 | } |
| 516 | 520 | |
| 517 | 521 | wp_send_json([ |
| 518 | 522 | 'status' => 'success', |
| 519 | - 'redirect_url' => $transaction->getReceiptPageUrl(true), | |
| 523 | + 'redirect_url' => $this->getConfirmRedirectUrl($transaction), | |
| 520 | 524 | 'order' => [ |
| 521 | 525 | 'uuid' => $transaction->order->uuid |
| 522 | 526 | ], |
| 523 | 527 | 'message' => __('Payment has been paid successfully! Redirecting...', 'fluent-cart') |
| @@ -600,9 +604,9 @@ | ||
| 600 | 604 | } |
| 601 | 605 | |
| 602 | 606 | wp_send_json([ |
| 603 | 607 | 'status' => 'success', |
| 604 | - 'redirect_url' => $transaction->getReceiptPageUrl(true), | |
| 608 | + 'redirect_url' => $this->getConfirmRedirectUrl($transaction), | |
| 605 | 609 | 'order' => [ |
| 606 | 610 | 'uuid' => $transaction->order->uuid |
| 607 | 611 | ], |
| 608 | 612 | 'message' => __('Your PayPal account has been saved successfully! Redirecting...', 'fluent-cart') |
| @@ -715,9 +719,9 @@ | ||
| 715 | 719 | |
| 716 | 720 | wp_send_json([ |
| 717 | 721 | 'status' => 'success', |
| 718 | 722 | 'message' => __('Subscription has been activated successfully!', 'fluent-cart'), |
| 719 | - 'redirect_url' => $transaction->getReceiptPageUrl(true), | |
| 723 | + 'redirect_url' => $this->getConfirmRedirectUrl($transaction), | |
| 720 | 724 | 'order' => [ |
| 721 | 725 | 'uuid' => $transaction->order->uuid |
| 722 | 726 | ], |
| 723 | 727 | ], 200); |
| @@ -727,8 +731,27 @@ | ||
| 727 | 731 | { |
| 728 | 732 | return API::getResource('billing/subscriptions/' . $subscriptionId); |
| 729 | 733 | } |
| 730 | 734 | |
| 735 | + /** | |
| 736 | + * Post-payment redirect for PayPal confirm responses. The canonical | |
| 737 | + * fluent_cart/payment/success_url filter fires inside getSuccessUrl(); | |
| 738 | + * the receipt_page_url filter is bridged for existing consumers of the | |
| 739 | + * previous PayPal redirect and will be dropped from this path later. | |
| 740 | + */ | |
| 741 | + private function getConfirmRedirectUrl($transaction) | |
| 742 | + { | |
| 743 | + $url = $transaction->getSuccessUrl(); | |
| 744 | + | |
| 745 | + return apply_filters_deprecated( | |
| 746 | + 'fluent_cart/transaction/receipt_page_url', | |
| 747 | + [$url, ['transaction' => $transaction, 'order' => $transaction->order]], | |
| 748 | + '1.6.2', | |
| 749 | + 'fluent_cart/payment/success_url', | |
| 750 | + 'PayPal post-payment redirects now go through fluent_cart/payment/success_url. Hook that filter instead; this bridge will be removed in a future release.' | |
| 751 | + ); | |
| 752 | + } | |
| 753 | + | |
| 731 | 754 | protected function verifyPayPalPayment($payPalReferenceId) |
| 732 | 755 | { |
| 733 | 756 | return API::verifyPayment($payPalReferenceId); |
| 734 | 757 | } |
| @@ -878,10 +901,10 @@ | ||
| 878 | 901 | if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'POST') { |
| 879 | 902 | return; |
| 880 | 903 | } |
| 881 | 904 | |
| 905 | + // Sends the HTTP status via status_header() and exits — never returns. | |
| 882 | 906 | (new IPN())->processWebhook(); |
| 883 | - exit(200); | |
| 884 | 907 | } |
| 885 | 908 | |
| 886 | 909 | public function getTransactionUrl($url, $data) |
| 887 | 910 | { |
| @@ -1197,8 +1220,9 @@ | ||
| 1197 | 1220 | 'No Subscription ID' => __('No Subscription ID', 'fluent-cart'), |
| 1198 | 1221 | 'no processing' => __('no processing', 'fluent-cart'), |
| 1199 | 1222 | 'not proper order handler' => __('not proper order handler', 'fluent-cart'), |
| 1200 | 1223 | 'Payment confirmation failed' => __('Payment confirmation failed', 'fluent-cart'), |
| 1224 | + 'Your payment is being reviewed. We will confirm your order once it completes.' => __('Your payment is being reviewed. We will confirm your order once it completes.', 'fluent-cart'), | |
| 1201 | 1225 | ] |
| 1202 | 1226 | ] |
| 1203 | 1227 | ]; |
| 1204 | 1228 | } |
| @@ -1235,12 +1259,14 @@ | ||
| 1235 | 1259 | } |
| 1236 | 1260 | |
| 1237 | 1261 | $paymentArgs['public_key'] = $clientId; |
| 1238 | 1262 | |
| 1263 | + $currency = strtoupper(CurrencySettings::get('currency')); | |
| 1264 | + | |
| 1239 | 1265 | $paymentDetails = [ |
| 1240 | 1266 | 'mode' => 'payment', |
| 1241 | - 'amount' => number_format(Helper::toDecimalWithoutComma($totalPrice), 2, '.', ''), | |
| 1242 | - 'currency' => strtoupper(CurrencySettings::get('currency')), | |
| 1267 | + 'amount' => PayPalHelper::formatAmount($totalPrice, $currency), | |
| 1268 | + 'currency' => $currency, | |
| 1243 | 1269 | ]; |
| 1244 | 1270 | |
| 1245 | 1271 | $renderAsSubscription = $this->shouldRenderAsSubscriptionMode($hasSubscription); |
| 1246 | 1272 | |