From 0669708ad928994ba51d62603ef1fc229ea91557 Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Mon, 18 Jan 2021 16:13:08 +0100 Subject: [PATCH 01/26] unset phone if empty --- .../ppcp-button/src/Endpoint/class-createorderendpoint.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php b/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php index b8452434e..b43fc9532 100644 --- a/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php +++ b/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Button\Endpoint; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer; use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentMethod; @@ -16,7 +17,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository; -use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; @@ -215,7 +215,11 @@ class CreateOrderEndpoint implements EndpointInterface { $number = preg_replace( '/[^0-9]/', '', $number ); $number = substr( $number, 0, 14 ); $data['payer']['phone']['phone_number']['national_number'] = $number; + if( empty($data['payer']['phone']['phone_number']['national_number'] ) ) { + unset($data['payer']['phone']); + } } + $payer = $this->payer_factory->from_paypal_response( json_decode( wp_json_encode( $data['payer'] ) ) ); } return $payer; From b82fc6128b4d3ee9b53e8bd77dd28a9c1b77f759 Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Mon, 18 Jan 2021 16:13:22 +0100 Subject: [PATCH 02/26] add test --- .../Endpoint/CreateOrderEndpointTest.php | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php diff --git a/tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php b/tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php new file mode 100644 index 000000000..c8b3b05a7 --- /dev/null +++ b/tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php @@ -0,0 +1,84 @@ +getMethod( 'payer' ); + $method->setAccessible( true ); + + + $payer = $method->invokeArgs( $testee, array( $data ) ); + $this->assertEquals($expectedResult, $payer); + + } + + public function dataForTestPhoneNumber() : array { + + return [ + 'emptyStringPhone' => [ + [ + 'context' => 'none', + 'payer'=>[ + 'phone'=>[ + 'phone_number'=>[ + 'national_number'=>'123456789876' + ] + ] + ] + ], + [ + [ + 'context' => 'none', + 'payer'=>[] + ] + ] + ] + ]; + } +} \ No newline at end of file From 1f39afc6e6cbf45eb479fd635932196a77b0b3b8 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Mon, 18 Jan 2021 17:04:09 +0100 Subject: [PATCH 03/26] Introduce pay in 3 for UK --- .../src/Helper/class-messagesapply.php | 1 + modules/ppcp-wc-gateway/services.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/modules/ppcp-button/src/Helper/class-messagesapply.php b/modules/ppcp-button/src/Helper/class-messagesapply.php index ccfdbbced..7f37fba86 100644 --- a/modules/ppcp-button/src/Helper/class-messagesapply.php +++ b/modules/ppcp-button/src/Helper/class-messagesapply.php @@ -22,6 +22,7 @@ class MessagesApply { */ private $countries = array( 'US', + 'GB', ); /** diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 1aba3f682..bb8c82d02 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1785,6 +1785,24 @@ return array( unset( $fields['disable_funding']['options']['card'] ); } + /** + * Enable Pay in 3 for UK. + */ + if ( 'GB' === $country ) { + $fields['message_heading'] = [ + 'heading' => __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_PROGRESSIVE, + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'messages' ), + 'gateway' => 'paypal', + 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), + 'class' => array( 'ppcp-subheading' ), + ]; + } + $dcc_applies = $container->get( 'api.helpers.dccapplies' ); /** * Depending on your store location, some credit cards can't be used. From 3ab4d0ece4477894588ff55cda986f8c2e783907 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Mon, 18 Jan 2021 17:23:53 +0100 Subject: [PATCH 04/26] Update title and description for single product and cart page --- modules/ppcp-wc-gateway/services.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index bb8c82d02..0b8edeb09 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1801,6 +1801,30 @@ return array( 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), 'class' => array( 'ppcp-subheading' ), ]; + $fields['message_product_heading'] = [ + 'heading' => __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_PROGRESSIVE, + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'messages' ), + 'gateway' => 'paypal', + 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), + 'class' => array( 'ppcp-subheading' ), + ]; + $fields['message_cart_heading'] = [ + 'heading' => __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_PROGRESSIVE, + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'messages' ), + 'gateway' => 'paypal', + 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), + 'class' => array( 'ppcp-subheading' ), + ]; } $dcc_applies = $container->get( 'api.helpers.dccapplies' ); From f826c25f64b14c770e73254fba12665349fc9e21 Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Tue, 19 Jan 2021 09:50:07 +0100 Subject: [PATCH 05/26] fix tests and cs --- .../Endpoint/class-createorderendpoint.php | 6 +- patchwork.json | 5 + .../Endpoint/CreateOrderEndpointTest.php | 161 ++++++++++++++---- 3 files changed, 138 insertions(+), 34 deletions(-) create mode 100644 patchwork.json diff --git a/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php b/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php index b43fc9532..ec4e88a99 100644 --- a/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php +++ b/modules/ppcp-button/src/Endpoint/class-createorderendpoint.php @@ -215,9 +215,9 @@ class CreateOrderEndpoint implements EndpointInterface { $number = preg_replace( '/[^0-9]/', '', $number ); $number = substr( $number, 0, 14 ); $data['payer']['phone']['phone_number']['national_number'] = $number; - if( empty($data['payer']['phone']['phone_number']['national_number'] ) ) { - unset($data['payer']['phone']); - } + if ( empty( $data['payer']['phone']['phone_number']['national_number'] ) ) { + unset( $data['payer']['phone'] ); + } } $payer = $this->payer_factory->from_paypal_response( json_decode( wp_json_encode( $data['payer'] ) ) ); diff --git a/patchwork.json b/patchwork.json new file mode 100644 index 000000000..dd62edf7f --- /dev/null +++ b/patchwork.json @@ -0,0 +1,5 @@ +{ + "redefinable-internals": [ + "json_decode" + ] +} diff --git a/tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php b/tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php index c8b3b05a7..2f4efbe8e 100644 --- a/tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php +++ b/tests/PHPUnit/Button/Endpoint/CreateOrderEndpointTest.php @@ -4,23 +4,23 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Button\Endpoint; +use Mockery; +use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use ReflectionClass; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; -use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory; use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository; use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\TestCase; -use Mockery; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use function Brain\Monkey\Functions\expect; class CreateOrderEndpointTest extends TestCase { - + use MockeryPHPUnitIntegration; /** * @dataProvider dataForTestPhoneNumber * @test @@ -28,34 +28,22 @@ class CreateOrderEndpointTest extends TestCase * @param $data * @param $expectedResult */ - public function payerVerifiesPhoneNumber($data, $expectedResult) { - $request_data = Mockery::mock(RequestData::class); - $cart_repository = Mockery::mock(CartRepository::class); - $purchase_unit_factory = Mockery::mock(PurchaseUnitFactory::class); - $order_endpoint = Mockery::mock(OrderEndpoint::class); - $payer_factory = Mockery::mock(PayerFactory::class); - $session_handler = Mockery::mock(SessionHandler::class); - $settings = Mockery::mock(Settings::class); - $early_order_handler = Mockery::mock(EarlyOrderHandler::class); + public function payerVerifiesPhoneNumber($data, $expectedResult) + { + list($payer_factory, $testee) = $this->mockTestee(); - $testee = new CreateOrderEndpoint( - $request_data, - $cart_repository, - $purchase_unit_factory, - $order_endpoint, - $payer_factory, - $session_handler, - $settings, - $early_order_handler - ); - $reflector = new ReflectionClass( CreateOrderEndpoint::class ); - $method = $reflector->getMethod( 'payer' ); - $method->setAccessible( true ); + $method = $this->testPrivateMethod(CreateOrderEndpoint::class, 'payer'); + $dataString = wp_json_encode($expectedResult['payer']); + $dataObj = json_decode(wp_json_encode($expectedResult['payer'])); + + expect('wp_json_encode')->once()->with($expectedResult['payer']) + ->andReturn($dataString); + expect('json_decode')->once()->with($dataString)->andReturn($dataObj); - $payer = $method->invokeArgs( $testee, array( $data ) ); - $this->assertEquals($expectedResult, $payer); + $payer_factory->expects('from_paypal_response')->with($dataObj); + $method->invokeArgs($testee, array($data)); } public function dataForTestPhoneNumber() : array { @@ -65,20 +53,131 @@ class CreateOrderEndpointTest extends TestCase [ 'context' => 'none', 'payer'=>[ + 'name'=>['given_name'=>'testName'], 'phone'=>[ 'phone_number'=>[ - 'national_number'=>'123456789876' + 'national_number'=>'' ] ] ] ], [ - [ - 'context' => 'none', - 'payer'=>[] + 'context' => 'none', + 'payer' => [ + 'name' => ['given_name' => 'testName'] + ] + ] + ], + 'tooLongStringPhone' => [ + [ + 'context' => 'none', + 'payer'=>[ + 'name'=>['given_name'=>'testName'], + 'phone'=>[ + 'phone_number'=>[ + 'national_number'=>'43241341234123412341234123123412341' + ] + ] + ] + ], + [ + 'context' => 'none', + 'payer'=>[ + 'name'=>['given_name'=>'testName'], + 'phone'=>[ + 'phone_number'=>[ + 'national_number'=>'43241341234123' + ] + ] + ] + ] + ], + 'removeNonISOStringPhone' => [ + [ + 'context' => 'none', + 'payer'=>[ + 'name'=>['given_name'=>'testName'], + 'phone'=>[ + 'phone_number'=>[ + 'national_number'=>'432a34as73737373' + ] + ] + ] + ], + [ + 'context' => 'none', + 'payer'=>[ + 'name'=>['given_name'=>'testName'], + 'phone'=>[ + 'phone_number'=>[ + 'national_number'=>'4323473737373' + ] + ] + ] + ] + ], + 'notNumbersStringPhone' => [ + [ + 'context' => 'none', + 'payer'=>[ + 'name'=>['given_name'=>'testName'], + 'phone'=>[ + 'phone_number'=>[ + 'national_number'=>'this is_notaPhone' + ] + ] + ] + ], + [ + 'context' => 'none', + 'payer'=>[ + 'name'=>['given_name'=>'testName'] ] ] ] ]; } + + /** + * @return array + */ + protected function mockTestee() + { + $request_data = Mockery::mock(RequestData::class); + $cart_repository = Mockery::mock(CartRepository::class); + $purchase_unit_factory = Mockery::mock(PurchaseUnitFactory::class); + $order_endpoint = Mockery::mock(OrderEndpoint::class); + $payer_factory = Mockery::mock(PayerFactory::class); + $session_handler = Mockery::mock(SessionHandler::class); + $settings = Mockery::mock(Settings::class); + $early_order_handler = Mockery::mock(EarlyOrderHandler::class); + + $testee = new CreateOrderEndpoint( + $request_data, + $cart_repository, + $purchase_unit_factory, + $order_endpoint, + $payer_factory, + $session_handler, + $settings, + $early_order_handler + ); + return array($payer_factory, $testee); + } + + /** + * @param $class + * + * @param $method + * + * @return \ReflectionMethod + * @throws \ReflectionException + */ + protected function testPrivateMethod($class, $method) + { + $reflector = new ReflectionClass($class); + $method = $reflector->getMethod($method); + $method->setAccessible(true); + return $method; + } } \ No newline at end of file From 426989118f9b8b22059d12fffe0ff80428ba142a Mon Sep 17 00:00:00 2001 From: dinamiko Date: Tue, 19 Jan 2021 12:13:15 +0100 Subject: [PATCH 06/26] Enable credit messaging for Germany --- modules/ppcp-button/src/Helper/class-messagesapply.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-button/src/Helper/class-messagesapply.php b/modules/ppcp-button/src/Helper/class-messagesapply.php index ccfdbbced..a1bbbf76a 100644 --- a/modules/ppcp-button/src/Helper/class-messagesapply.php +++ b/modules/ppcp-button/src/Helper/class-messagesapply.php @@ -22,6 +22,7 @@ class MessagesApply { */ private $countries = array( 'US', + 'DE', ); /** From 1d17335a99059c5e76ae893ed7c45446ab5ae0bd Mon Sep 17 00:00:00 2001 From: dinamiko Date: Wed, 20 Jan 2021 09:48:47 +0100 Subject: [PATCH 07/26] Fix phpcs errors --- modules/ppcp-wc-gateway/services.php | 82 ++++++++++++++-------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 0b8edeb09..87209ccd2 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1785,47 +1785,47 @@ return array( unset( $fields['disable_funding']['options']['card'] ); } - /** - * Enable Pay in 3 for UK. - */ - if ( 'GB' === $country ) { - $fields['message_heading'] = [ - 'heading' => __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-heading', - 'screens' => array( - State::STATE_PROGRESSIVE, - State::STATE_ONBOARDED, - ), - 'requirements' => array( 'messages' ), - 'gateway' => 'paypal', - 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), - 'class' => array( 'ppcp-subheading' ), - ]; - $fields['message_product_heading'] = [ - 'heading' => __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-heading', - 'screens' => array( - State::STATE_PROGRESSIVE, - State::STATE_ONBOARDED, - ), - 'requirements' => array( 'messages' ), - 'gateway' => 'paypal', - 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), - 'class' => array( 'ppcp-subheading' ), - ]; - $fields['message_cart_heading'] = [ - 'heading' => __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-heading', - 'screens' => array( - State::STATE_PROGRESSIVE, - State::STATE_ONBOARDED, - ), - 'requirements' => array( 'messages' ), - 'gateway' => 'paypal', - 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), - 'class' => array( 'ppcp-subheading' ), - ]; - } + /** + * Enable Pay in 3 for UK. + */ + if ( 'GB' === $country ) { + $fields['message_heading'] = array( + 'heading' => __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_PROGRESSIVE, + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'messages' ), + 'gateway' => 'paypal', + 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), + 'class' => array( 'ppcp-subheading' ), + ); + $fields['message_product_heading'] = array( + 'heading' => __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_PROGRESSIVE, + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'messages' ), + 'gateway' => 'paypal', + 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), + 'class' => array( 'ppcp-subheading' ), + ); + $fields['message_cart_heading'] = array( + 'heading' => __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_PROGRESSIVE, + State::STATE_ONBOARDED, + ), + 'requirements' => array( 'messages' ), + 'gateway' => 'paypal', + 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), + 'class' => array( 'ppcp-subheading' ), + ); + } $dcc_applies = $container->get( 'api.helpers.dccapplies' ); /** From cec2fa045981aa761676031defd1c14ebd208003 Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Thu, 21 Jan 2021 08:31:37 +0100 Subject: [PATCH 08/26] fix OrderEndpointTest --- tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php b/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php index 975185f14..cbfba53b6 100644 --- a/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php +++ b/tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php @@ -6,10 +6,12 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint; use Hamcrest\Matchers; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext; +use Woocommerce\PayPalCommerce\ApiClient\Entity\Capture; use WooCommerce\PayPalCommerce\ApiClient\Entity\Order; use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus; use WooCommerce\PayPalCommerce\ApiClient\Entity\PatchCollection; use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer; +use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments; use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit; use WooCommerce\PayPalCommerce\ApiClient\Entity\Token; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; @@ -238,6 +240,13 @@ class OrderEndpointTest extends TestCase ); expect('is_wp_error')->with($rawResponse)->andReturn(false); expect('wp_remote_retrieve_response_code')->with($rawResponse)->andReturn(201); + $purchaseUnit = Mockery::mock(PurchaseUnit::class); + $payment = Mockery::mock(Payments::class); + $capture = Mockery::mock(Capture::class); + $expectedOrder->shouldReceive('purchase_units')->once()->andReturn(['0'=>$purchaseUnit]); + $purchaseUnit->shouldReceive('payments')->once()->andReturn($payment); + $payment->shouldReceive('captures')->once()->andReturn(['0'=>$capture]); + $capture->shouldReceive('status')->once()->andReturn(''); $result = $testee->capture($orderToCapture); $this->assertEquals($expectedOrder, $result); From bb07e45e24a998f257be089ea0f65e20fde1987a Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Thu, 21 Jan 2021 08:36:30 +0100 Subject: [PATCH 09/26] fix PayerTest --- tests/PHPUnit/ApiClient/Entity/PayerTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/PHPUnit/ApiClient/Entity/PayerTest.php b/tests/PHPUnit/ApiClient/Entity/PayerTest.php index 95c62c7d0..b3ef019cb 100644 --- a/tests/PHPUnit/ApiClient/Entity/PayerTest.php +++ b/tests/PHPUnit/ApiClient/Entity/PayerTest.php @@ -16,6 +16,9 @@ class PayerTest extends TestCase $address ->expects('to_array') ->andReturn(['address']); + $address + ->expects('country_code') + ->andReturn('UK'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') From 48a3f6d3f22ae36bc5752c4af00d2ce606ca486f Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Thu, 21 Jan 2021 08:38:41 +0100 Subject: [PATCH 10/26] fix PayerTest all the others --- tests/PHPUnit/ApiClient/Entity/PayerTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/PHPUnit/ApiClient/Entity/PayerTest.php b/tests/PHPUnit/ApiClient/Entity/PayerTest.php index b3ef019cb..43bfa8fb7 100644 --- a/tests/PHPUnit/ApiClient/Entity/PayerTest.php +++ b/tests/PHPUnit/ApiClient/Entity/PayerTest.php @@ -68,6 +68,9 @@ class PayerTest extends TestCase $address ->expects('to_array') ->andReturn(['address']); + $address + ->expects('country_code') + ->andReturn('UK'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') @@ -105,6 +108,9 @@ class PayerTest extends TestCase $address ->expects('to_array') ->andReturn(['address']); + $address + ->expects('country_code') + ->andReturn('UK'); $phone = null; $taxInfo = Mockery::mock(PayerTaxInfo::class); $taxInfo @@ -139,6 +145,9 @@ class PayerTest extends TestCase $address ->expects('to_array') ->andReturn(['address']); + $address + ->expects('country_code') + ->andReturn('UK'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') @@ -173,6 +182,9 @@ class PayerTest extends TestCase $address ->expects('to_array') ->andReturn(['address']); + $address + ->expects('country_code') + ->andReturn('UK'); $phone = Mockery::mock(PhoneWithType::class); $phone ->expects('to_array') From 0761f892694ed6083f70e60c253c227b14fbc405 Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Thu, 21 Jan 2021 08:49:44 +0100 Subject: [PATCH 11/26] fix ItemFactoryTests --- .../ApiClient/Factory/ItemFactoryTest.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php b/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php index c7a185641..bd9e0596a 100644 --- a/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php +++ b/tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php @@ -48,7 +48,9 @@ class ItemFactoryTest extends TestCase expect('wc_get_price_excluding_tax') ->with($product) ->andReturn(1); - + expect('wp_strip_all_tags') + ->with('description') + ->andReturn('description'); $result = $testee->from_wc_cart($cart); $this->assertCount(1, $result); @@ -102,6 +104,9 @@ class ItemFactoryTest extends TestCase expect('wc_get_price_excluding_tax') ->with($product) ->andReturn(1); + expect('wp_strip_all_tags') + ->with('description') + ->andReturn('description'); $result = $testee->from_wc_cart($cart); @@ -126,6 +131,9 @@ class ItemFactoryTest extends TestCase $product ->expects('is_virtual') ->andReturn(false); + expect('wp_strip_all_tags') + ->with('description') + ->andReturn('description'); $item = Mockery::mock(\WC_Order_Item_Product::class); $item @@ -183,6 +191,9 @@ class ItemFactoryTest extends TestCase $product ->expects('is_virtual') ->andReturn(true); + expect('wp_strip_all_tags') + ->with('description') + ->andReturn('description'); $item = Mockery::mock(\WC_Order_Item_Product::class); $item @@ -235,6 +246,9 @@ class ItemFactoryTest extends TestCase $product ->expects('is_virtual') ->andReturn(true); + expect('wp_strip_all_tags') + ->with($description) + ->andReturn(mb_substr( $description, 0, 127 )); $item = Mockery::mock(\WC_Order_Item_Product::class); $item From 09fdd98369c8a764e2929df2e39b2f17dc543843 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Thu, 21 Jan 2021 11:11:23 +0100 Subject: [PATCH 12/26] Replace `PayPal Credit` to `Pay Later` in payment settings page --- modules/ppcp-wc-gateway/services.php | 10 +++++----- .../src/Gateway/class-paypalgateway.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 1aba3f682..a8230744a 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -541,7 +541,7 @@ return array( 'default' => false, 'desc_tip' => true, 'description' => __( - 'If you enable this setting, PayPal will be instructed not to allow the buyer to use funding sources that take additional time to complete (for example, eChecks). Instead, the buyer will be required to use an instant funding source, such as an instant transfer, a credit/debit card, or PayPal Credit.', + 'If you enable this setting, PayPal will be instructed not to allow the buyer to use funding sources that take additional time to complete (for example, eChecks). Instead, the buyer will be required to use an instant funding source, such as an instant transfer, a credit/debit card, or Pay Later.', 'woocommerce-paypal-payments' ), 'label' => __( 'Require Instant Payment', 'woocommerce-paypal-payments' ), @@ -603,7 +603,7 @@ return array( ), 'options' => array( 'card' => _x( 'Credit or debit cards', 'Name of payment method', 'woocommerce-paypal-payments' ), - 'credit' => _x( 'PayPal Credit', 'Name of payment method', 'woocommerce-paypal-payments' ), + 'credit' => _x( 'Pay Later', 'Name of payment method', 'woocommerce-paypal-payments' ), 'sepa' => _x( 'SEPA-Lastschrift', 'Name of payment method', 'woocommerce-paypal-payments' ), 'bancontact' => _x( 'Bancontact', 'Name of payment method', 'woocommerce-paypal-payments' ), 'eps' => _x( 'eps', 'Name of payment method', 'woocommerce-paypal-payments' ), @@ -804,7 +804,7 @@ return array( ), 'requirements' => array( 'messages' ), 'gateway' => 'paypal', - 'description' => str_replace( '', '', __( 'Customize the appearance of PayPal Credit messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ), + 'description' => str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ), 'class' => array( 'ppcp-subheading' ), ), 'message_enabled' => array( @@ -1107,7 +1107,7 @@ return array( ), 'requirements' => array( 'messages' ), 'gateway' => 'paypal', - 'description' => str_replace( '', '', __( 'Customize the appearance of PayPal Credit messages on product pages to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ), + 'description' => str_replace( '', '', __( 'Customize the appearance of Pay Later messages on product pages to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ), 'class' => array( 'ppcp-subheading' ), ), 'message_product_enabled' => array( @@ -1410,7 +1410,7 @@ return array( ), 'requirements' => array( 'messages' ), 'gateway' => 'paypal', - 'description' => str_replace( '', '', __( 'Customize the appearance of PayPal Credit messages on your cart page to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ), + 'description' => str_replace( '', '', __( 'Customize the appearance of Pay Later messages on your cart page to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ), 'class' => array( 'ppcp-subheading' ), ), 'message_cart_enabled' => array( diff --git a/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php b/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php index b7bc31a66..e9c9ccace 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/class-paypalgateway.php @@ -290,7 +290,7 @@ class PayPalGateway extends \WC_Payment_Gateway { } return __( - 'Accept PayPal, PayPal Credit and alternative payment types.', + 'Accept PayPal, Pay Later and alternative payment types.', 'woocommerce-paypal-payments' ); } From 237ee98ba7eecc703c47928aae265f4c2f4946ea Mon Sep 17 00:00:00 2001 From: dinamiko Date: Fri, 22 Jan 2021 15:23:49 +0100 Subject: [PATCH 13/26] Move `oomphinc/composer-installers-extender` to `require-dev` --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 4a60a4a09..143a6b8d7 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,6 @@ "require": { "dhii/module-interface": "0.1", "psr/container": "^1.0", - "oomphinc/composer-installers-extender": "^1.1", "container-interop/service-provider": "^0.4.0", "dhii/containers": "v0.1.0-alpha1", "dhii/wp-containers": "v0.1.0-alpha1", @@ -17,7 +16,8 @@ "require-dev": { "woocommerce/woocommerce-sniffs": "^0.1.0", "phpunit/phpunit": "^9.1", - "brain/monkey": "^2.4" + "brain/monkey": "^2.4", + "oomphinc/composer-installers-extender": "^1.1" }, "autoload": { "classmap": [ From 47015a8f235542903f4c0a604b36b425c8328f20 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Mon, 25 Jan 2021 09:25:08 +0100 Subject: [PATCH 14/26] Delete `oomphinc/composer-installers-extender` --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 143a6b8d7..3fdaf9e21 100644 --- a/composer.json +++ b/composer.json @@ -16,8 +16,7 @@ "require-dev": { "woocommerce/woocommerce-sniffs": "^0.1.0", "phpunit/phpunit": "^9.1", - "brain/monkey": "^2.4", - "oomphinc/composer-installers-extender": "^1.1" + "brain/monkey": "^2.4" }, "autoload": { "classmap": [ From 0ee6cfc0352f0410e0284377177e8152ce222bc9 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Wed, 27 Jan 2021 11:21:17 +0100 Subject: [PATCH 15/26] Replace credit with pay later --- modules/ppcp-wc-gateway/services.php | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 36ee1fb6a..8e90ab81b 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -796,7 +796,7 @@ return array( 'gateway' => 'paypal', ), 'message_heading' => array( - 'heading' => __( 'Credit Messaging on Checkout', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Pay Later on Checkout', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( State::STATE_PROGRESSIVE, @@ -820,7 +820,7 @@ return array( 'gateway' => 'paypal', ), 'message_layout' => array( - 'title' => __( 'Credit Messaging layout', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -842,7 +842,7 @@ return array( 'gateway' => 'paypal', ), 'message_logo' => array( - 'title' => __( 'Credit Messaging logo', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging logo', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -866,7 +866,7 @@ return array( 'gateway' => 'paypal', ), 'message_position' => array( - 'title' => __( 'Credit Messaging logo position', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging logo position', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -889,7 +889,7 @@ return array( 'gateway' => 'paypal', ), 'message_color' => array( - 'title' => __( 'Credit Messaging text color', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging text color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -913,7 +913,7 @@ return array( 'gateway' => 'paypal', ), 'message_flex_color' => array( - 'title' => __( 'Credit Messaging color', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -940,7 +940,7 @@ return array( 'gateway' => 'paypal', ), 'message_flex_ratio' => array( - 'title' => __( 'Credit Messaging ratio', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging ratio', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1099,7 +1099,7 @@ return array( ), 'message_product_heading' => array( - 'heading' => __( 'Credit Messaging on Single Product Page', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Pay Later on Single Product Page', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( State::STATE_PROGRESSIVE, @@ -1123,7 +1123,7 @@ return array( 'gateway' => 'paypal', ), 'message_product_layout' => array( - 'title' => __( 'Credit Messaging layout', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1145,7 +1145,7 @@ return array( 'gateway' => 'paypal', ), 'message_product_logo' => array( - 'title' => __( 'Credit Messaging logo', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging logo', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1169,7 +1169,7 @@ return array( 'gateway' => 'paypal', ), 'message_product_position' => array( - 'title' => __( 'Credit Messaging logo position', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging logo position', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1192,7 +1192,7 @@ return array( 'gateway' => 'paypal', ), 'message_product_color' => array( - 'title' => __( 'Credit Messaging text color', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging text color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1216,7 +1216,7 @@ return array( 'gateway' => 'paypal', ), 'message_product_flex_color' => array( - 'title' => __( 'Credit Messaging color', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1243,7 +1243,7 @@ return array( 'gateway' => 'paypal', ), 'message_product_flex_ratio' => array( - 'title' => __( 'Credit Messaging ratio', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging ratio', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1402,7 +1402,7 @@ return array( ), 'message_cart_heading' => array( - 'heading' => __( 'Credit Messaging on Cart', 'woocommerce-paypal-payments' ), + 'heading' => __( 'Pay Later on Cart', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-heading', 'screens' => array( State::STATE_PROGRESSIVE, @@ -1426,7 +1426,7 @@ return array( 'gateway' => 'paypal', ), 'message_cart_layout' => array( - 'title' => __( 'Credit Messaging layout', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging layout', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1448,7 +1448,7 @@ return array( 'gateway' => 'paypal', ), 'message_cart_logo' => array( - 'title' => __( 'Credit Messaging logo', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging logo', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1472,7 +1472,7 @@ return array( 'gateway' => 'paypal', ), 'message_cart_position' => array( - 'title' => __( 'Credit Messaging logo position', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging logo position', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1495,7 +1495,7 @@ return array( 'gateway' => 'paypal', ), 'message_cart_color' => array( - 'title' => __( 'Credit Messaging text color', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging text color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1519,7 +1519,7 @@ return array( 'gateway' => 'paypal', ), 'message_cart_flex_color' => array( - 'title' => __( 'Credit Messaging color', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging color', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), @@ -1546,7 +1546,7 @@ return array( 'gateway' => 'paypal', ), 'message_cart_flex_ratio' => array( - 'title' => __( 'Credit Messaging ratio', 'woocommerce-paypal-payments' ), + 'title' => __( 'Pay Later Messaging ratio', 'woocommerce-paypal-payments' ), 'type' => 'select', 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), From 8c514a8f9d48e6dace604f0930b12b5265cae143 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Thu, 28 Jan 2021 10:10:47 +0100 Subject: [PATCH 16/26] Display pay later link for germany --- modules/ppcp-wc-gateway/services.php | 55 +++++++++------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 8e90ab81b..c7cbb3219 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1786,47 +1786,28 @@ return array( } /** - * Enable Pay in 3 for UK. + * Set Pay in 3 heading and description for UK. */ if ( 'GB' === $country ) { - $fields['message_heading'] = array( - 'heading' => __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-heading', - 'screens' => array( - State::STATE_PROGRESSIVE, - State::STATE_ONBOARDED, - ), - 'requirements' => array( 'messages' ), - 'gateway' => 'paypal', - 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), - 'class' => array( 'ppcp-subheading' ), - ); - $fields['message_product_heading'] = array( - 'heading' => __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-heading', - 'screens' => array( - State::STATE_PROGRESSIVE, - State::STATE_ONBOARDED, - ), - 'requirements' => array( 'messages' ), - 'gateway' => 'paypal', - 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), - 'class' => array( 'ppcp-subheading' ), - ); - $fields['message_cart_heading'] = array( - 'heading' => __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ), - 'type' => 'ppcp-heading', - 'screens' => array( - State::STATE_PROGRESSIVE, - State::STATE_ONBOARDED, - ), - 'requirements' => array( 'messages' ), - 'gateway' => 'paypal', - 'description' => __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ), - 'class' => array( 'ppcp-subheading' ), - ); + $fields['message_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); + $fields['message_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); + + $fields['message_product_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); + $fields['message_product_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); + + $fields['message_cart_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); + $fields['message_cart_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); } + /** + * Set Pay Later link for DE + */ + if ( 'DE' === $country ) { + $fields['message_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); + $fields['message_product_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); + $fields['message_cart_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); + } + $dcc_applies = $container->get( 'api.helpers.dccapplies' ); /** * Depending on your store location, some credit cards can't be used. From 2344c203a82a6619e0a985a45a76d7df66e079b3 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Fri, 29 Jan 2021 10:33:11 +0100 Subject: [PATCH 17/26] Fix typo in message headings --- modules/ppcp-wc-gateway/services.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index c7cbb3219..6618679a4 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1792,10 +1792,10 @@ return array( $fields['message_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); $fields['message_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); - $fields['message_product_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); + $fields['message_product_heading']['heading'] = __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' ); $fields['message_product_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); - $fields['message_cart_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); + $fields['message_cart_heading']['heading'] = __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ); $fields['message_cart_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); } From c2678a4d35022aacb4104325bc83f8670d1190f9 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Mon, 1 Feb 2021 11:06:58 +0100 Subject: [PATCH 18/26] Fix phpcs errors --- modules/ppcp-wc-gateway/services.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 6618679a4..097923492 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1789,24 +1789,24 @@ return array( * Set Pay in 3 heading and description for UK. */ if ( 'GB' === $country ) { - $fields['message_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); - $fields['message_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); + $fields['message_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' ); + $fields['message_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); - $fields['message_product_heading']['heading'] = __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' ); - $fields['message_product_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); + $fields['message_product_heading']['heading'] = __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' ); + $fields['message_product_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); - $fields['message_cart_heading']['heading'] = __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ); - $fields['message_cart_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); + $fields['message_cart_heading']['heading'] = __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' ); + $fields['message_cart_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' ); } - /** - * Set Pay Later link for DE - */ - if ( 'DE' === $country ) { - $fields['message_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); - $fields['message_product_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); - $fields['message_cart_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); - } + /** + * Set Pay Later link for DE + */ + if ( 'DE' === $country ) { + $fields['message_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); + $fields['message_product_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); + $fields['message_cart_heading']['description'] = str_replace( '', '', __( 'Customize the appearance of Pay Later messages on checkout to promote special financing offers, which help increase sales.', 'woocommerce-paypal-payments' ) ); + } $dcc_applies = $container->get( 'api.helpers.dccapplies' ); /** From 4f72957906c08cc7cbdbaae17db551c0bda032b7 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Mon, 1 Feb 2021 11:36:29 +0100 Subject: [PATCH 19/26] Bump 1.1.0 version --- changelog.txt | 5 +++++ package.json | 2 +- readme.txt | 7 ++++++- woocommerce-paypal-payments.php | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 7461464ac..2ae207139 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ *** Changelog *** += 1.1.0 - 2021-02-01 = +* Add - Buy Now Pay Later for UK. #104 +* Add - DE now has 12 month installments. #106 +* Fix - Check phone for empty string. #102 + = 1.0.4 - 2021-01-18 = * Fix - Check if WooCommerce is active before initialize. #99 * Fix - Payment buttons only visible on order-pay site when Mini Cart is enabled; payment fails. #96 diff --git a/package.json b/package.json index 81b143f93..85d9f419d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "woocommerce-paypal-payments", - "version": "1.0.4", + "version": "1.1.0", "description": "WooCommerce PayPal Payments", "repository": "https://github.com/woocommerce/woocommerce-paypal-payments", "license": "GPL-2.0", diff --git a/readme.txt b/readme.txt index 12fd28d02..3bafd47a0 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, e-commerce, store, sales, sell, Requires at least: 5.3 Tested up to: 5.6 Requires PHP: 7.0 -Stable tag: 1.0.4 +Stable tag: 1.1.0 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -58,6 +58,11 @@ Follow the steps below to connect the plugin to your PayPal account: == Changelog == += 1.1.0 = +* Add - Buy Now Pay Later for UK. #104 +* Add - DE now has 12 month installments. #106 +* Fix - Check phone for empty string. #102 + = 1.0.4 = * Fix - Check if WooCommerce is active before initialize. #99 * Fix - Payment buttons only visible on order-pay site when Mini Cart is enabled; payment fails. #96 diff --git a/woocommerce-paypal-payments.php b/woocommerce-paypal-payments.php index b4c47dbd6..a25c077b7 100644 --- a/woocommerce-paypal-payments.php +++ b/woocommerce-paypal-payments.php @@ -3,7 +3,7 @@ * Plugin Name: WooCommerce PayPal Payments * Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/ * Description: PayPal's latest complete payments processing solution. Accept PayPal, PayPal Credit, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage. - * Version: 1.0.4 + * Version: 1.1.0 * Author: WooCommerce * Author URI: https://woocommerce.com/ * License: GPL-2.0 From 08d0489fbce7c6edc5f36aa97d8a3d5753c77f16 Mon Sep 17 00:00:00 2001 From: "Jorge A. Torres" Date: Wed, 27 Jan 2021 14:55:36 -0500 Subject: [PATCH 20/26] Make `partner_config_override/return_url` and `partner_config_override/return_url_description` filterable --- .../src/Repository/class-partnerreferralsdata.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-api-client/src/Repository/class-partnerreferralsdata.php b/modules/ppcp-api-client/src/Repository/class-partnerreferralsdata.php index 3f1a5a718..9514e8eb9 100644 --- a/modules/ppcp-api-client/src/Repository/class-partnerreferralsdata.php +++ b/modules/ppcp-api-client/src/Repository/class-partnerreferralsdata.php @@ -74,12 +74,13 @@ class PartnerReferralsData { return array( 'partner_config_override' => array( 'partner_logo_url' => 'https://connect.woocommerce.com/images/woocommerce_logo.png', - 'return_url' => admin_url( - 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' + 'return_url' => apply_filters( + 'woocommerce_paypal_payments_partner_config_override_return_url', + admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ) ), - 'return_url_description' => __( - 'Return to your shop.', - 'woocommerce-paypal-payments' + 'return_url_description' => apply_filters( + 'woocommerce_paypal_payments_partner_config_override_return_url_description', + __( 'Return to your shop.', 'woocommerce-paypal-payments' ) ), 'show_add_credit_card' => true, ), From 202502a2f94aa2a258379bf3074cd391335f8eb7 Mon Sep 17 00:00:00 2001 From: "Jorge A. Torres" Date: Wed, 27 Jan 2021 14:56:26 -0500 Subject: [PATCH 21/26] Allow overriding redirect URL after merchant ID is populated during the onboarding flow - Adds action `woocommerce_paypal_payments_onboarding_before_redirect` - Adds filter `woocommerce_paypal_payments_onboarding_redirect_url` --- .../src/Settings/class-settingslistener.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php b/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php index 6f314c3f5..75f0ab463 100644 --- a/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php +++ b/modules/ppcp-wc-gateway/src/Settings/class-settingslistener.php @@ -117,10 +117,14 @@ class SettingsListener { $this->settings->set( 'merchant_email_production', $merchant_email ); } $this->settings->persist(); - $redirect_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ); + + do_action( 'woocommerce_paypal_payments_onboarding_before_redirect' ); + + $redirect_url = apply_filters( 'woocommerce_paypal_payments_onboarding_redirect_url', admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ) ); if ( ! $this->settings->has( 'client_id' ) || ! $this->settings->get( 'client_id' ) ) { - $redirect_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-onboarding-error=1' ); + $redirect_url = add_query_arg( 'ppcp-onboarding-error', '1', $redirect_url ); } + wp_safe_redirect( $redirect_url, 302 ); exit; } From ef8fbf6b6a574e1df78f008876d17ead8aa56702 Mon Sep 17 00:00:00 2001 From: "Jorge A. Torres" Date: Thu, 4 Feb 2021 10:09:24 -0500 Subject: [PATCH 22/26] Make `Settings::persist()` returns the result of `update_option()` --- modules/ppcp-wc-gateway/src/Settings/class-settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/class-settings.php b/modules/ppcp-wc-gateway/src/Settings/class-settings.php index 91696354b..3701721de 100644 --- a/modules/ppcp-wc-gateway/src/Settings/class-settings.php +++ b/modules/ppcp-wc-gateway/src/Settings/class-settings.php @@ -69,7 +69,7 @@ class Settings implements ContainerInterface { */ public function persist() { - update_option( self::KEY, $this->settings ); + return update_option( self::KEY, $this->settings ); } From b8870415afb5d246371f2258b4ac45695ecef45d Mon Sep 17 00:00:00 2001 From: "Jorge A. Torres" Date: Wed, 27 Jan 2021 14:53:45 -0500 Subject: [PATCH 23/26] Rework onboarding rendering and JS code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `ppcp_onboarding` object and separate sandbox/production callbacks. - Prevent errors when loading `onboarding.js` outside of the settings screen. - Workaround PayPal’s partner.js shortcomings. --- .../ppcp-onboarding/assets/js/onboarding.js | 150 ++++++++++++++---- .../src/Assets/class-onboardingassets.php | 10 +- .../src/Render/class-onboardingrenderer.php | 48 +++--- 3 files changed, 148 insertions(+), 60 deletions(-) diff --git a/modules/ppcp-onboarding/assets/js/onboarding.js b/modules/ppcp-onboarding/assets/js/onboarding.js index 15d2abc05..fd63915ff 100644 --- a/modules/ppcp-onboarding/assets/js/onboarding.js +++ b/modules/ppcp-onboarding/assets/js/onboarding.js @@ -1,22 +1,104 @@ -function onboardingCallback(authCode, sharedId) { - const sandboxSwitchElement = document.querySelector('#ppcp-sandbox_on'); - fetch( - PayPalCommerceGatewayOnboarding.endpoint, - { - method: 'POST', - headers: { - 'content-type': 'application/json' - }, - body: JSON.stringify( - { - authCode: authCode, - sharedId: sharedId, - nonce: PayPalCommerceGatewayOnboarding.nonce, - env: sandboxSwitchElement && sandboxSwitchElement.checked ? 'sandbox' : 'production' - } - ) +// Onboarding. +const ppcp_onboarding = { + BUTTON_SELECTOR: '[data-paypal-onboard-button]', + PAYPAL_JS_ID: 'ppcp-onboarding-paypal-js', + _timeout: false, + + init: function() { + document.addEventListener('DOMContentLoaded', this.reload); + }, + + reload: function() { + const buttons = document.querySelectorAll(ppcp_onboarding.BUTTON_SELECTOR); + + if (0 === buttons.length) { + return; } - ); + + // Add event listeners to buttons. + buttons.forEach( + (element) => { + if (element.hasAttribute('data-ppcp-button-initialized')) { + return; + } + + element.addEventListener( + 'click', + (e) => { + if (!element.hasAttribute('data-ppcp-button-initialized') || 'undefined' === typeof window.PAYPAL) { + e.preventDefault(); + } + } + ); + } + ); + + // Clear any previous PayPal scripts. + [ppcp_onboarding.PAYPAL_JS_ID, 'signup-js', 'biz-js'].forEach( + (scriptID) => { + const scriptTag = document.getElementById(scriptID); + + if (scriptTag) { + scriptTag.parentNode.removeChild(scriptTag); + } + + if ('undefined' !== typeof window.PAYPAL) { + delete window.PAYPAL; + } + } + ); + + // Load PayPal scripts. + const paypalScriptTag = document.createElement('script'); + paypalScriptTag.id = ppcp_onboarding.PAYPAL_JS_ID; + paypalScriptTag.src = PayPalCommerceGatewayOnboarding.paypal_js_url; + document.body.append(paypalScriptTag); + + if (ppcp_onboarding._timeout) { + clearTimeout(ppcp_onboarding._timeout); + } + + ppcp_onboarding._timeout = setTimeout( + () => { + buttons.forEach((element) => { element.setAttribute('data-ppcp-button-initialized', 'true'); }); + + if ('undefined' !== window.PAYPAL.apps.Signup) { + window.PAYPAL.apps.Signup.render(); + } + }, + 1000 + ); + }, + + loginSeller: function(env, authCode, sharedId) { + fetch( + PayPalCommerceGatewayOnboarding.endpoint, + { + method: 'POST', + headers: { + 'content-type': 'application/json' + }, + body: JSON.stringify( + { + authCode: authCode, + sharedId: sharedId, + nonce: PayPalCommerceGatewayOnboarding.nonce, + env: env + } + ) + } + ); + }, + + +}; + +function ppcp_onboarding_sandboxCallback(...args) { + return ppcp_onboarding.loginSeller('sandbox', ...args); +} + +function ppcp_onboarding_productionCallback(...args) { + return ppcp_onboarding.loginSeller('production', ...args); } /** @@ -174,21 +256,23 @@ const disconnect = (event) => { ); // Prevent a possibly dirty form arising from this particular checkbox. - sandboxSwitchElement.addEventListener( - 'click', - (event) => { - const value = event.target.checked; + if (sandboxSwitchElement) { + sandboxSwitchElement.addEventListener( + 'click', + (event) => { + const value = event.target.checked; - toggleSandboxProduction( ! value ); + toggleSandboxProduction( ! value ); - event.preventDefault(); - event.stopPropagation(); - setTimeout( () => { - event.target.checked = value; - }, 1 - ); - } - ); + event.preventDefault(); + event.stopPropagation(); + setTimeout( () => { + event.target.checked = value; + }, 1 + ); + } + ); + } // document.querySelectorAll('#mainform input[type="checkbox"]').forEach( // (checkbox) => { @@ -207,6 +291,8 @@ const disconnect = (event) => { } ) } - ) + ); + // Onboarding buttons. + ppcp_onboarding.init(); })(); diff --git a/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php b/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php index e06b0509c..8cc1d87b4 100644 --- a/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php +++ b/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php @@ -51,7 +51,7 @@ class OnboardingAssets { LoginSellerEndpoint $login_seller_endpoint ) { - $this->module_url = $module_url; + $this->module_url = untrailingslashit( $module_url ); $this->state = $state; $this->login_seller_endpoint = $login_seller_endpoint; } @@ -78,9 +78,6 @@ class OnboardingAssets { 1, true ); - if ( ! $this->should_render_onboarding_script() ) { - return false; - } $url = $this->module_url . '/assets/js/onboarding.js'; wp_register_script( @@ -94,8 +91,9 @@ class OnboardingAssets { 'ppcp-onboarding', 'PayPalCommerceGatewayOnboarding', array( - 'endpoint' => home_url( \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ) ), - 'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ), + 'endpoint' => home_url( \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ) ), + 'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ), + 'paypal_js_url' => 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js', ) ); diff --git a/modules/ppcp-onboarding/src/Render/class-onboardingrenderer.php b/modules/ppcp-onboarding/src/Render/class-onboardingrenderer.php index da35d2b8a..cc2fa38f1 100644 --- a/modules/ppcp-onboarding/src/Render/class-onboardingrenderer.php +++ b/modules/ppcp-onboarding/src/Render/class-onboardingrenderer.php @@ -52,6 +52,23 @@ class OnboardingRenderer { $this->sandbox_partner_referrals = $sandbox_partner_referrals; } + /** + * Returns the action URL for the onboarding button/link. + * + * @param boolean $is_production Whether the production or sandbox button should be rendered. + * @return string URL. + */ + public function get_signup_link( bool $is_production ) { + $args = array( + 'displayMode' => 'minibrowser', + ); + + $url = $is_production ? $this->production_partner_referrals->signup_link() : $this->sandbox_partner_referrals->signup_link(); + $url = add_query_arg( $args, $url ); + + return $url; + } + /** * Renders the "Connect to PayPal" button. * @@ -59,27 +76,12 @@ class OnboardingRenderer { */ public function render( bool $is_production ) { try { - $args = array( - 'displayMode' => 'minibrowser', + $this->render_button( + $this->get_signup_link( $is_production ), + $is_production ? 'connect-to-production' : 'connect-to-sandbox', + $is_production ? __( 'Connect to PayPal', 'woocommerce-paypal-payments' ) : __( 'Connect to PayPal Sandbox', 'woocommerce-paypal-payments' ), + $is_production ? 'production' : 'sandbox' ); - - $url = $is_production ? $this->production_partner_referrals->signup_link() : $this->sandbox_partner_referrals->signup_link(); - $url = add_query_arg( $args, $url ); - $id = $is_production ? 'connect-to-production' : 'connect-to-sandbox'; - $label = $is_production ? __( 'Connect to PayPal', 'woocommerce-paypal-payments' ) : __( 'Connect to PayPal Sandbox', 'woocommerce-paypal-payments' ); - $this->render_button( - $url, - $id, - $label - ); - - $script_url = 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js'; ?> - - - From 11aa5daca96210a4685de9de6bd30ef01b167f50 Mon Sep 17 00:00:00 2001 From: "Jorge A. Torres" Date: Wed, 27 Jan 2021 14:56:42 -0500 Subject: [PATCH 24/26] Add REST routes related to onboarding Adds various routes under `/wc-paypal/v1/onboarding` including `/status` (onboarding status), `/set-credentials` (manually set merchant ID/email and keys) and `/get-params` (information useful for presenting the user with an onboarding button). --- modules/ppcp-onboarding/services.php | 4 + .../src/Assets/class-onboardingassets.php | 19 +- .../src/class-onboarding-rest-controller.php | 321 ++++++++++++++++++ .../src/class-onboardingmodule.php | 5 +- 4 files changed, 343 insertions(+), 6 deletions(-) create mode 100644 modules/ppcp-onboarding/src/class-onboarding-rest-controller.php diff --git a/modules/ppcp-onboarding/services.php b/modules/ppcp-onboarding/services.php index ac87010b4..3c9577510 100644 --- a/modules/ppcp-onboarding/services.php +++ b/modules/ppcp-onboarding/services.php @@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets; use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer; +use WooCommerce\PayPalCommerce\Onboarding\Onboarding_REST_Controller; return array( 'api.sandbox-host' => static function ( $container ): string { @@ -207,4 +208,7 @@ return array( $partner_referrals_sandbox ); }, + 'onboarding.rest' => static function( $container ) : Onboarding_REST_Controller { + return new Onboarding_REST_Controller( $container ); + }, ); diff --git a/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php b/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php index 8cc1d87b4..33ff78730 100644 --- a/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php +++ b/modules/ppcp-onboarding/src/Assets/class-onboardingassets.php @@ -90,16 +90,25 @@ class OnboardingAssets { wp_localize_script( 'ppcp-onboarding', 'PayPalCommerceGatewayOnboarding', - array( - 'endpoint' => home_url( \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ) ), - 'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ), - 'paypal_js_url' => 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js', - ) + $this->get_script_data() ); return true; } + /** + * Returns the data associated to the onboarding script. + * + * @return array + */ + public function get_script_data() { + return array( + 'endpoint' => home_url( \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ) ), + 'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ), + 'paypal_js_url' => 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js', + ); + } + /** * Enqueues the necessary scripts. * diff --git a/modules/ppcp-onboarding/src/class-onboarding-rest-controller.php b/modules/ppcp-onboarding/src/class-onboarding-rest-controller.php new file mode 100644 index 000000000..1cbc77794 --- /dev/null +++ b/modules/ppcp-onboarding/src/class-onboarding-rest-controller.php @@ -0,0 +1,321 @@ +container = $container; + } + + /** + * Registers REST routes under 'wc-paypal/v1/onboarding'. + * Specifically: + * - `/onboarding/get-params`, which returns information useful to display an onboarding button. + * - `/onboarding/get-status`, which returns information about the current environment and its onboarding state. + * - `/onboarding/set-credentials`, which allows setting merchant/API credentials. + */ + public function register_routes() { + register_rest_route( + $this->rest_namespace, + '/' . $this->rest_base . '/get-params', + array( + 'methods' => 'POST', + 'callback' => array( $this, 'get_params' ), + 'permission_callback' => array( $this, 'check_permission' ), + ) + ); + + register_rest_route( + $this->rest_namespace, + '/' . $this->rest_base . '/get-status', + array( + 'methods' => 'GET', + 'callback' => array( $this, 'get_status' ), + 'permission_callback' => array( $this, 'check_permission' ), + ) + ); + + register_rest_route( + $this->rest_namespace, + '/' . $this->rest_base . '/set-credentials', + array( + 'methods' => 'POST', + 'callback' => array( $this, 'set_credentials' ), + 'permission_callback' => array( $this, 'check_permission' ), + ) + ); + } + + /** + * Validate the requester's permissions. + * + * @param WP_REST_Request $request The request. + * @return bool + */ + public function check_permission( $request ) { + return current_user_can( 'install_plugins' ); + } + + /** + * Callback for the `/onboarding/get-params` endpoint. + * + * @param WP_REST_Request $request The request. + * @return array + */ + public function get_params( $request ) { + $params = $request->get_json_params(); + + $environment = ( isset( $params['environment'] ) && in_array( $params['environment'], array( 'production', 'sandbox' ), true ) ) ? $params['environment'] : 'sandbox'; + + return array( + 'scriptURL' => trailingslashit( $this->container->get( 'onboarding.url' ) ) . 'assets/js/onboarding.js', + 'scriptData' => $this->container->get( 'onboarding.assets' )->get_script_data(), + 'environment' => $environment, + 'onboardCompleteCallback' => 'ppcp_onboarding_' . $environment . 'Callback', + 'signupLink' => $this->generate_signup_link( $environment, ( ! empty( $params['returnUrlArgs'] ) ? $params['returnUrlArgs'] : array() ) ), + ); + } + + /** + * Callback for the `/onboarding/get-status` endpoint. + * + * @param WP_REST_Request $request The request. + * @return array + */ + public function get_status( $request ) { + $environment = $this->container->get( 'onboarding.environment' ); + $state = $this->container->get( 'onboarding.state' ); + + return array( + 'environment' => $environment->current_environment(), + 'onboarded' => ( $state->current_state() >= State::STATE_ONBOARDED ), + 'state' => $this->get_onboarding_state_name( $state->current_state() ), + 'sandbox' => array( + 'state' => $this->get_onboarding_state_name( $state->sandbox_state() ), + 'onboarded' => ( $state->sandbox_state() >= State::STATE_ONBOARDED ), + ), + 'production' => array( + 'state' => $this->get_onboarding_state_name( $state->production_state() ), + 'onboarded' => ( $state->production_state() >= State::STATE_ONBOARDED ), + ), + ); + } + + /** + * Callback for the `/onboarding/set-credentials` endpoint. + * + * @param WP_REST_Request $request The request. + * @return WP_Error|array + */ + public function set_credentials( $request ) { + static $credential_keys = array( + 'merchant_id', + 'merchant_email', + 'client_id', + 'client_secret', + ); + + // Sanitize params. + $params = array_filter( array_map( 'trim', $request->get_json_params() ) ); + + // Validate 'environment'. + if ( empty( $params['environment'] ) || ! in_array( $params['environment'], array( 'sandbox', 'production' ), true ) ) { + return new \WP_Error( + 'woocommerce_paypal_payments_invalid_environment', + sprintf( + /* translators: placeholder is an arbitrary string. */ + __( 'Environment "%s" is invalid. Use "sandbox" or "production".', 'woocommerce-paypal-payments' ), + isset( $params['environment'] ) ? $params['environment'] : '' + ), + array( 'status' => 400 ) + ); + } + + // Validate the other fields. + $missing_keys = array_values( array_diff( $credential_keys, array_keys( $params ) ) ); + if ( $missing_keys ) { + return new \WP_Error( + 'woocommerce_paypal_payments_credentials_incomplete', + sprintf( + /* translators: placeholder is a comma-separated list of fields. */ + __( 'Credentials are incomplete. Missing fields: %s.', 'woocommerce-paypal-payments' ), + implode( ', ', $missing_keys ) + ), + array( + 'missing_fields' => $missing_keys, + 'status' => 400, + ) + ); + } + + $settings = $this->container->get( 'wcgateway.settings' ); + $skip_persist = true; + + // Enable gateway. + if ( ! $settings->has( 'enabled' ) || ! $settings->get( 'enabled' ) ) { + $settings->set( 'enabled', true ); + $skip_persist = false; + } + + foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) { + if ( PayPalGateway::ID === $gateway->id ) { + $gateway->update_option( 'enabled', 'yes' ); + break; + } + } + + // Update settings. + $sandbox_on = ( 'sandbox' === $params['environment'] ); + if ( ! $settings->has( 'sandbox_on' ) || ( (bool) $settings->get( 'sandbox_on' ) !== $sandbox_on ) ) { + $settings->set( 'sandbox_on', $sandbox_on ); + $skip_persist = false; + } + + foreach ( $credential_keys as $key ) { + $value = $params[ $key ]; + $env_key = $key . '_' . $params['environment']; + + if ( ! $settings->has( $key ) || ! $settings->has( $env_key ) || $settings->get( $key ) !== $value || $settings->get( $env_key ) !== $value ) { + $settings->set( $key, $value ); + $settings->set( $env_key, $value ); + $skip_persist = false; + } + } + + if ( $skip_persist ) { + return array(); + } + + $settings->set( 'products_dcc_enabled', null ); + + if ( ! $settings->persist() ) { + return new \WP_Error( + 'woocommerce_paypal_payments_credentials_not_saved', + __( 'An error occurred while saving the credentials.', 'woocommerce-paypal-payments' ), + array( + 'status' => 500, + ) + ); + } + + $webhook_registrar = $this->container->get( 'webhook.registrar' ); + $webhook_registrar->unregister(); + $webhook_registrar->register(); + + return array(); + } + + /** + * Appends URL parameters stored in this class to a given URL. + * + * @hooked woocommerce_paypal_payments_partner_config_override_return_url - 10 + * @param string $url URL. + * @return string The URL with the stored URL parameters added to it. + */ + public function add_args_to_return_url( $url ) { + return add_query_arg( $this->return_url_args, $url ); + } + + /** + * Translates an onboarding state to a string. + * + * @param int $state An onboarding state to translate as returned by {@link State} methods. + * @return string A string representing the state: "start", "progressive" or "onboarded". + * @see State::current_state(), State::sandbox_state(), State::production_state(). + */ + public function get_onboarding_state_name( $state ) { + $name = 'unknown'; + + switch ( absint( $state ) ) { + case State::STATE_START: + $name = 'start'; + break; + case State::STATE_PROGRESSIVE: + $name = 'progressive'; + break; + case State::STATE_ONBOARDED: + $name = 'onboarded'; + break; + default: + break; + + } + + return $name; + } + + /** + * Generates a signup link for onboarding for a given environment and optionally adding certain URL arguments + * to the URL users are redirected after completing the onboarding flow. + * + * @param string $environment The environment to use. Either 'sandbox' or 'production'. Defaults to 'sandbox'. + * @param array $url_args An array of URL arguments to add to the return URL via {@link add_query_arg()}. + * @return string + */ + private function generate_signup_link( $environment = 'sandbox', $url_args = array() ) { + $this->return_url_args = ( ! empty( $url_args ) && is_array( $url_args ) ) ? $url_args : array(); + + if ( $this->return_url_args ) { + add_filter( 'woocommerce_paypal_payments_partner_config_override_return_url', array( $this, 'add_args_to_return_url' ) ); + } + + $link = $this->container->get( 'onboarding.render' )->get_signup_link( 'production' === $environment ); + + if ( $this->return_url_args ) { + remove_filter( 'woocommerce_paypal_payments_partner_config_override_return_url', array( $this, 'add_args_to_return_url' ) ); + $this->return_url_args = array(); + } + + return $link; + } + +} diff --git a/modules/ppcp-onboarding/src/class-onboardingmodule.php b/modules/ppcp-onboarding/src/class-onboardingmodule.php index f5dbf0ec5..3526f7c33 100644 --- a/modules/ppcp-onboarding/src/class-onboardingmodule.php +++ b/modules/ppcp-onboarding/src/class-onboardingmodule.php @@ -41,7 +41,6 @@ class OnboardingModule implements ModuleInterface { * @param ContainerInterface|null $container The container. */ public function run( ContainerInterface $container = null ) { - $asset_loader = $container->get( 'onboarding.assets' ); /** * The OnboardingAssets. @@ -100,6 +99,10 @@ class OnboardingModule implements ModuleInterface { $endpoint->handle_request(); } ); + + // Initialize REST routes at the appropriate time. + $rest_controller = $container->get( 'onboarding.rest' ); + add_action( 'rest_api_init', array( $rest_controller, 'register_routes' ) ); } /** From 04a64383c7c1389e9abd6fe4c2f4f9fa667768f9 Mon Sep 17 00:00:00 2001 From: "Jorge A. Torres" Date: Fri, 5 Feb 2021 09:47:38 -0300 Subject: [PATCH 25/26] Update php.yml --- .github/workflows/php.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index f532dfbe9..8b015b410 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -14,9 +14,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Packagist.com Auth - run: composer config --global --auth http-basic.repo.packagist.com token 5863d6c7b313709512b6d5b7f93c7fad8807a5aef92b2155019f7f41ccac - - name: Validate composer.json and composer.lock run: composer validate From 25282da555cb61c6ac4d574323a344a1c13a1197 Mon Sep 17 00:00:00 2001 From: "Jorge A. Torres" Date: Fri, 5 Feb 2021 09:49:07 -0300 Subject: [PATCH 26/26] Update php.yml --- .github/workflows/php.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 8b015b410..e2d5f1752 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -2,9 +2,9 @@ name: PHP Composer on: push: - branches: [ master ] + branches: [ trunk ] pull_request: - branches: [ master ] + branches: [ trunk ] jobs: build: