PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.17.0
GiveWP – Donation Plugin and Fundraising Platform v4.17.0
4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 All 256 releases
← All changes | src/PaymentGateways/PayPalCommerce/AjaxRequestHandler.php +17 -102 4.16.8 → 4.17.0 View file →
@@ -6,9 +6,8 @@
6 6 use Give\DonationForms\Exceptions\DonationFormFieldErrorsException;
7 7 use Give\DonationForms\Exceptions\DonationFormForbidden;
8 8 use Give\Log\Log;
9 9 use Give\PaymentGateways\PayPalCommerce\Models\MerchantDetail;
10 -use Give\PaymentGateways\PayPalCommerce\PayPalCheckoutSdk\ProcessorResponseError;
11 10 use Give\PaymentGateways\PayPalCommerce\Repositories\MerchantDetails;
12 11 use Give\PaymentGateways\PayPalCommerce\Repositories\PayPalAuth;
13 12 use Give\PaymentGateways\PayPalCommerce\Repositories\PayPalOrder;
14 13 use Give\PaymentGateways\PayPalCommerce\Repositories\Settings;
@@ -328,12 +327,14 @@
328 327 ];
329 328 }
330 329
331 330 /**
332 - * Approve order.
331 + * Refuses every request. Both form versions now send their order id with the donation and let
332 + * PayPalCommerce::createPayment() capture it, so nothing legitimate captures from the browser.
333 + * The endpoint stays registered so anything still calling it receives an error it can report,
334 + * rather than an empty response from a missing action.
333 335 *
334 - * @todo: handle payment capture error on frontend.
335 - *
336 + * @since 4.16.9 Refuse every request; the capture for both form versions happens in PayPalCommerce::createPayment().
336 337 * @since 4.16.7.1 Refuse v3 forms; their capture happens in PayPalCommerce::createPayment(). Validate
337 338 * the posted form before every capture, not only when the amount changed.
338 339 * @since 4.14.4 Validate donation amount before approving an order.
339 340 * @since 3.2.0 Discover error by checking capture status.
@@ -340,33 +341,20 @@
340 341 * @since 2.9.0
341 342 */
342 343 public function approveOrder()
343 344 {
344 - $this->validateFrontendRequest();
345 - $this->rejectV3FormRequest();
346 -
347 - $orderId = give_clean($_GET['order']);
348 - $updateAmount = filter_var(give_clean($_GET['update_amount']), FILTER_VALIDATE_BOOLEAN);
349 -
350 - try {
351 - $orderData = $this->getOrderData();
352 -
353 - if ($updateAmount) {
354 - $this->validateOrderAmountNotDecreased($orderId, $orderData['donationAmount']);
355 - give(PayPalOrder::class)->updateOrderAmount($orderId, $orderData);
356 - }
357 -
358 - $result = give(PayPalOrder::class)->approveOrder($orderId);
359 - // PayPal does not return error in case of invalid cvv. So we need to check capture status and return error.
360 - // ref - https://feedback.givewp.com/bug-reports/p/paypal-credit-card-donations-can-generate-a-fatal-error
361 - $this->returnErrorOnFailedApproveOrderResponse($result);
362 - wp_send_json_success(['order' => $result,]);
363 - } catch (\Exception $ex) {
364 - wp_send_json_error(['error' => json_decode($ex->getMessage(), true),]);
365 - }
345 + wp_send_json_error(
346 + ['error' => __('PayPal orders are captured when the donation is submitted.', 'give')]
347 + );
366 348 }
367 349
368 350 /**
351 + * Refuses every request. The order amount is reconciled against the donation in
352 + * PayPalCommerce::createPayment() before the capture, so no form version needs the browser to
353 + * change an order's amount. The endpoint stays registered for the same reason approveOrder()
354 + * does: a caller gets an error it can report rather than an empty response.
355 + *
356 + * @since 4.16.9 Refuse every request; the order amount is reconciled in PayPalCommerce::createPayment().
369 357 * @since 4.16.7.1 Refuse v3 forms; PayPalCommerce::createPayment() reconciles their order amount.
370 358 * @since 4.14.4 Validate donation amount before updating an order amount.
371 359 * @since 3.4.2
372 360 */
@@ -371,22 +359,11 @@
371 359 * @since 3.4.2
372 360 */
373 361 public function updateOrderAmount()
374 362 {
375 - $this->validateFrontendRequest();
376 - $this->rejectV3FormRequest();
377 -
378 - $orderId = give_clean($_GET['order']);
379 -
380 - try {
381 - $orderData = $this->getOrderData();
382 - $this->validateOrderAmountNotDecreased($orderId, $orderData['donationAmount']);
383 - give(PayPalOrder::class)->updateOrderAmount($orderId, $orderData);
384 -
385 - wp_send_json_success(['order' => $orderId,]);
386 - } catch (\Exception $ex) {
387 - wp_send_json_error(['error' => json_decode($ex->getMessage(), true),]);
388 - }
363 + wp_send_json_error(
364 + ['error' => __('PayPal order amounts are reconciled when the donation is submitted.', 'give')]
365 + );
389 366 }
390 367
391 368 /**
392 369 * Return on boarding trouble notice.
@@ -530,47 +507,8 @@
530 507 }
531 508 }
532 509
533 510 /**
534 - * Visual Form Builder (v3) forms never call the approve and update-amount endpoints: their order
535 - * is reconciled and captured in PayPalCommerce::createPayment(), after the donation exists.
536 - * Refusing them here keeps these endpoints from capturing outside donation processing.
537 - *
538 - * @since 4.16.7.1
539 - */
540 - private function rejectV3FormRequest(): void
541 - {
542 - if (FormUtils::isV3Form(absint($_POST['give-form-id']))) {
543 - wp_send_json_error(
544 - ['error' => __('This request is not supported for this donation form.', 'give')],
545 - 403
546 - );
547 - }
548 - }
549 -
550 - /**
551 - * Validate that the new donation amount is not less than the original PayPal order amount.
552 - *
553 - * @since 4.14.4
554 - *
555 - * @param string $orderId
556 - * @param float|string $newAmount
557 - */
558 - private function validateOrderAmountNotDecreased(string $orderId, $newAmount): void
559 - {
560 - $newAmount = (float)$newAmount;
561 -
562 - $currentOrder = give(PayPalOrder::class)->getApprovedOrder($orderId);
563 - $currentAmount = (float)$currentOrder->purchase_units[0]->amount->value;
564 -
565 - if ($newAmount < $currentAmount) {
566 - wp_send_json_error([
567 - 'error' => __('Donation amount cannot be decreased.', 'give'),
568 - ]);
569 - }
570 - }
571 -
572 - /**
573 511 * This function should return address array in PayPal rest api accepted format.
574 512 *
575 513 * @since 3.1.0 Return address only if setting enabled and has valida country in PayPal accepted formatted.
576 514 * @since 2.11.1
@@ -590,28 +528,5 @@
590 528
591 529 return $address;
592 530 }
593 531
594 - /**
595 - * This function should validate PayPal ApproveOrder response and respond to ajax request on error.
596 - *
597 - * @since 3.2.0
598 - */
599 - private function returnErrorOnFailedApproveOrderResponse(\stdClass $response)
600 - {
601 - // Get capture.
602 - // ref - https://developer.paypal.com/docs/api/orders/v2/#orders_capture
603 - $capture = $response->purchase_units[0]->payments->captures[0];
604 -
605 - // Check if capture status is failed or declined.
606 - if (
607 - in_array($capture->status, ['FAILED', 'DECLINED'])
608 - && property_exists($capture, 'processor_response')
609 - ) {
610 - $error = ProcessorResponseError::getError($capture->processor_response);
611 -
612 - if ($error) {
613 - wp_send_json_error(['error' => $error]);
614 - }
615 - }
616 - }
617 532 }