diff --git a/changelog.txt b/changelog.txt index 2314e02d4..d6448106d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,7 @@ *** Changelog *** = 1.6.5 - 2022-01-31 = -* Fix - Allow guest users to purchase subscription products #422 +* Fix - Allow guest users to purchase subscription products from checkout page #422 * Fix - Transaction ID missing for renewal order #424 * Fix - Save your credit card checkbox should be removed in pay for order for subscriptions #420 * Fix - Null currency error when the Aelia currency switcher plugin is active #426 diff --git a/modules/ppcp-api-client/src/Factory/PayerFactory.php b/modules/ppcp-api-client/src/Factory/PayerFactory.php index fedeaa5a1..70d33dee3 100644 --- a/modules/ppcp-api-client/src/Factory/PayerFactory.php +++ b/modules/ppcp-api-client/src/Factory/PayerFactory.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\ApiClient\Factory; +use WooCommerce\PayPalCommerce\ApiClient\Entity\Address; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer; use WooCommerce\PayPalCommerce\ApiClient\Entity\PayerName; use WooCommerce\PayPalCommerce\ApiClient\Entity\PayerTaxInfo; @@ -147,4 +148,55 @@ class PayerFactory { $tax_info ); } + + /** + * Returns a Payer object based off the given checkout form fields. + * + * @param array $form_fields The checkout form fields. + * @return Payer + */ + public function from_checkout_form( array $form_fields ): Payer { + + $first_name = $form_fields['billing_first_name'] ?? ''; + $last_name = $form_fields['billing_last_name'] ?? ''; + $billing_email = $form_fields['billing_email'] ?? ''; + $billing_country = $form_fields['billing_country'] ?? ''; + $billing_address_1 = $form_fields['billing_address_1'] ?? ''; + $billing_address_2 = $form_fields['billing_address_2'] ?? ''; + $admin_area_1 = $form_fields['billing_state'] ?? ''; + $admin_area_2 = $form_fields['billing_city'] ?? ''; + $billing_postcode = $form_fields['billing_postcode'] ?? ''; + + $phone = null; + if ( isset( $form_fields['billing_phone'] ) && '' !== $form_fields['billing_phone'] ) { + // make sure the phone number contains only numbers and is max 14. chars long. + $national_number = $form_fields['billing_phone']; + $national_number = preg_replace( '/[^0-9]/', '', $national_number ); + + if ( null !== $national_number ) { + $national_number = substr( $national_number, 0, 14 ); + + $phone = new PhoneWithType( + 'HOME', + new Phone( $national_number ) + ); + } + } + + return new Payer( + new PayerName( $first_name, $last_name ), + $billing_email, + '', + new Address( + $billing_country, + $billing_address_1, + $billing_address_2, + $admin_area_1, + $admin_area_2, + $billing_postcode + ), + null, + $phone + ); + } } diff --git a/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php b/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php index 4a7f63348..ec6b55c7a 100644 --- a/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php +++ b/modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php @@ -12,8 +12,10 @@ namespace WooCommerce\PayPalCommerce\Button\Endpoint; use Exception; use Psr\Log\LoggerInterface; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; +use WooCommerce\PayPalCommerce\ApiClient\Entity\Address; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer; +use WooCommerce\PayPalCommerce\ApiClient\Entity\PayerName; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentMethod; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; @@ -337,6 +339,15 @@ class CreateOrderEndpoint implements EndpointInterface { $payer = $this->payer_factory->from_paypal_response( json_decode( wp_json_encode( $data['payer'] ) ) ); } + + if ( ! $payer && isset( $data['form'] ) ) { + parse_str( $data['form'], $form_fields ); + + if ( isset( $form_fields['billing_email'] ) && '' !== $form_fields['billing_email'] ) { + return $this->payer_factory->from_checkout_form( $form_fields ); + } + } + return $payer; } diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 395f98bca..2eafb4ccb 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -741,7 +741,7 @@ return array( 'gateway' => 'paypal', ), 'disable_funding' => array( - 'title' => __( 'Disable funding sources', 'woocommerce-paypal-payments' ), + 'title' => __( 'Hide Funding Source(s)', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-multiselect', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), diff --git a/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php b/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php index ce5e9ee96..319f2c844 100644 --- a/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php +++ b/modules/ppcp-wc-gateway/src/Notice/ConnectAdminNotice.php @@ -57,7 +57,7 @@ class ConnectAdminNotice { $message = sprintf( /* translators: %1$s the gateway name. */ __( - 'PayPal Checkout is almost ready. To get started, connect your account.', + 'PayPal Payments is almost ready. To get started, connect your account.', 'woocommerce-paypal-payments' ), admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ) diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php index b3db8d3a6..ba2f4b08c 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php @@ -14,9 +14,9 @@ use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\Onboarding\State; -use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\Webhooks\WebhookRegistrar; +use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; /** * Class SettingsListener diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php index 5de6680d6..ee8746ca5 100644 --- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php +++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php @@ -21,6 +21,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Assets\SettingsPageAssets; use WooCommerce\PayPalCommerce\WcGateway\Checkout\CheckoutPayPalAddressPreset; use WooCommerce\PayPalCommerce\WcGateway\Checkout\DisableGateways; use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint; +use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice; @@ -132,6 +133,23 @@ class WCGatewayModule implements ModuleInterface { $endpoint->handle_request(); } ); + + add_action( + 'woocommerce_paypal_payments_gateway_migrate', + static function () use ( $c ) { + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof Settings ); + + try { + if ( $settings->get( '3d_secure_contingency' ) === '3D_SECURE' ) { + $settings->set( '3d_secure_contingency', 'SCA_ALWAYS' ); + $settings->persist(); + } + } catch ( NotFoundException $exception ) { + return; + } + } + ); } /** diff --git a/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php b/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php index bc56dd935..ed85bc040 100644 --- a/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php +++ b/modules/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php @@ -10,13 +10,14 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Webhooks\Handler; use Psr\Log\LoggerInterface; +use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait; /** * Class PaymentCaptureRefunded */ class PaymentCaptureRefunded implements RequestHandler { - use PrefixTrait; + use PrefixTrait, TransactionIdHandlingTrait; /** * The logger. @@ -150,6 +151,11 @@ class PaymentCaptureRefunded implements RequestHandler { 'order' => $wc_order, ) ); + + if ( is_array( $request['resource'] ) && isset( $request['resource']['id'] ) ) { + $this->update_transaction_id( $request['resource']['id'], $wc_order, $this->logger ); + } + $response['success'] = true; return rest_ensure_response( $response ); } diff --git a/readme.txt b/readme.txt index f01ee26dd..b607564d9 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: woocommerce, automattic Tags: woocommerce, paypal, payments, ecommerce, e-commerce, store, sales, sell, shop, shopping, cart, checkout Requires at least: 5.3 -Tested up to: 5.8 +Tested up to: 5.9 Requires PHP: 7.1 Stable tag: 1.6.5 License: GPLv2 @@ -82,7 +82,7 @@ Follow the steps below to connect the plugin to your PayPal account: == Changelog == = 1.6.5 = -* Fix - Allow guest users to purchase subscription products #422 +* Fix - Allow guest users to purchase subscription products from checkout page #422 * Fix - Transaction ID missing for renewal order #424 * Fix - Save your credit card checkbox should be removed in pay for order for subscriptions #420 * Fix - Null currency error when the Aelia currency switcher plugin is active #426