Merge branch 'trunk' into PCP-412-when-there-is-a-payment-saved-th

This commit is contained in:
dinamiko 2021-12-20 11:35:57 +01:00
commit ba7bea6fa6
23 changed files with 349 additions and 225 deletions

View file

@ -1,6 +1,15 @@
*** Changelog ***
= 1.6.3 - TBD =
= 1.6.4 - TBD =
* Fix - Non admin user cannot save changes to the plugin settings #278
* Fix - Empty space in invoice prefix causes smart buttons to not load #390
* Fix - woocommerce_payment_complete action not triggered for payments completed via webhook #399
* Fix - Paying with Venmo - Change funding source on checkout page and receipt to Venmo #394
* Fix - Internal server error on checkout when selected saved card but then switched to paypal #403
* Enhancement - Allow formatted text for the Description field #407
* Enhancement - Remove filter to prevent On-Hold emails #411
= 1.6.3 - 2021-12-14 =
* Fix - Payments fail when using custom order numbers #354
* Fix - Do not display saved payments on PayPal buttons if vault option is disabled #358
* Fix - Double "Place Order" button #362

View file

@ -14,7 +14,10 @@ const bootstrap = () => {
const errorHandler = new ErrorHandler(PayPalCommerceGateway.labels.error.generic);
const spinner = new Spinner();
const creditCardRenderer = new CreditCardRenderer(PayPalCommerceGateway, errorHandler, spinner);
const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway);
const onSmartButtonClick = data => {
window.ppcpFundingSource = data.fundingSource;
};
const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway, onSmartButtonClick);
const messageRenderer = new MessageRenderer(PayPalCommerceGateway.messages);
const context = PayPalCommerceGateway.context;
if (context === 'mini-cart' || context === 'product') {

View file

@ -4,7 +4,8 @@ const onApprove = (context, errorHandler) => {
method: 'POST',
body: JSON.stringify({
nonce: context.config.ajax.approve_order.nonce,
order_id:data.orderID
order_id:data.orderID,
funding_source: window.ppcpFundingSource,
})
}).then((res)=>{
return res.json();
@ -13,7 +14,7 @@ const onApprove = (context, errorHandler) => {
errorHandler.genericError();
return actions.restart().catch(err => {
errorHandler.genericError();
});;
});
}
location.href = context.config.redirect;
});

View file

@ -7,7 +7,8 @@ const onApprove = (context, errorHandler, spinner) => {
method: 'POST',
body: JSON.stringify({
nonce: context.config.ajax.approve_order.nonce,
order_id:data.orderID
order_id:data.orderID,
funding_source: window.ppcpFundingSource,
})
}).then((res)=>{
return res.json();

View file

@ -1,7 +1,8 @@
class Renderer {
constructor(creditCardRenderer, defaultConfig) {
constructor(creditCardRenderer, defaultConfig, onSmartButtonClick) {
this.defaultConfig = defaultConfig;
this.creditCardRenderer = creditCardRenderer;
this.onSmartButtonClick = onSmartButtonClick;
}
render(wrapper, hostedFieldsWrapper, contextConfig) {
@ -19,6 +20,7 @@ class Renderer {
paypal.Buttons({
style,
...contextConfig,
onClick: this.onSmartButtonClick,
}).render(wrapper);
}

View file

@ -184,6 +184,9 @@ class ApproveOrderEndpoint implements EndpointInterface {
throw new RuntimeException( $message );
}
$funding_source = $data['funding_source'] ?? null;
$this->session_handler->replace_funding_source( $funding_source );
$this->session_handler->replace_order( $order );
wp_send_json_success( $order );
return true;

View file

@ -88,3 +88,7 @@
.woocommerce_page_wc-settings h3.ppcp-subheading {
font-size: 1.1em;
}
.input-text[pattern]:invalid {
border: red solid 2px;
}

View file

@ -28,7 +28,10 @@ return array(
return $session_handler;
},
'session.cancellation.view' => function ( ContainerInterface $container ) : CancelView {
return new CancelView();
return new CancelView(
$container->get( 'wcgateway.settings' ),
$container->get( 'wcgateway.funding-source.renderer' )
);
},
'session.cancellation.controller' => function ( ContainerInterface $container ) : CancelController {
return new CancelController(

View file

@ -67,7 +67,7 @@ class CancelController {
add_action(
'woocommerce_review_order_after_submit',
function () use ( $url ) {
$this->view->render_session_cancellation( $url );
$this->view->render_session_cancellation( $url, $this->session_handler->funding_source() );
}
);
}

View file

@ -9,31 +9,66 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Session\Cancellation;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
/**
* Class CancelView
*/
class CancelView {
/**
* The settings.
*
* @var ContainerInterface
*/
protected $settings;
/**
* The funding source renderer.
*
* @var FundingSourceRenderer
*/
protected $funding_source_renderer;
/**
* CancelView constructor.
*
* @param ContainerInterface $settings The settings.
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
*/
public function __construct(
ContainerInterface $settings,
FundingSourceRenderer $funding_source_renderer
) {
$this->settings = $settings;
$this->funding_source_renderer = $funding_source_renderer;
}
/**
* Renders the cancel link.
*
* @param string $url The URL.
* @param string|null $funding_source The ID of the funding source, such as 'venmo'.
*/
public function render_session_cancellation( string $url ) {
public function render_session_cancellation( string $url, ?string $funding_source ) {
?>
<p id="ppcp-cancel"
class="has-text-align-center ppcp-cancel"
>
<?php
$name = $funding_source ?
$this->funding_source_renderer->render_name( $funding_source )
: ( $this->settings->has( 'title' ) ? $this->settings->get( 'title' ) : __( 'PayPal', 'woocommerce-paypal-payments' ) );
printf(
// translators: the placeholders are html tags for a link.
// translators: %3$ is funding source like "PayPal" or "Venmo", other placeholders are html tags for a link.
esc_html__(
'You are currently paying with PayPal. If you want to cancel
'You are currently paying with %3$s. If you want to cancel
this process, please click %1$shere%2$s.',
'woocommerce-paypal-payments'
),
'<a href="' . esc_url( $url ) . '">',
'</a>'
'</a>',
esc_html( $name )
);
?>
</p>

View file

@ -40,6 +40,13 @@ class SessionHandler {
*/
private $insufficient_funding_tries = 0;
/**
* The funding source of the current checkout (venmo, ...) or null.
*
* @var string|null
*/
private $funding_source = null;
/**
* Returns the order.
*
@ -84,6 +91,28 @@ class SessionHandler {
return $this;
}
/**
* Returns the funding source of the current checkout (venmo, ...) or null.
*
* @return string|null
*/
public function funding_source(): ?string {
return $this->funding_source;
}
/**
* Replaces the funding source of the current checkout.
*
* @param string|null $funding_source The funding source.
*
* @return SessionHandler
*/
public function replace_funding_source( ?string $funding_source ): SessionHandler {
$this->funding_source = $funding_source;
$this->store_session();
return $this;
}
/**
* Returns how many times the customer tried to use the PayPal Gateway in this session.
*
@ -113,6 +142,7 @@ class SessionHandler {
$this->order = null;
$this->bn_code = '';
$this->insufficient_funding_tries = 0;
$this->funding_source = null;
$this->store_session();
return $this;
}

View file

@ -24,6 +24,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderAuthorizeAction;
use WooCommerce\PayPalCommerce\WcGateway\Checkout\CheckoutPayPalAddressPreset;
use WooCommerce\PayPalCommerce\WcGateway\Checkout\DisableGateways;
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
@ -45,6 +46,7 @@ return array(
'wcgateway.paypal-gateway' => static function ( ContainerInterface $container ): PayPalGateway {
$order_processor = $container->get( 'wcgateway.order-processor' );
$settings_renderer = $container->get( 'wcgateway.settings.render' );
$funding_source_renderer = $container->get( 'wcgateway.funding-source.renderer' );
$authorized_payments = $container->get( 'wcgateway.processor.authorized-payments' );
$settings = $container->get( 'wcgateway.settings' );
$session_handler = $container->get( 'session.handler' );
@ -60,6 +62,7 @@ return array(
$logger = $container->get( 'woocommerce.logger.woocommerce' );
return new PayPalGateway(
$settings_renderer,
$funding_source_renderer,
$order_processor,
$authorized_payments,
$settings,
@ -749,7 +752,11 @@ return array(
'title' => __( 'Invoice prefix', 'woocommerce-paypal-payments' ),
'type' => 'text',
'desc_tip' => true,
'description' => __( 'If you use your PayPal account with more than one installation, please use a distinct prefix to separate those installations. Please do not use numbers in your prefix.', 'woocommerce-paypal-payments' ),
'description' => __( 'If you use your PayPal account with more than one installation, please use a distinct prefix to separate those installations. Please use only English letters and "-", "_" characters.', 'woocommerce-paypal-payments' ),
'maxlength' => 15,
'custom_attributes' => array(
'pattern' => '[a-zA-Z_-]+',
),
'default' => ( static function (): string {
$site_url = get_site_url( get_current_blog_id() );
$hash = md5( $site_url );
@ -2039,4 +2046,10 @@ return array(
$container->get( 'api.shop.country' )
);
},
'wcgateway.funding-source.renderer' => function ( ContainerInterface $container ) : FundingSourceRenderer {
return new FundingSourceRenderer(
$container->get( 'wcgateway.settings' )
);
},
);

View file

@ -0,0 +1,61 @@
<?php
/**
* Renders info about funding sources like Venmo.
*
* @package WooCommerce\PayPalCommerce\WcGateway\FundingSource
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway\FundingSource;
use Psr\Container\ContainerInterface;
/**
* Class FundingSourceRenderer
*/
class FundingSourceRenderer {
/**
* The settings.
*
* @var ContainerInterface
*/
protected $settings;
/**
* FundingSourceRenderer constructor.
*
* @param ContainerInterface $settings The settings.
*/
public function __construct( ContainerInterface $settings ) {
$this->settings = $settings;
}
/**
* Returns name of the funding source (suitable for displaying to user).
*
* @param string $id The ID of the funding source, such as 'venmo'.
*/
public function render_name( string $id ): string {
if ( 'venmo' === $id ) {
return __( 'Venmo', 'woocommerce-paypal-payments' );
}
return $this->settings->has( 'title' ) ?
$this->settings->get( 'title' )
: __( 'PayPal', 'woocommerce-paypal-payments' );
}
/**
* Returns description of the funding source (for checkout).
*
* @param string $id The ID of the funding source, such as 'venmo'.
*/
public function render_description( string $id ): string {
if ( 'venmo' === $id ) {
return __( 'Pay via Venmo.', 'woocommerce-paypal-payments' );
}
return $this->settings->has( 'description' ) ?
$this->settings->get( 'description' )
: __( 'Pay via PayPal.', 'woocommerce-paypal-payments' );
}
}

View file

@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\Session\SessionHandler;
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
@ -44,6 +45,13 @@ class PayPalGateway extends \WC_Payment_Gateway {
*/
protected $settings_renderer;
/**
* The funding source renderer.
*
* @var FundingSourceRenderer
*/
protected $funding_source_renderer;
/**
* The processor for orders.
*
@ -153,6 +161,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
* PayPalGateway constructor.
*
* @param SettingsRenderer $settings_renderer The Settings Renderer.
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
* @param OrderProcessor $order_processor The Order Processor.
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The Authorized Payments Processor.
* @param ContainerInterface $config The settings.
@ -170,6 +179,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
*/
public function __construct(
SettingsRenderer $settings_renderer,
FundingSourceRenderer $funding_source_renderer,
OrderProcessor $order_processor,
AuthorizedPaymentsProcessor $authorized_payments_processor,
ContainerInterface $config,
@ -190,6 +200,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
$this->order_processor = $order_processor;
$this->authorized_payments_processor = $authorized_payments_processor;
$this->settings_renderer = $settings_renderer;
$this->funding_source_renderer = $funding_source_renderer;
$this->config = $config;
$this->session_handler = $session_handler;
$this->refund_processor = $refund_processor;
@ -241,6 +252,12 @@ class PayPalGateway extends \WC_Payment_Gateway {
$this->description = $this->config->has( 'description' ) ?
$this->config->get( 'description' ) : $this->method_description;
$funding_source = $this->session_handler->funding_source();
if ( $funding_source ) {
$this->title = $this->funding_source_renderer->render_name( $funding_source );
$this->description = $this->funding_source_renderer->render_description( $funding_source );
}
$this->init_form_fields();
$this->init_settings();
@ -344,12 +361,19 @@ class PayPalGateway extends \WC_Payment_Gateway {
);
}
if ( is_admin() ) {
return __(
'Accept PayPal, Pay Later and alternative payment types.',
'woocommerce-paypal-payments'
);
}
return __(
'Pay via PayPal.',
'woocommerce-paypal-payments'
);
}
// phpcs:disable WordPress.Security.NonceVerification.Recommended
/**

View file

@ -54,12 +54,14 @@ trait ProcessPaymentTrait {
return $failure_data;
}
$payment_method = filter_input( INPUT_POST, 'payment_method', FILTER_SANITIZE_STRING );
/**
* If customer has chosen a saved credit card payment.
*/
$saved_credit_card = filter_input( INPUT_POST, 'saved_credit_card', FILTER_SANITIZE_STRING );
$change_payment = filter_input( INPUT_POST, 'woocommerce_change_payment', FILTER_SANITIZE_STRING );
if ( $saved_credit_card && ! isset( $change_payment ) ) {
if ( CreditCardGateway::ID === $payment_method && $saved_credit_card && ! isset( $change_payment ) ) {
$user_id = (int) $wc_order->get_customer_id();
$customer = new \WC_Customer( $user_id );

View file

@ -372,14 +372,11 @@ class SettingsListener {
case 'text':
case 'number':
case 'ppcp-text-input':
$settings[ $key ] = isset( $raw_data[ $key ] ) ? wp_kses_post( $raw_data[ $key ] ) : '';
break;
case 'ppcp-password':
$settings[ $key ] = isset( $raw_data[ $key ] ) ? sanitize_text_field( $raw_data[ $key ] ) : '';
break;
case 'password':
if ( empty( $raw_data[ $key ] ) ) {
break;
}
$settings[ $key ] = sanitize_text_field( $raw_data[ $key ] );
$settings[ $key ] = $raw_data[ $key ] ?? '';
break;
case 'ppcp-multiselect':
$values = isset( $raw_data[ $key ] ) ? (array) $raw_data[ $key ] : array();
@ -451,7 +448,7 @@ class SettingsListener {
// phpcs:enable WordPress.Security.NonceVerification.Missing
// phpcs:enable WordPress.Security.NonceVerification.Recommended
if ( ! current_user_can( 'manage_options' ) ) {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return false;
}
return true;

View file

@ -132,18 +132,6 @@ class WCGatewayModule implements ModuleInterface {
$endpoint->handle_request();
}
);
add_filter(
'woocommerce_email_recipient_customer_on_hold_order',
function( $recipient, $order ) {
if ( $order->get_payment_method() === PayPalGateway::ID || $order->get_payment_method() === CreditCardGateway::ID ) {
$recipient = '';
}
return $recipient;
},
10,
2
);
}
/**

View file

@ -136,7 +136,7 @@ class CheckoutOrderApproved implements RequestHandler {
}
if ( $order->intent() === 'CAPTURE' ) {
$this->order_endpoint->capture( $order );
$order = $this->order_endpoint->capture( $order );
}
} catch ( RuntimeException $error ) {
$message = sprintf(
@ -187,23 +187,18 @@ class CheckoutOrderApproved implements RequestHandler {
return rest_ensure_response( $response );
}
$new_status = $order->intent() === 'CAPTURE' ? 'processing' : 'on-hold';
$status_message = $order->intent() === 'CAPTURE' ?
__( 'Payment received.', 'woocommerce-paypal-payments' )
: __( 'Payment can be captured.', 'woocommerce-paypal-payments' );
foreach ( $wc_orders as $wc_order ) {
if ( ! in_array( $wc_order->get_status(), array( 'pending', 'on-hold' ), true ) ) {
continue;
}
/**
* The WooCommerce order.
*
* @var \WC_Order $wc_order
*/
if ( $order->intent() === 'CAPTURE' ) {
$wc_order->payment_complete();
} else {
$wc_order->update_status(
$new_status,
$status_message
'on-hold',
__( 'Payment can be captured.', 'woocommerce-paypal-payments' )
);
}
$this->logger->log(
'info',
sprintf(

View file

@ -134,15 +134,7 @@ class CheckoutOrderCompleted implements RequestHandler {
if ( ! in_array( $wc_order->get_status(), array( 'pending', 'on-hold' ), true ) ) {
continue;
}
/**
* The WooCommerce order.
*
* @var \WC_Order $wc_order
*/
$wc_order->update_status(
'processing',
__( 'Payment received.', 'woocommerce-paypal-payments' )
);
$wc_order->payment_complete();
$this->logger->log(
'info',
sprintf(

View file

@ -1,6 +1,6 @@
{
"name": "woocommerce-paypal-payments",
"version": "1.6.3",
"version": "1.6.4",
"description": "WooCommerce PayPal Payments",
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
"license": "GPL-2.0",

View file

@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, e-commerce, store, sales, sell,
Requires at least: 5.3
Tested up to: 5.8
Requires PHP: 7.1
Stable tag: 1.6.3
Stable tag: 1.6.4
License: GPLv2
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@ -81,6 +81,15 @@ Follow the steps below to connect the plugin to your PayPal account:
== Changelog ==
= 1.6.4 =
* Fix - Non admin user cannot save changes to the plugin settings #278
* Fix - Empty space in invoice prefix causes smart buttons to not load #390
* Fix - woocommerce_payment_complete action not triggered for payments completed via webhook #399
* Fix - Paying with Venmo - Change funding source on checkout page and receipt to Venmo #394
* Fix - Internal server error on checkout when selected saved card but then switched to paypal #403
* Enhancement - Allow formatted text for the Description field #407
* Enhancement - Remove filter to prevent On-Hold emails #411
= 1.6.3 =
* Fix - Payments fail when using custom order numbers #354
* Fix - Do not display saved payments on PayPal buttons if vault option is disabled #358

View file

@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\Session\SessionHandler;
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
use WooCommerce\PayPalCommerce\TestCase;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
@ -28,75 +29,107 @@ use function Brain\Monkey\Functions\when;
class WcGatewayTest extends TestCase
{
private $isAdmin = false;
private $sessionHandler;
private $fundingSource = null;
private $settingsRenderer;
private $funding_source_renderer;
private $orderProcessor;
private $authorizedOrdersProcessor;
private $settings;
private $refundProcessor;
private $onboardingState;
private $transactionUrlProvider;
private $subscriptionHelper;
private $environment;
private $paymentTokenRepository;
private $logger;
private $paymentsEndpoint;
private $orderEndpoint;
public function setUp(): void {
parent::setUp();
expect('is_admin')->andReturnUsing(function () {
return $this->isAdmin;
});
$this->settingsRenderer = Mockery::mock(SettingsRenderer::class);
$this->orderProcessor = Mockery::mock(OrderProcessor::class);
$this->authorizedOrdersProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
$this->settings = Mockery::mock(Settings::class);
$this->sessionHandler = Mockery::mock(SessionHandler::class);
$this->refundProcessor = Mockery::mock(RefundProcessor::class);
$this->onboardingState = Mockery::mock(State::class);
$this->transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
$this->subscriptionHelper = Mockery::mock(SubscriptionHelper::class);
$this->environment = Mockery::mock(Environment::class);
$this->paymentTokenRepository = Mockery::mock(PaymentTokenRepository::class);
$this->logger = Mockery::mock(LoggerInterface::class);
$this->paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class);
$this->orderEndpoint = Mockery::mock(OrderEndpoint::class);
$this->funding_source_renderer = new FundingSourceRenderer($this->settings);
$this->onboardingState->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
$this->sessionHandler
->shouldReceive('funding_source')
->andReturnUsing(function () {
return $this->fundingSource;
});
$this->settings->shouldReceive('has')->andReturnFalse();
$this->logger->shouldReceive('info');
}
private function createGateway()
{
return new PayPalGateway(
$this->settingsRenderer,
$this->funding_source_renderer,
$this->orderProcessor,
$this->authorizedOrdersProcessor,
$this->settings,
$this->sessionHandler,
$this->refundProcessor,
$this->onboardingState,
$this->transactionUrlProvider,
$this->subscriptionHelper,
PayPalGateway::ID,
$this->environment,
$this->paymentTokenRepository,
$this->logger,
$this->paymentsEndpoint,
$this->orderEndpoint
);
}
public function testProcessPaymentSuccess() {
expect('is_admin')->andReturn(false);
$orderId = 1;
$wcOrder = Mockery::mock(\WC_Order::class);
$wcOrder->shouldReceive('get_customer_id')->andReturn(1);
$wcOrder->shouldReceive('get_meta')->andReturn('');
$settingsRenderer = Mockery::mock(SettingsRenderer::class);
$orderProcessor = Mockery::mock(OrderProcessor::class);
$orderProcessor
$this->orderProcessor
->expects('process')
->andReturnUsing(
function(\WC_Order $order) use ($wcOrder) : bool {
return $order === $wcOrder;
}
);
$authorizedPaymentsProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
$settings = Mockery::mock(Settings::class);
$sessionHandler = Mockery::mock(SessionHandler::class);
$sessionHandler
$this->sessionHandler
->shouldReceive('destroy_session_data');
$settings
->shouldReceive('has')->andReturnFalse();
$refundProcessor = Mockery::mock(RefundProcessor::class);
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
$state = Mockery::mock(State::class);
$state
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
$subscriptionHelper = Mockery::mock(SubscriptionHelper::class);
$subscriptionHelper
$this->subscriptionHelper
->shouldReceive('has_subscription')
->with($orderId)
->andReturn(true)
->andReturn(false);
$subscriptionHelper
$this->subscriptionHelper
->shouldReceive('is_subscription_change_payment')
->andReturn(true);
$paymentTokenRepository = Mockery::mock(PaymentTokenRepository::class);
$logger = Mockery::mock(LoggerInterface::class);
$logger->shouldReceive('info');
$paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class);
$orderEndpoint = Mockery::mock(OrderEndpoint::class);
$testee = new PayPalGateway(
$settingsRenderer,
$orderProcessor,
$authorizedPaymentsProcessor,
$settings,
$sessionHandler,
$refundProcessor,
$state,
$transactionUrlProvider,
$subscriptionHelper,
PayPalGateway::ID,
$this->environment,
$paymentTokenRepository,
$logger,
$paymentsEndpoint,
$orderEndpoint
);
$testee = $this->createGateway();
expect('wc_get_order')
->with($orderId)
@ -121,45 +154,9 @@ class WcGatewayTest extends TestCase
}
public function testProcessPaymentOrderNotFound() {
expect('is_admin')->andReturn(false);
$orderId = 1;
$settingsRenderer = Mockery::mock(SettingsRenderer::class);
$orderProcessor = Mockery::mock(OrderProcessor::class);
$authorizedPaymentsProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
$settings = Mockery::mock(Settings::class);
$settings
->shouldReceive('has')->andReturnFalse();
$sessionHandler = Mockery::mock(SessionHandler::class);
$refundProcessor = Mockery::mock(RefundProcessor::class);
$state = Mockery::mock(State::class);
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
$state
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
$subscriptionHelper = Mockery::mock(SubscriptionHelper::class);
$paymentTokenRepository = Mockery::mock(PaymentTokenRepository::class);
$logger = Mockery::mock(LoggerInterface::class);
$paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class);
$orderEndpoint = Mockery::mock(OrderEndpoint::class);
$testee = new PayPalGateway(
$settingsRenderer,
$orderProcessor,
$authorizedPaymentsProcessor,
$settings,
$sessionHandler,
$refundProcessor,
$state,
$transactionUrlProvider,
$subscriptionHelper,
PayPalGateway::ID,
$this->environment,
$paymentTokenRepository,
$logger,
$paymentsEndpoint,
$orderEndpoint
);
$testee = $this->createGateway();
expect('wc_get_order')
->with($orderId)
@ -184,56 +181,20 @@ class WcGatewayTest extends TestCase
public function testProcessPaymentFails() {
expect('is_admin')->andReturn(false);
$orderId = 1;
$wcOrder = Mockery::mock(\WC_Order::class);
$lastError = 'some-error';
$settingsRenderer = Mockery::mock(SettingsRenderer::class);
$orderProcessor = Mockery::mock(OrderProcessor::class);
$orderProcessor
$this->orderProcessor
->expects('process')
->andReturnFalse();
$orderProcessor
$this->orderProcessor
->expects('last_error')
->andReturn($lastError);
$authorizedPaymentsProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
$settings = Mockery::mock(Settings::class);
$settings
->shouldReceive('has')->andReturnFalse();
$sessionHandler = Mockery::mock(SessionHandler::class);
$refundProcessor = Mockery::mock(RefundProcessor::class);
$state = Mockery::mock(State::class);
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
$state
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
$subscriptionHelper = Mockery::mock(SubscriptionHelper::class);
$subscriptionHelper->shouldReceive('has_subscription')->with($orderId)->andReturn(true);
$subscriptionHelper->shouldReceive('is_subscription_change_payment')->andReturn(true);
$this->subscriptionHelper->shouldReceive('has_subscription')->with($orderId)->andReturn(true);
$this->subscriptionHelper->shouldReceive('is_subscription_change_payment')->andReturn(true);
$wcOrder->shouldReceive('update_status')->andReturn(true);
$paymentTokenRepository = Mockery::mock(PaymentTokenRepository::class);
$logger = Mockery::mock(LoggerInterface::class);
$paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class);
$orderEndpoint = Mockery::mock(OrderEndpoint::class);
$testee = new PayPalGateway(
$settingsRenderer,
$orderProcessor,
$authorizedPaymentsProcessor,
$settings,
$sessionHandler,
$refundProcessor,
$state,
$transactionUrlProvider,
$subscriptionHelper,
PayPalGateway::ID,
$this->environment,
$paymentTokenRepository,
$logger,
$paymentsEndpoint,
$orderEndpoint
);
$testee = $this->createGateway();
expect('wc_get_order')
->with($orderId)
@ -261,49 +222,31 @@ class WcGatewayTest extends TestCase
*/
public function testNeedsSetup($currentState, $needSetup)
{
expect('is_admin')->andReturn(true);
$settingsRenderer = Mockery::mock(SettingsRenderer::class);
$orderProcessor = Mockery::mock(OrderProcessor::class);
$authorizedOrdersProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
$config = Mockery::mock(ContainerInterface::class);
$config
->shouldReceive('has')
->andReturn(false);
$sessionHandler = Mockery::mock(SessionHandler::class);
$refundProcessor = Mockery::mock(RefundProcessor::class);
$onboardingState = Mockery::mock(State::class);
$onboardingState
$this->isAdmin = true;
$this->onboardingState = Mockery::mock(State::class);
$this->onboardingState
->expects('current_state')
->andReturn($currentState);
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
$subscriptionHelper = Mockery::mock(SubscriptionHelper::class);
$paymentTokenRepository = Mockery::mock(PaymentTokenRepository::class);
$logger = Mockery::mock(LoggerInterface::class);
$paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class);
$orderEndpoint = Mockery::mock(OrderEndpoint::class);
$testee = new PayPalGateway(
$settingsRenderer,
$orderProcessor,
$authorizedOrdersProcessor,
$config,
$sessionHandler,
$refundProcessor,
$onboardingState,
$transactionUrlProvider,
$subscriptionHelper,
PayPalGateway::ID,
$this->environment,
$paymentTokenRepository,
$logger,
$paymentsEndpoint,
$orderEndpoint
);
$testee = $this->createGateway();
$this->assertSame($needSetup, $testee->needs_setup());
}
/**
* @dataProvider dataForFundingSource
*/
public function testFundingSource($fundingSource, $title, $description)
{
$this->fundingSource = $fundingSource;
$testee = $this->createGateway();
self::assertEquals($title, $testee->title);
self::assertEquals($description, $testee->description);
}
public function dataForTestCaptureAuthorizedPaymentNoActionableFailures() : array
{
return [
@ -330,4 +273,13 @@ class WcGatewayTest extends TestCase
[State::STATE_ONBOARDED, false]
];
}
public function dataForFundingSource(): array
{
return [
[null, 'PayPal', 'Pay via PayPal.'],
['venmo', 'Venmo', 'Pay via Venmo.'],
['qwerty', 'PayPal', 'Pay via PayPal.'],
];
}
}

View file

@ -3,13 +3,13 @@
* Plugin Name: WooCommerce PayPal Payments
* Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/
* Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, 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.6.3
* Version: 1.6.4
* Author: WooCommerce
* Author URI: https://woocommerce.com/
* License: GPL-2.0
* Requires PHP: 7.1
* WC requires at least: 3.9
* WC tested up to: 5.9
* WC tested up to: 6.0
* Text Domain: woocommerce-paypal-payments
*
* @package WooCommerce\PayPalCommerce