mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge branch 'trunk' into PCP-2006-google-pay-settings-improvements
This commit is contained in:
commit
a4ddb81d54
18 changed files with 298 additions and 116 deletions
|
@ -2107,3 +2107,16 @@ function wc_get_page_screen_id( $for ) {}
|
|||
*
|
||||
*/
|
||||
class WC_Product_Subscription_Variation extends WC_Product_Variation {}
|
||||
|
||||
/**
|
||||
* Variable Subscription Product Class
|
||||
*
|
||||
* This class extends the WC Variable product class to create variable products with recurring payments.
|
||||
*
|
||||
* @class WC_Product_Variable_Subscription
|
||||
* @package WooCommerce Subscriptions
|
||||
* @category Class
|
||||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3
|
||||
*
|
||||
*/
|
||||
class WC_Product_Variable_Subscription extends WC_Product_Variable {}
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
*** Changelog ***
|
||||
|
||||
= 2.3.0 - XXXX-XX-XX =
|
||||
= 2.3.1 - 2023-09-26 =
|
||||
* Fix - Fatal error when saving product while WooCommerce Subscriptions plugin is not active #1731
|
||||
* Fix - Validate tracking data only for add/update Package Tracking #1729
|
||||
* Fix - Disable Package Tracking for order if transaction ID doesn't exist #1727
|
||||
|
||||
= 2.3.0 - 2023-09-26 =
|
||||
* Fix - Plus sign in PayPal account email address gets converted to space #771
|
||||
* Fix - Payment method dropdown option label on edit order screen for ppcp-gateway option displaying wrong name #1639
|
||||
* Fix - WooCommerce Bookings products don't remain in Cart as a guest when PayPal button active on single product #1645
|
||||
* Fix - Since version > 2.2.0 the PayPal Checkout button on single product pages does not redirect anymore #1664
|
||||
* Fix - PayPal fee and PayPal Payout do not change on order if we do partial refund #1578
|
||||
* Fix - Order does not contain intent error when using ACDC payment token while buyer is not present #1506
|
||||
* Fix - Error when product description linked with a PayPal subscription exceeds 127 characters #1700
|
||||
* Fix - $_POST uses the wrong key to hold the shipping method #1652
|
||||
* Fix - WC Payment Token created multiple times when webhook is received #1663
|
||||
* Fix - Subtotal mismatch line name shows on Account settings page when merchant is disconnected #1702
|
||||
* Fix - Warning prevents payments on Pay for Order page when debugging is enabled #1703
|
||||
* Fix - paypal-overlay-uid_ blocks page after closing PayPal popup on Pay for Order page | Terms checkbox validation fails on Pay for Order page #1704
|
||||
* Enhancement - Add support for HPOS for tracking module #1676
|
||||
* Enhancement - Billing agreements endpoint called too frequently for Reference Transactions check #1646
|
||||
* Enhancement - Do not declare subscription support for PayPal when only ACDC vaulting #1669
|
||||
|
@ -21,6 +32,20 @@
|
|||
* Enhancement - Compatibility with WooCommerce Product Add-Ons plugin #1586
|
||||
* Enhancement - Remove "no shipment" message after adding tracking #1674
|
||||
* Enhancement - Improve error & success validation messages #1675
|
||||
* Enhancement - Compatibility with third-party "Product Add-Ons" plugins #1601
|
||||
* Enhancement - PayPal logo flashes when switching between tabs #1345
|
||||
* Enhancement - Include url & image_url in create order call #1649
|
||||
* Enhancement - Include item_url & image_url to tracking call #1712
|
||||
* Enhancement - Update strings for tracking metabox #1714
|
||||
* Enhancement - Validate email address API credentials field #1691
|
||||
* Enhancement - Set payment method title for order edit page only if our gateway #1661
|
||||
* Enhancement - Fix missing Pay Later messages in cart + refactoring #1683
|
||||
* Enhancement - Product page PP button keep loading popup - "wc_add_to_cart_params is not defined" error in WooCommerce #1655
|
||||
* Enhancement - Remove PayPal Subscriptions API feature flag #1690
|
||||
* Enhancement - Don't send image_url when it is empty #1678
|
||||
* Enhancement - Subscription support depending on Vaulting setting instead of subscription mode setting #1697
|
||||
* Enhancement - Wrong PayPal subscription id on vaulted subscriptions #1699
|
||||
* Enhancement - Remove payment vaulted checker functionality (2030) #1711
|
||||
* Feature preview - Apple Pay integration #1514
|
||||
* Feature preview - Google Pay integration #1654
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ const PayPalComponent = ({
|
|||
shippingData,
|
||||
isEditing,
|
||||
}) => {
|
||||
const {onPaymentSetup, onCheckoutAfterProcessingWithError} = eventRegistration;
|
||||
const {onPaymentSetup, onCheckoutAfterProcessingWithError, onCheckoutValidation} = eventRegistration;
|
||||
const {responseTypes} = emitResponse;
|
||||
|
||||
const [paypalOrder, setPaypalOrder] = useState(null);
|
||||
|
@ -79,8 +79,40 @@ const PayPalComponent = ({
|
|||
}
|
||||
};
|
||||
|
||||
const getCheckoutRedirectUrl = () => {
|
||||
const checkoutUrl = new URL(config.scriptData.redirect);
|
||||
// sometimes some browsers may load some kind of cached version of the page,
|
||||
// so adding a parameter to avoid that
|
||||
checkoutUrl.searchParams.append('ppcp-continuation-redirect', (new Date()).getTime().toString());
|
||||
return checkoutUrl.toString();
|
||||
}
|
||||
|
||||
const handleApprove = async (data, actions) => {
|
||||
try {
|
||||
const order = await actions.order.get();
|
||||
|
||||
if (order) {
|
||||
const addresses = paypalOrderToWcAddresses(order);
|
||||
|
||||
let promises = [
|
||||
// save address on server
|
||||
wp.data.dispatch('wc/store/cart').updateCustomerData({
|
||||
billing_address: addresses.billingAddress,
|
||||
shipping_address: addresses.shippingAddress,
|
||||
}),
|
||||
];
|
||||
if (!config.finalReviewEnabled) {
|
||||
// set address in UI
|
||||
promises.push(wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress));
|
||||
if (shippingData.needsShipping) {
|
||||
promises.push(wp.data.dispatch('wc/store/cart').setShippingAddress(addresses.shippingAddress))
|
||||
}
|
||||
}
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
setPaypalOrder(order);
|
||||
|
||||
const res = await fetch(config.scriptData.ajax.approve_order.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
|
@ -104,25 +136,8 @@ const PayPalComponent = ({
|
|||
throw new Error(config.scriptData.labels.error.generic)
|
||||
}
|
||||
|
||||
const order = await actions.order.get();
|
||||
|
||||
setPaypalOrder(order);
|
||||
|
||||
if (config.finalReviewEnabled) {
|
||||
if (order) {
|
||||
const addresses = paypalOrderToWcAddresses(order);
|
||||
|
||||
await wp.data.dispatch('wc/store/cart').updateCustomerData({
|
||||
billing_address: addresses.billingAddress,
|
||||
shipping_address: addresses.shippingAddress,
|
||||
});
|
||||
}
|
||||
const checkoutUrl = new URL(config.scriptData.redirect);
|
||||
// sometimes some browsers may load some kind of cached version of the page,
|
||||
// so adding a parameter to avoid that
|
||||
checkoutUrl.searchParams.append('ppcp-continuation-redirect', (new Date()).getTime().toString());
|
||||
|
||||
location.href = checkoutUrl.toString();
|
||||
location.href = getCheckoutRedirectUrl();
|
||||
} else {
|
||||
onSubmit();
|
||||
}
|
||||
|
@ -137,6 +152,21 @@ const PayPalComponent = ({
|
|||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = onCheckoutValidation(() => {
|
||||
if (config.scriptData.continuation) {
|
||||
return true;
|
||||
}
|
||||
if (wp.data.select('wc/store/validation').hasValidationErrors()) {
|
||||
location.href = getCheckoutRedirectUrl();
|
||||
return { type: responseTypes.ERROR };
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
return unsubscribe;
|
||||
}, [onCheckoutValidation] );
|
||||
|
||||
const handleClick = (data, actions) => {
|
||||
if (isEditing) {
|
||||
return actions.reject();
|
||||
|
|
|
@ -17,7 +17,7 @@ class SingleProductBootstap {
|
|||
this.formSelector = 'form.cart';
|
||||
|
||||
// Prevent simulate cart being called too many times in a burst.
|
||||
this.simulateCartThrottled = throttle(this.simulateCart, 5000);
|
||||
this.simulateCartThrottled = throttle(this.simulateCart, this.gateway.simulate_cart.throttling || 5000);
|
||||
|
||||
this.renderer.onButtonsInit(this.gateway.button.wrapper, () => {
|
||||
this.handleChange();
|
||||
|
@ -217,6 +217,10 @@ class SingleProductBootstap {
|
|||
}
|
||||
|
||||
simulateCart() {
|
||||
if (!this.gateway.simulate_cart.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const actionHandler = new SingleProductActionHandler(
|
||||
null,
|
||||
null,
|
||||
|
|
|
@ -482,7 +482,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
echo '<p class="woocommerce-mini-cart__buttons buttons">';
|
||||
echo '<span id="ppc-button-minicart"></span>';
|
||||
do_action( 'woocommerce_paypal_payments_minicart_button_render' );
|
||||
echo '</div>';
|
||||
echo '</p>';
|
||||
},
|
||||
30
|
||||
);
|
||||
|
@ -963,6 +963,10 @@ class SmartButton implements SmartButtonInterface {
|
|||
// phpcs:ignore WordPress.WP.I18n
|
||||
'shipping_field' => _x( 'Shipping %s', 'checkout-validation', 'woocommerce' ),
|
||||
),
|
||||
'simulate_cart' => array(
|
||||
'enabled' => apply_filters( 'woocommerce_paypal_payments_simulate_cart_enabled', true ),
|
||||
'throttling' => apply_filters( 'woocommerce_paypal_payments_simulate_cart_throttling', 5000 ),
|
||||
),
|
||||
'order_id' => 'pay-now' === $this->context() ? $this->get_order_pay_id() : 0,
|
||||
'single_product_buttons_enabled' => $this->settings_status->is_smart_button_enabled_for_location( 'product' ),
|
||||
'mini_cart_buttons_enabled' => $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' ),
|
||||
|
|
|
@ -151,6 +151,7 @@ class SimulateCartEndpoint extends AbstractCartEndpoint {
|
|||
|
||||
/**
|
||||
* Restores the real cart.
|
||||
* Currently, unsets the WC cart to prevent race conditions arising from it being persisted.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
@ -158,10 +159,17 @@ class SimulateCartEndpoint extends AbstractCartEndpoint {
|
|||
// Remove from cart because some plugins reserve resources internally when adding to cart.
|
||||
$this->remove_cart_items();
|
||||
|
||||
// Restore cart and unset cart clone.
|
||||
if ( null !== $this->real_cart ) {
|
||||
WC()->cart = $this->real_cart;
|
||||
if ( apply_filters( 'woocommerce_paypal_payments_simulate_cart_prevent_updates', true ) ) {
|
||||
// Removes shutdown actions to prevent persisting session, transients and save cookies.
|
||||
remove_all_actions( 'shutdown' );
|
||||
unset( WC()->cart );
|
||||
} else {
|
||||
// Restores cart, may lead to race conditions.
|
||||
if ( null !== $this->real_cart ) {
|
||||
WC()->cart = $this->real_cart;
|
||||
}
|
||||
}
|
||||
|
||||
unset( $this->cart );
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ trait AdminContextTrait {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( ! $order->get_meta( PayPalGateway::ORDER_ID_META_KEY ) ) {
|
||||
if ( ! $order->get_meta( PayPalGateway::ORDER_ID_META_KEY ) || empty( $order->get_transaction_id() ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ class OrderTrackingEndpoint {
|
|||
$order_id = (int) $data['order_id'];
|
||||
$action = $data['action'] ?? '';
|
||||
|
||||
$this->validate_tracking_info( $data );
|
||||
$shipment = $this->create_shipment( $order_id, $data );
|
||||
|
||||
$action === 'update'
|
||||
|
@ -381,45 +382,53 @@ class OrderTrackingEndpoint {
|
|||
$carrier = $data['carrier'] ?? '';
|
||||
|
||||
$tracking_info = array(
|
||||
'transaction_id' => $data['transaction_id'] ?? '',
|
||||
'status' => $data['status'] ?? '',
|
||||
'tracking_number' => $data['tracking_number'] ?? '',
|
||||
'carrier' => $carrier,
|
||||
'transaction_id' => $data['transaction_id'] ?? '',
|
||||
'status' => $data['status'] ?? '',
|
||||
'tracking_number' => $data['tracking_number'] ?? '',
|
||||
'carrier' => $carrier,
|
||||
'carrier_name_other' => $data['carrier_name_other'] ?? '',
|
||||
);
|
||||
|
||||
if ( ! empty( $data['items'] ) ) {
|
||||
$tracking_info['items'] = array_map( 'intval', $data['items'] );
|
||||
}
|
||||
|
||||
if ( $carrier === 'OTHER' ) {
|
||||
$tracking_info['carrier_name_other'] = $data['carrier_name_other'] ?? '';
|
||||
}
|
||||
|
||||
$this->validate_tracking_info( $tracking_info );
|
||||
|
||||
return $this->shipment_factory->create_shipment(
|
||||
$wc_order_id,
|
||||
$tracking_info['transaction_id'],
|
||||
$tracking_info['tracking_number'],
|
||||
$tracking_info['status'],
|
||||
$tracking_info['carrier'],
|
||||
$tracking_info['carrier_name_other'] ?? '',
|
||||
$tracking_info['carrier_name_other'],
|
||||
$tracking_info['items'] ?? array()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the requested tracking info.
|
||||
* Validates tracking info for given request values.
|
||||
*
|
||||
* @param array<string, mixed> $tracking_info A map of tracking information keys to values.
|
||||
* @param array<string, mixed> $request_values A map of request keys to values.
|
||||
* @return void
|
||||
* @throws RuntimeException If validation failed.
|
||||
*/
|
||||
protected function validate_tracking_info( array $tracking_info ): void {
|
||||
protected function validate_tracking_info( array $request_values ): void {
|
||||
$error_message = __( 'Missing required information: ', 'woocommerce-paypal-payments' );
|
||||
$empty_keys = array();
|
||||
|
||||
foreach ( $tracking_info as $key => $value ) {
|
||||
$carrier = $request_values['carrier'] ?? '';
|
||||
|
||||
$data_to_check = array(
|
||||
'transaction_id' => $request_values['transaction_id'] ?? '',
|
||||
'status' => $request_values['status'] ?? '',
|
||||
'tracking_number' => $request_values['tracking_number'] ?? '',
|
||||
'carrier' => $carrier,
|
||||
);
|
||||
|
||||
if ( $carrier === 'OTHER' ) {
|
||||
$data_to_check['carrier_name_other'] = $request_values['carrier_name_other'] ?? '';
|
||||
}
|
||||
|
||||
foreach ( $data_to_check as $key => $value ) {
|
||||
if ( ! empty( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace WooCommerce\PayPalCommerce\Subscription\Helper;
|
|||
|
||||
use WC_Product;
|
||||
use WC_Product_Subscription_Variation;
|
||||
use WC_Subscriptions;
|
||||
use WC_Subscriptions_Product;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
|
@ -120,7 +121,7 @@ class SubscriptionHelper {
|
|||
*/
|
||||
public function plugin_is_active(): bool {
|
||||
|
||||
return class_exists( \WC_Subscriptions::class );
|
||||
return class_exists( WC_Subscriptions::class ) && class_exists( WC_Subscriptions_Product::class );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\Subscription;
|
|||
use ActionScheduler_Store;
|
||||
use Exception;
|
||||
use WC_Product;
|
||||
use WC_Product_Subscription;
|
||||
use WC_Product_Subscription_Variation;
|
||||
use WC_Product_Variable;
|
||||
use WC_Product_Variable_Subscription;
|
||||
|
@ -194,7 +195,22 @@ class SubscriptionModule implements ModuleInterface {
|
|||
//phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
$post_id = wc_clean( wp_unslash( $_GET['post'] ?? '' ) );
|
||||
$product = wc_get_product( $post_id );
|
||||
if ( ! ( is_a( $product, WC_Product::class ) || is_a( $product, WC_Product_Subscription_Variation::class ) ) || ! WC_Subscriptions_Product::is_subscription( $product ) ) {
|
||||
if ( ! ( is_a( $product, WC_Product::class ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscriptions_helper = $c->get( 'subscription.helper' );
|
||||
assert( $subscriptions_helper instanceof SubscriptionHelper );
|
||||
|
||||
if (
|
||||
! $subscriptions_helper->plugin_is_active()
|
||||
|| ! (
|
||||
is_a( $product, WC_Product_Subscription::class )
|
||||
|| is_a( $product, WC_Product_Variable_Subscription::class )
|
||||
|| is_a( $product, WC_Product_Subscription_Variation::class )
|
||||
)
|
||||
|| ! WC_Subscriptions_Product::is_subscription( $product )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -210,6 +226,14 @@ class SubscriptionModule implements ModuleInterface {
|
|||
$products = array( $this->set_product_config( $product ) );
|
||||
if ( $product->get_type() === 'variable-subscription' ) {
|
||||
$products = array();
|
||||
|
||||
/**
|
||||
* Suppress pslam.
|
||||
*
|
||||
* @psalm-suppress TypeDoesNotContainType
|
||||
*
|
||||
* WC_Product_Variable_Subscription extends WC_Product_Variable.
|
||||
*/
|
||||
assert( $product instanceof WC_Product_Variable );
|
||||
$available_variations = $product->get_available_variations();
|
||||
foreach ( $available_variations as $variation ) {
|
||||
|
@ -541,8 +565,13 @@ class SubscriptionModule implements ModuleInterface {
|
|||
*/
|
||||
function( $variation_id ) use ( $c ) {
|
||||
$wcsnonce_save_variations = wc_clean( wp_unslash( $_POST['_wcsnonce_save_variations'] ?? '' ) );
|
||||
|
||||
$subscriptions_helper = $c->get( 'subscription.helper' );
|
||||
assert( $subscriptions_helper instanceof SubscriptionHelper );
|
||||
|
||||
if (
|
||||
! WC_Subscriptions_Product::is_subscription( $variation_id )
|
||||
! $subscriptions_helper->plugin_is_active()
|
||||
|| ! WC_Subscriptions_Product::is_subscription( $variation_id )
|
||||
|| ! is_string( $wcsnonce_save_variations )
|
||||
|| ! wp_verify_nonce( $wcsnonce_save_variations, 'wcs_subscription_variations' )
|
||||
) {
|
||||
|
@ -568,55 +597,60 @@ class SubscriptionModule implements ModuleInterface {
|
|||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $id, $subscription ) use ( $c ) {
|
||||
function( $id, $post ) use ( $c ) {
|
||||
$subscription = wcs_get_subscription( $id );
|
||||
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
return;
|
||||
}
|
||||
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( $subscription_id ) {
|
||||
$subscriptions_endpoint = $c->get( 'api.endpoint.billing-subscriptions' );
|
||||
assert( $subscriptions_endpoint instanceof BillingSubscriptions );
|
||||
if ( ! $subscription_id ) {
|
||||
return;
|
||||
}
|
||||
$subscriptions_endpoint = $c->get( 'api.endpoint.billing-subscriptions' );
|
||||
assert( $subscriptions_endpoint instanceof BillingSubscriptions );
|
||||
|
||||
if ( $subscription->get_status() === 'cancelled' ) {
|
||||
try {
|
||||
$subscriptions_endpoint->cancel( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not cancel subscription product on PayPal. ' . $error );
|
||||
if ( $subscription->get_status() === 'cancelled' ) {
|
||||
try {
|
||||
$subscriptions_endpoint->cancel( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not cancel subscription product on PayPal. ' . $error );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $subscription->get_status() === 'pending-cancel' ) {
|
||||
try {
|
||||
$subscriptions_endpoint->suspend( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not suspend subscription product on PayPal. ' . $error );
|
||||
if ( $subscription->get_status() === 'pending-cancel' ) {
|
||||
try {
|
||||
$subscriptions_endpoint->suspend( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not suspend subscription product on PayPal. ' . $error );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $subscription->get_status() === 'active' ) {
|
||||
try {
|
||||
$current_subscription = $subscriptions_endpoint->subscription( $subscription_id );
|
||||
if ( $current_subscription->status === 'SUSPENDED' ) {
|
||||
$subscriptions_endpoint->activate( $subscription_id );
|
||||
}
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not reactivate subscription product on PayPal. ' . $error );
|
||||
if ( $subscription->get_status() === 'active' ) {
|
||||
try {
|
||||
$current_subscription = $subscriptions_endpoint->subscription( $subscription_id );
|
||||
if ( $current_subscription->status === 'SUSPENDED' ) {
|
||||
$subscriptions_endpoint->activate( $subscription_id );
|
||||
}
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not reactivate subscription product on PayPal. ' . $error );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -632,7 +666,7 @@ class SubscriptionModule implements ModuleInterface {
|
|||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $actions, $subscription ): array {
|
||||
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
if ( ! is_array( $actions ) || ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
return $actions;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ class SubscriptionsApiHandler {
|
|||
*/
|
||||
public function create_product( WC_Product $product ) {
|
||||
try {
|
||||
$subscription_product = $this->products_endpoint->create( $product->get_title(), $product->get_description() );
|
||||
$subscription_product = $this->products_endpoint->create( $product->get_title(), $this->prepare_description( $product->get_description() ) );
|
||||
$product->update_meta_data( 'ppcp_subscription_product', $subscription_product->to_array() );
|
||||
$product->save();
|
||||
} catch ( RuntimeException $exception ) {
|
||||
|
@ -137,7 +137,7 @@ class SubscriptionsApiHandler {
|
|||
public function create_plan( string $plan_name, WC_Product $product ): void {
|
||||
try {
|
||||
$subscription_plan = $this->billing_plans_endpoint->create(
|
||||
$plan_name,
|
||||
$plan_name ?: $product->get_title(),
|
||||
$product->get_meta( 'ppcp_subscription_product' )['id'] ?? '',
|
||||
$this->billing_cycles( $product ),
|
||||
$this->payment_preferences_factory->from_wc_product( $product )->to_array()
|
||||
|
@ -168,7 +168,10 @@ class SubscriptionsApiHandler {
|
|||
$catalog_product = $this->products_endpoint->product( $catalog_product_id );
|
||||
$catalog_product_name = $catalog_product->name() ?: '';
|
||||
$catalog_product_description = $catalog_product->description() ?: '';
|
||||
if ( $catalog_product_name !== $product->get_title() || $catalog_product_description !== $product->get_description() ) {
|
||||
|
||||
$wc_product_description = $this->prepare_description( $product->get_description() ) ?: $product->get_title();
|
||||
|
||||
if ( $catalog_product_name !== $product->get_title() || $catalog_product_description !== $wc_product_description ) {
|
||||
$data = array();
|
||||
if ( $catalog_product_name !== $product->get_title() ) {
|
||||
$data[] = (object) array(
|
||||
|
@ -177,11 +180,11 @@ class SubscriptionsApiHandler {
|
|||
'value' => $product->get_title(),
|
||||
);
|
||||
}
|
||||
if ( $catalog_product_description !== $product->get_description() ) {
|
||||
if ( $catalog_product_description !== $wc_product_description ) {
|
||||
$data[] = (object) array(
|
||||
'op' => 'replace',
|
||||
'path' => '/description',
|
||||
'value' => $this->prepare_description( $product->get_description() ) ?: '',
|
||||
'value' => $wc_product_description,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -202,8 +202,10 @@ return array(
|
|||
|
||||
'wcgateway.settings' => SingletonDecorator::make(
|
||||
static function ( ContainerInterface $container ): Settings {
|
||||
$default_button_locations = $container->get( 'wcgateway.button.default-locations' );
|
||||
return new Settings( $default_button_locations );
|
||||
return new Settings(
|
||||
$container->get( 'wcgateway.button.default-locations' ),
|
||||
$container->get( 'wcgateway.settings.dcc-gateway-title.default' )
|
||||
);
|
||||
}
|
||||
),
|
||||
'wcgateway.notice.connect' => static function ( ContainerInterface $container ): ConnectAdminNotice {
|
||||
|
@ -489,7 +491,7 @@ return array(
|
|||
'This controls the title which the user sees during checkout.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'default' => __( 'Credit Cards', 'woocommerce-paypal-payments' ),
|
||||
'default' => $container->get( 'wcgateway.settings.dcc-gateway-title.default' ),
|
||||
'desc_tip' => true,
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
|
@ -1190,6 +1192,10 @@ return array(
|
|||
return $vaulting_label;
|
||||
},
|
||||
|
||||
'wcgateway.settings.dcc-gateway-title.default' => static function ( ContainerInterface $container ): string {
|
||||
return __( 'Debit & Credit Cards', 'woocommerce-paypal-payments' );
|
||||
},
|
||||
|
||||
'wcgateway.settings.card_billing_data_mode.default' => static function ( ContainerInterface $container ): string {
|
||||
return $container->get( 'api.shop.is-latin-america' ) ? CardBillingMode::MINIMAL_INPUT : CardBillingMode::USE_WC;
|
||||
},
|
||||
|
|
|
@ -35,13 +35,22 @@ class Settings implements ContainerInterface {
|
|||
*/
|
||||
protected $default_button_locations;
|
||||
|
||||
/**
|
||||
* The default ACDC gateway title.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $default_dcc_gateway_title;
|
||||
|
||||
/**
|
||||
* Settings constructor.
|
||||
*
|
||||
* @param string[] $default_button_locations The list of selected default button locations.
|
||||
* @param string $default_dcc_gateway_title The default ACDC gateway title.
|
||||
*/
|
||||
public function __construct( array $default_button_locations ) {
|
||||
$this->default_button_locations = $default_button_locations;
|
||||
public function __construct( array $default_button_locations, string $default_dcc_gateway_title ) {
|
||||
$this->default_button_locations = $default_button_locations;
|
||||
$this->default_dcc_gateway_title = $default_dcc_gateway_title;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,7 +125,7 @@ class Settings implements ContainerInterface {
|
|||
'pay_later_button_locations' => $this->default_button_locations,
|
||||
'pay_later_messaging_locations' => $this->default_button_locations,
|
||||
'brand_name' => get_bloginfo( 'name' ),
|
||||
'dcc_gateway_title' => __( 'Credit Cards', 'woocommerce-paypal-payments' ),
|
||||
'dcc_gateway_title' => $this->default_dcc_gateway_title,
|
||||
'dcc_gateway_description' => __(
|
||||
'Pay with your credit card.',
|
||||
'woocommerce-paypal-payments'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "woocommerce-paypal-payments",
|
||||
"version": "2.3.0",
|
||||
"version": "2.3.1",
|
||||
"description": "WooCommerce PayPal Payments",
|
||||
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
|
||||
"license": "GPL-2.0",
|
||||
|
|
29
readme.txt
29
readme.txt
|
@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple
|
|||
Requires at least: 5.3
|
||||
Tested up to: 6.3
|
||||
Requires PHP: 7.2
|
||||
Stable tag: 2.3.0
|
||||
Stable tag: 2.3.1
|
||||
License: GPLv2
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
|
@ -180,13 +180,24 @@ If you encounter issues with the PayPal buttons not appearing after an update, p
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= 2.3.0 - XXXX-XX-XX =
|
||||
= 2.3.1 - 2023-09-26 =
|
||||
* Fix - Fatal error when saving product while WooCommerce Subscriptions plugin is not active #1731
|
||||
* Fix - Validate tracking data only for add/update Package Tracking #1729
|
||||
* Fix - Disable Package Tracking for order if transaction ID doesn't exist #1727
|
||||
|
||||
= 2.3.0 - 2023-09-26 =
|
||||
* Fix - Plus sign in PayPal account email address gets converted to space #771
|
||||
* Fix - Payment method dropdown option label on edit order screen for ppcp-gateway option displaying wrong name #1639
|
||||
* Fix - WooCommerce Bookings products don't remain in Cart as a guest when PayPal button active on single product #1645
|
||||
* Fix - Since version > 2.2.0 the PayPal Checkout button on single product pages does not redirect anymore #1664
|
||||
* Fix - PayPal fee and PayPal Payout do not change on order if we do partial refund #1578
|
||||
* Fix - Order does not contain intent error when using ACDC payment token while buyer is not present #1506
|
||||
* Fix - Error when product description linked with a PayPal subscription exceeds 127 characters #1700
|
||||
* Fix - $_POST uses the wrong key to hold the shipping method #1652
|
||||
* Fix - WC Payment Token created multiple times when webhook is received #1663
|
||||
* Fix - Subtotal mismatch line name shows on Account settings page when merchant is disconnected #1702
|
||||
* Fix - Warning prevents payments on Pay for Order page when debugging is enabled #1703
|
||||
* Fix - paypal-overlay-uid_ blocks page after closing PayPal popup on Pay for Order page | Terms checkbox validation fails on Pay for Order page #1704
|
||||
* Enhancement - Add support for HPOS for tracking module #1676
|
||||
* Enhancement - Billing agreements endpoint called too frequently for Reference Transactions check #1646
|
||||
* Enhancement - Do not declare subscription support for PayPal when only ACDC vaulting #1669
|
||||
|
@ -201,6 +212,20 @@ If you encounter issues with the PayPal buttons not appearing after an update, p
|
|||
* Enhancement - Compatibility with WooCommerce Product Add-Ons plugin #1586
|
||||
* Enhancement - Remove "no shipment" message after adding tracking #1674
|
||||
* Enhancement - Improve error & success validation messages #1675
|
||||
* Enhancement - Compatibility with third-party "Product Add-Ons" plugins #1601
|
||||
* Enhancement - PayPal logo flashes when switching between tabs #1345
|
||||
* Enhancement - Include url & image_url in create order call #1649
|
||||
* Enhancement - Include item_url & image_url to tracking call #1712
|
||||
* Enhancement - Update strings for tracking metabox #1714
|
||||
* Enhancement - Validate email address API credentials field #1691
|
||||
* Enhancement - Set payment method title for order edit page only if our gateway #1661
|
||||
* Enhancement - Fix missing Pay Later messages in cart + refactoring #1683
|
||||
* Enhancement - Product page PP button keep loading popup - "wc_add_to_cart_params is not defined" error in WooCommerce #1655
|
||||
* Enhancement - Remove PayPal Subscriptions API feature flag #1690
|
||||
* Enhancement - Don't send image_url when it is empty #1678
|
||||
* Enhancement - Subscription support depending on Vaulting setting instead of subscription mode setting #1697
|
||||
* Enhancement - Wrong PayPal subscription id on vaulted subscriptions #1699
|
||||
* Enhancement - Remove payment vaulted checker functionality (2030) #1711
|
||||
* Feature preview - Apple Pay integration #1514
|
||||
* Feature preview - Google Pay integration #1654
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ class ModularTestCase extends TestCase
|
|||
$wpdb->posts = '';
|
||||
$wpdb->postmeta = '';
|
||||
|
||||
!defined('PAYPAL_API_URL') && define('PAYPAL_API_URL', 'https://api.paypal.com');
|
||||
!defined('PAYPAL_SANDBOX_API_URL') && define('PAYPAL_SANDBOX_API_URL', 'https://api.sandbox.paypal.com');
|
||||
!defined('PAYPAL_API_URL') && define('PAYPAL_API_URL', 'https://api-m.paypal.com');
|
||||
!defined('PAYPAL_SANDBOX_API_URL') && define('PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com');
|
||||
!defined('PAYPAL_INTEGRATION_DATE') && define('PAYPAL_INTEGRATION_DATE', '2020-10-15');
|
||||
|
||||
!defined('PPCP_FLAG_SUBSCRIPTION') && define('PPCP_FLAG_SUBSCRIPTION', true);
|
||||
|
|
|
@ -11,6 +11,16 @@ const {
|
|||
CART_URL,
|
||||
} = process.env;
|
||||
|
||||
const longText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ultricies integer quis auctor elit sed vulputate mi. Aliquam sem et tortor consequat id porta nibh venenatis cras. Massa enim nec dui nunc. Nulla porttitor massa id neque aliquam vestibulum morbi blandit cursus. Eu lobortis elementum nibh tellus molestie nunc. Euismod nisi porta lorem mollis aliquam ut porttitor. Ultrices tincidunt arcu non sodales neque sodales ut etiam. Urna cursus eget nunc scelerisque. Pulvinar sapien et ligula ullamcorper malesuada proin libero. Convallis a cras semper auctor neque vitae tempus quam pellentesque. Phasellus egestas tellus rutrum tellus pellentesque eu tincidunt tortor aliquam. Cras tincidunt lobortis feugiat vivamus. Nec ultrices dui sapien eget mi proin sed libero enim. Neque gravida in fermentum et sollicitudin ac orci phasellus egestas. Aliquam faucibus purus in massa. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae. At augue eget arcu dictum varius duis. Commodo ullamcorper a lacus vestibulum sed arcu non odio.\n' +
|
||||
'\n' +
|
||||
'Id cursus metus aliquam eleifend mi in nulla. A diam sollicitudin tempor id eu nisl. Faucibus purus in massa tempor. Lacus luctus accumsan tortor posuere ac ut consequat. Mauris augue neque gravida in fermentum et sollicitudin ac. Venenatis tellus in metus vulputate. Consectetur libero id faucibus nisl tincidunt eget. Pellentesque eu tincidunt tortor aliquam nulla facilisi cras fermentum odio. Dolor sed viverra ipsum nunc aliquet bibendum. Turpis in eu mi bibendum neque. Ac tincidunt vitae semper quis lectus nulla at volutpat. Felis imperdiet proin fermentum leo vel orci porta. Sed sed risus pretium quam vulputate dignissim.\n' +
|
||||
'\n' +
|
||||
'Urna et pharetra pharetra massa massa ultricies mi quis. Egestas purus viverra accumsan in nisl nisi. Elit sed vulputate mi sit amet mauris commodo. Cras fermentum odio eu feugiat pretium nibh ipsum consequat. Justo laoreet sit amet cursus sit amet dictum. Nunc id cursus metus aliquam. Tortor at auctor urna nunc id. Quis lectus nulla at volutpat diam ut. Lorem ipsum dolor sit amet consectetur adipiscing elit pellentesque. Tincidunt lobortis feugiat vivamus at augue eget arcu dictum varius.\n' +
|
||||
'\n' +
|
||||
'Mattis nunc sed blandit libero. Vitae ultricies leo integer malesuada nunc vel risus. Dapibus ultrices in iaculis nunc. Interdum varius sit amet mattis. Tortor vitae purus faucibus ornare. Netus et malesuada fames ac turpis. Elit duis tristique sollicitudin nibh sit amet. Lacus suspendisse faucibus interdum posuere lorem. In pellentesque massa placerat duis. Fusce ut placerat orci nulla pellentesque dignissim. Dictum fusce ut placerat orci nulla pellentesque dignissim enim. Nibh sit amet commodo nulla facilisi. Maecenas sed enim ut sem. Non consectetur a erat nam at lectus urna duis convallis. Diam phasellus vestibulum lorem sed risus ultricies tristique nulla. Nunc congue nisi vitae suscipit. Tortor condimentum lacinia quis vel eros donec ac. Eleifend mi in nulla posuere.\n' +
|
||||
'\n' +
|
||||
'Vestibulum lectus mauris ultrices eros. Massa sed elementum tempus egestas sed sed risus. Ut placerat orci nulla pellentesque dignissim enim sit. Duis ut diam quam nulla porttitor. Morbi tincidunt ornare massa eget egestas purus. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Arcu odio ut sem nulla pharetra diam sit. Risus sed vulputate odio ut enim. Faucibus et molestie ac feugiat. A scelerisque purus semper eget. Odio facilisis mauris sit amet massa vitae tortor. Condimentum vitae sapien pellentesque habitant morbi tristique senectus. Nec feugiat in fermentum posuere urna. Volutpat est velit egestas dui id ornare arcu odio ut. Ullamcorper malesuada proin libero nunc consequat interdum. Suspendisse in est ante in nibh mauris cursus mattis molestie. Vel eros donec ac odio tempor orci dapibus. Et tortor at risus viverra adipiscing at in tellus. Metus aliquam eleifend mi in.'
|
||||
|
||||
async function purchaseSubscriptionFromCart(page) {
|
||||
await loginAsCustomer(page);
|
||||
await page.goto(SUBSCRIPTION_URL);
|
||||
|
@ -57,7 +67,7 @@ test.describe.serial('Subscriptions Merchant', () => {
|
|||
const message = await page.locator('.notice-success');
|
||||
await expect(message).toContainText('Product published.');
|
||||
|
||||
const products = await request.get('https://api.sandbox.paypal.com/v1/catalogs/products?page_size=100&page=1&total_required=true', {
|
||||
const products = await request.get('https://api-m.sandbox.paypal.com/v1/catalogs/products?page_size=100&page=1&total_required=true', {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -73,7 +83,7 @@ test.describe.serial('Subscriptions Merchant', () => {
|
|||
|
||||
product_id = product.id;
|
||||
|
||||
const plans = await request.get(`https://api.sandbox.paypal.com/v1/billing/plans?product_id=${product_id}&page_size=10&page=1&total_required=true`, {
|
||||
const plans = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/plans?product_id=${product_id}&page_size=10&page=1&total_required=true`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -98,6 +108,7 @@ test.describe.serial('Subscriptions Merchant', () => {
|
|||
|
||||
await page.fill('#title', `Updated ${productTitle}`);
|
||||
await page.fill('#_subscription_price', '20');
|
||||
await page.fill('#content', longText)
|
||||
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
|
@ -107,7 +118,7 @@ test.describe.serial('Subscriptions Merchant', () => {
|
|||
const message = await page.locator('.notice-success');
|
||||
await expect(message).toContainText('Product updated.');
|
||||
|
||||
const products = await request.get('https://api.sandbox.paypal.com/v1/catalogs/products?page_size=100&page=1&total_required=true', {
|
||||
const products = await request.get('https://api-m.sandbox.paypal.com/v1/catalogs/products?page_size=100&page=1&total_required=true', {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -121,7 +132,7 @@ test.describe.serial('Subscriptions Merchant', () => {
|
|||
});
|
||||
await expect(product.id).toBeTruthy;
|
||||
|
||||
const plan = await request.get(`https://api.sandbox.paypal.com/v1/billing/plans/${plan_id}`, {
|
||||
const plan = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/plans/${plan_id}`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -156,7 +167,7 @@ test('Create new free trial subscription product', async ({page, request}) => {
|
|||
const message = await page.locator('.notice-success');
|
||||
await expect(message).toContainText('Product published.');
|
||||
|
||||
const products = await request.get('https://api.sandbox.paypal.com/v1/catalogs/products?page_size=100&page=1&total_required=true', {
|
||||
const products = await request.get('https://api-m.sandbox.paypal.com/v1/catalogs/products?page_size=100&page=1&total_required=true', {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -170,7 +181,7 @@ test('Create new free trial subscription product', async ({page, request}) => {
|
|||
});
|
||||
await expect(product.id).toBeTruthy;
|
||||
|
||||
const plans = await request.get(`https://api.sandbox.paypal.com/v1/billing/plans?product_id=${product.id}&page_size=10&page=1&total_required=true`, {
|
||||
const plans = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/plans?product_id=${product.id}&page_size=10&page=1&total_required=true`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -184,7 +195,7 @@ test('Create new free trial subscription product', async ({page, request}) => {
|
|||
});
|
||||
await expect(plan.id).toBeTruthy;
|
||||
|
||||
const planDetail = await request.get(`https://api.sandbox.paypal.com/v1/billing/plans/${plan.id}`, {
|
||||
const planDetail = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/plans/${plan.id}`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -253,7 +264,7 @@ test.describe('Subscriber my account actions', () => {
|
|||
await page.locator('text=View').first().click();
|
||||
|
||||
const subscriptionId = await page.locator('#ppcp-subscription-id').textContent();
|
||||
let subscription = await request.get(`https://api.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
let subscription = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -267,7 +278,7 @@ test.describe('Subscriber my account actions', () => {
|
|||
const title = page.locator('.woocommerce-message');
|
||||
await expect(title).toHaveText('Your subscription has been cancelled.');
|
||||
|
||||
subscription = await request.get(`https://api.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
subscription = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -285,7 +296,7 @@ test.describe('Subscriber my account actions', () => {
|
|||
await page.locator('text=View').first().click();
|
||||
|
||||
const subscriptionId = await page.locator('#ppcp-subscription-id').textContent();
|
||||
let subscription = await request.get(`https://api.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
let subscription = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
@ -299,7 +310,7 @@ test.describe('Subscriber my account actions', () => {
|
|||
const title = page.locator('.woocommerce-message');
|
||||
await expect(title).toHaveText('Your subscription has been cancelled.');
|
||||
|
||||
subscription = await request.get(`https://api.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
subscription = await request.get(`https://api-m.sandbox.paypal.com/v1/billing/subscriptions/${subscriptionId}`, {
|
||||
headers: {
|
||||
'Authorization': AUTHORIZATION,
|
||||
'Content-Type': 'application/json'
|
||||
|
|
|
@ -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, 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: 2.3.0
|
||||
* Version: 2.3.1
|
||||
* Author: WooCommerce
|
||||
* Author URI: https://woocommerce.com/
|
||||
* License: GPL-2.0
|
||||
|
@ -21,9 +21,9 @@ namespace WooCommerce\PayPalCommerce;
|
|||
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
define( 'PAYPAL_API_URL', 'https://api.paypal.com' );
|
||||
define( 'PAYPAL_SANDBOX_API_URL', 'https://api.sandbox.paypal.com' );
|
||||
define( 'PAYPAL_INTEGRATION_DATE', '2023-09-13' );
|
||||
define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' );
|
||||
define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' );
|
||||
define( 'PAYPAL_INTEGRATION_DATE', '2023-09-26' );
|
||||
|
||||
! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' );
|
||||
! defined( 'CONNECT_WOO_SANDBOX_CLIENT_ID' ) && define( 'CONNECT_WOO_SANDBOX_CLIENT_ID', 'AYmOHbt1VHg-OZ_oihPdzKEVbU3qg0qXonBcAztuzniQRaKE0w1Hr762cSFwd4n8wxOl-TCWohEa0XM_' );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue