mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-30 05:00:51 +08:00
Merge branch 'trunk' into pcp-401-custom-order-id
This commit is contained in:
commit
6e6b4c4b40
18 changed files with 201 additions and 205 deletions
|
@ -1,18 +1,21 @@
|
|||
*** Changelog ***
|
||||
|
||||
= 1.6.2 - TBD =
|
||||
= 1.6.2 - 2021-11-22 =
|
||||
* Fix - Order of WooCommerce checkout actions causing incompatibility with AvaTax address validation #335
|
||||
* Fix - Can't checkout to certain countries with optional postcode #330
|
||||
* FIx - Prevent subscription from being purchased when saving payment fails #308
|
||||
* FIx - Guest users must checkout twice for subscriptions, no smart buttons loaded #342
|
||||
* FIx - Failed PayPal API request causing strange error #347
|
||||
* FIx - PayPal payments page empty after switching packages #350
|
||||
* FIx - Could Not Validate Nonce Error #239
|
||||
* FIx - Refund via PayPal dashboard does not set the WooCommerce order to "Refunded" #241
|
||||
* FIx - Uncaught TypeError: round() #344
|
||||
* FIx - Broken multi-level (nested) associative array values after getting submitted from checkout page #307
|
||||
* FIx - Transaction id missing in some cases #328
|
||||
* FIx - Payment not possible in pay for order form because of terms checkbox missing #294
|
||||
* Fix - Prevent subscription from being purchased when saving payment fails #308
|
||||
* Fix - Guest users must checkout twice for subscriptions, no smart buttons loaded #342
|
||||
* Fix - Failed PayPal API request causing strange error #347
|
||||
* Fix - PayPal payments page empty after switching packages #350
|
||||
* Fix - Could Not Validate Nonce Error #239
|
||||
* Fix - Refund via PayPal dashboard does not set the WooCommerce order to "Refunded" #241
|
||||
* Fix - Uncaught TypeError: round() #344
|
||||
* Fix - Broken multi-level (nested) associative array values after getting submitted from checkout page #307
|
||||
* Fix - Transaction id missing in some cases #328
|
||||
* Fix - Payment not possible in pay for order form because of terms checkbox missing #294
|
||||
* Fix - "Save your Credit Card" shouldn't be optional when paying for a subscription #368
|
||||
* Fix - When paying for a subscription and vaulting fails, cart is cleared #367
|
||||
* Fix - Fatal error when activating PayPal Checkout plugin #363
|
||||
|
||||
= 1.6.1 - 2021-10-12 =
|
||||
* Fix - Handle authorization capture failures #312
|
||||
|
|
|
@ -130,14 +130,15 @@ return array(
|
|||
);
|
||||
},
|
||||
'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken {
|
||||
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$prefix = $container->get( 'api.prefix' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
return new IdentityToken(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$logger,
|
||||
$prefix
|
||||
$prefix,
|
||||
$settings
|
||||
);
|
||||
},
|
||||
'api.endpoint.payments' => static function ( ContainerInterface $container ): PaymentsEndpoint {
|
||||
|
|
|
@ -14,6 +14,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Token;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class IdentityToken
|
||||
|
@ -50,6 +51,13 @@ class IdentityToken {
|
|||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* The settings
|
||||
*
|
||||
* @var Settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* IdentityToken constructor.
|
||||
*
|
||||
|
@ -57,12 +65,14 @@ class IdentityToken {
|
|||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $prefix The prefix.
|
||||
* @param Settings $settings The settings.
|
||||
*/
|
||||
public function __construct( string $host, Bearer $bearer, LoggerInterface $logger, string $prefix ) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
$this->prefix = $prefix;
|
||||
public function __construct( string $host, Bearer $bearer, LoggerInterface $logger, string $prefix, Settings $settings ) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
$this->prefix = $prefix;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,7 +94,11 @@ class IdentityToken {
|
|||
'Content-Type' => 'application/json',
|
||||
),
|
||||
);
|
||||
if ( $customer_id && defined( 'PPCP_FLAG_SUBSCRIPTION' ) && PPCP_FLAG_SUBSCRIPTION ) {
|
||||
if (
|
||||
$customer_id
|
||||
&& ( $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' ) )
|
||||
&& defined( 'PPCP_FLAG_SUBSCRIPTION' ) && PPCP_FLAG_SUBSCRIPTION
|
||||
) {
|
||||
$args['body'] = wp_json_encode( array( 'customer_id' => $this->prefix . $customer_id ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -121,8 +121,10 @@ class PurchaseUnitFactory {
|
|||
$payee = $this->payee_repository->payee();
|
||||
$custom_id = (string) $order->get_id();
|
||||
$invoice_id = $this->prefix . $order->get_order_number();
|
||||
$retry = $order->get_meta( 'ppcp-retry' ) ? '-' . $order->get_meta( 'ppcp-retry' ) : '';
|
||||
$soft_descriptor = '';
|
||||
$purchase_unit = new PurchaseUnit(
|
||||
|
||||
$purchase_unit = new PurchaseUnit(
|
||||
$amount,
|
||||
$items,
|
||||
$shipping,
|
||||
|
|
|
@ -11,3 +11,7 @@
|
|||
.ppcp-credit-card-gateway-form-field-disabled {
|
||||
opacity: .5 !important;
|
||||
}
|
||||
|
||||
.ppcp-dcc-order-button {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ErrorHandler from '../ErrorHandler';
|
||||
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
|
||||
import { setVisible } from '../Helper/Hiding';
|
||||
|
||||
class CheckoutBootstap {
|
||||
constructor(gateway, renderer, messages, spinner) {
|
||||
|
@ -7,31 +8,38 @@ class CheckoutBootstap {
|
|||
this.renderer = renderer;
|
||||
this.messages = messages;
|
||||
this.spinner = spinner;
|
||||
|
||||
this.standardOrderButtonSelector = '#place_order';
|
||||
|
||||
this.buttonChangeObserver = new MutationObserver((el) => {
|
||||
this.updateUi();
|
||||
});
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
this.render();
|
||||
|
||||
// Unselect saved card.
|
||||
// WC saves form values, so with our current UI it would be a bit weird
|
||||
// if the user paid with saved, then after some time tries to pay again,
|
||||
// but wants to enter a new card, and to do that they have to choose “Select payment” in the list.
|
||||
jQuery('#saved-credit-card').val(jQuery('#saved-credit-card option:first').val());
|
||||
|
||||
jQuery(document.body).on('updated_checkout', () => {
|
||||
this.render()
|
||||
});
|
||||
|
||||
jQuery(document.body).
|
||||
on('updated_checkout payment_method_selected', () => {
|
||||
this.switchBetweenPayPalandOrderButton()
|
||||
this.displayPlaceOrderButtonForSavedCreditCards()
|
||||
|
||||
})
|
||||
jQuery(document.body).on('updated_checkout payment_method_selected', () => {
|
||||
this.updateUi();
|
||||
});
|
||||
|
||||
jQuery(document).on('hosted_fields_loaded', () => {
|
||||
jQuery('#saved-credit-card').on('change', () => {
|
||||
this.displayPlaceOrderButtonForSavedCreditCards()
|
||||
this.updateUi();
|
||||
})
|
||||
});
|
||||
|
||||
this.switchBetweenPayPalandOrderButton()
|
||||
this.displayPlaceOrderButtonForSavedCreditCards()
|
||||
this.updateUi();
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
|
@ -60,55 +68,35 @@ class CheckoutBootstap {
|
|||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
|
||||
this.buttonChangeObserver.observe(
|
||||
document.querySelector(this.standardOrderButtonSelector),
|
||||
{attributes: true}
|
||||
);
|
||||
}
|
||||
|
||||
switchBetweenPayPalandOrderButton() {
|
||||
jQuery('#saved-credit-card').val(jQuery('#saved-credit-card option:first').val());
|
||||
updateUi() {
|
||||
const currentPaymentMethod = this.currentPaymentMethod();
|
||||
const isPaypal = currentPaymentMethod === 'ppcp-gateway';
|
||||
const isCard = currentPaymentMethod === 'ppcp-credit-card-gateway';
|
||||
const isSavedCard = isCard && this.isSavedCardSelected();
|
||||
const isNotOurGateway = !isPaypal && !isCard;
|
||||
|
||||
const currentPaymentMethod = jQuery(
|
||||
'input[name="payment_method"]:checked').val();
|
||||
setVisible(this.standardOrderButtonSelector, isNotOurGateway || isSavedCard, true);
|
||||
setVisible(this.gateway.button.wrapper, isPaypal);
|
||||
setVisible(this.gateway.messages.wrapper, isPaypal);
|
||||
setVisible(this.gateway.hosted_fields.wrapper, isCard && !isSavedCard);
|
||||
|
||||
if (currentPaymentMethod !== 'ppcp-gateway' && currentPaymentMethod !== 'ppcp-credit-card-gateway') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
jQuery('#place_order').show();
|
||||
if (isPaypal) {
|
||||
this.messages.render();
|
||||
}
|
||||
else {
|
||||
jQuery('#place_order').hide();
|
||||
if (currentPaymentMethod === 'ppcp-gateway') {
|
||||
this.renderer.showButtons(this.gateway.button.wrapper);
|
||||
this.renderer.showButtons(this.gateway.messages.wrapper);
|
||||
this.messages.render()
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper)
|
||||
|
||||
if (isCard) {
|
||||
if (isSavedCard) {
|
||||
this.disableCreditCardFields();
|
||||
} else {
|
||||
this.enableCreditCardFields();
|
||||
}
|
||||
if (currentPaymentMethod === 'ppcp-credit-card-gateway') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper)
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper)
|
||||
this.renderer.showButtons(this.gateway.hosted_fields.wrapper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
displayPlaceOrderButtonForSavedCreditCards() {
|
||||
const currentPaymentMethod = jQuery(
|
||||
'input[name="payment_method"]:checked').val();
|
||||
if (currentPaymentMethod !== 'ppcp-credit-card-gateway') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jQuery('#saved-credit-card').length && jQuery('#saved-credit-card').val() !== '') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper)
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper)
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper)
|
||||
jQuery('#place_order').show()
|
||||
this.disableCreditCardFields()
|
||||
} else {
|
||||
jQuery('#place_order').hide()
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper)
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper)
|
||||
this.renderer.showButtons(this.gateway.hosted_fields.wrapper)
|
||||
this.enableCreditCardFields()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,6 +125,15 @@ class CheckoutBootstap {
|
|||
jQuery('#ppcp-credit-card-vault').attr("disabled", false)
|
||||
this.renderer.enableCreditCardFields()
|
||||
}
|
||||
|
||||
currentPaymentMethod() {
|
||||
return jQuery('input[name="payment_method"]:checked').val();
|
||||
}
|
||||
|
||||
isSavedCardSelected() {
|
||||
const savedCardList = jQuery('#saved-credit-card');
|
||||
return savedCardList.length && savedCardList.val() !== '';
|
||||
}
|
||||
}
|
||||
|
||||
export default CheckoutBootstap
|
||||
|
|
|
@ -1,86 +1,17 @@
|
|||
import ErrorHandler from '../ErrorHandler';
|
||||
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
|
||||
import CheckoutBootstap from './CheckoutBootstap'
|
||||
|
||||
class PayNowBootstrap {
|
||||
class PayNowBootstrap extends CheckoutBootstap {
|
||||
constructor(gateway, renderer, messages, spinner) {
|
||||
this.gateway = gateway;
|
||||
this.renderer = renderer;
|
||||
this.messages = messages;
|
||||
this.spinner = spinner;
|
||||
super(gateway, renderer, messages, spinner)
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
this.render();
|
||||
|
||||
jQuery(document.body).on('updated_checkout', () => {
|
||||
this.render();
|
||||
});
|
||||
|
||||
jQuery(document.body).
|
||||
on('updated_checkout payment_method_selected', () => {
|
||||
this.switchBetweenPayPalandOrderButton();
|
||||
});
|
||||
this.switchBetweenPayPalandOrderButton();
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
if (document.querySelector(this.gateway.button.cancel_wrapper)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
if (document.querySelector(this.gateway.hosted_fields.wrapper + '>div')) {
|
||||
document.querySelector(this.gateway.hosted_fields.wrapper + '>div').setAttribute('style', '');
|
||||
}
|
||||
const actionHandler = new CheckoutActionHandler(
|
||||
PayPalCommerceGateway,
|
||||
new ErrorHandler(this.gateway.labels.error.generic),
|
||||
this.spinner
|
||||
);
|
||||
|
||||
this.renderer.render(
|
||||
this.gateway.button.wrapper,
|
||||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
}
|
||||
|
||||
switchBetweenPayPalandOrderButton() {
|
||||
updateUi() {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
if (urlParams.has('change_payment_method')) {
|
||||
return
|
||||
}
|
||||
|
||||
const currentPaymentMethod = jQuery(
|
||||
'input[name="payment_method"]:checked').val();
|
||||
|
||||
if (currentPaymentMethod !== 'ppcp-gateway' && currentPaymentMethod !== 'ppcp-credit-card-gateway') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
jQuery('#place_order').show();
|
||||
}
|
||||
else {
|
||||
jQuery('#place_order').hide();
|
||||
if (currentPaymentMethod === 'ppcp-gateway') {
|
||||
this.renderer.showButtons(this.gateway.button.wrapper);
|
||||
this.renderer.showButtons(this.gateway.messages.wrapper);
|
||||
this.messages.render();
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
}
|
||||
if (currentPaymentMethod === 'ppcp-credit-card-gateway') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper);
|
||||
this.renderer.showButtons(this.gateway.hosted_fields.wrapper);
|
||||
}
|
||||
}
|
||||
super.updateUi();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
44
modules/ppcp-button/resources/js/modules/Helper/Hiding.js
Normal file
44
modules/ppcp-button/resources/js/modules/Helper/Hiding.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
const getElement = (selectorOrElement) => {
|
||||
if (typeof selectorOrElement === 'string') {
|
||||
return document.querySelector(selectorOrElement);
|
||||
}
|
||||
return selectorOrElement;
|
||||
}
|
||||
|
||||
export const isVisible = (element) => {
|
||||
return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
|
||||
}
|
||||
|
||||
export const setVisible = (selectorOrElement, show, important = false) => {
|
||||
const element = getElement(selectorOrElement);
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentValue = element.style.getPropertyValue('display');
|
||||
|
||||
if (!show) {
|
||||
if (currentValue === 'none') {
|
||||
return;
|
||||
}
|
||||
|
||||
element.style.setProperty('display', 'none', important ? 'important' : '');
|
||||
} else {
|
||||
if (currentValue === 'none') {
|
||||
element.style.removeProperty('display');
|
||||
}
|
||||
|
||||
// still not visible (if something else added display: none in CSS)
|
||||
if (!isVisible(element)) {
|
||||
element.style.setProperty('display', 'block');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const hide = (selectorOrElement, important = false) => {
|
||||
setVisible(selectorOrElement, false, important);
|
||||
};
|
||||
|
||||
export const show = (selectorOrElement) => {
|
||||
setVisible(selectorOrElement, true);
|
||||
};
|
|
@ -199,14 +199,18 @@ class SmartButton implements SmartButtonInterface {
|
|||
11
|
||||
);
|
||||
|
||||
$subscription_helper = $this->subscription_helper;
|
||||
add_filter(
|
||||
'woocommerce_credit_card_form_fields',
|
||||
function ( $default_fields, $id ) {
|
||||
function ( array $default_fields, $id ) use ( $subscription_helper ) : array {
|
||||
if ( is_user_logged_in() && $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' ) && CreditCardGateway::ID === $id ) {
|
||||
$default_fields['card-vault'] = sprintf(
|
||||
'<p class="form-row form-row-wide"><label for="vault"><input class="ppcp-credit-card-vault" type="checkbox" id="ppcp-credit-card-vault" name="vault">%s</label></p>',
|
||||
esc_html__( 'Save your Credit Card', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
|
||||
if ( ! $subscription_helper->cart_contains_subscription() ) {
|
||||
$default_fields['card-vault'] = sprintf(
|
||||
'<p class="form-row form-row-wide"><label for="vault"><input class="ppcp-credit-card-vault" type="checkbox" id="ppcp-credit-card-vault" name="vault">%s</label></p>',
|
||||
esc_html__( 'Save your Credit Card', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
}
|
||||
|
||||
$tokens = $this->payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( $tokens && $this->payment_token_repository->tokens_contains_card( $tokens ) ) {
|
||||
|
@ -560,7 +564,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
|
||||
printf(
|
||||
'<div id="%1$s" style="display:none;">
|
||||
<button class="button alt">%2$s</button>
|
||||
<button class="button alt ppcp-dcc-order-button">%2$s</button>
|
||||
</div><div id="payments-sdk__contingency-lightbox"></div><style id="ppcp-hide-dcc">.payment_method_ppcp-credit-card-gateway {display:none;}</style>',
|
||||
esc_attr( $id ),
|
||||
esc_html( $label )
|
||||
|
|
|
@ -47,7 +47,7 @@ class SubscriptionHelper {
|
|||
if ( ! isset( $item['data'] ) || ! is_a( $item['data'], \WC_Product::class ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $item['data']->is_type( 'subscription' ) ) {
|
||||
if ( $item['data']->is_type( 'subscription' ) || $item['data']->is_type( 'subscription_variation' ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,11 @@ class VaultingModule implements ModuleInterface {
|
|||
*/
|
||||
public function run( ContainerInterface $container ): void {
|
||||
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
if ( ! $settings->has( 'vault_enabled' ) || ! $settings->get( 'vault_enabled' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter(
|
||||
'woocommerce_account_menu_items',
|
||||
function( $menu_links ) {
|
||||
|
|
|
@ -58,8 +58,8 @@ trait ProcessPaymentTrait {
|
|||
* If customer has chosen a saved credit card payment.
|
||||
*/
|
||||
$saved_credit_card = filter_input( INPUT_POST, 'saved_credit_card', FILTER_SANITIZE_STRING );
|
||||
$pay_for_order = filter_input( INPUT_GET, 'pay_for_order', FILTER_SANITIZE_STRING );
|
||||
if ( $saved_credit_card && ! isset( $pay_for_order ) ) {
|
||||
$change_payment = filter_input( INPUT_GET, 'woocommerce_change_payment', FILTER_SANITIZE_STRING );
|
||||
if ( $saved_credit_card && ! isset( $change_payment ) ) {
|
||||
|
||||
$user_id = (int) $wc_order->get_customer_id();
|
||||
$customer = new \WC_Customer( $user_id );
|
||||
|
@ -253,13 +253,19 @@ trait ProcessPaymentTrait {
|
|||
}
|
||||
}
|
||||
|
||||
// Adds retry counter meta to avoid duplicate invoice id error on consequent tries.
|
||||
$wc_order->update_meta_data( 'ppcp-retry', (int) $wc_order->get_meta( 'ppcp-retry' ) + 1 );
|
||||
$wc_order->save_meta_data();
|
||||
|
||||
$this->session_handler->destroy_session_data();
|
||||
wc_add_notice( $error_message, 'error' );
|
||||
|
||||
return $failure_data;
|
||||
}
|
||||
|
||||
WC()->cart->empty_cart();
|
||||
$this->session_handler->destroy_session_data();
|
||||
|
||||
return array(
|
||||
'result' => 'success',
|
||||
'redirect' => $this->get_return_url( $wc_order ),
|
||||
|
|
|
@ -189,8 +189,6 @@ class OrderProcessor {
|
|||
$wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'true' );
|
||||
$wc_order->update_status( 'processing' );
|
||||
}
|
||||
WC()->cart->empty_cart();
|
||||
$this->session_handler->destroy_session_data();
|
||||
$this->last_error = '';
|
||||
return true;
|
||||
}
|
||||
|
|
23
readme.txt
23
readme.txt
|
@ -84,16 +84,19 @@ Follow the steps below to connect the plugin to your PayPal account:
|
|||
= 1.6.2 =
|
||||
* Fix - Order of WooCommerce checkout actions causing incompatibility with AvaTax address validation #335
|
||||
* Fix - Can't checkout to certain countries with optional postcode #330
|
||||
* FIx - Prevent subscription from being purchased when saving payment fails #308
|
||||
* FIx - Guest users must checkout twice for subscriptions, no smart buttons loaded #342
|
||||
* FIx - Failed PayPal API request causing strange error #347
|
||||
* FIx - PayPal payments page empty after switching packages #350
|
||||
* FIx - Could Not Validate Nonce Error #239
|
||||
* FIx - Refund via PayPal dashboard does not set the WooCommerce order to "Refunded" #241
|
||||
* FIx - Uncaught TypeError: round() #344
|
||||
* FIx - Broken multi-level (nested) associative array values after getting submitted from checkout page #307
|
||||
* FIx - Transaction id missing in some cases #328
|
||||
* FIx - Payment not possible in pay for order form because of terms checkbox missing #294
|
||||
* Fix - Prevent subscription from being purchased when saving payment fails #308
|
||||
* Fix - Guest users must checkout twice for subscriptions, no smart buttons loaded #342
|
||||
* Fix - Failed PayPal API request causing strange error #347
|
||||
* Fix - PayPal payments page empty after switching packages #350
|
||||
* Fix - Could Not Validate Nonce Error #239
|
||||
* Fix - Refund via PayPal dashboard does not set the WooCommerce order to "Refunded" #241
|
||||
* Fix - Uncaught TypeError: round() #344
|
||||
* Fix - Broken multi-level (nested) associative array values after getting submitted from checkout page #307
|
||||
* Fix - Transaction id missing in some cases #328
|
||||
* Fix - Payment not possible in pay for order form because of terms checkbox missing #294
|
||||
* Fix - "Save your Credit Card" shouldn't be optional when paying for a subscription #368
|
||||
* Fix - When paying for a subscription and vaulting fails, cart is cleared #367
|
||||
* Fix - Fatal error when activating PayPal Checkout plugin #363
|
||||
|
||||
= 1.6.1 =
|
||||
* Fix - Handle authorization capture failures #312
|
||||
|
|
|
@ -11,6 +11,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
|
||||
use Mockery;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use function Brain\Monkey\Functions\expect;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
|
||||
|
@ -20,6 +21,7 @@ class IdentityTokenTest extends TestCase
|
|||
private $bearer;
|
||||
private $logger;
|
||||
private $prefix;
|
||||
private $settings;
|
||||
private $sut;
|
||||
|
||||
public function setUp(): void
|
||||
|
@ -30,7 +32,9 @@ class IdentityTokenTest extends TestCase
|
|||
$this->bearer = Mockery::mock(Bearer::class);
|
||||
$this->logger = Mockery::mock(LoggerInterface::class);
|
||||
$this->prefix = 'prefix';
|
||||
$this->sut = new IdentityToken($this->host, $this->bearer, $this->logger, $this->prefix);
|
||||
$this->settings = Mockery::mock(Settings::class);
|
||||
|
||||
$this->sut = new IdentityToken($this->host, $this->bearer, $this->logger, $this->prefix, $this->settings);
|
||||
}
|
||||
|
||||
public function testGenerateForCustomerReturnsToken()
|
||||
|
@ -46,6 +50,8 @@ class IdentityTokenTest extends TestCase
|
|||
$headers = Mockery::mock(Requests_Utility_CaseInsensitiveDictionary::class);
|
||||
$headers->shouldReceive('getAll');
|
||||
$this->logger->shouldReceive('debug');
|
||||
$this->settings->shouldReceive('has')->andReturn(true);
|
||||
$this->settings->shouldReceive('get')->andReturn(true);
|
||||
|
||||
$rawResponse = [
|
||||
'body' => '{"client_token":"abc123", "expires_in":3600}',
|
||||
|
@ -96,6 +102,8 @@ class IdentityTokenTest extends TestCase
|
|||
when('wc_print_r')->returnArg();
|
||||
$this->logger->shouldReceive('log');
|
||||
$this->logger->shouldReceive('debug');
|
||||
$this->settings->shouldReceive('has')->andReturn(true);
|
||||
$this->settings->shouldReceive('get')->andReturn(true);
|
||||
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->sut->generate_for_customer(1);
|
||||
|
@ -120,6 +128,8 @@ class IdentityTokenTest extends TestCase
|
|||
when('wc_print_r')->returnArg();
|
||||
$this->logger->shouldReceive('log');
|
||||
$this->logger->shouldReceive('debug');
|
||||
$this->settings->shouldReceive('has')->andReturn(true);
|
||||
$this->settings->shouldReceive('get')->andReturn(true);
|
||||
|
||||
$this->expectException(PayPalApiException::class);
|
||||
$this->sut->generate_for_customer(1);
|
||||
|
|
|
@ -26,6 +26,7 @@ class PurchaseUnitFactoryTest extends TestCase
|
|||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$wcOrder->expects('get_order_number')->andReturn($this->wcOrderNumber);
|
||||
$wcOrder->expects('get_id')->andReturn($this->wcOrderId);
|
||||
$wcOrder->expects('get_meta')->andReturn('');
|
||||
$amount = Mockery::mock(Amount::class);
|
||||
$amountFactory = Mockery::mock(AmountFactory::class);
|
||||
$amountFactory
|
||||
|
@ -90,6 +91,7 @@ class PurchaseUnitFactoryTest extends TestCase
|
|||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$wcOrder->expects('get_order_number')->andReturn($this->wcOrderNumber);
|
||||
$wcOrder->expects('get_id')->andReturn($this->wcOrderId);
|
||||
$wcOrder->expects('get_meta')->andReturn('');
|
||||
$amount = Mockery::mock(Amount::class);
|
||||
$amountFactory = Mockery::mock(AmountFactory::class);
|
||||
$amountFactory
|
||||
|
@ -145,6 +147,7 @@ class PurchaseUnitFactoryTest extends TestCase
|
|||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$wcOrder->expects('get_order_number')->andReturn($this->wcOrderNumber);
|
||||
$wcOrder->expects('get_id')->andReturn($this->wcOrderId);
|
||||
$wcOrder->expects('get_meta')->andReturn('');
|
||||
$amount = Mockery::mock(Amount::class);
|
||||
$amountFactory = Mockery::mock(AmountFactory::class);
|
||||
$amountFactory
|
||||
|
|
|
@ -42,7 +42,7 @@ class WcGatewayTest extends TestCase
|
|||
$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
|
||||
|
@ -106,6 +106,12 @@ class WcGatewayTest extends TestCase
|
|||
when('wc_get_checkout_url')
|
||||
->justReturn('test');
|
||||
|
||||
$woocommerce = Mockery::mock(\WooCommerce::class);
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
when('WC')->justReturn($woocommerce);
|
||||
$woocommerce->cart = $cart;
|
||||
$cart->shouldReceive('empty_cart');
|
||||
|
||||
$result = $testee->process_payment($orderId);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
|
|
|
@ -88,8 +88,6 @@ class OrderProcessorTest extends TestCase
|
|||
$sessionHandler
|
||||
->expects('order')
|
||||
->andReturn($currentOrder);
|
||||
$sessionHandler
|
||||
->expects('destroy_session_data');
|
||||
|
||||
$orderEndpoint = Mockery::mock(OrderEndpoint::class);
|
||||
$orderEndpoint
|
||||
|
@ -129,15 +127,6 @@ class OrderProcessorTest extends TestCase
|
|||
$this->environment
|
||||
);
|
||||
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
$cart
|
||||
->expects('empty_cart');
|
||||
$woocommerce = Mockery::mock(\WooCommerce::class);
|
||||
when('WC')
|
||||
->justReturn($woocommerce);
|
||||
|
||||
$woocommerce->cart = $cart;
|
||||
|
||||
$wcOrder
|
||||
->expects('update_meta_data')
|
||||
->with(
|
||||
|
@ -211,8 +200,6 @@ class OrderProcessorTest extends TestCase
|
|||
$sessionHandler
|
||||
->expects('order')
|
||||
->andReturn($currentOrder);
|
||||
$sessionHandler
|
||||
->expects('destroy_session_data');
|
||||
$orderEndpoint = Mockery::mock(OrderEndpoint::class);
|
||||
$orderEndpoint
|
||||
->expects('patch_order_with')
|
||||
|
@ -234,21 +221,8 @@ class OrderProcessorTest extends TestCase
|
|||
->shouldReceive('has')
|
||||
->andReturnFalse();
|
||||
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
$cart
|
||||
->shouldReceive('empty_cart');
|
||||
|
||||
$woocommerce = Mockery::Mock(\Woocommerce::class);
|
||||
$woocommerce
|
||||
->shouldReceive('__get')
|
||||
->with('cart')
|
||||
->set('cart', $cart);
|
||||
when('WC')
|
||||
->justReturn($woocommerce);
|
||||
|
||||
$logger = Mockery::mock(LoggerInterface::class);
|
||||
|
||||
|
||||
$testee = new OrderProcessor(
|
||||
$sessionHandler,
|
||||
$orderEndpoint,
|
||||
|
@ -260,15 +234,6 @@ class OrderProcessorTest extends TestCase
|
|||
$this->environment
|
||||
);
|
||||
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
$cart
|
||||
->expects('empty_cart');
|
||||
$woocommerce = Mockery::mock(\WooCommerce::class);
|
||||
$woocommerce->cart = $cart;
|
||||
|
||||
when('WC')
|
||||
->justReturn($woocommerce);
|
||||
|
||||
$wcOrder
|
||||
->expects('update_meta_data')
|
||||
->with(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue