mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 09:08:09 +08:00
Merge branch 'trunk' into PCP-3171-several-issues-on-backwpup-com
This commit is contained in:
commit
39b6f8a1aa
67 changed files with 1716 additions and 490 deletions
|
@ -1,6 +1,20 @@
|
||||||
*** Changelog ***
|
*** Changelog ***
|
||||||
|
|
||||||
= 2.7.1 - xxxx-xx-xx =
|
= 2.8.0 - 2024-06-11 =
|
||||||
|
* Fix - Calculate totals after adding shipping to include taxes #2296
|
||||||
|
* Fix - Package tracking integration throws error in 2.7.1 #2289
|
||||||
|
* Fix - Make PayPal Subscription products unique in cart #2265
|
||||||
|
* Fix - PayPal declares subscription support when merchant not enabled for Reference Transactions #2282
|
||||||
|
* Fix - Google Pay and Apple Pay Settings button from Connection tab have wrong links #2273
|
||||||
|
* Fix - Smart Buttons in Block Checkout not respecting the location setting (2830) #2278
|
||||||
|
* Fix - Disable Pay Upon Invoice if billing/shipping country not set #2281
|
||||||
|
* Fix - Critical error on pay for order page when we try to pay with ACDC gateway #2321
|
||||||
|
* Enhancement - Enable shipping callback for WC subscriptions #2259
|
||||||
|
* Enhancement - Disable the shipping callback for "venmo" when vaulting is active #2269
|
||||||
|
* Enhancement - Improve "Could not retrieve order" error message #2271
|
||||||
|
* Enhancement - Add block Checkout compatibility to Advanced Card Processing #2246
|
||||||
|
|
||||||
|
= 2.7.1 - 2024-05-28 =
|
||||||
* Fix - Ensure package tracking data is sent to original PayPal transaction #2180
|
* Fix - Ensure package tracking data is sent to original PayPal transaction #2180
|
||||||
* Fix - Set the 'Woo_PPCP' as a default value for data-partner-attribution-id #2188
|
* Fix - Set the 'Woo_PPCP' as a default value for data-partner-attribution-id #2188
|
||||||
* Fix - Allow PUI Gateway for refund processor #2192
|
* Fix - Allow PUI Gateway for refund processor #2192
|
||||||
|
|
10
modules.php
10
modules.php
|
@ -18,8 +18,8 @@ return function ( string $root_dir ): iterable {
|
||||||
( require "$modules_dir/woocommerce-logging/module.php" )(),
|
( require "$modules_dir/woocommerce-logging/module.php" )(),
|
||||||
( require "$modules_dir/ppcp-admin-notices/module.php" )(),
|
( require "$modules_dir/ppcp-admin-notices/module.php" )(),
|
||||||
( require "$modules_dir/ppcp-api-client/module.php" )(),
|
( require "$modules_dir/ppcp-api-client/module.php" )(),
|
||||||
( require "$modules_dir/ppcp-button/module.php" )(),
|
|
||||||
( require "$modules_dir/ppcp-compat/module.php" )(),
|
( require "$modules_dir/ppcp-compat/module.php" )(),
|
||||||
|
( require "$modules_dir/ppcp-button/module.php" )(),
|
||||||
( require "$modules_dir/ppcp-onboarding/module.php" )(),
|
( require "$modules_dir/ppcp-onboarding/module.php" )(),
|
||||||
( require "$modules_dir/ppcp-session/module.php" )(),
|
( require "$modules_dir/ppcp-session/module.php" )(),
|
||||||
( require "$modules_dir/ppcp-status-report/module.php" )(),
|
( require "$modules_dir/ppcp-status-report/module.php" )(),
|
||||||
|
@ -73,12 +73,12 @@ return function ( string $root_dir ): iterable {
|
||||||
$modules[] = ( require "$modules_dir/ppcp-paylater-block/module.php" )();
|
$modules[] = ( require "$modules_dir/ppcp-paylater-block/module.php" )();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( PayLaterWCBlocksModule::is_module_loading_required() ) {
|
|
||||||
$modules[] = ( require "$modules_dir/ppcp-paylater-wc-blocks/module.php" )();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( PayLaterConfiguratorModule::is_enabled() ) {
|
if ( PayLaterConfiguratorModule::is_enabled() ) {
|
||||||
$modules[] = ( require "$modules_dir/ppcp-paylater-configurator/module.php" )();
|
$modules[] = ( require "$modules_dir/ppcp-paylater-configurator/module.php" )();
|
||||||
|
|
||||||
|
if ( PayLaterWCBlocksModule::is_module_loading_required() ) {
|
||||||
|
$modules[] = ( require "$modules_dir/ppcp-paylater-wc-blocks/module.php" )();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( apply_filters(
|
if ( apply_filters(
|
||||||
|
|
|
@ -73,6 +73,7 @@ class SdkClientToken {
|
||||||
|
|
||||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||||
$domain = wp_unslash( $_SERVER['HTTP_HOST'] ?? '' );
|
$domain = wp_unslash( $_SERVER['HTTP_HOST'] ?? '' );
|
||||||
|
$domain = preg_replace( '/^www\./', '', $domain );
|
||||||
|
|
||||||
$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials&response_type=client_token&intent=sdk_init&domains[]=' . $domain;
|
$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials&response_type=client_token&intent=sdk_init&domains[]=' . $domain;
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,7 @@ class ShippingOptionFactory {
|
||||||
$cart->calculate_shipping();
|
$cart->calculate_shipping();
|
||||||
|
|
||||||
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods', array() );
|
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods', array() );
|
||||||
if ( ! is_array( $chosen_shipping_methods ) ) {
|
$chosen_shipping_method = $chosen_shipping_methods[0] ?? false;
|
||||||
$chosen_shipping_methods = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$packages = WC()->shipping()->get_packages();
|
$packages = WC()->shipping()->get_packages();
|
||||||
$options = array();
|
$options = array();
|
||||||
|
@ -62,11 +60,10 @@ class ShippingOptionFactory {
|
||||||
if ( ! $rate instanceof \WC_Shipping_Rate ) {
|
if ( ! $rate instanceof \WC_Shipping_Rate ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$options[] = new ShippingOption(
|
$options[] = new ShippingOption(
|
||||||
$rate->get_id(),
|
$rate->get_id(),
|
||||||
$rate->get_label(),
|
$rate->get_label(),
|
||||||
in_array( $rate->get_id(), $chosen_shipping_methods, true ),
|
$rate->get_id() === $chosen_shipping_method,
|
||||||
new Money(
|
new Money(
|
||||||
(float) $rate->get_cost(),
|
(float) $rate->get_cost(),
|
||||||
get_woocommerce_currency()
|
get_woocommerce_currency()
|
||||||
|
|
|
@ -964,7 +964,7 @@ return array(
|
||||||
: $container->get( 'applepay.enable-url-sandbox' );
|
: $container->get( 'applepay.enable-url-sandbox' );
|
||||||
|
|
||||||
$button_url = $enabled
|
$button_url = $enabled
|
||||||
? admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway#field-alternative_payment_methods' )
|
? admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-credit-card-gateway#ppcp-applepay_button_enabled' )
|
||||||
: $enable_url;
|
: $enable_url;
|
||||||
|
|
||||||
return sprintf(
|
return sprintf(
|
||||||
|
|
|
@ -148,14 +148,8 @@ return array(
|
||||||
'axo_privacy' => array(
|
'axo_privacy' => array(
|
||||||
'title' => __( 'Privacy', 'woocommerce-paypal-payments' ),
|
'title' => __( 'Privacy', 'woocommerce-paypal-payments' ),
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'label' => __(
|
|
||||||
'This setting will control whether Fastlane branding is shown by email field.
|
|
||||||
<p class="description">PayPal powers this accelerated checkout solution from Fastlane. Since you\'ll share consumers\' email addresses with PayPal, please consult your legal advisors on the apropriate privacy setting for your business.</p>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
'desc_tip' => true,
|
|
||||||
'description' => __(
|
'description' => __(
|
||||||
'This setting will control whether Fastlane branding is shown by email field.',
|
'PayPal powers this accelerated checkout solution from Fastlane. Since you\'ll share consumers\' email address with PayPal, please consult your legal advisors on the appropriate privacy setting for your business.',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
),
|
||||||
'classes' => array( 'ppcp-field-indent' ),
|
'classes' => array( 'ppcp-field-indent' ),
|
||||||
|
@ -168,12 +162,14 @@ return array(
|
||||||
'requirements' => array( 'axo' ),
|
'requirements' => array( 'axo' ),
|
||||||
),
|
),
|
||||||
'axo_name_on_card' => array(
|
'axo_name_on_card' => array(
|
||||||
'title' => __( 'Display Name on Card', 'woocommerce-paypal-payments' ),
|
'title' => __( 'Cardholder Name', 'woocommerce-paypal-payments' ),
|
||||||
'type' => 'checkbox',
|
'type' => 'select',
|
||||||
'default' => 'yes',
|
'default' => 'yes',
|
||||||
|
'options' => PropertiesDictionary::cardholder_name_options(),
|
||||||
'classes' => array( 'ppcp-field-indent' ),
|
'classes' => array( 'ppcp-field-indent' ),
|
||||||
'class' => array(),
|
'class' => array(),
|
||||||
'label' => __( 'Enable this to display the "Name on Card" field for new Fastlane buyers.', 'woocommerce-paypal-payments' ),
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'description' => __( 'This setting will control whether or not the cardholder name is displayed in the card field\'s UI.', 'woocommerce-paypal-payments' ),
|
||||||
'screens' => array( State::STATE_ONBOARDED ),
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
'gateway' => array( 'dcc', 'axo' ),
|
'gateway' => array( 'dcc', 'axo' ),
|
||||||
'requirements' => array( 'axo' ),
|
'requirements' => array( 'axo' ),
|
||||||
|
@ -196,7 +192,7 @@ return array(
|
||||||
sprintf(
|
sprintf(
|
||||||
// translators: %1$s and %2$s is a link tag.
|
// translators: %1$s and %2$s is a link tag.
|
||||||
__(
|
__(
|
||||||
'Leave the default styling, or customize how Fastlane looks on your website. %1$sSee PayPal\'s developer docs%2$s for info',
|
'Leave the default styling, or customize how Fastlane looks on your website. Styles that don\'t meet accessibility guidelines will revert to the defaults. See %1$sPayPal\'s developer docs%2$s for info.',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
),
|
),
|
||||||
'<a href="https://www.paypal.com/us/fastlane" target="_blank">',
|
'<a href="https://www.paypal.com/us/fastlane" target="_blank">',
|
||||||
|
@ -236,18 +232,6 @@ return array(
|
||||||
'requirements' => array( 'axo' ),
|
'requirements' => array( 'axo' ),
|
||||||
'gateway' => array( 'dcc', 'axo' ),
|
'gateway' => array( 'dcc', 'axo' ),
|
||||||
),
|
),
|
||||||
'axo_style_root_primary_color' => array(
|
|
||||||
'title' => __( 'Primary Color', 'woocommerce-paypal-payments' ),
|
|
||||||
'type' => 'text',
|
|
||||||
'placeholder' => '#0057F',
|
|
||||||
'classes' => array( 'ppcp-field-indent' ),
|
|
||||||
'default' => '',
|
|
||||||
'screens' => array(
|
|
||||||
State::STATE_ONBOARDED,
|
|
||||||
),
|
|
||||||
'requirements' => array( 'axo' ),
|
|
||||||
'gateway' => array( 'dcc', 'axo' ),
|
|
||||||
),
|
|
||||||
'axo_style_root_error_color' => array(
|
'axo_style_root_error_color' => array(
|
||||||
'title' => __( 'Error Color', 'woocommerce-paypal-payments' ),
|
'title' => __( 'Error Color', 'woocommerce-paypal-payments' ),
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
|
@ -308,6 +292,18 @@ return array(
|
||||||
'requirements' => array( 'axo' ),
|
'requirements' => array( 'axo' ),
|
||||||
'gateway' => array( 'dcc', 'axo' ),
|
'gateway' => array( 'dcc', 'axo' ),
|
||||||
),
|
),
|
||||||
|
'axo_style_root_primary_color' => array(
|
||||||
|
'title' => __( 'Primary Color', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'placeholder' => '#0057FF',
|
||||||
|
'classes' => array( 'ppcp-field-indent' ),
|
||||||
|
'default' => '',
|
||||||
|
'screens' => array(
|
||||||
|
State::STATE_ONBOARDED,
|
||||||
|
),
|
||||||
|
'requirements' => array( 'axo' ),
|
||||||
|
'gateway' => array( 'dcc', 'axo' ),
|
||||||
|
),
|
||||||
'axo_style_input_heading' => array(
|
'axo_style_input_heading' => array(
|
||||||
'heading' => __( 'Input Settings', 'woocommerce-paypal-payments' ),
|
'heading' => __( 'Input Settings', 'woocommerce-paypal-payments' ),
|
||||||
'type' => 'ppcp-heading',
|
'type' => 'ppcp-heading',
|
||||||
|
|
|
@ -1,6 +1,48 @@
|
||||||
.ppcp-axo-watermark-container {
|
.ppcp-axo-watermark-container {
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.loader:before {
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
margin-left: -6px;
|
||||||
|
margin-top: -6px;
|
||||||
|
left: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ppcp-axo-billing-email-field-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ppcp-axo-billing-email-submit-button {
|
||||||
|
margin-top: 0;
|
||||||
|
position: relative;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
align-self: flex-start;
|
||||||
|
|
||||||
|
.loader:before {
|
||||||
|
display: inline;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
margin-left: -6px;
|
||||||
|
margin-top: -6px;
|
||||||
|
left: auto;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-axo-billing-email-submit-button {
|
||||||
|
&-hidden {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-loaded:not([disabled]) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ppcp-axo-payment-container {
|
.ppcp-axo-payment-container {
|
||||||
|
@ -28,6 +70,7 @@
|
||||||
|
|
||||||
.ppcp-axo-customer-details {
|
.ppcp-axo-customer-details {
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.axo-checkout-header-section {
|
.axo-checkout-header-section {
|
||||||
|
@ -44,6 +87,31 @@
|
||||||
padding: 0.6em 1em;
|
padding: 0.6em 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ppcp-axo-watermark-loading {
|
||||||
|
min-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-axo-overlay,
|
||||||
|
.ppcp-axo-watermark-loading:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(255, 255, 255, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 999;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-axo-loading .col-1 {
|
||||||
|
position: relative;
|
||||||
|
opacity: 0.9;
|
||||||
|
transition: opacity 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
#payment .payment_methods li label[for="payment_method_ppcp-axo-gateway"] {
|
#payment .payment_methods li label[for="payment_method_ppcp-axo-gateway"] {
|
||||||
img {
|
img {
|
||||||
float: none;
|
float: none;
|
||||||
|
@ -54,3 +122,22 @@
|
||||||
max-height: 25px;
|
max-height: 25px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ppcp-axo-customer-details #billing_email_field .woocommerce-input-wrapper {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 719px) {
|
||||||
|
#ppcp-axo-billing-email {
|
||||||
|
&-field-wrapper {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-submit-button {
|
||||||
|
align-self: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@ class AxoManager {
|
||||||
active: false,
|
active: false,
|
||||||
validEmail: false,
|
validEmail: false,
|
||||||
hasProfile: false,
|
hasProfile: false,
|
||||||
useEmailWidget: this.useEmailWidget()
|
useEmailWidget: this.useEmailWidget(),
|
||||||
|
hasCard: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.data = {
|
this.data = {
|
||||||
|
@ -59,7 +60,6 @@ class AxoManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
document.axoDebugObject = () => {
|
document.axoDebugObject = () => {
|
||||||
console.log(this);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +156,7 @@ class AxoManager {
|
||||||
this.el.showGatewaySelectionLink.on('click', async () => {
|
this.el.showGatewaySelectionLink.on('click', async () => {
|
||||||
this.hideGatewaySelection = false;
|
this.hideGatewaySelection = false;
|
||||||
this.$('.wc_payment_methods label').show();
|
this.$('.wc_payment_methods label').show();
|
||||||
|
this.$('.wc_payment_methods input').show();
|
||||||
this.cardView.refresh();
|
this.cardView.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -164,18 +165,20 @@ class AxoManager {
|
||||||
this.$('form.woocommerce-checkout input').on('keydown', async (ev) => {
|
this.$('form.woocommerce-checkout input').on('keydown', async (ev) => {
|
||||||
if(ev.key === 'Enter' && getCurrentPaymentMethod() === 'ppcp-axo-gateway' ) {
|
if(ev.key === 'Enter' && getCurrentPaymentMethod() === 'ppcp-axo-gateway' ) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
log('Enter key attempt');
|
log(`Enter key attempt - emailInput: ${this.emailInput.value}`);
|
||||||
log('emailInput', this.emailInput.value);
|
log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`);
|
||||||
log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity);
|
this.validateEmail(this.el.fieldBillingEmail.selector);
|
||||||
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
||||||
await this.onChangeEmail();
|
await this.onChangeEmail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.reEnableEmailInput();
|
||||||
|
|
||||||
// Clear last email checked identity when email field is focused.
|
// Clear last email checked identity when email field is focused.
|
||||||
this.$('#billing_email_field input').on('focus', (ev) => {
|
this.$('#billing_email_field input').on('focus', (ev) => {
|
||||||
log('Clear the last email checked:', this.lastEmailCheckedIdentity);
|
log(`Clear the last email checked: ${this.lastEmailCheckedIdentity}`);
|
||||||
this.lastEmailCheckedIdentity = '';
|
this.lastEmailCheckedIdentity = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -212,15 +215,17 @@ class AxoManager {
|
||||||
this.status.hasProfile
|
this.status.hasProfile
|
||||||
);
|
);
|
||||||
|
|
||||||
log('Scenario', scenario);
|
log(`Scenario: ${JSON.stringify(scenario)}`);
|
||||||
|
|
||||||
// Reset some elements to a default status.
|
// Reset some elements to a default status.
|
||||||
this.el.watermarkContainer.hide();
|
this.el.watermarkContainer.hide();
|
||||||
|
|
||||||
if (scenario.defaultSubmitButton) {
|
if (scenario.defaultSubmitButton) {
|
||||||
this.el.defaultSubmitButton.show();
|
this.el.defaultSubmitButton.show();
|
||||||
|
this.el.billingEmailSubmitButton.hide();
|
||||||
} else {
|
} else {
|
||||||
this.el.defaultSubmitButton.hide();
|
this.el.defaultSubmitButton.hide();
|
||||||
|
this.el.billingEmailSubmitButton.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scenario.defaultEmailField) {
|
if (scenario.defaultEmailField) {
|
||||||
|
@ -231,6 +236,7 @@ class AxoManager {
|
||||||
|
|
||||||
if (scenario.defaultFormFields) {
|
if (scenario.defaultFormFields) {
|
||||||
this.el.customerDetails.show();
|
this.el.customerDetails.show();
|
||||||
|
this.toggleLoaderAndOverlay(this.el.customerDetails, 'loader', 'ppcp-axo-overlay');
|
||||||
} else {
|
} else {
|
||||||
this.el.customerDetails.hide();
|
this.el.customerDetails.hide();
|
||||||
}
|
}
|
||||||
|
@ -245,10 +251,9 @@ class AxoManager {
|
||||||
this.el.watermarkContainer.show();
|
this.el.watermarkContainer.show();
|
||||||
|
|
||||||
// Move watermark to after email.
|
// Move watermark to after email.
|
||||||
this.$(this.el.fieldBillingEmail.selector).append(
|
document.querySelector('#billing_email_field .woocommerce-input-wrapper').append(
|
||||||
this.$(this.el.watermarkContainer.selector)
|
document.querySelector(this.el.watermarkContainer.selector)
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.el.emailWidgetContainer.hide();
|
this.el.emailWidgetContainer.hide();
|
||||||
if (!scenario.defaultEmailField) {
|
if (!scenario.defaultEmailField) {
|
||||||
|
@ -257,12 +262,14 @@ class AxoManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scenario.axoProfileViews) {
|
if (scenario.axoProfileViews) {
|
||||||
this.el.billingAddressContainer.hide();
|
|
||||||
|
|
||||||
this.shippingView.activate();
|
this.shippingView.activate();
|
||||||
this.billingView.activate();
|
|
||||||
this.cardView.activate();
|
this.cardView.activate();
|
||||||
|
|
||||||
|
if (this.status.hasCard) {
|
||||||
|
this.billingView.activate();
|
||||||
|
}
|
||||||
|
|
||||||
// Move watermark to after shipping.
|
// Move watermark to after shipping.
|
||||||
this.$(this.el.shippingAddressContainer.selector).after(
|
this.$(this.el.shippingAddressContainer.selector).after(
|
||||||
this.$(this.el.watermarkContainer.selector)
|
this.$(this.el.watermarkContainer.selector)
|
||||||
|
@ -278,6 +285,8 @@ class AxoManager {
|
||||||
|
|
||||||
if (scenario.axoPaymentContainer) {
|
if (scenario.axoPaymentContainer) {
|
||||||
this.el.paymentContainer.show();
|
this.el.paymentContainer.show();
|
||||||
|
this.el.gatewayDescription.hide();
|
||||||
|
document.querySelector(this.el.billingEmailSubmitButton.selector).setAttribute('disabled', 'disabled');
|
||||||
} else {
|
} else {
|
||||||
this.el.paymentContainer.hide();
|
this.el.paymentContainer.hide();
|
||||||
}
|
}
|
||||||
|
@ -372,7 +381,7 @@ class AxoManager {
|
||||||
setStatus(key, value) {
|
setStatus(key, value) {
|
||||||
this.status[key] = value;
|
this.status[key] = value;
|
||||||
|
|
||||||
log('Status updated', JSON.parse(JSON.stringify(this.status)));
|
log(`Status updated: ${JSON.stringify(this.status)}`);
|
||||||
|
|
||||||
document.dispatchEvent(new CustomEvent("axo_status_updated", {detail: this.status}));
|
document.dispatchEvent(new CustomEvent("axo_status_updated", {detail: this.status}));
|
||||||
|
|
||||||
|
@ -384,9 +393,8 @@ class AxoManager {
|
||||||
this.initFastlane();
|
this.initFastlane();
|
||||||
this.setStatus('active', true);
|
this.setStatus('active', true);
|
||||||
|
|
||||||
log('Attempt on activation');
|
log(`Attempt on activation - emailInput: ${this.emailInput.value}`);
|
||||||
log('emailInput', this.emailInput.value);
|
log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`);
|
||||||
log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity);
|
|
||||||
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
||||||
this.onChangeEmail();
|
this.onChangeEmail();
|
||||||
}
|
}
|
||||||
|
@ -424,10 +432,18 @@ class AxoManager {
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// billingEmailFieldWrapper
|
||||||
|
const befw = this.el.billingEmailFieldWrapper;
|
||||||
|
if (!document.querySelector(befw.selector)) {
|
||||||
|
document.querySelector('#billing_email_field .woocommerce-input-wrapper').insertAdjacentHTML('afterend', `
|
||||||
|
<div id="${befw.id}"></div>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
// Watermark container
|
// Watermark container
|
||||||
const wc = this.el.watermarkContainer;
|
const wc = this.el.watermarkContainer;
|
||||||
if (!document.querySelector(wc.selector)) {
|
if (!document.querySelector(wc.selector)) {
|
||||||
this.emailInput.insertAdjacentHTML('afterend', `
|
document.querySelector(befw.selector).insertAdjacentHTML('beforeend', `
|
||||||
<div class="${wc.className}" id="${wc.id}"></div>
|
<div class="${wc.className}" id="${wc.id}"></div>
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
@ -457,10 +473,10 @@ class AxoManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Move email to the AXO container.
|
// Move email to the AXO container.
|
||||||
let emailRow = document.querySelector(this.el.fieldBillingEmail.selector);
|
let emailRow = document.querySelector(this.el.fieldBillingEmail.selector);
|
||||||
wrapperElement.prepend(emailRow);
|
wrapperElement.prepend(emailRow);
|
||||||
|
document.querySelector(this.el.billingEmailFieldWrapper.selector).prepend(document.querySelector('#billing_email_field .woocommerce-input-wrapper'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,7 +487,8 @@ class AxoManager {
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
|
||||||
await this.connect();
|
await this.connect();
|
||||||
this.renderWatermark();
|
await this.renderWatermark();
|
||||||
|
this.renderEmailSubmitButton();
|
||||||
this.watchEmail();
|
this.watchEmail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,6 +513,26 @@ class AxoManager {
|
||||||
(await this.fastlane.FastlaneWatermarkComponent({
|
(await this.fastlane.FastlaneWatermarkComponent({
|
||||||
includeAdditionalInfo
|
includeAdditionalInfo
|
||||||
})).render(this.el.watermarkContainer.selector);
|
})).render(this.el.watermarkContainer.selector);
|
||||||
|
|
||||||
|
this.toggleWatermarkLoading(this.el.watermarkContainer, 'ppcp-axo-watermark-loading', 'loader');
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEmailSubmitButton() {
|
||||||
|
const billingEmailSubmitButton = this.el.billingEmailSubmitButton;
|
||||||
|
const billingEmailSubmitButtonSpinner = this.el.billingEmailSubmitButtonSpinner;
|
||||||
|
|
||||||
|
if (!document.querySelector(billingEmailSubmitButton.selector)) {
|
||||||
|
document.querySelector(this.el.billingEmailFieldWrapper.selector).insertAdjacentHTML('beforeend', `
|
||||||
|
<button type="button" id="${billingEmailSubmitButton.id}" class="${billingEmailSubmitButton.className}">
|
||||||
|
${this.axoConfig.billing_email_button_text}
|
||||||
|
<span id="${billingEmailSubmitButtonSpinner.id}"></span>
|
||||||
|
</button>
|
||||||
|
`);
|
||||||
|
|
||||||
|
document.querySelector(this.el.billingEmailSubmitButton.selector).offsetHeight;
|
||||||
|
document.querySelector(this.el.billingEmailSubmitButton.selector).classList.remove('ppcp-axo-billing-email-submit-button-hidden');
|
||||||
|
document.querySelector(this.el.billingEmailSubmitButton.selector).classList.add('ppcp-axo-billing-email-submit-button-loaded');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEmail() {
|
watchEmail() {
|
||||||
|
@ -506,17 +543,16 @@ class AxoManager {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.emailInput.addEventListener('change', async ()=> {
|
this.emailInput.addEventListener('change', async ()=> {
|
||||||
log('Change event attempt');
|
log(`Change event attempt - emailInput: ${this.emailInput.value}`);
|
||||||
log('emailInput', this.emailInput.value);
|
log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`);
|
||||||
log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity);
|
|
||||||
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
||||||
|
this.validateEmail(this.el.fieldBillingEmail.selector);
|
||||||
this.onChangeEmail();
|
this.onChangeEmail();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
log('Last, this.emailInput.value attempt');
|
log(`Last, this.emailInput.value attempt - emailInput: ${this.emailInput.value}`);
|
||||||
log('emailInput', this.emailInput.value);
|
log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`);
|
||||||
log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity);
|
|
||||||
if (this.emailInput.value) {
|
if (this.emailInput.value) {
|
||||||
this.onChangeEmail();
|
this.onChangeEmail();
|
||||||
}
|
}
|
||||||
|
@ -536,7 +572,7 @@ class AxoManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log('Email changed: ' + (this.emailInput ? this.emailInput.value : '<empty>'));
|
log(`Email changed: ${this.emailInput ? this.emailInput.value : '<empty>'}`);
|
||||||
|
|
||||||
this.$(this.el.paymentContainer.selector + '-detail').html('');
|
this.$(this.el.paymentContainer.selector + '-detail').html('');
|
||||||
this.$(this.el.paymentContainer.selector + '-form').html('');
|
this.$(this.el.paymentContainer.selector + '-form').html('');
|
||||||
|
@ -548,7 +584,7 @@ class AxoManager {
|
||||||
|
|
||||||
this.lastEmailCheckedIdentity = this.emailInput.value;
|
this.lastEmailCheckedIdentity = this.emailInput.value;
|
||||||
|
|
||||||
if (!this.emailInput.value || !this.emailInput.checkValidity()) {
|
if (!this.emailInput.value || !this.emailInput.checkValidity() || !this.validateEmailFormat(this.emailInput.value)) {
|
||||||
log('The email address is not valid.');
|
log('The email address is not valid.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -565,12 +601,19 @@ class AxoManager {
|
||||||
page_type: 'checkout'
|
page_type: 'checkout'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
this.disableGatewaySelection();
|
||||||
|
this.spinnerToggleLoaderAndOverlay(this.el.billingEmailSubmitButtonSpinner, 'loader', 'ppcp-axo-overlay');
|
||||||
await this.lookupCustomerByEmail();
|
await this.lookupCustomerByEmail();
|
||||||
|
this.spinnerToggleLoaderAndOverlay(this.el.billingEmailSubmitButtonSpinner, 'loader', 'ppcp-axo-overlay');
|
||||||
|
this.enableGatewaySelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
async lookupCustomerByEmail() {
|
async lookupCustomerByEmail() {
|
||||||
const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value);
|
const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value);
|
||||||
|
|
||||||
|
log(`lookupCustomerByEmail: ${JSON.stringify(lookupResponse)}`);
|
||||||
|
|
||||||
if (lookupResponse.customerContextId) {
|
if (lookupResponse.customerContextId) {
|
||||||
// Email is associated with a Connect profile or a PayPal member.
|
// Email is associated with a Connect profile or a PayPal member.
|
||||||
// Authenticate the customer to get access to their profile.
|
// Authenticate the customer to get access to their profile.
|
||||||
|
@ -578,18 +621,24 @@ class AxoManager {
|
||||||
|
|
||||||
const authResponse = await this.fastlane.identity.triggerAuthenticationFlow(lookupResponse.customerContextId);
|
const authResponse = await this.fastlane.identity.triggerAuthenticationFlow(lookupResponse.customerContextId);
|
||||||
|
|
||||||
log('AuthResponse', authResponse);
|
log(`AuthResponse - triggerAuthenticationFlow: ${JSON.stringify(authResponse)}`);
|
||||||
|
|
||||||
if (authResponse.authenticationState === 'succeeded') {
|
if (authResponse.authenticationState === 'succeeded') {
|
||||||
log(JSON.stringify(authResponse));
|
|
||||||
|
|
||||||
const shippingData = authResponse.profileData.shippingAddress;
|
const shippingData = authResponse.profileData.shippingAddress;
|
||||||
if(shippingData) {
|
if (shippingData) {
|
||||||
this.setShipping(shippingData);
|
this.setShipping(shippingData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (authResponse.profileData.card) {
|
||||||
|
this.setStatus('hasCard', true);
|
||||||
|
} else {
|
||||||
|
this.cardComponent = (await this.fastlane.FastlaneCardComponent(
|
||||||
|
this.cardComponentData()
|
||||||
|
)).render(this.el.paymentContainer.selector + '-form');
|
||||||
|
}
|
||||||
|
|
||||||
const cardBillingAddress = authResponse.profileData?.card?.paymentSource?.card?.billingAddress;
|
const cardBillingAddress = authResponse.profileData?.card?.paymentSource?.card?.billingAddress;
|
||||||
if(cardBillingAddress) {
|
if (cardBillingAddress) {
|
||||||
this.setCard(authResponse.profileData.card);
|
this.setCard(authResponse.profileData.card);
|
||||||
|
|
||||||
const billingData = {
|
const billingData = {
|
||||||
|
@ -608,6 +657,7 @@ class AxoManager {
|
||||||
|
|
||||||
this.hideGatewaySelection = true;
|
this.hideGatewaySelection = true;
|
||||||
this.$('.wc_payment_methods label').hide();
|
this.$('.wc_payment_methods label').hide();
|
||||||
|
this.$('.wc_payment_methods input').hide();
|
||||||
|
|
||||||
await this.renderWatermark(false);
|
await this.renderWatermark(false);
|
||||||
|
|
||||||
|
@ -644,6 +694,14 @@ class AxoManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disableGatewaySelection() {
|
||||||
|
this.$('.wc_payment_methods input').prop('disabled', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
enableGatewaySelection() {
|
||||||
|
this.$('.wc_payment_methods input').prop('disabled', false);
|
||||||
|
}
|
||||||
|
|
||||||
clearData() {
|
clearData() {
|
||||||
this.data = {
|
this.data = {
|
||||||
email: null,
|
email: null,
|
||||||
|
@ -672,7 +730,7 @@ class AxoManager {
|
||||||
// TODO: validate data.
|
// TODO: validate data.
|
||||||
|
|
||||||
if (this.data.card) { // Ryan flow
|
if (this.data.card) { // Ryan flow
|
||||||
log('Ryan flow.');
|
log('Starting Ryan flow.');
|
||||||
|
|
||||||
this.$('#ship-to-different-address-checkbox').prop('checked', 'checked');
|
this.$('#ship-to-different-address-checkbox').prop('checked', 'checked');
|
||||||
|
|
||||||
|
@ -683,20 +741,23 @@ class AxoManager {
|
||||||
|
|
||||||
this.ensureBillingPhoneNumber(data);
|
this.ensureBillingPhoneNumber(data);
|
||||||
|
|
||||||
|
log(`Ryan flow - submitted nonce: ${this.data.card.id}` )
|
||||||
|
|
||||||
this.submit(this.data.card.id, data);
|
this.submit(this.data.card.id, data);
|
||||||
|
|
||||||
} else { // Gary flow
|
} else { // Gary flow
|
||||||
log('Gary flow.');
|
log('Starting Gary flow.');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.cardComponent.getPaymentToken(
|
this.cardComponent.getPaymentToken(
|
||||||
this.tokenizeData()
|
this.tokenizeData()
|
||||||
).then((response) => {
|
).then((response) => {
|
||||||
|
log(`Gary flow - submitted nonce: ${response.id}` )
|
||||||
this.submit(response.id);
|
this.submit(response.id);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log('Error tokenizing.');
|
|
||||||
alert('Error tokenizing data.');
|
alert('Error tokenizing data.');
|
||||||
|
log(`Error tokenizing data. ${e.message}`, 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,7 +775,7 @@ class AxoManager {
|
||||||
|
|
||||||
tokenizeData() {
|
tokenizeData() {
|
||||||
return {
|
return {
|
||||||
name: {
|
cardholderName: {
|
||||||
fullName: this.billingView.fullName()
|
fullName: this.billingView.fullName()
|
||||||
},
|
},
|
||||||
billingAddress: {
|
billingAddress: {
|
||||||
|
@ -776,7 +837,9 @@ class AxoManager {
|
||||||
scrollTop: $notices.offset().top
|
scrollTop: $notices.offset().top
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
console.error('Failure:', responseData);
|
|
||||||
|
log(`Error sending checkout form. ${responseData}`, 'error');
|
||||||
|
|
||||||
this.hideLoading();
|
this.hideLoading();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -785,7 +848,8 @@ class AxoManager {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error:', error);
|
log(`Error sending checkout form. ${error.message}`, 'error');
|
||||||
|
|
||||||
this.hideLoading();
|
this.hideLoading();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -840,6 +904,69 @@ class AxoManager {
|
||||||
data.billing_phone = phone;
|
data.billing_phone = phone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleLoaderAndOverlay(element, loaderClass, overlayClass) {
|
||||||
|
const loader = document.querySelector(`${element.selector} .${loaderClass}`);
|
||||||
|
const overlay = document.querySelector(`${element.selector} .${overlayClass}`);
|
||||||
|
if (loader) {
|
||||||
|
loader.classList.toggle(loaderClass);
|
||||||
|
}
|
||||||
|
if (overlay) {
|
||||||
|
overlay.classList.toggle(overlayClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spinnerToggleLoaderAndOverlay(element, loaderClass, overlayClass) {
|
||||||
|
const spinner = document.querySelector(`${element.selector}`);
|
||||||
|
if (spinner) {
|
||||||
|
spinner.classList.toggle(loaderClass);
|
||||||
|
spinner.classList.toggle(overlayClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleWatermarkLoading(container, loadingClass, loaderClass) {
|
||||||
|
const watermarkLoading = document.querySelector(`${container.selector}.${loadingClass}`);
|
||||||
|
const watermarkLoader = document.querySelector(`${container.selector}.${loaderClass}`);
|
||||||
|
if (watermarkLoading) {
|
||||||
|
watermarkLoading.classList.toggle(loadingClass);
|
||||||
|
}
|
||||||
|
if (watermarkLoader) {
|
||||||
|
watermarkLoader.classList.toggle(loaderClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validateEmailFormat(value) {
|
||||||
|
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return emailPattern.test(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateEmail(billingEmail) {
|
||||||
|
const billingEmailSelector = document.querySelector(billingEmail);
|
||||||
|
const value = document.querySelector(billingEmail + ' input').value;
|
||||||
|
|
||||||
|
if (this.validateEmailFormat(value)) {
|
||||||
|
billingEmailSelector.classList.remove('woocommerce-invalid');
|
||||||
|
billingEmailSelector.classList.add('woocommerce-validated');
|
||||||
|
this.setStatus('validEmail', true);
|
||||||
|
} else {
|
||||||
|
billingEmailSelector.classList.remove('woocommerce-validated');
|
||||||
|
billingEmailSelector.classList.add('woocommerce-invalid');
|
||||||
|
this.setStatus('validEmail', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reEnableEmailInput() {
|
||||||
|
const reEnableInput = (ev) => {
|
||||||
|
const submitButton = document.querySelector(this.el.billingEmailSubmitButton.selector);
|
||||||
|
if (submitButton.hasAttribute('disabled')) {
|
||||||
|
submitButton.removeAttribute('disabled');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$('#billing_email_field input').on('focus', reEnableInput);
|
||||||
|
this.$('#billing_email_field input').on('input', reEnableInput);
|
||||||
|
this.$('#billing_email_field input').on('click', reEnableInput);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AxoManager;
|
export default AxoManager;
|
||||||
|
|
|
@ -7,6 +7,10 @@ class DomElementCollection {
|
||||||
selector: '#payment_method_ppcp-axo-gateway',
|
selector: '#payment_method_ppcp-axo-gateway',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.gatewayDescription = new DomElement({
|
||||||
|
selector: '.payment_box.payment_method_ppcp-axo-gateway',
|
||||||
|
});
|
||||||
|
|
||||||
this.defaultSubmitButton = new DomElement({
|
this.defaultSubmitButton = new DomElement({
|
||||||
selector: '#place_order',
|
selector: '#place_order',
|
||||||
});
|
});
|
||||||
|
@ -20,7 +24,7 @@ class DomElementCollection {
|
||||||
this.watermarkContainer = new DomElement({
|
this.watermarkContainer = new DomElement({
|
||||||
id: 'ppcp-axo-watermark-container',
|
id: 'ppcp-axo-watermark-container',
|
||||||
selector: '#ppcp-axo-watermark-container',
|
selector: '#ppcp-axo-watermark-container',
|
||||||
className: 'ppcp-axo-watermark-container'
|
className: 'ppcp-axo-watermark-container ppcp-axo-watermark-loading loader'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.customerDetails = new DomElement({
|
this.customerDetails = new DomElement({
|
||||||
|
@ -56,6 +60,23 @@ class DomElementCollection {
|
||||||
selector: '#billing_email_field'
|
selector: '#billing_email_field'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.billingEmailFieldWrapper = new DomElement({
|
||||||
|
id: 'ppcp-axo-billing-email-field-wrapper',
|
||||||
|
selector: '#ppcp-axo-billing-email-field-wrapper',
|
||||||
|
});
|
||||||
|
|
||||||
|
this.billingEmailSubmitButton = new DomElement({
|
||||||
|
id: 'ppcp-axo-billing-email-submit-button',
|
||||||
|
selector: '#ppcp-axo-billing-email-submit-button',
|
||||||
|
className: 'ppcp-axo-billing-email-submit-button-hidden button alt wp-element-button wc-block-components-button'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.billingEmailSubmitButtonSpinner = new DomElement({
|
||||||
|
id: 'ppcp-axo-billing-email-submit-button-spinner',
|
||||||
|
selector: '#ppcp-axo-billing-email-submit-button-spinner',
|
||||||
|
className: 'loader ppcp-axo-overlay'
|
||||||
|
});
|
||||||
|
|
||||||
this.submitButtonContainer = new DomElement({
|
this.submitButtonContainer = new DomElement({
|
||||||
selector: '#ppcp-axo-submit-button-container',
|
selector: '#ppcp-axo-submit-button-container',
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,26 @@
|
||||||
|
export function log(message, level = 'info') {
|
||||||
|
const endpoint = window.wc_ppcp_axo?.ajax?.frontend_logger?.endpoint;
|
||||||
|
if(!endpoint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
export function log(...args) {
|
fetch(endpoint, {
|
||||||
//console.log('[AXO] ', ...args);
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify({
|
||||||
|
nonce: window.wc_ppcp_axo.ajax.frontend_logger.nonce,
|
||||||
|
log: {
|
||||||
|
message,
|
||||||
|
level,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).then(() => {
|
||||||
|
switch (level) {
|
||||||
|
case 'error':
|
||||||
|
console.error(`[AXO] ${message}`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`[AXO] ${message}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,22 +34,7 @@ class BillingView {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
return `
|
return '';
|
||||||
<div style="margin-bottom: 20px;">
|
|
||||||
<div class="axo-checkout-header-section">
|
|
||||||
<h3>Billing</h3>
|
|
||||||
<a href="javascript:void(0)" ${this.el.changeBillingAddressLink.attributes}>Edit</a>
|
|
||||||
</div>
|
|
||||||
<div>${data.value('email')}</div>
|
|
||||||
<div>${data.value('company')}</div>
|
|
||||||
<div>${data.value('firstName')} ${data.value('lastName')}</div>
|
|
||||||
<div>${data.value('street1')}</div>
|
|
||||||
<div>${data.value('street2')}</div>
|
|
||||||
<div>${data.value('postCode')} ${data.value('city')}</div>
|
|
||||||
<div>${valueOfSelect('#billing_state', data.value('stateCode'))}</div>
|
|
||||||
<div>${valueOfSelect('#billing_country', data.value('countryCode'))}</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
email: {
|
email: {
|
||||||
|
|
|
@ -20,10 +20,6 @@ class CardView {
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
return `
|
return `
|
||||||
<div style="margin-bottom: 20px; text-align: center;">
|
<div style="margin-bottom: 20px; text-align: center;">
|
||||||
<div style="border:2px solid #cccccc; border-radius: 10px; padding: 26px 20px; margin-bottom: 20px; background-color:#f6f6f6">
|
|
||||||
<div>Please fill in your card details.</div>
|
|
||||||
</div>
|
|
||||||
<h4><a href="javascript:void(0)" ${this.el.changeCardLink.attributes}>Add card details</a></h4>
|
|
||||||
${selectOtherPaymentMethod()}
|
${selectOtherPaymentMethod()}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -34,8 +30,8 @@ class CardView {
|
||||||
const cardIcons = {
|
const cardIcons = {
|
||||||
'VISA': 'visa-light.svg',
|
'VISA': 'visa-light.svg',
|
||||||
'MASTER_CARD': 'mastercard-light.svg',
|
'MASTER_CARD': 'mastercard-light.svg',
|
||||||
'AMEX': 'amex.svg',
|
'AMEX': 'amex-light.svg',
|
||||||
'DISCOVER': 'discover.svg',
|
'DISCOVER': 'discover-light.svg',
|
||||||
'DINERS': 'dinersclub-light.svg',
|
'DINERS': 'dinersclub-light.svg',
|
||||||
'JCB': 'jcb-light.svg',
|
'JCB': 'jcb-light.svg',
|
||||||
'UNIONPAY': 'unionpay-light.svg',
|
'UNIONPAY': 'unionpay-light.svg',
|
||||||
|
@ -52,7 +48,7 @@ class CardView {
|
||||||
<img
|
<img
|
||||||
class="ppcp-card-icon"
|
class="ppcp-card-icon"
|
||||||
title="${data.value('brand')}"
|
title="${data.value('brand')}"
|
||||||
src="${window.wc_ppcp_axo.module_url}/assets/images/axo/${cardIcons[data.value('brand')]}"
|
src="${window.wc_ppcp_axo.icons_directory}${cardIcons[data.value('brand')]}"
|
||||||
alt="${data.value('brand')}"
|
alt="${data.value('brand')}"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,10 @@ use WooCommerce\PayPalCommerce\Axo\Assets\AxoManager;
|
||||||
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
|
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
|
||||||
use WooCommerce\PayPalCommerce\Axo\Helper\ApmApplies;
|
use WooCommerce\PayPalCommerce\Axo\Helper\ApmApplies;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
|
||||||
|
@ -58,7 +61,8 @@ return array(
|
||||||
$container->get( 'onboarding.environment' ),
|
$container->get( 'onboarding.environment' ),
|
||||||
$container->get( 'wcgateway.settings.status' ),
|
$container->get( 'wcgateway.settings.status' ),
|
||||||
$container->get( 'api.shop.currency' ),
|
$container->get( 'api.shop.currency' ),
|
||||||
$container->get( 'woocommerce.logger.woocommerce' )
|
$container->get( 'woocommerce.logger.woocommerce' ),
|
||||||
|
$container->get( 'wcgateway.url' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -144,6 +148,11 @@ return array(
|
||||||
'woocommerce_paypal_payments_axo_supported_country_currency_matrix',
|
'woocommerce_paypal_payments_axo_supported_country_currency_matrix',
|
||||||
array(
|
array(
|
||||||
'US' => array(
|
'US' => array(
|
||||||
|
'AUD',
|
||||||
|
'CAD',
|
||||||
|
'EUR',
|
||||||
|
'GBP',
|
||||||
|
'JPY',
|
||||||
'USD',
|
'USD',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -191,6 +200,40 @@ return array(
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return '<div class="ppcp-notice ppcp-notice-error"><p>' . $notice_content . '</p></div>';
|
||||||
|
},
|
||||||
|
|
||||||
|
'axo.smart-button-location-notice' => static function ( ContainerInterface $container ) : string {
|
||||||
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
|
if ( $settings->has( 'axo_enabled' ) && $settings->get( 'axo_enabled' ) ) {
|
||||||
|
$fastlane_settings_url = admin_url(
|
||||||
|
sprintf(
|
||||||
|
'admin.php?page=wc-settings&tab=checkout§ion=%1$s&ppcp-tab=%2$s#field-axo_heading',
|
||||||
|
PayPalGateway::ID,
|
||||||
|
CreditCardGateway::ID
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$notice_content = sprintf(
|
||||||
|
/* translators: %1$s: URL to the Checkout edit page. */
|
||||||
|
__(
|
||||||
|
'<span class="highlight">Important:</span> The <code>Cart</code> & <code>Classic Cart</code> <strong>Smart Button Locations</strong> cannot be disabled while <a href="%1$s">Fastlane</a> is active.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
esc_url( $fastlane_settings_url )
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
return '<div class="ppcp-notice ppcp-notice-warning"><p>' . $notice_content . '</p></div>';
|
return '<div class="ppcp-notice ppcp-notice-warning"><p>' . $notice_content . '</p></div>';
|
||||||
},
|
},
|
||||||
|
'axo.endpoint.frontend-logger' => static function ( ContainerInterface $container ): FrontendLoggerEndpoint {
|
||||||
|
return new FrontendLoggerEndpoint(
|
||||||
|
$container->get( 'button.request-data' ),
|
||||||
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,7 @@ declare(strict_types=1);
|
||||||
namespace WooCommerce\PayPalCommerce\Axo\Assets;
|
namespace WooCommerce\PayPalCommerce\Axo\Assets;
|
||||||
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Axo\FrontendLoggerEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||||
|
@ -78,6 +79,13 @@ class AxoManager {
|
||||||
*/
|
*/
|
||||||
private $session_handler;
|
private $session_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The WcGateway module URL.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $wcgateway_module_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AxoManager constructor.
|
* AxoManager constructor.
|
||||||
*
|
*
|
||||||
|
@ -89,6 +97,7 @@ class AxoManager {
|
||||||
* @param SettingsStatus $settings_status The Settings status helper.
|
* @param SettingsStatus $settings_status The Settings status helper.
|
||||||
* @param string $currency 3-letter currency code of the shop.
|
* @param string $currency 3-letter currency code of the shop.
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param LoggerInterface $logger The logger.
|
||||||
|
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $module_url,
|
string $module_url,
|
||||||
|
@ -98,17 +107,19 @@ class AxoManager {
|
||||||
Environment $environment,
|
Environment $environment,
|
||||||
SettingsStatus $settings_status,
|
SettingsStatus $settings_status,
|
||||||
string $currency,
|
string $currency,
|
||||||
LoggerInterface $logger
|
LoggerInterface $logger,
|
||||||
|
string $wcgateway_module_url
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->module_url = $module_url;
|
$this->module_url = $module_url;
|
||||||
$this->version = $version;
|
$this->version = $version;
|
||||||
$this->session_handler = $session_handler;
|
$this->session_handler = $session_handler;
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
$this->environment = $environment;
|
$this->environment = $environment;
|
||||||
$this->settings_status = $settings_status;
|
$this->settings_status = $settings_status;
|
||||||
$this->currency = $currency;
|
$this->currency = $currency;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
|
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,13 +162,13 @@ class AxoManager {
|
||||||
*/
|
*/
|
||||||
private function script_data() {
|
private function script_data() {
|
||||||
return array(
|
return array(
|
||||||
'environment' => array(
|
'environment' => array(
|
||||||
'is_sandbox' => $this->environment->current_environment() === 'sandbox',
|
'is_sandbox' => $this->environment->current_environment() === 'sandbox',
|
||||||
),
|
),
|
||||||
'widgets' => array(
|
'widgets' => array(
|
||||||
'email' => 'render',
|
'email' => 'render',
|
||||||
),
|
),
|
||||||
'insights' => array(
|
'insights' => array(
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
'client_id' => ( $this->settings->has( 'client_id' ) ? $this->settings->get( 'client_id' ) : null ),
|
'client_id' => ( $this->settings->has( 'client_id' ) ? $this->settings->get( 'client_id' ) : null ),
|
||||||
'session_id' =>
|
'session_id' =>
|
||||||
|
@ -171,7 +182,7 @@ class AxoManager {
|
||||||
'value' => WC()->cart->get_total( 'numeric' ),
|
'value' => WC()->cart->get_total( 'numeric' ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'style_options' => array(
|
'style_options' => array(
|
||||||
'root' => array(
|
'root' => array(
|
||||||
'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '',
|
'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '',
|
||||||
'errorColor' => $this->settings->has( 'axo_style_root_error_color' ) ? $this->settings->get( 'axo_style_root_error_color' ) : '',
|
'errorColor' => $this->settings->has( 'axo_style_root_error_color' ) ? $this->settings->get( 'axo_style_root_error_color' ) : '',
|
||||||
|
@ -190,14 +201,22 @@ class AxoManager {
|
||||||
'focusBorderColor' => $this->settings->has( 'axo_style_input_focus_border_color' ) ? $this->settings->get( 'axo_style_input_focus_border_color' ) : '',
|
'focusBorderColor' => $this->settings->has( 'axo_style_input_focus_border_color' ) ? $this->settings->get( 'axo_style_input_focus_border_color' ) : '',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'name_on_card' => $this->settings->has( 'axo_name_on_card' ) ? $this->settings->get( 'axo_name_on_card' ) : '',
|
'name_on_card' => $this->settings->has( 'axo_name_on_card' ) ? $this->settings->get( 'axo_name_on_card' ) : '',
|
||||||
'woocommerce' => array(
|
'woocommerce' => array(
|
||||||
'states' => array(
|
'states' => array(
|
||||||
'US' => WC()->countries->get_states( 'US' ),
|
'US' => WC()->countries->get_states( 'US' ),
|
||||||
'CA' => WC()->countries->get_states( 'CA' ),
|
'CA' => WC()->countries->get_states( 'CA' ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'module_url' => untrailingslashit( $this->module_url ),
|
'icons_directory' => esc_url( $this->wcgateway_module_url ) . 'assets/images/axo/',
|
||||||
|
'module_url' => untrailingslashit( $this->module_url ),
|
||||||
|
'ajax' => array(
|
||||||
|
'frontend_logger' => array(
|
||||||
|
'endpoint' => \WC_AJAX::get_endpoint( FrontendLoggerEndpoint::ENDPOINT ),
|
||||||
|
'nonce' => wp_create_nonce( FrontendLoggerEndpoint::nonce() ),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'billing_email_button_text' => __( 'Continue', 'woocommerce-paypal-payments' ),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AxoModule
|
* Class AxoModule
|
||||||
|
@ -43,7 +44,6 @@ class AxoModule implements ModuleInterface {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public function run( ContainerInterface $c ): void {
|
public function run( ContainerInterface $c ): void {
|
||||||
$module = $this;
|
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_payment_gateways',
|
'woocommerce_payment_gateways',
|
||||||
|
@ -74,6 +74,10 @@ class AxoModule implements ModuleInterface {
|
||||||
return $methods;
|
return $methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $this->is_excluded_endpoint() ) {
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
|
||||||
$methods[] = $gateway;
|
$methods[] = $gateway;
|
||||||
return $methods;
|
return $methods;
|
||||||
},
|
},
|
||||||
|
@ -108,9 +112,31 @@ class AxoModule implements ModuleInterface {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Force 'cart-block' and 'cart' Smart Button locations in the settings.
|
||||||
|
add_action(
|
||||||
|
'admin_init',
|
||||||
|
static function () use ( $c ) {
|
||||||
|
$listener = $c->get( 'wcgateway.settings.listener' );
|
||||||
|
assert( $listener instanceof SettingsListener );
|
||||||
|
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
|
$listener->filter_settings(
|
||||||
|
$settings->has( 'axo_enabled' ) && $settings->get( 'axo_enabled' ),
|
||||||
|
'smart_button_locations',
|
||||||
|
function( array $existing_setting_value ) {
|
||||||
|
$axo_forced_locations = array( 'cart-block', 'cart' );
|
||||||
|
return array_unique( array_merge( $existing_setting_value, $axo_forced_locations ) );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'init',
|
'init',
|
||||||
function () use ( $c, $module ) {
|
function () use ( $c ) {
|
||||||
|
$module = $this;
|
||||||
|
|
||||||
// Check if the module is applicable, correct country, currency, ... etc.
|
// Check if the module is applicable, correct country, currency, ... etc.
|
||||||
if ( ! $c->get( 'axo.eligible' ) ) {
|
if ( ! $c->get( 'axo.eligible' ) ) {
|
||||||
|
@ -123,11 +149,15 @@ class AxoModule implements ModuleInterface {
|
||||||
// Enqueue frontend scripts.
|
// Enqueue frontend scripts.
|
||||||
add_action(
|
add_action(
|
||||||
'wp_enqueue_scripts',
|
'wp_enqueue_scripts',
|
||||||
static function () use ( $c, $manager ) {
|
static function () use ( $c, $manager, $module ) {
|
||||||
|
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
$smart_button = $c->get( 'button.smart-button' );
|
$smart_button = $c->get( 'button.smart-button' );
|
||||||
assert( $smart_button instanceof SmartButtonInterface );
|
assert( $smart_button instanceof SmartButtonInterface );
|
||||||
|
|
||||||
if ( $smart_button->should_load_ppcp_script() ) {
|
if ( $module->should_render_fastlane( $settings ) && $smart_button->should_load_ppcp_script() ) {
|
||||||
$manager->enqueue();
|
$manager->enqueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,6 +247,18 @@ class AxoModule implements ModuleInterface {
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'wc_ajax_' . FrontendLoggerEndpoint::ENDPOINT,
|
||||||
|
static function () use ( $c ) {
|
||||||
|
$endpoint = $c->get( 'axo.endpoint.frontend-logger' );
|
||||||
|
assert( $endpoint instanceof FrontendLoggerEndpoint );
|
||||||
|
|
||||||
|
$endpoint->handle_request();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the markup necessary for displaying overlays and loaders for Axo on the checkout page.
|
||||||
|
$this->add_checkout_loader_markup( $c );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -290,6 +332,60 @@ class AxoModule implements ModuleInterface {
|
||||||
|
|
||||||
return ! is_user_logged_in()
|
return ! is_user_logged_in()
|
||||||
&& CartCheckoutDetector::has_classic_checkout()
|
&& CartCheckoutDetector::has_classic_checkout()
|
||||||
&& $is_axo_enabled;
|
&& $is_axo_enabled
|
||||||
|
&& ! $this->is_excluded_endpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the markup necessary for displaying overlays and loaders for Axo on the checkout page.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface $c The container.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function add_checkout_loader_markup( ContainerInterface $c ): void {
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
|
if ( $this->should_render_fastlane( $settings ) ) {
|
||||||
|
add_action(
|
||||||
|
'woocommerce_checkout_before_customer_details',
|
||||||
|
function () {
|
||||||
|
echo '<div class="ppcp-axo-loading">';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_checkout_after_customer_details',
|
||||||
|
function () {
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_checkout_billing',
|
||||||
|
function () {
|
||||||
|
echo '<div class="loader"><div class="ppcp-axo-overlay"></div>';
|
||||||
|
},
|
||||||
|
8
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_checkout_billing',
|
||||||
|
function () {
|
||||||
|
echo '</div>';
|
||||||
|
},
|
||||||
|
12
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condition to evaluate if the current endpoint is excluded.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function is_excluded_endpoint(): bool {
|
||||||
|
// Exclude the Order Pay endpoint.
|
||||||
|
return is_wc_endpoint_url( 'order-pay' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
80
modules/ppcp-axo/src/FrontendLoggerEndpoint.php
Normal file
80
modules/ppcp-axo/src/FrontendLoggerEndpoint.php
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The endpoint to log entries from frontend.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\Button\Endpoint
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Axo;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FrontendLoggerEndpoint
|
||||||
|
*/
|
||||||
|
class FrontendLoggerEndpoint implements EndpointInterface {
|
||||||
|
|
||||||
|
const ENDPOINT = 'ppc-frontend-logger';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The request data helper.
|
||||||
|
*
|
||||||
|
* @var RequestData
|
||||||
|
*/
|
||||||
|
private $request_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FrontendLoggerEndpoint constructor.
|
||||||
|
*
|
||||||
|
* @param RequestData $request_data The request data helper.
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
|
*/
|
||||||
|
public function __construct( RequestData $request_data, LoggerInterface $logger ) {
|
||||||
|
$this->request_data = $request_data;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nonce.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function nonce(): string {
|
||||||
|
return self::ENDPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws Exception On Error.
|
||||||
|
*/
|
||||||
|
public function handle_request(): bool {
|
||||||
|
$data = $this->request_data->read_request( $this->nonce() );
|
||||||
|
$level = $data['log']['level'] ?? 'info';
|
||||||
|
|
||||||
|
switch ( $level ) {
|
||||||
|
case 'error':
|
||||||
|
$this->logger->error( '[AXO] ' . $data['log']['message'] );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->logger->info( '[AXO] ' . $data['log']['message'] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_send_json_success();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -168,7 +168,7 @@ class AxoGateway extends WC_Payment_Gateway {
|
||||||
? $this->ppcp_settings->get( 'axo_gateway_title' )
|
? $this->ppcp_settings->get( 'axo_gateway_title' )
|
||||||
: $this->get_option( 'title', $this->method_title );
|
: $this->get_option( 'title', $this->method_title );
|
||||||
|
|
||||||
$this->description = $this->get_option( 'description', '' );
|
$this->description = __( 'Enter your email address to continue.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
$this->init_form_fields();
|
$this->init_form_fields();
|
||||||
$this->init_settings();
|
$this->init_settings();
|
||||||
|
|
|
@ -26,4 +26,16 @@ class PropertiesDictionary {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of possible cardholder name options.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function cardholder_name_options(): array {
|
||||||
|
return array(
|
||||||
|
'yes' => __( 'Yes', 'woocommerce-paypal-payments' ),
|
||||||
|
'no' => __( 'No', 'woocommerce-paypal-payments' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,16 +51,7 @@ return array(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
$should_disable_checkbox = apply_filters( 'woocommerce_paypal_payments_toggle_final_review_checkbox', false );
|
||||||
|
|
||||||
if ( $subscription_helper->plugin_is_active() ) {
|
|
||||||
$label .= __(
|
|
||||||
'<div class="ppcp-notice ppcp-notice-warning"><p><span class="highlight">Important:</span> Cannot be deactivated while the WooCommerce Subscriptions plugin is active.</p></div>',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$should_disable_checkbox = $subscription_helper->plugin_is_active() || apply_filters( 'woocommerce_paypal_payments_toggle_final_review_checkbox', false );
|
|
||||||
|
|
||||||
return $insert_after(
|
return $insert_after(
|
||||||
$fields,
|
$fields,
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"Edge >= 14"
|
"Edge >= 14"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@paypal/react-paypal-js": "^8.2.0",
|
"@paypal/react-paypal-js": "^8.3.0",
|
||||||
"core-js": "^3.25.0",
|
"core-js": "^3.25.0",
|
||||||
"react": "^17.0.0",
|
"react": "^17.0.0",
|
||||||
"react-dom": "^17.0.0"
|
"react-dom": "^17.0.0"
|
||||||
|
|
87
modules/ppcp-blocks/resources/js/Components/card-fields.js
Normal file
87
modules/ppcp-blocks/resources/js/Components/card-fields.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import {useEffect, useState} from '@wordpress/element';
|
||||||
|
|
||||||
|
import {
|
||||||
|
PayPalScriptProvider,
|
||||||
|
PayPalCardFieldsProvider,
|
||||||
|
PayPalCardFieldsForm,
|
||||||
|
} from "@paypal/react-paypal-js";
|
||||||
|
|
||||||
|
import {CheckoutHandler} from "./checkout-handler";
|
||||||
|
import {createOrder, onApprove} from "../card-fields-config";
|
||||||
|
import {cartHasSubscriptionProducts} from "../Helper/Subscription";
|
||||||
|
|
||||||
|
export function CardFields({config, eventRegistration, emitResponse, components}) {
|
||||||
|
const {onPaymentSetup} = eventRegistration;
|
||||||
|
const {responseTypes} = emitResponse;
|
||||||
|
const { PaymentMethodIcons } = components;
|
||||||
|
|
||||||
|
const [cardFieldsForm, setCardFieldsForm] = useState();
|
||||||
|
const getCardFieldsForm = (cardFieldsForm) => {
|
||||||
|
setCardFieldsForm(cardFieldsForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSavePayment = (savePayment) => {
|
||||||
|
localStorage.setItem('ppcp-save-card-payment', savePayment);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasSubscriptionProducts = cartHasSubscriptionProducts(config.scriptData);
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.removeItem('ppcp-save-card-payment');
|
||||||
|
|
||||||
|
if(hasSubscriptionProducts) {
|
||||||
|
localStorage.setItem('ppcp-save-card-payment', 'true');
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [hasSubscriptionProducts])
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
onPaymentSetup(() => {
|
||||||
|
async function handlePaymentProcessing() {
|
||||||
|
await cardFieldsForm.submit()
|
||||||
|
.catch((error) => {
|
||||||
|
return {
|
||||||
|
type: responseTypes.ERROR,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: responseTypes.SUCCESS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return handlePaymentProcessing();
|
||||||
|
}),
|
||||||
|
[onPaymentSetup, cardFieldsForm]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PayPalScriptProvider
|
||||||
|
options={{
|
||||||
|
clientId: config.scriptData.client_id,
|
||||||
|
components: "card-fields",
|
||||||
|
dataNamespace: 'ppcp-block-card-fields',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PayPalCardFieldsProvider
|
||||||
|
createOrder={createOrder}
|
||||||
|
onApprove={onApprove}
|
||||||
|
onError={(err) => {
|
||||||
|
console.error(err);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PayPalCardFieldsForm/>
|
||||||
|
<PaymentMethodIcons icons={config.card_icons} align="left" />
|
||||||
|
<CheckoutHandler
|
||||||
|
getCardFieldsForm={getCardFieldsForm}
|
||||||
|
getSavePayment={getSavePayment}
|
||||||
|
hasSubscriptionProducts={hasSubscriptionProducts}
|
||||||
|
saveCardText={config.save_card_text}
|
||||||
|
is_vaulting_enabled={config.is_vaulting_enabled}
|
||||||
|
/>
|
||||||
|
</PayPalCardFieldsProvider>
|
||||||
|
</PayPalScriptProvider>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import {useEffect} from '@wordpress/element';
|
||||||
|
import {usePayPalCardFields} from "@paypal/react-paypal-js";
|
||||||
|
|
||||||
|
export const CheckoutHandler = ({getCardFieldsForm, getSavePayment, hasSubscriptionProducts, saveCardText, is_vaulting_enabled}) => {
|
||||||
|
const {cardFieldsForm} = usePayPalCardFields();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCardFieldsForm(cardFieldsForm)
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!is_vaulting_enabled) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="save"
|
||||||
|
name="save"
|
||||||
|
onChange={(e) => getSavePayment(e.target.checked)}
|
||||||
|
defaultChecked={hasSubscriptionProducts}
|
||||||
|
disabled={hasSubscriptionProducts}
|
||||||
|
/>
|
||||||
|
<label htmlFor="save">{saveCardText}</label>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import {CardFields} from "./Components/card-fields";
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting('ppcp-credit-card-gateway_data');
|
||||||
|
|
||||||
|
registerPaymentMethod({
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={{__html: config.title}}/>,
|
||||||
|
content: <CardFields config={config}/>,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {return true},
|
||||||
|
supports: {
|
||||||
|
showSavedCards: true,
|
||||||
|
features: config.supports
|
||||||
|
}
|
||||||
|
})
|
43
modules/ppcp-blocks/resources/js/card-fields-config.js
Normal file
43
modules/ppcp-blocks/resources/js/card-fields-config.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
const config = wc.wcSettings.getSetting('ppcp-credit-card-gateway_data');
|
||||||
|
|
||||||
|
export async function createOrder() {
|
||||||
|
return fetch(config.scriptData.ajax.create_order.endpoint, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
nonce: config.scriptData.ajax.create_order.nonce,
|
||||||
|
context: config.scriptData.context,
|
||||||
|
payment_method: 'ppcp-credit-card-gateway',
|
||||||
|
save_payment_method: localStorage.getItem('ppcp-save-card-payment') === 'true',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((order) => {
|
||||||
|
return order.data.id;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function onApprove(data) {
|
||||||
|
return fetch(config.scriptData.ajax.approve_order.endpoint, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
order_id: data.orderID,
|
||||||
|
nonce: config.scriptData.ajax.approve_order.nonce,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
localStorage.removeItem('ppcp-save-card-payment');
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
|
@ -23,6 +23,9 @@ import {
|
||||||
import buttonModuleWatcher from "../../../ppcp-button/resources/js/modules/ButtonModuleWatcher";
|
import buttonModuleWatcher from "../../../ppcp-button/resources/js/modules/ButtonModuleWatcher";
|
||||||
import BlockCheckoutMessagesBootstrap from "./Bootstrap/BlockCheckoutMessagesBootstrap";
|
import BlockCheckoutMessagesBootstrap from "./Bootstrap/BlockCheckoutMessagesBootstrap";
|
||||||
import {keysToCamelCase} from "../../../ppcp-button/resources/js/modules/Helper/Utils";
|
import {keysToCamelCase} from "../../../ppcp-button/resources/js/modules/Helper/Utils";
|
||||||
|
import {
|
||||||
|
handleShippingOptionsChange
|
||||||
|
} from "../../../ppcp-button/resources/js/modules/Helper/ShippingHandler";
|
||||||
const config = wc.wcSettings.getSetting('ppcp-gateway_data');
|
const config = wc.wcSettings.getSetting('ppcp-gateway_data');
|
||||||
|
|
||||||
window.ppcpFundingSource = config.fundingSource;
|
window.ppcpFundingSource = config.fundingSource;
|
||||||
|
@ -146,7 +149,7 @@ const PayPalComponent = ({
|
||||||
shipping_address: addresses.shippingAddress,
|
shipping_address: addresses.shippingAddress,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
if (!config.finalReviewEnabled) {
|
if (shouldHandleShippingInPayPal()) {
|
||||||
// set address in UI
|
// set address in UI
|
||||||
promises.push(wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress));
|
promises.push(wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress));
|
||||||
if (shippingData.needsShipping) {
|
if (shippingData.needsShipping) {
|
||||||
|
@ -181,7 +184,7 @@ const PayPalComponent = ({
|
||||||
throw new Error(config.scriptData.labels.error.generic)
|
throw new Error(config.scriptData.labels.error.generic)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.finalReviewEnabled) {
|
if (!shouldHandleShippingInPayPal()) {
|
||||||
location.href = getCheckoutRedirectUrl();
|
location.href = getCheckoutRedirectUrl();
|
||||||
} else {
|
} else {
|
||||||
setGotoContinuationOnError(true);
|
setGotoContinuationOnError(true);
|
||||||
|
@ -220,7 +223,7 @@ const PayPalComponent = ({
|
||||||
shipping_address: addresses.shippingAddress,
|
shipping_address: addresses.shippingAddress,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
if (!config.finalReviewEnabled) {
|
if (shouldHandleShippingInPayPal()) {
|
||||||
// set address in UI
|
// set address in UI
|
||||||
promises.push(wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress));
|
promises.push(wp.data.dispatch('wc/store/cart').setBillingAddress(addresses.billingAddress));
|
||||||
if (shippingData.needsShipping) {
|
if (shippingData.needsShipping) {
|
||||||
|
@ -255,7 +258,7 @@ const PayPalComponent = ({
|
||||||
throw new Error(config.scriptData.labels.error.generic)
|
throw new Error(config.scriptData.labels.error.generic)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.finalReviewEnabled) {
|
if (!shouldHandleShippingInPayPal()) {
|
||||||
location.href = getCheckoutRedirectUrl();
|
location.href = getCheckoutRedirectUrl();
|
||||||
} else {
|
} else {
|
||||||
setGotoContinuationOnError(true);
|
setGotoContinuationOnError(true);
|
||||||
|
@ -297,8 +300,12 @@ const PayPalComponent = ({
|
||||||
onClick();
|
onClick();
|
||||||
};
|
};
|
||||||
|
|
||||||
const isVenmoAndVaultingEnabled = () => {
|
const shouldHandleShippingInPayPal = () => {
|
||||||
return window.ppcpFundingSource === 'venmo' && config.scriptData.vaultingEnabled;
|
if (config.finalReviewEnabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return window.ppcpFundingSource !== 'venmo' || !config.scriptData.vaultingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
let handleShippingOptionsChange = null;
|
let handleShippingOptionsChange = null;
|
||||||
|
@ -306,7 +313,7 @@ const PayPalComponent = ({
|
||||||
let handleSubscriptionShippingOptionsChange = null;
|
let handleSubscriptionShippingOptionsChange = null;
|
||||||
let handleSubscriptionShippingAddressChange = null;
|
let handleSubscriptionShippingAddressChange = null;
|
||||||
|
|
||||||
if (shippingData.needsShipping && !config.finalReviewEnabled) {
|
if (shippingData.needsShipping && shouldHandleShippingInPayPal()) {
|
||||||
handleShippingOptionsChange = async (data, actions) => {
|
handleShippingOptionsChange = async (data, actions) => {
|
||||||
try {
|
try {
|
||||||
const shippingOptionId = data.selectedShippingOption?.id;
|
const shippingOptionId = data.selectedShippingOption?.id;
|
||||||
|
@ -391,6 +398,21 @@ const PayPalComponent = ({
|
||||||
|
|
||||||
await shippingData.setShippingAddress(address);
|
await shippingData.setShippingAddress(address);
|
||||||
|
|
||||||
|
const res = await fetch(config.ajax.update_shipping.endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify({
|
||||||
|
nonce: config.ajax.update_shipping.nonce,
|
||||||
|
order_id: data.orderID,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
if (!json.success) {
|
||||||
|
throw new Error(json.data.message);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
||||||
|
@ -447,7 +469,7 @@ const PayPalComponent = ({
|
||||||
if (config.scriptData.continuation) {
|
if (config.scriptData.continuation) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!config.finalReviewEnabled) {
|
if (shouldHandleShippingInPayPal()) {
|
||||||
location.href = getCheckoutRedirectUrl();
|
location.href = getCheckoutRedirectUrl();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -493,8 +515,16 @@ const PayPalComponent = ({
|
||||||
onError={onClose}
|
onError={onClose}
|
||||||
createSubscription={createSubscription}
|
createSubscription={createSubscription}
|
||||||
onApprove={handleApproveSubscription}
|
onApprove={handleApproveSubscription}
|
||||||
onShippingOptionsChange={handleSubscriptionShippingOptionsChange}
|
onShippingOptionsChange={(data, actions) => {
|
||||||
onShippingAddressChange={handleSubscriptionShippingAddressChange}
|
shouldHandleShippingInPayPal()
|
||||||
|
? handleSubscriptionShippingOptionsChange(data, actions)
|
||||||
|
: null;
|
||||||
|
}}
|
||||||
|
onShippingAddressChange={(data, actions) => {
|
||||||
|
shouldHandleShippingInPayPal()
|
||||||
|
? handleSubscriptionShippingAddressChange(data, actions)
|
||||||
|
: null;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -508,8 +538,16 @@ const PayPalComponent = ({
|
||||||
onError={onClose}
|
onError={onClose}
|
||||||
createOrder={createOrder}
|
createOrder={createOrder}
|
||||||
onApprove={handleApprove}
|
onApprove={handleApprove}
|
||||||
onShippingOptionsChange={handleShippingOptionsChange}
|
onShippingOptionsChange={(data, actions) => {
|
||||||
onShippingAddressChange={handleShippingAddressChange}
|
shouldHandleShippingInPayPal()
|
||||||
|
? handleShippingOptionsChange(data, actions)
|
||||||
|
: null;
|
||||||
|
}}
|
||||||
|
onShippingAddressChange={(data, actions) => {
|
||||||
|
shouldHandleShippingInPayPal()
|
||||||
|
? handleShippingAddressChange(data, actions)
|
||||||
|
: null;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -568,7 +606,7 @@ if(cartHasSubscriptionProducts(config.scriptData)) {
|
||||||
features.push('subscriptions');
|
features.push('subscriptions');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block_enabled) {
|
if (block_enabled && config.enabled) {
|
||||||
if ((config.addPlaceOrderMethod || config.usePlaceOrder) && !config.scriptData.continuation) {
|
if ((config.addPlaceOrderMethod || config.usePlaceOrder) && !config.scriptData.continuation) {
|
||||||
let descriptionElement = <div dangerouslySetInnerHTML={{__html: config.description}}></div>;
|
let descriptionElement = <div dangerouslySetInnerHTML={{__html: config.description}}></div>;
|
||||||
if (config.placeOrderButtonDescription) {
|
if (config.placeOrderButtonDescription) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\Blocks;
|
namespace WooCommerce\PayPalCommerce\Blocks;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\Blocks\Endpoint\GetPayPalOrderFromSession;
|
||||||
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
|
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
||||||
|
@ -45,6 +46,17 @@ return array(
|
||||||
$container->get( 'wcgateway.all-funding-sources' )
|
$container->get( 'wcgateway.all-funding-sources' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'blocks.advanced-card-method' => static function( ContainerInterface $container ): AdvancedCardPaymentMethod {
|
||||||
|
return new AdvancedCardPaymentMethod(
|
||||||
|
$container->get( 'blocks.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'wcgateway.credit-card-gateway' ),
|
||||||
|
function () use ( $container ): SmartButtonInterface {
|
||||||
|
return $container->get( 'button.smart-button' );
|
||||||
|
},
|
||||||
|
$container->get( 'wcgateway.settings' )
|
||||||
|
);
|
||||||
|
},
|
||||||
'blocks.settings.final_review_enabled' => static function ( ContainerInterface $container ): bool {
|
'blocks.settings.final_review_enabled' => static function ( ContainerInterface $container ): bool {
|
||||||
$settings = $container->get( 'wcgateway.settings' );
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
assert( $settings instanceof ContainerInterface );
|
assert( $settings instanceof ContainerInterface );
|
||||||
|
|
142
modules/ppcp-blocks/src/AdvancedCardPaymentMethod.php
Normal file
142
modules/ppcp-blocks/src/AdvancedCardPaymentMethod.php
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Advanced card payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\Blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Blocks;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AdvancedCardPaymentMethod
|
||||||
|
*/
|
||||||
|
class AdvancedCardPaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credit card gateway.
|
||||||
|
*
|
||||||
|
* @var CreditCardGateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The smart button script loading handler.
|
||||||
|
*
|
||||||
|
* @var SmartButtonInterface|callable
|
||||||
|
*/
|
||||||
|
private $smart_button;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings.
|
||||||
|
*
|
||||||
|
* @var Settings
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AdvancedCardPaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param CreditCardGateway $gateway Credit card gateway.
|
||||||
|
* @param SmartButtonInterface|callable $smart_button The smart button script loading handler.
|
||||||
|
* @param Settings $settings The settings.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
CreditCardGateway $gateway,
|
||||||
|
$smart_button,
|
||||||
|
Settings $settings
|
||||||
|
) {
|
||||||
|
$this->name = CreditCardGateway::ID;
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
$this->smart_button = $smart_button;
|
||||||
|
$this->settings = $settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-advanced-card-checkout-block',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/advanced-card-checkout-block.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-advanced-card-checkout-block' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
$script_data = $this->smart_button_instance()->script_data();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'scriptData' => $script_data,
|
||||||
|
'supports' => $this->gateway->supports,
|
||||||
|
'save_card_text' => esc_html__( 'Save your card', 'woocommerce-paypal-payments' ),
|
||||||
|
'is_vaulting_enabled' => $this->settings->has( 'vault_enabled_dcc' ) && $this->settings->get( 'vault_enabled_dcc' ),
|
||||||
|
'card_icons' => $this->settings->has( 'card_icons' ) ? (array) $this->settings->get( 'card_icons' ) : array(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The smart button.
|
||||||
|
*
|
||||||
|
* @return SmartButtonInterface
|
||||||
|
*/
|
||||||
|
private function smart_button_instance(): SmartButtonInterface {
|
||||||
|
if ( $this->smart_button instanceof SmartButtonInterface ) {
|
||||||
|
return $this->smart_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_callable( $this->smart_button ) ) {
|
||||||
|
$this->smart_button = ( $this->smart_button )();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->smart_button;
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,6 +61,7 @@ class BlocksModule implements ModuleInterface {
|
||||||
'woocommerce_blocks_payment_method_type_registration',
|
'woocommerce_blocks_payment_method_type_registration',
|
||||||
function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void {
|
function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void {
|
||||||
$payment_method_registry->register( $c->get( 'blocks.method' ) );
|
$payment_method_registry->register( $c->get( 'blocks.method' ) );
|
||||||
|
$payment_method_registry->register( $c->get( 'blocks.advanced-card-method' ) );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ module.exports = {
|
||||||
plugins: [ new DependencyExtractionWebpackPlugin() ],
|
plugins: [ new DependencyExtractionWebpackPlugin() ],
|
||||||
entry: {
|
entry: {
|
||||||
'checkout-block': path.resolve('./resources/js/checkout-block.js'),
|
'checkout-block': path.resolve('./resources/js/checkout-block.js'),
|
||||||
|
'advanced-card-checkout-block': path.resolve('./resources/js/advanced-card-checkout-block.js'),
|
||||||
"gateway": path.resolve('./resources/css/gateway.scss')
|
"gateway": path.resolve('./resources/css/gateway.scss')
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
|
|
@ -1005,19 +1005,19 @@
|
||||||
"@jridgewell/resolve-uri" "3.1.0"
|
"@jridgewell/resolve-uri" "3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "1.4.14"
|
"@jridgewell/sourcemap-codec" "1.4.14"
|
||||||
|
|
||||||
"@paypal/paypal-js@^8.0.4":
|
"@paypal/paypal-js@^8.0.5":
|
||||||
version "8.0.4"
|
version "8.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@paypal/paypal-js/-/paypal-js-8.0.4.tgz#abe9f40f519b1d2c306adddfbe733be03eb26ce5"
|
resolved "https://registry.yarnpkg.com/@paypal/paypal-js/-/paypal-js-8.0.5.tgz#77bc461b4d1e5a2c6f081269e3ef0b2e3331a68c"
|
||||||
integrity sha512-91g5fhRBHGEBoikDzQT6uBn3PzlJQ75g0c3MvqVJqN0XRm5kHa9wz+6+Uaq8QQuxRzz5C2x55Zg057CW6EuwpQ==
|
integrity sha512-yQNV7rOILeaVCNU4aVDRPqEnbIlzfxgQfFsxzsBuZW1ouqRD/4kYBWJDzczCiscSr2xOeA/Pkm7e3a9fRfnuMQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
promise-polyfill "^8.3.0"
|
promise-polyfill "^8.3.0"
|
||||||
|
|
||||||
"@paypal/react-paypal-js@^8.2.0":
|
"@paypal/react-paypal-js@^8.3.0":
|
||||||
version "8.2.0"
|
version "8.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@paypal/react-paypal-js/-/react-paypal-js-8.2.0.tgz#4b1a142bbb68e62dca4a92da4a6b5568f54901f0"
|
resolved "https://registry.yarnpkg.com/@paypal/react-paypal-js/-/react-paypal-js-8.3.0.tgz#a103080b752766b8ff59b8620887abf802e1a01b"
|
||||||
integrity sha512-SworUfu0BNNcqoh0O53Ke4MFpx2m3qJRu3hayXvlluEEXJpKqGSV5aaSGFhbsZqi8hnbsx/hZR7BQbmqsggiGQ==
|
integrity sha512-SX17d2h1CMNFGI+wtjb329AEDaBR8Ziy2LCV076eDcY1Q0MFKRkfQ/v0HOAvZtk3sJoydRmYez2pq47BRblwqQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@paypal/paypal-js" "^8.0.4"
|
"@paypal/paypal-js" "^8.0.5"
|
||||||
"@paypal/sdk-constants" "^1.0.122"
|
"@paypal/sdk-constants" "^1.0.122"
|
||||||
|
|
||||||
"@paypal/sdk-constants@^1.0.122":
|
"@paypal/sdk-constants@^1.0.122":
|
||||||
|
|
|
@ -23,7 +23,8 @@ class CartActionHandler {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
nonce: this.config.ajax.approve_subscription.nonce,
|
nonce: this.config.ajax.approve_subscription.nonce,
|
||||||
order_id: data.orderID,
|
order_id: data.orderID,
|
||||||
subscription_id: data.subscriptionID
|
subscription_id: data.subscriptionID,
|
||||||
|
should_create_wc_order: !context.config.vaultingEnabled || data.paymentSource !== 'venmo'
|
||||||
})
|
})
|
||||||
}).then((res)=>{
|
}).then((res)=>{
|
||||||
return res.json();
|
return res.json();
|
||||||
|
@ -33,7 +34,9 @@ class CartActionHandler {
|
||||||
throw Error(data.data.message);
|
throw Error(data.data.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
location.href = this.config.redirect;
|
let orderReceivedUrl = data.data?.order_received_url
|
||||||
|
|
||||||
|
location.href = orderReceivedUrl ? orderReceivedUrl : context.config.redirect;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
|
@ -60,8 +63,7 @@ class CartActionHandler {
|
||||||
funding_source: window.ppcpFundingSource,
|
funding_source: window.ppcpFundingSource,
|
||||||
bn_code:bnCode,
|
bn_code:bnCode,
|
||||||
payer,
|
payer,
|
||||||
context:this.config.context,
|
context:this.config.context
|
||||||
payment_source: data.paymentSource
|
|
||||||
}),
|
}),
|
||||||
}).then(function(res) {
|
}).then(function(res) {
|
||||||
return res.json();
|
return res.json();
|
||||||
|
|
|
@ -4,6 +4,7 @@ import widgetBuilder from "../Renderer/WidgetBuilder";
|
||||||
import merge from "deepmerge";
|
import merge from "deepmerge";
|
||||||
import {keysToCamelCase} from "./Utils";
|
import {keysToCamelCase} from "./Utils";
|
||||||
import {getCurrentPaymentMethod} from "./CheckoutMethodState";
|
import {getCurrentPaymentMethod} from "./CheckoutMethodState";
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
// This component may be used by multiple modules. This assures that options are shared between all instances.
|
// This component may be used by multiple modules. This assures that options are shared between all instances.
|
||||||
let options = window.ppcpWidgetBuilder = window.ppcpWidgetBuilder || {
|
let options = window.ppcpWidgetBuilder = window.ppcpWidgetBuilder || {
|
||||||
|
@ -63,9 +64,10 @@ export const loadPaypalScript = (config, onLoaded, onError = null) => {
|
||||||
|
|
||||||
// Axo SDK options
|
// Axo SDK options
|
||||||
const sdkClientToken = config?.axo?.sdk_client_token;
|
const sdkClientToken = config?.axo?.sdk_client_token;
|
||||||
|
const uuid = uuidv4().replace(/-/g, '');
|
||||||
if(sdkClientToken) {
|
if(sdkClientToken) {
|
||||||
scriptOptions['data-sdk-client-token'] = sdkClientToken;
|
scriptOptions['data-sdk-client-token'] = sdkClientToken;
|
||||||
scriptOptions['data-client-metadata-id'] = 'ppcp-cm-id';
|
scriptOptions['data-client-metadata-id'] = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load PayPal script for special case with data-client-token
|
// Load PayPal script for special case with data-client-token
|
||||||
|
|
|
@ -39,19 +39,21 @@ export const handleShippingOptionsChange = async (data, actions, config) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await fetch(config.ajax.update_shipping.endpoint, {
|
if (!config.data_client_id.has_subscriptions) {
|
||||||
method: 'POST',
|
const res = await fetch(config.ajax.update_shipping.endpoint, {
|
||||||
credentials: 'same-origin',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
credentials: 'same-origin',
|
||||||
nonce: config.ajax.update_shipping.nonce,
|
body: JSON.stringify({
|
||||||
order_id: data.orderID,
|
nonce: config.ajax.update_shipping.nonce,
|
||||||
})
|
order_id: data.orderID,
|
||||||
});
|
})
|
||||||
|
});
|
||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
|
|
||||||
if (!json.success) {
|
if (!json.success) {
|
||||||
throw new Error(json.data.message);
|
throw new Error(json.data.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -104,20 +106,20 @@ export const handleShippingAddressChange = async (data, actions, config) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await fetch(config.ajax.update_shipping.endpoint, {
|
const res = await fetch(config.ajax.update_shipping.endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: 'same-origin',
|
credentials: 'same-origin',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
nonce: config.ajax.update_shipping.nonce,
|
nonce: config.ajax.update_shipping.nonce,
|
||||||
order_id: data.orderID,
|
order_id: data.orderID,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
|
|
||||||
if (!json.success) {
|
if (!json.success) {
|
||||||
throw new Error(json.data.message);
|
throw new Error(json.data.message);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
||||||
|
|
|
@ -68,14 +68,6 @@ class Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldHandleShippingInPaypal = (venmoButtonClicked) => {
|
|
||||||
if (!this.defaultSettings.should_handle_shipping_in_paypal) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !venmoButtonClicked || !this.defaultSettings.vaultingEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderButtons(wrapper, style, contextConfig, hasEnabledSeparateGateways, fundingSource = null) {
|
renderButtons(wrapper, style, contextConfig, hasEnabledSeparateGateways, fundingSource = null) {
|
||||||
if (! document.querySelector(wrapper) || this.isAlreadyRendered(wrapper, fundingSource, hasEnabledSeparateGateways) ) {
|
if (! document.querySelector(wrapper) || this.isAlreadyRendered(wrapper, fundingSource, hasEnabledSeparateGateways) ) {
|
||||||
// Try to render registered buttons again in case they were removed from the DOM by an external source.
|
// Try to render registered buttons again in case they were removed from the DOM by an external source.
|
||||||
|
@ -93,7 +85,16 @@ class Renderer {
|
||||||
const options = {
|
const options = {
|
||||||
style,
|
style,
|
||||||
...contextConfig,
|
...contextConfig,
|
||||||
onClick: this.onSmartButtonClick,
|
onClick: (data, actions) => {
|
||||||
|
if (this.onSmartButtonClick) {
|
||||||
|
this.onSmartButtonClick(data, actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
venmoButtonClicked = false;
|
||||||
|
if (data.fundingSource === 'venmo') {
|
||||||
|
venmoButtonClicked = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
onInit: (data, actions) => {
|
onInit: (data, actions) => {
|
||||||
if (this.onSmartButtonsInit) {
|
if (this.onSmartButtonsInit) {
|
||||||
this.onSmartButtonsInit(data, actions);
|
this.onSmartButtonsInit(data, actions);
|
||||||
|
@ -103,9 +104,17 @@ class Renderer {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check the condition and add the handler if needed
|
// Check the condition and add the handler if needed
|
||||||
if (this.shouldHandleShippingInPaypal(venmoButtonClicked)) {
|
if (this.defaultSettings.should_handle_shipping_in_paypal) {
|
||||||
options.onShippingOptionsChange = (data, actions) => handleShippingOptionsChange(data, actions, this.defaultSettings);
|
options.onShippingOptionsChange = (data, actions) => {
|
||||||
options.onShippingAddressChange = (data, actions) => handleShippingAddressChange(data, actions, this.defaultSettings);
|
!this.isVenmoButtonClickedWhenVaultingIsEnabled(venmoButtonClicked)
|
||||||
|
? handleShippingOptionsChange(data, actions, this.defaultSettings)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
options.onShippingAddressChange = (data, actions) => {
|
||||||
|
!this.isVenmoButtonClickedWhenVaultingIsEnabled(venmoButtonClicked)
|
||||||
|
? handleShippingAddressChange(data, actions, this.defaultSettings)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
@ -139,6 +148,10 @@ class Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVenmoButtonClickedWhenVaultingIsEnabled = (venmoButtonClicked) => {
|
||||||
|
return venmoButtonClicked && this.defaultSettings.vaultingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
isAlreadyRendered(wrapper, fundingSource) {
|
isAlreadyRendered(wrapper, fundingSource) {
|
||||||
return this.renderedSources.has(wrapper + (fundingSource ?? ''));
|
return this.renderedSources.has(wrapper + (fundingSource ?? ''));
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,6 @@ return array(
|
||||||
$final_review_enabled = $container->get( 'blocks.settings.final_review_enabled' );
|
$final_review_enabled = $container->get( 'blocks.settings.final_review_enabled' );
|
||||||
$wc_order_creator = $container->get( 'button.helper.wc-order-creator' );
|
$wc_order_creator = $container->get( 'button.helper.wc-order-creator' );
|
||||||
$gateway = $container->get( 'wcgateway.paypal-gateway' );
|
$gateway = $container->get( 'wcgateway.paypal-gateway' );
|
||||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
|
||||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||||
return new ApproveOrderEndpoint(
|
return new ApproveOrderEndpoint(
|
||||||
$request_data,
|
$request_data,
|
||||||
|
@ -252,7 +251,6 @@ return array(
|
||||||
$final_review_enabled,
|
$final_review_enabled,
|
||||||
$gateway,
|
$gateway,
|
||||||
$wc_order_creator,
|
$wc_order_creator,
|
||||||
$subscription_helper,
|
|
||||||
$logger
|
$logger
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -260,7 +258,10 @@ return array(
|
||||||
return new ApproveSubscriptionEndpoint(
|
return new ApproveSubscriptionEndpoint(
|
||||||
$container->get( 'button.request-data' ),
|
$container->get( 'button.request-data' ),
|
||||||
$container->get( 'api.endpoint.order' ),
|
$container->get( 'api.endpoint.order' ),
|
||||||
$container->get( 'session.handler' )
|
$container->get( 'session.handler' ),
|
||||||
|
$container->get( 'blocks.settings.final_review_enabled' ),
|
||||||
|
$container->get( 'button.helper.wc-order-creator' ),
|
||||||
|
$container->get( 'wcgateway.paypal-gateway' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'button.checkout-form-saver' => static function ( ContainerInterface $container ): CheckoutFormSaver {
|
'button.checkout-form-saver' => static function ( ContainerInterface $container ): CheckoutFormSaver {
|
||||||
|
@ -362,6 +363,10 @@ return array(
|
||||||
},
|
},
|
||||||
|
|
||||||
'button.helper.wc-order-creator' => static function ( ContainerInterface $container ): WooCommerceOrderCreator {
|
'button.helper.wc-order-creator' => static function ( ContainerInterface $container ): WooCommerceOrderCreator {
|
||||||
return new WooCommerceOrderCreator( $container->get( 'wcgateway.funding-source.renderer' ), $container->get( 'session.handler' ) );
|
return new WooCommerceOrderCreator(
|
||||||
|
$container->get( 'wcgateway.funding-source.renderer' ),
|
||||||
|
$container->get( 'session.handler' ),
|
||||||
|
$container->get( 'wc-subscriptions.helper' )
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -1421,7 +1421,7 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
||||||
$disable_funding,
|
$disable_funding,
|
||||||
array_diff(
|
array_diff(
|
||||||
array_keys( $this->all_funding_sources ),
|
array_keys( $this->all_funding_sources ),
|
||||||
array( 'venmo', 'paylater', 'paypal' )
|
array( 'venmo', 'paylater', 'paypal', 'card' )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,13 +105,6 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
||||||
*/
|
*/
|
||||||
protected $wc_order_creator;
|
protected $wc_order_creator;
|
||||||
|
|
||||||
/**
|
|
||||||
* The Subscription Helper.
|
|
||||||
*
|
|
||||||
* @var SubscriptionHelper
|
|
||||||
*/
|
|
||||||
protected $subscription_helper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
*
|
*
|
||||||
|
@ -132,7 +125,6 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
||||||
* @param bool $final_review_enabled Whether the final review is enabled.
|
* @param bool $final_review_enabled Whether the final review is enabled.
|
||||||
* @param PayPalGateway $gateway The WC gateway.
|
* @param PayPalGateway $gateway The WC gateway.
|
||||||
* @param WooCommerceOrderCreator $wc_order_creator The WooCommerce order creator.
|
* @param WooCommerceOrderCreator $wc_order_creator The WooCommerce order creator.
|
||||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param LoggerInterface $logger The logger.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -146,7 +138,6 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
||||||
bool $final_review_enabled,
|
bool $final_review_enabled,
|
||||||
PayPalGateway $gateway,
|
PayPalGateway $gateway,
|
||||||
WooCommerceOrderCreator $wc_order_creator,
|
WooCommerceOrderCreator $wc_order_creator,
|
||||||
SubscriptionHelper $subscription_helper,
|
|
||||||
LoggerInterface $logger
|
LoggerInterface $logger
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -160,7 +151,6 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
||||||
$this->final_review_enabled = $final_review_enabled;
|
$this->final_review_enabled = $final_review_enabled;
|
||||||
$this->gateway = $gateway;
|
$this->gateway = $gateway;
|
||||||
$this->wc_order_creator = $wc_order_creator;
|
$this->wc_order_creator = $wc_order_creator;
|
||||||
$this->subscription_helper = $subscription_helper;
|
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +237,7 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
||||||
|
|
||||||
$this->session_handler->replace_order( $order );
|
$this->session_handler->replace_order( $order );
|
||||||
|
|
||||||
if ( ! $this->subscription_helper->plugin_is_active() && apply_filters( 'woocommerce_paypal_payments_toggle_final_review_checkbox', false ) ) {
|
if ( apply_filters( 'woocommerce_paypal_payments_toggle_final_review_checkbox', false ) ) {
|
||||||
$this->toggle_final_review_enabled_setting();
|
$this->toggle_final_review_enabled_setting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,18 @@ namespace WooCommerce\PayPalCommerce\Button\Endpoint;
|
||||||
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Helper\WooCommerceOrderCreator;
|
||||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ApproveSubscriptionEndpoint
|
* Class ApproveSubscriptionEndpoint
|
||||||
*/
|
*/
|
||||||
class ApproveSubscriptionEndpoint implements EndpointInterface {
|
class ApproveSubscriptionEndpoint implements EndpointInterface {
|
||||||
|
|
||||||
|
use ContextTrait;
|
||||||
|
|
||||||
const ENDPOINT = 'ppc-approve-subscription';
|
const ENDPOINT = 'ppc-approve-subscription';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,21 +46,51 @@ class ApproveSubscriptionEndpoint implements EndpointInterface {
|
||||||
*/
|
*/
|
||||||
private $session_handler;
|
private $session_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the final review is enabled.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $final_review_enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The WooCommerce order creator.
|
||||||
|
*
|
||||||
|
* @var WooCommerceOrderCreator
|
||||||
|
*/
|
||||||
|
protected $wc_order_creator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The WC gateway.
|
||||||
|
*
|
||||||
|
* @var PayPalGateway
|
||||||
|
*/
|
||||||
|
protected $gateway;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ApproveSubscriptionEndpoint constructor.
|
* ApproveSubscriptionEndpoint constructor.
|
||||||
*
|
*
|
||||||
* @param RequestData $request_data The request data helper.
|
* @param RequestData $request_data The request data helper.
|
||||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||||
* @param SessionHandler $session_handler The session handler.
|
* @param SessionHandler $session_handler The session handler.
|
||||||
|
* @param bool $final_review_enabled Whether the final review is enabled.
|
||||||
|
* @param WooCommerceOrderCreator $wc_order_creator The WooCommerce order creator.
|
||||||
|
* @param PayPalGateway $gateway The WC gateway.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
RequestData $request_data,
|
RequestData $request_data,
|
||||||
OrderEndpoint $order_endpoint,
|
OrderEndpoint $order_endpoint,
|
||||||
SessionHandler $session_handler
|
SessionHandler $session_handler,
|
||||||
|
bool $final_review_enabled,
|
||||||
|
WooCommerceOrderCreator $wc_order_creator,
|
||||||
|
PayPalGateway $gateway
|
||||||
) {
|
) {
|
||||||
$this->request_data = $request_data;
|
$this->request_data = $request_data;
|
||||||
$this->order_endpoint = $order_endpoint;
|
$this->order_endpoint = $order_endpoint;
|
||||||
$this->session_handler = $session_handler;
|
$this->session_handler = $session_handler;
|
||||||
|
$this->final_review_enabled = $final_review_enabled;
|
||||||
|
$this->wc_order_creator = $wc_order_creator;
|
||||||
|
$this->gateway = $gateway;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +123,15 @@ class ApproveSubscriptionEndpoint implements EndpointInterface {
|
||||||
WC()->session->set( 'ppcp_subscription_id', $data['subscription_id'] );
|
WC()->session->set( 'ppcp_subscription_id', $data['subscription_id'] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$should_create_wc_order = $data['should_create_wc_order'] ?? false;
|
||||||
|
if ( ! $this->final_review_enabled && ! $this->is_checkout() && $should_create_wc_order ) {
|
||||||
|
$wc_order = $this->wc_order_creator->create_from_paypal_order( $order, WC()->cart );
|
||||||
|
$this->gateway->process_payment( $wc_order->get_id() );
|
||||||
|
$order_received_url = $wc_order->get_checkout_order_received_url();
|
||||||
|
|
||||||
|
wp_send_json_success( array( 'order_received_url' => $order_received_url ) );
|
||||||
|
}
|
||||||
|
|
||||||
wp_send_json_success();
|
wp_send_json_success();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,6 @@ class CreateOrderEndpoint implements EndpointInterface {
|
||||||
$this->parsed_request_data = $data;
|
$this->parsed_request_data = $data;
|
||||||
$payment_method = $data['payment_method'] ?? '';
|
$payment_method = $data['payment_method'] ?? '';
|
||||||
$funding_source = $data['funding_source'] ?? '';
|
$funding_source = $data['funding_source'] ?? '';
|
||||||
$payment_source = $data['payment_source'] ?? '';
|
|
||||||
$wc_order = null;
|
$wc_order = null;
|
||||||
if ( 'pay-now' === $data['context'] ) {
|
if ( 'pay-now' === $data['context'] ) {
|
||||||
$wc_order = wc_get_order( (int) $data['order_id'] );
|
$wc_order = wc_get_order( (int) $data['order_id'] );
|
||||||
|
@ -262,7 +261,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
||||||
}
|
}
|
||||||
$this->purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
$this->purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
} else {
|
} else {
|
||||||
$this->purchase_unit = $this->purchase_unit_factory->from_wc_cart( null, $this->should_handle_shipping_in_paypal( $payment_source ) );
|
$this->purchase_unit = $this->purchase_unit_factory->from_wc_cart( null, $this->should_handle_shipping_in_paypal( $funding_source ) );
|
||||||
|
|
||||||
// Do not allow completion by webhooks when started via non-checkout buttons,
|
// Do not allow completion by webhooks when started via non-checkout buttons,
|
||||||
// it is needed only for some APMs in checkout.
|
// it is needed only for some APMs in checkout.
|
||||||
|
@ -615,16 +614,16 @@ class CreateOrderEndpoint implements EndpointInterface {
|
||||||
/**
|
/**
|
||||||
* Checks if the shipping should be handled in PayPal popup.
|
* Checks if the shipping should be handled in PayPal popup.
|
||||||
*
|
*
|
||||||
* @param string $payment_source The payment source.
|
* @param string $funding_source The funding source.
|
||||||
* @return bool true if the shipping should be handled in PayPal popup, otherwise false.
|
* @return bool true if the shipping should be handled in PayPal popup, otherwise false.
|
||||||
*/
|
*/
|
||||||
protected function should_handle_shipping_in_paypal( string $payment_source ): bool {
|
protected function should_handle_shipping_in_paypal( string $funding_source ): bool {
|
||||||
$is_vaulting_enabled = $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' );
|
$is_vaulting_enabled = $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' );
|
||||||
|
|
||||||
if ( ! $this->handle_shipping_in_paypal ) {
|
if ( ! $this->handle_shipping_in_paypal ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ! $is_vaulting_enabled || $payment_source !== 'venmo';
|
return ! $is_vaulting_enabled || $funding_source !== 'venmo';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,47 +95,51 @@ trait ContextTrait {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function context(): string {
|
protected function context(): string {
|
||||||
if ( is_product() || wc_post_content_has_shortcode( 'product_page' ) ) {
|
// Default context.
|
||||||
|
$context = 'mini-cart';
|
||||||
|
|
||||||
// Do this check here instead of reordering outside conditions.
|
switch ( true ) {
|
||||||
// In order to have more control over the context.
|
case is_product() || wc_post_content_has_shortcode( 'product_page' ):
|
||||||
if ( $this->is_checkout() && ! $this->is_paypal_continuation() ) {
|
// Do this check here instead of reordering outside conditions.
|
||||||
return 'checkout';
|
// In order to have more control over the context.
|
||||||
}
|
if ( $this->is_checkout() && ! $this->is_paypal_continuation() ) {
|
||||||
|
$context = 'checkout';
|
||||||
|
} else {
|
||||||
|
$context = 'product';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
return 'product';
|
// has_block may not work if called too early, such as during the block registration.
|
||||||
|
case has_block( 'woocommerce/cart' ):
|
||||||
|
$context = 'cart-block';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case $this->is_cart():
|
||||||
|
$context = 'cart';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case is_checkout_pay_page():
|
||||||
|
$context = 'pay-now';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case has_block( 'woocommerce/checkout' ):
|
||||||
|
$context = 'checkout-block';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case $this->is_checkout() && ! $this->is_paypal_continuation():
|
||||||
|
$context = 'checkout';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case $this->is_add_payment_method_page():
|
||||||
|
$context = 'add-payment-method';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case $this->is_block_editor():
|
||||||
|
$context = 'block-editor';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// has_block may not work if called too early, such as during the block registration.
|
return apply_filters( 'woocommerce_paypal_payments_context', $context );
|
||||||
if ( has_block( 'woocommerce/cart' ) ) {
|
|
||||||
return 'cart-block';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $this->is_cart() ) {
|
|
||||||
return 'cart';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_checkout_pay_page() ) {
|
|
||||||
return 'pay-now';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( has_block( 'woocommerce/checkout' ) ) {
|
|
||||||
return 'checkout-block';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $this->is_checkout() && ! $this->is_paypal_continuation() ) {
|
|
||||||
return 'checkout';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $this->is_add_payment_method_page() ) {
|
|
||||||
return 'add-payment-method';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $this->is_block_editor() ) {
|
|
||||||
return 'block-editor';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'mini-cart';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,12 +14,16 @@ use WC_Cart;
|
||||||
use WC_Order;
|
use WC_Order;
|
||||||
use WC_Order_Item_Product;
|
use WC_Order_Item_Product;
|
||||||
use WC_Order_Item_Shipping;
|
use WC_Order_Item_Shipping;
|
||||||
|
use WC_Subscription;
|
||||||
|
use WC_Subscriptions_Product;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Shipping;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Shipping;
|
||||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
|
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||||
|
use WP_Error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class WooCommerceOrderCreator
|
* Class WooCommerceOrderCreator
|
||||||
|
@ -40,18 +44,28 @@ class WooCommerceOrderCreator {
|
||||||
*/
|
*/
|
||||||
protected $session_handler;
|
protected $session_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subscription helper
|
||||||
|
*
|
||||||
|
* @var SubscriptionHelper
|
||||||
|
*/
|
||||||
|
protected $subscription_helper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WooCommerceOrderCreator constructor.
|
* WooCommerceOrderCreator constructor.
|
||||||
*
|
*
|
||||||
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
|
* @param FundingSourceRenderer $funding_source_renderer The funding source renderer.
|
||||||
* @param SessionHandler $session_handler The session handler.
|
* @param SessionHandler $session_handler The session handler.
|
||||||
|
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
FundingSourceRenderer $funding_source_renderer,
|
FundingSourceRenderer $funding_source_renderer,
|
||||||
SessionHandler $session_handler
|
SessionHandler $session_handler,
|
||||||
|
SubscriptionHelper $subscription_helper
|
||||||
) {
|
) {
|
||||||
$this->funding_source_renderer = $funding_source_renderer;
|
$this->funding_source_renderer = $funding_source_renderer;
|
||||||
$this->session_handler = $session_handler;
|
$this->session_handler = $session_handler;
|
||||||
|
$this->subscription_helper = $subscription_helper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,10 +83,13 @@ class WooCommerceOrderCreator {
|
||||||
throw new RuntimeException( 'Problem creating WC order.' );
|
throw new RuntimeException( 'Problem creating WC order.' );
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->configure_line_items( $wc_order, $wc_cart );
|
$payer = $order->payer();
|
||||||
$this->configure_shipping( $wc_order, $order->payer(), $order->purchase_units()[0]->shipping() );
|
$shipping = $order->purchase_units()[0]->shipping();
|
||||||
|
|
||||||
$this->configure_payment_source( $wc_order );
|
$this->configure_payment_source( $wc_order );
|
||||||
$this->configure_customer( $wc_order );
|
$this->configure_customer( $wc_order );
|
||||||
|
$this->configure_line_items( $wc_order, $wc_cart, $payer, $shipping );
|
||||||
|
$this->configure_shipping( $wc_order, $payer, $shipping );
|
||||||
$this->configure_coupons( $wc_order, $wc_cart->get_applied_coupons() );
|
$this->configure_coupons( $wc_order, $wc_cart->get_applied_coupons() );
|
||||||
|
|
||||||
$wc_order->calculate_totals();
|
$wc_order->calculate_totals();
|
||||||
|
@ -84,11 +101,13 @@ class WooCommerceOrderCreator {
|
||||||
/**
|
/**
|
||||||
* Configures the line items.
|
* Configures the line items.
|
||||||
*
|
*
|
||||||
* @param WC_Order $wc_order The WC order.
|
* @param WC_Order $wc_order The WC order.
|
||||||
* @param WC_Cart $wc_cart The Cart.
|
* @param WC_Cart $wc_cart The Cart.
|
||||||
|
* @param Payer|null $payer The payer.
|
||||||
|
* @param Shipping|null $shipping The shipping.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function configure_line_items( WC_Order $wc_order, WC_Cart $wc_cart ): void {
|
protected function configure_line_items( WC_Order $wc_order, WC_Cart $wc_cart, ?Payer $payer, ?Shipping $shipping ): void {
|
||||||
$cart_contents = $wc_cart->get_cart();
|
$cart_contents = $wc_cart->get_cart();
|
||||||
|
|
||||||
foreach ( $cart_contents as $cart_item ) {
|
foreach ( $cart_contents as $cart_item ) {
|
||||||
|
@ -111,9 +130,37 @@ class WooCommerceOrderCreator {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$total = $product->get_price() * $quantity;
|
||||||
|
|
||||||
$item->set_name( $product->get_name() );
|
$item->set_name( $product->get_name() );
|
||||||
$item->set_subtotal( $product->get_price() * $quantity );
|
$item->set_subtotal( $total );
|
||||||
$item->set_total( $product->get_price() * $quantity );
|
$item->set_total( $total );
|
||||||
|
|
||||||
|
$product_id = $product->get_id();
|
||||||
|
|
||||||
|
if ( $this->is_subscription( $product_id ) ) {
|
||||||
|
$subscription = $this->create_subscription( $wc_order, $product_id );
|
||||||
|
$sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee( $product );
|
||||||
|
$subscription_total = $total + $sign_up_fee;
|
||||||
|
|
||||||
|
$item->set_subtotal( $subscription_total );
|
||||||
|
$item->set_total( $subscription_total );
|
||||||
|
|
||||||
|
$subscription->add_product( $product );
|
||||||
|
$this->configure_shipping( $subscription, $payer, $shipping );
|
||||||
|
$this->configure_payment_source( $subscription );
|
||||||
|
$this->configure_coupons( $subscription, $wc_cart->get_applied_coupons() );
|
||||||
|
|
||||||
|
$dates = array(
|
||||||
|
'trial_end' => WC_Subscriptions_Product::get_trial_expiration_date( $product_id ),
|
||||||
|
'next_payment' => WC_Subscriptions_Product::get_first_renewal_payment_date( $product_id ),
|
||||||
|
'end' => WC_Subscriptions_Product::get_expiration_date( $product_id ),
|
||||||
|
);
|
||||||
|
|
||||||
|
$subscription->update_dates( $dates );
|
||||||
|
$subscription->calculate_totals();
|
||||||
|
$subscription->payment_complete_for_order( $wc_order );
|
||||||
|
}
|
||||||
|
|
||||||
$wc_order->add_item( $item );
|
$wc_order->add_item( $item );
|
||||||
}
|
}
|
||||||
|
@ -179,8 +226,18 @@ class WooCommerceOrderCreator {
|
||||||
$shipping->set_method_id( $shipping_options->id() );
|
$shipping->set_method_id( $shipping_options->id() );
|
||||||
$shipping->set_total( $shipping_options->amount()->value_str() );
|
$shipping->set_total( $shipping_options->amount()->value_str() );
|
||||||
|
|
||||||
|
$items = $wc_order->get_items();
|
||||||
|
$items_in_package = array();
|
||||||
|
foreach ( $items as $item ) {
|
||||||
|
$items_in_package[] = $item->get_name() . ' × ' . (string) $item->get_quantity();
|
||||||
|
}
|
||||||
|
|
||||||
|
$shipping->add_meta_data( __( 'Items', 'woocommerce-paypal-payments' ), implode( ', ', $items_in_package ) );
|
||||||
|
|
||||||
$wc_order->add_item( $shipping );
|
$wc_order->add_item( $shipping );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$wc_order->calculate_totals();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -225,4 +282,43 @@ class WooCommerceOrderCreator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the product with given ID is WC subscription.
|
||||||
|
*
|
||||||
|
* @param int $product_id The product ID.
|
||||||
|
* @return bool true if the product is subscription, otherwise false.
|
||||||
|
*/
|
||||||
|
protected function is_subscription( int $product_id ): bool {
|
||||||
|
if ( ! $this->subscription_helper->plugin_is_active() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WC_Subscriptions_Product::is_subscription( $product_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates WC subscription from given order and product ID.
|
||||||
|
*
|
||||||
|
* @param WC_Order $wc_order The WC order.
|
||||||
|
* @param int $product_id The product ID.
|
||||||
|
* @return WC_Subscription The subscription order
|
||||||
|
* @throws RuntimeException If problem creating.
|
||||||
|
*/
|
||||||
|
protected function create_subscription( WC_Order $wc_order, int $product_id ): WC_Subscription {
|
||||||
|
$subscription = wcs_create_subscription(
|
||||||
|
array(
|
||||||
|
'order_id' => $wc_order->get_id(),
|
||||||
|
'status' => 'pending',
|
||||||
|
'billing_period' => WC_Subscriptions_Product::get_period( $product_id ),
|
||||||
|
'billing_interval' => WC_Subscriptions_Product::get_interval( $product_id ),
|
||||||
|
'customer_id' => $wc_order->get_customer_id(),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $subscription instanceof WP_Error ) {
|
||||||
|
throw new RuntimeException( $subscription->get_error_message() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $subscription;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,9 +105,8 @@ class CardFieldsModule implements ModuleInterface {
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'ppcp_create_order_request_body_data',
|
'ppcp_create_order_request_body_data',
|
||||||
function( array $data ) use ( $c ): array {
|
function( array $data, string $payment_method ) use ( $c ): array {
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
$payment_method = wc_clean( wp_unslash( $_POST['payment_method'] ?? '' ) );
|
|
||||||
if ( $payment_method !== CreditCardGateway::ID ) {
|
if ( $payment_method !== CreditCardGateway::ID ) {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +133,9 @@ class CardFieldsModule implements ModuleInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
},
|
||||||
|
10,
|
||||||
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,18 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'compat.plugin-script-file-names' => static function( ContainerInterface $container ) : array {
|
||||||
|
return array(
|
||||||
|
'button.js',
|
||||||
|
'gateway-settings.js',
|
||||||
|
'status-page.js',
|
||||||
|
'order-edit-page.js',
|
||||||
|
'fraudnet.js',
|
||||||
|
'tracking-compat.js',
|
||||||
|
'ppcp-clear-db.js',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
'compat.gzd.is_supported_plugin_version_active' => function (): bool {
|
'compat.gzd.is_supported_plugin_version_active' => function (): bool {
|
||||||
return function_exists( 'wc_gzd_get_shipments_by_order' ); // 3.0+
|
return function_exists( 'wc_gzd_get_shipments_by_order' ); // 3.0+
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,6 +15,7 @@ use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\Compat\Assets\CompatAssets;
|
use WooCommerce\PayPalCommerce\Compat\Assets\CompatAssets;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +42,6 @@ class CompatModule implements ModuleInterface {
|
||||||
public function run( ContainerInterface $c ): void {
|
public function run( ContainerInterface $c ): void {
|
||||||
|
|
||||||
$this->initialize_ppec_compat_layer( $c );
|
$this->initialize_ppec_compat_layer( $c );
|
||||||
$this->fix_site_ground_optimizer_compatibility( $c );
|
|
||||||
$this->initialize_tracking_compat_layer( $c );
|
$this->initialize_tracking_compat_layer( $c );
|
||||||
|
|
||||||
$asset_loader = $c->get( 'compat.assets' );
|
$asset_loader = $c->get( 'compat.assets' );
|
||||||
|
@ -54,6 +54,8 @@ class CompatModule implements ModuleInterface {
|
||||||
$this->migrate_smart_button_settings( $c );
|
$this->migrate_smart_button_settings( $c );
|
||||||
|
|
||||||
$this->fix_page_builders();
|
$this->fix_page_builders();
|
||||||
|
$this->exclude_cache_plugins_js_minification( $c );
|
||||||
|
$this->set_elementor_checkout_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,24 +90,6 @@ class CompatModule implements ModuleInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixes the compatibility issue for <a href="https://wordpress.org/plugins/sg-cachepress/">SiteGround Optimizer plugin</a>.
|
|
||||||
*
|
|
||||||
* @link https://wordpress.org/plugins/sg-cachepress/
|
|
||||||
*
|
|
||||||
* @param ContainerInterface $c The Container.
|
|
||||||
*/
|
|
||||||
protected function fix_site_ground_optimizer_compatibility( ContainerInterface $c ): void {
|
|
||||||
$ppcp_script_names = $c->get( 'compat.plugin-script-names' );
|
|
||||||
add_filter(
|
|
||||||
'sgo_js_minify_exclude',
|
|
||||||
function ( array $scripts ) use ( $ppcp_script_names ) {
|
|
||||||
return array_merge( $scripts, $ppcp_script_names );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -329,4 +313,69 @@ class CompatModule implements ModuleInterface {
|
||||||
$parent = $theme->parent();
|
$parent = $theme->parent();
|
||||||
return ( $parent && $parent->get( 'Name' ) === 'Divi' );
|
return ( $parent && $parent->get( 'Name' ) === 'Divi' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the context for the Elementor checkout page.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function set_elementor_checkout_context(): void {
|
||||||
|
add_action(
|
||||||
|
'wp',
|
||||||
|
function() {
|
||||||
|
$page_id = get_the_ID();
|
||||||
|
if ( ! $page_id || ! CartCheckoutDetector::has_elementor_checkout( $page_id ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_paypal_payments_context',
|
||||||
|
function ( string $context ): string {
|
||||||
|
// Default context.
|
||||||
|
return ( 'mini-cart' === $context ) ? 'checkout' : $context;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excludes PayPal scripts from being minified by cache plugins.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface $c The Container.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function exclude_cache_plugins_js_minification( ContainerInterface $c ): void {
|
||||||
|
$ppcp_script_names = $c->get( 'compat.plugin-script-names' );
|
||||||
|
$ppcp_script_file_names = $c->get( 'compat.plugin-script-file-names' );
|
||||||
|
|
||||||
|
// Siteground SG Optimize.
|
||||||
|
add_filter(
|
||||||
|
'sgo_js_minify_exclude',
|
||||||
|
function( array $scripts ) use ( $ppcp_script_names ) {
|
||||||
|
return array_merge( $scripts, $ppcp_script_names );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// LiteSpeed Cache.
|
||||||
|
add_filter(
|
||||||
|
'litespeed_optimize_js_excludes',
|
||||||
|
function( array $excluded_js ) use ( $ppcp_script_file_names ) {
|
||||||
|
return array_merge( $excluded_js, $ppcp_script_file_names );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// W3 Total Cache.
|
||||||
|
add_filter(
|
||||||
|
'w3tc_minify_js_do_tag_minification',
|
||||||
|
function( bool $do_tag_minification, string $script_tag, string $file ) {
|
||||||
|
if ( $file && strpos( $file, 'ppcp' ) !== false ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $do_tag_minification;
|
||||||
|
},
|
||||||
|
10,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -926,7 +926,7 @@ return array(
|
||||||
: $container->get( 'googlepay.enable-url-sandbox' );
|
: $container->get( 'googlepay.enable-url-sandbox' );
|
||||||
|
|
||||||
$button_url = $enabled
|
$button_url = $enabled
|
||||||
? admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway#field-alternative_payment_methods' )
|
? admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-credit-card-gateway#ppcp-googlepay_button_enabled' )
|
||||||
: $enable_url;
|
: $enable_url;
|
||||||
|
|
||||||
return sprintf(
|
return sprintf(
|
||||||
|
|
|
@ -73,34 +73,34 @@ class GermanizedShipmentIntegration implements Integration {
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_gzd_shipment_status_shipped',
|
'woocommerce_gzd_shipment_status_shipped',
|
||||||
function( int $shipment_id, Shipment $shipment ) {
|
function( int $shipment_id, Shipment $shipment ) {
|
||||||
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wc_order = $shipment->get_order();
|
|
||||||
|
|
||||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
|
||||||
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
|
||||||
$wc_order_id = $wc_order->get_id();
|
|
||||||
$tracking_number = $shipment->get_tracking_id();
|
|
||||||
$carrier = $shipment->get_shipping_provider();
|
|
||||||
|
|
||||||
$items = array_map(
|
|
||||||
function ( ShipmentItem $item ): int {
|
|
||||||
return $item->get_order_item_id();
|
|
||||||
},
|
|
||||||
$shipment->get_items()
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( ! $tracking_number || ! $carrier || ! $capture_id ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$wc_order = $shipment->get_order();
|
||||||
|
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
||||||
|
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
||||||
|
$wc_order_id = $wc_order->get_id();
|
||||||
|
$tracking_number = $shipment->get_tracking_id();
|
||||||
|
$carrier = $shipment->get_shipping_provider();
|
||||||
|
|
||||||
|
$items = array_map(
|
||||||
|
function ( ShipmentItem $item ): int {
|
||||||
|
return $item->get_order_item_id();
|
||||||
|
},
|
||||||
|
$shipment->get_items()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! $tracking_number || ! $carrier || ! $capture_id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$ppcp_shipment = $this->shipment_factory->create_shipment(
|
$ppcp_shipment = $this->shipment_factory->create_shipment(
|
||||||
$wc_order_id,
|
$wc_order_id,
|
||||||
$capture_id,
|
$capture_id,
|
||||||
|
@ -118,7 +118,7 @@ class GermanizedShipmentIntegration implements Integration {
|
||||||
: $this->endpoint->add_tracking_information( $ppcp_shipment, $wc_order_id );
|
: $this->endpoint->add_tracking_information( $ppcp_shipment, $wc_order_id );
|
||||||
|
|
||||||
} catch ( Exception $exception ) {
|
} catch ( Exception $exception ) {
|
||||||
$this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() );
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
500,
|
500,
|
||||||
|
|
|
@ -76,25 +76,25 @@ class ShipStationIntegration implements Integration {
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
function( $wc_order, array $data ) {
|
function( $wc_order, array $data ) {
|
||||||
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ship_station_tracking', true ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
|
||||||
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
|
||||||
$order_id = $wc_order->get_id();
|
|
||||||
$tracking_number = $data['tracking_number'] ?? '';
|
|
||||||
$carrier = $data['carrier'] ?? '';
|
|
||||||
|
|
||||||
if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $capture_id ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ship_station_tracking', true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
||||||
|
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
||||||
|
$order_id = $wc_order->get_id();
|
||||||
|
$tracking_number = $data['tracking_number'] ?? '';
|
||||||
|
$carrier = $data['carrier'] ?? '';
|
||||||
|
|
||||||
|
if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $capture_id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$ppcp_shipment = $this->shipment_factory->create_shipment(
|
$ppcp_shipment = $this->shipment_factory->create_shipment(
|
||||||
$order_id,
|
$order_id,
|
||||||
$capture_id,
|
$capture_id,
|
||||||
|
@ -112,7 +112,7 @@ class ShipStationIntegration implements Integration {
|
||||||
: $this->endpoint->add_tracking_information( $ppcp_shipment, $order_id );
|
: $this->endpoint->add_tracking_information( $ppcp_shipment, $order_id );
|
||||||
|
|
||||||
} catch ( Exception $exception ) {
|
} catch ( Exception $exception ) {
|
||||||
$this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() );
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
500,
|
500,
|
||||||
|
|
|
@ -73,30 +73,35 @@ class ShipmentTrackingIntegration implements Integration {
|
||||||
add_action(
|
add_action(
|
||||||
'wp_ajax_wc_shipment_tracking_save_form',
|
'wp_ajax_wc_shipment_tracking_save_form',
|
||||||
function() {
|
function() {
|
||||||
check_ajax_referer( 'create-tracking-item', 'security', true );
|
try {
|
||||||
|
check_ajax_referer( 'create-tracking-item', 'security', true );
|
||||||
|
|
||||||
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) {
|
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_id = (int) wc_clean( wp_unslash( $_POST['order_id'] ?? '' ) );
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
||||||
|
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
||||||
|
$tracking_number = wc_clean( wp_unslash( $_POST['tracking_number'] ?? '' ) );
|
||||||
|
$carrier = wc_clean( wp_unslash( $_POST['tracking_provider'] ?? '' ) );
|
||||||
|
$carrier_other = wc_clean( wp_unslash( $_POST['custom_tracking_provider'] ?? '' ) );
|
||||||
|
$carrier = $carrier ?: $carrier_other ?: '';
|
||||||
|
|
||||||
|
if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $capture_id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sync_tracking( $order_id, $capture_id, $tracking_number, $carrier );
|
||||||
|
|
||||||
|
} catch ( Exception $exception ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$order_id = (int) wc_clean( wp_unslash( $_POST['order_id'] ?? '' ) );
|
|
||||||
$wc_order = wc_get_order( $order_id );
|
|
||||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
|
||||||
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
|
||||||
$tracking_number = wc_clean( wp_unslash( $_POST['tracking_number'] ?? '' ) );
|
|
||||||
$carrier = wc_clean( wp_unslash( $_POST['tracking_provider'] ?? '' ) );
|
|
||||||
$carrier_other = wc_clean( wp_unslash( $_POST['custom_tracking_provider'] ?? '' ) );
|
|
||||||
$carrier = $carrier ?: $carrier_other ?: '';
|
|
||||||
|
|
||||||
if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $capture_id ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->sync_tracking( $order_id, $capture_id, $tracking_number, $carrier );
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -106,34 +111,39 @@ class ShipmentTrackingIntegration implements Integration {
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_rest_prepare_order_shipment_tracking',
|
'woocommerce_rest_prepare_order_shipment_tracking',
|
||||||
function( WP_REST_Response $response, array $tracking_item, WP_REST_Request $request ): WP_REST_Response {
|
function( WP_REST_Response $response, array $tracking_item, WP_REST_Request $request ): WP_REST_Response {
|
||||||
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) {
|
try {
|
||||||
|
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$callback = $request->get_attributes()['callback']['1'] ?? '';
|
||||||
|
if ( $callback !== 'create_item' ) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_id = $tracking_item['order_id'] ?? 0;
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
||||||
|
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
||||||
|
$tracking_number = $tracking_item['tracking_number'] ?? '';
|
||||||
|
$carrier = $tracking_item['tracking_provider'] ?? '';
|
||||||
|
$carrier_other = $tracking_item['custom_tracking_provider'] ?? '';
|
||||||
|
$carrier = $carrier ?: $carrier_other ?: '';
|
||||||
|
|
||||||
|
if ( ! $tracking_number || ! $carrier || ! $capture_id ) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sync_tracking( $order_id, $capture_id, $tracking_number, $carrier );
|
||||||
|
|
||||||
|
} catch ( Exception $exception ) {
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
$callback = $request->get_attributes()['callback']['1'] ?? '';
|
|
||||||
if ( $callback !== 'create_item' ) {
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
$order_id = $tracking_item['order_id'] ?? 0;
|
|
||||||
$wc_order = wc_get_order( $order_id );
|
|
||||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
|
||||||
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
|
||||||
$tracking_number = $tracking_item['tracking_number'] ?? '';
|
|
||||||
$carrier = $tracking_item['tracking_provider'] ?? '';
|
|
||||||
$carrier_other = $tracking_item['custom_tracking_provider'] ?? '';
|
|
||||||
$carrier = $carrier ?: $carrier_other ?: '';
|
|
||||||
|
|
||||||
if ( ! $tracking_number || ! $carrier || ! $capture_id ) {
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->sync_tracking( $order_id, $capture_id, $tracking_number, $carrier );
|
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
},
|
},
|
||||||
10,
|
10,
|
||||||
|
|
|
@ -75,44 +75,48 @@ class WcShippingTaxIntegration implements Integration {
|
||||||
add_filter(
|
add_filter(
|
||||||
'rest_post_dispatch',
|
'rest_post_dispatch',
|
||||||
function( WP_HTTP_Response $response, WP_REST_Server $server, WP_REST_Request $request ): WP_HTTP_Response {
|
function( WP_HTTP_Response $response, WP_REST_Server $server, WP_REST_Request $request ): WP_HTTP_Response {
|
||||||
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) ) {
|
try {
|
||||||
|
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) ) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = $request->get_params();
|
||||||
|
$order_id = (int) ( $params['order_id'] ?? 0 );
|
||||||
|
$label_id = (int) ( $params['label_ids'] ?? 0 );
|
||||||
|
|
||||||
|
if ( ! $order_id || "/wc/v1/connect/label/{$order_id}/{$label_id}" !== $request->get_route() ) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $response->get_data() ?? array();
|
||||||
|
$labels = $data['labels'] ?? array();
|
||||||
|
|
||||||
|
foreach ( $labels as $label ) {
|
||||||
|
$tracking_number = $label['tracking'] ?? '';
|
||||||
|
if ( ! $tracking_number ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
||||||
|
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
||||||
|
$carrier = $label['carrier_id'] ?? $label['service_name'] ?? '';
|
||||||
|
$items = array_map( 'intval', $label['product_ids'] ?? array() );
|
||||||
|
|
||||||
|
if ( ! $carrier || ! $capture_id ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sync_tracking( $order_id, $capture_id, $tracking_number, $carrier, $items );
|
||||||
|
}
|
||||||
|
} catch ( Exception $exception ) {
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = $request->get_params();
|
|
||||||
$order_id = (int) ( $params['order_id'] ?? 0 );
|
|
||||||
$label_id = (int) ( $params['label_ids'] ?? 0 );
|
|
||||||
|
|
||||||
if ( ! $order_id || "/wc/v1/connect/label/{$order_id}/{$label_id}" !== $request->get_route() ) {
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $response->get_data() ?? array();
|
|
||||||
$labels = $data['labels'] ?? array();
|
|
||||||
|
|
||||||
foreach ( $labels as $label ) {
|
|
||||||
$tracking_number = $label['tracking'] ?? '';
|
|
||||||
if ( ! $tracking_number ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wc_order = wc_get_order( $order_id );
|
|
||||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
|
||||||
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
|
||||||
$carrier = $label['carrier_id'] ?? $label['service_name'] ?? '';
|
|
||||||
$items = array_map( 'intval', $label['product_ids'] ?? array() );
|
|
||||||
|
|
||||||
if ( ! $carrier || ! $capture_id ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->sync_tracking( $order_id, $capture_id, $tracking_number, $carrier, $items );
|
|
||||||
}
|
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
},
|
},
|
||||||
10,
|
10,
|
||||||
|
|
|
@ -71,27 +71,27 @@ class YithShipmentIntegration implements Integration {
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_process_shop_order_meta',
|
'woocommerce_process_shop_order_meta',
|
||||||
function( int $order_id ) {
|
function( int $order_id ) {
|
||||||
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ywot_tracking', true ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wc_order = wc_get_order( $order_id );
|
|
||||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
|
||||||
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
|
||||||
$tracking_number = wc_clean( wp_unslash( $_POST['ywot_tracking_code'] ?? '' ) );
|
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
|
||||||
$carrier = wc_clean( wp_unslash( $_POST['ywot_carrier_name'] ?? '' ) );
|
|
||||||
|
|
||||||
if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $capture_id ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ywot_tracking', true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
||||||
|
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
||||||
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
|
$tracking_number = wc_clean( wp_unslash( $_POST['ywot_tracking_code'] ?? '' ) );
|
||||||
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
|
$carrier = wc_clean( wp_unslash( $_POST['ywot_carrier_name'] ?? '' ) );
|
||||||
|
|
||||||
|
if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $capture_id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$ppcp_shipment = $this->shipment_factory->create_shipment(
|
$ppcp_shipment = $this->shipment_factory->create_shipment(
|
||||||
$order_id,
|
$order_id,
|
||||||
$capture_id,
|
$capture_id,
|
||||||
|
@ -109,7 +109,7 @@ class YithShipmentIntegration implements Integration {
|
||||||
: $this->endpoint->add_tracking_information( $ppcp_shipment, $order_id );
|
: $this->endpoint->add_tracking_information( $ppcp_shipment, $order_id );
|
||||||
|
|
||||||
} catch ( Exception $exception ) {
|
} catch ( Exception $exception ) {
|
||||||
$this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() );
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
500,
|
500,
|
||||||
|
|
|
@ -17,12 +17,14 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
return array(
|
return array(
|
||||||
'paylater-configurator.url' => static function ( ContainerInterface $container ): string {
|
'paylater-configurator.url' => static function ( ContainerInterface $container ): string {
|
||||||
/**
|
/**
|
||||||
|
* The return value must not contain a trailing slash.
|
||||||
|
*
|
||||||
* Cannot return false for this path.
|
* Cannot return false for this path.
|
||||||
*
|
*
|
||||||
* @psalm-suppress PossiblyFalseArgument
|
* @psalm-suppress PossiblyFalseArgument
|
||||||
*/
|
*/
|
||||||
return plugins_url(
|
return plugins_url(
|
||||||
'/modules/ppcp-paylater-configurator/',
|
'/modules/ppcp-paylater-configurator',
|
||||||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,6 +38,9 @@ document.addEventListener(
|
||||||
|
|
||||||
const subscriptionTrial = document.querySelector('._subscription_trial_length_field');
|
const subscriptionTrial = document.querySelector('._subscription_trial_length_field');
|
||||||
subscriptionTrial.style.display = 'none';
|
subscriptionTrial.style.display = 'none';
|
||||||
|
|
||||||
|
const soldIndividually = document.querySelector( '#_sold_individually' );
|
||||||
|
soldIndividually.setAttribute( 'disabled', 'disabled' );
|
||||||
}
|
}
|
||||||
|
|
||||||
const setupProducts = () => {
|
const setupProducts = () => {
|
||||||
|
|
|
@ -87,6 +87,44 @@ class PayPalSubscriptionsModule implements ModuleInterface {
|
||||||
12
|
12
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_add_to_cart_validation',
|
||||||
|
/**
|
||||||
|
* Param types removed to avoid third-party issues.
|
||||||
|
*
|
||||||
|
* @psalm-suppress MissingClosureParamType
|
||||||
|
*/
|
||||||
|
static function ( $passed_validation, $product_id ) {
|
||||||
|
if ( WC()->cart->is_empty() ) {
|
||||||
|
return $passed_validation;
|
||||||
|
}
|
||||||
|
|
||||||
|
$product = wc_get_product( $product_id );
|
||||||
|
|
||||||
|
if ( $product && $product->get_meta( '_ppcp_enable_subscription_product', true ) === 'yes' ) {
|
||||||
|
if ( ! $product->get_sold_individually() ) {
|
||||||
|
$product->set_sold_individually( true );
|
||||||
|
$product->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
wc_add_notice( __( 'You cannot add a subscription product to a cart with other items.', 'woocommerce-paypal-payments' ), 'error' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
|
||||||
|
$cart_product = wc_get_product( $cart_item['product_id'] );
|
||||||
|
if ( $cart_product && $cart_product->get_meta( '_ppcp_enable_subscription_product', true ) === 'yes' ) {
|
||||||
|
wc_add_notice( __( 'You can only have one subscription product in your cart.', 'woocommerce-paypal-payments' ), 'error' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $passed_validation;
|
||||||
|
},
|
||||||
|
10,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_save_product_variation',
|
'woocommerce_save_product_variation',
|
||||||
/**
|
/**
|
||||||
|
@ -654,12 +692,18 @@ class PayPalSubscriptionsModule implements ModuleInterface {
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification
|
// phpcs:ignore WordPress.Security.NonceVerification
|
||||||
$enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) );
|
$enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) );
|
||||||
$product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product );
|
$product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product );
|
||||||
|
|
||||||
|
if ( ! $product->get_sold_individually() ) {
|
||||||
|
$product->set_sold_individually( true );
|
||||||
|
}
|
||||||
|
|
||||||
$product->save();
|
$product->save();
|
||||||
|
|
||||||
if ( ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) && $enable_subscription_product === 'yes' ) {
|
if ( ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) && $enable_subscription_product === 'yes' ) {
|
||||||
if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||||
$subscriptions_api_handler->update_product( $product );
|
$subscriptions_api_handler->update_product( $product );
|
||||||
$subscriptions_api_handler->update_plan( $product );
|
$subscriptions_api_handler->update_plan( $product );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,17 +61,33 @@ $background-ident-color: #fbfbfb;
|
||||||
border: 1px solid #c3c4c7;
|
border: 1px solid #c3c4c7;
|
||||||
border-left-width: 4px;
|
border-left-width: 4px;
|
||||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
||||||
margin: 5px 0px 2px;
|
margin: 5px 15px 2px 0;
|
||||||
padding: 0px 12px 4px 12px;
|
padding: 1px 12px;
|
||||||
|
|
||||||
|
p, .form-table td & p {
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background: transparent;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ppcp-notice-warning {
|
.ppcp-notice-warning {
|
||||||
border-left-color: #dba617;
|
border-left-color: #dba617;
|
||||||
|
|
||||||
.highlight {
|
.highlight {
|
||||||
background: transparent;
|
|
||||||
color: #dba617;
|
color: #dba617;
|
||||||
font-weight: 600;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ppcp-notice-error {
|
||||||
|
border-left-color: #d63638;
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
color: #d63638;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -347,7 +347,6 @@ return array(
|
||||||
$container->get( 'api.partner_merchant_id-production' ),
|
$container->get( 'api.partner_merchant_id-production' ),
|
||||||
$container->get( 'api.partner_merchant_id-sandbox' ),
|
$container->get( 'api.partner_merchant_id-sandbox' ),
|
||||||
$container->get( 'api.endpoint.billing-agreements' ),
|
$container->get( 'api.endpoint.billing-agreements' ),
|
||||||
$container->get( 'wc-subscriptions.helper' ),
|
|
||||||
$logger
|
$logger
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Endpoint;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
use WC_Order;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
|
||||||
|
@ -131,16 +132,25 @@ class CaptureCardPayment {
|
||||||
/**
|
/**
|
||||||
* Creates PayPal order from the given card vault id.
|
* Creates PayPal order from the given card vault id.
|
||||||
*
|
*
|
||||||
* @param string $vault_id Vault id.
|
* @param string $vault_id Vault id.
|
||||||
* @param string $custom_id Custom id.
|
* @param string $custom_id Custom id.
|
||||||
* @param string $invoice_id Invoice id.
|
* @param string $invoice_id Invoice id.
|
||||||
|
* @param WC_Order $wc_order The WC order.
|
||||||
* @return stdClass
|
* @return stdClass
|
||||||
* @throws RuntimeException When request fails.
|
* @throws RuntimeException When request fails.
|
||||||
*/
|
*/
|
||||||
public function create_order( string $vault_id, string $custom_id, string $invoice_id ): stdClass {
|
public function create_order( string $vault_id, string $custom_id, string $invoice_id, WC_Order $wc_order ): stdClass {
|
||||||
$intent = $this->settings->has( 'intent' ) && strtoupper( (string) $this->settings->get( 'intent' ) ) === 'AUTHORIZE' ? 'AUTHORIZE' : 'CAPTURE';
|
$intent = $this->settings->has( 'intent' ) && strtoupper( (string) $this->settings->get( 'intent' ) ) === 'AUTHORIZE' ? 'AUTHORIZE' : 'CAPTURE';
|
||||||
$items = array( $this->purchase_unit_factory->from_wc_cart() );
|
$items = array( $this->purchase_unit_factory->from_wc_cart() );
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.Security.NonceVerification
|
||||||
|
$pay_for_order = wc_clean( wp_unslash( $_GET['pay_for_order'] ?? '' ) );
|
||||||
|
$order_key = wc_clean( wp_unslash( $_GET['key'] ?? '' ) );
|
||||||
|
// phpcs:enable
|
||||||
|
if ( $pay_for_order && $order_key === $wc_order->get_order_key() ) {
|
||||||
|
$items = array( $this->purchase_unit_factory->from_wc_order( $wc_order ) );
|
||||||
|
}
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'intent' => $intent,
|
'intent' => $intent,
|
||||||
'purchase_units' => array_map(
|
'purchase_units' => array_map(
|
||||||
|
|
|
@ -490,7 +490,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
||||||
|
|
||||||
$custom_id = $wc_order->get_order_number();
|
$custom_id = $wc_order->get_order_number();
|
||||||
$invoice_id = $this->prefix . $wc_order->get_order_number();
|
$invoice_id = $this->prefix . $wc_order->get_order_number();
|
||||||
$create_order = $this->capture_card_payment->create_order( $token->get_token(), $custom_id, $invoice_id );
|
$create_order = $this->capture_card_payment->create_order( $token->get_token(), $custom_id, $invoice_id, $wc_order );
|
||||||
|
|
||||||
$order = $this->order_endpoint->order( $create_order->id );
|
$order = $this->order_endpoint->order( $create_order->id );
|
||||||
$wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() );
|
$wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() );
|
||||||
|
|
|
@ -57,12 +57,19 @@ class CartCheckoutDetector {
|
||||||
/**
|
/**
|
||||||
* Check if the Checkout page is using Elementor.
|
* Check if the Checkout page is using Elementor.
|
||||||
*
|
*
|
||||||
|
* @param int $page_id The ID of the page.
|
||||||
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function has_elementor_checkout(): bool {
|
public static function has_elementor_checkout( int $page_id = 0 ): bool {
|
||||||
// Check if Elementor is installed and activated.
|
// Check if Elementor is installed and activated.
|
||||||
if ( did_action( 'elementor/loaded' ) ) {
|
if ( did_action( 'elementor/loaded' ) ) {
|
||||||
$elementor_widgets = self::get_elementor_widgets( wc_get_page_id( 'checkout' ) );
|
if ( $page_id ) {
|
||||||
|
$elementor_widgets = self::get_elementor_widgets( $page_id );
|
||||||
|
} else {
|
||||||
|
// Check the WooCommerce checkout page.
|
||||||
|
$elementor_widgets = self::get_elementor_widgets( wc_get_page_id( 'checkout' ) );
|
||||||
|
}
|
||||||
|
|
||||||
if ( $elementor_widgets ) {
|
if ( $elementor_widgets ) {
|
||||||
return in_array( 'woocommerce-checkout-page', $elementor_widgets, true );
|
return in_array( 'woocommerce-checkout-page', $elementor_widgets, true );
|
||||||
|
@ -114,7 +121,7 @@ class CartCheckoutDetector {
|
||||||
*/
|
*/
|
||||||
public static function has_classic_checkout(): bool {
|
public static function has_classic_checkout(): bool {
|
||||||
$checkout_page_id = wc_get_page_id( 'checkout' );
|
$checkout_page_id = wc_get_page_id( 'checkout' );
|
||||||
return $checkout_page_id && has_block( 'woocommerce/classic-shortcode', $checkout_page_id );
|
return $checkout_page_id && ( has_block( 'woocommerce/classic-shortcode', $checkout_page_id ) || self::has_classic_shortcode( $checkout_page_id, 'woocommerce_checkout' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,6 +131,25 @@ class CartCheckoutDetector {
|
||||||
*/
|
*/
|
||||||
public static function has_classic_cart(): bool {
|
public static function has_classic_cart(): bool {
|
||||||
$cart_page_id = wc_get_page_id( 'cart' );
|
$cart_page_id = wc_get_page_id( 'cart' );
|
||||||
return $cart_page_id && has_block( 'woocommerce/classic-shortcode', $cart_page_id );
|
return $cart_page_id && ( has_block( 'woocommerce/classic-shortcode', $cart_page_id ) || self::has_classic_shortcode( $cart_page_id, 'woocommerce_cart' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a page has a specific shortcode.
|
||||||
|
*
|
||||||
|
* @param int $page_id The ID of the page.
|
||||||
|
* @param string $shortcode The shortcode to check for.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function has_classic_shortcode( int $page_id, string $shortcode ): bool {
|
||||||
|
if ( ! $page_id ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = get_post( $page_id );
|
||||||
|
$page_content = is_object( $page ) ? $page->post_content : '';
|
||||||
|
|
||||||
|
return str_contains( $page_content, $shortcode );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,14 +56,14 @@ class PayUponInvoiceHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
$billing_country = wc_clean( wp_unslash( $_POST['country'] ?? '' ) );
|
$billing_country = WC()->customer->get_billing_country();
|
||||||
if ( $billing_country && 'DE' !== $billing_country ) {
|
if ( empty( $billing_country ) || 'DE' !== $billing_country ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
$shipping_country = wc_clean( wp_unslash( $_POST['s_country'] ?? '' ) );
|
$shipping_country = WC()->customer->get_shipping_country();
|
||||||
if ( $shipping_country && 'DE' !== $shipping_country ) {
|
if ( empty( $shipping_country ) || 'DE' !== $shipping_country ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,8 +220,8 @@ class OrderProcessor {
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new PayPalOrderMissingException(
|
throw new PayPalOrderMissingException(
|
||||||
__(
|
esc_attr__(
|
||||||
'Could not retrieve order. Maybe it was already completed or this browser is not supported. Please check your email or try again with a different browser.',
|
'There was an error processing your order. Please check for any charges in your payment method and review your order history before placing the order again.',
|
||||||
'woocommerce-paypal-payments'
|
'woocommerce-paypal-payments'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -36,6 +36,8 @@ return function ( ContainerInterface $container, array $fields ): array {
|
||||||
</div>';
|
</div>';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$axo_smart_button_location_notice = $container->has( 'axo.smart-button-location-notice' ) ? $container->get( 'axo.smart-button-location-notice' ) : '';
|
||||||
|
|
||||||
$smart_button_fields = array(
|
$smart_button_fields = array(
|
||||||
'button_style_heading' => array(
|
'button_style_heading' => array(
|
||||||
'heading' => __( 'PayPal Smart Buttons', 'woocommerce-paypal-payments' ),
|
'heading' => __( 'PayPal Smart Buttons', 'woocommerce-paypal-payments' ),
|
||||||
|
@ -65,7 +67,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
||||||
'type' => 'ppcp-multiselect',
|
'type' => 'ppcp-multiselect',
|
||||||
'input_class' => array( 'wc-enhanced-select' ),
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
'default' => $container->get( 'wcgateway.button.default-locations' ),
|
'default' => $container->get( 'wcgateway.button.default-locations' ),
|
||||||
'description' => __( 'Select where the PayPal smart buttons should be displayed.', 'woocommerce-paypal-payments' ),
|
'description' => __( 'Select where the PayPal smart buttons should be displayed.', 'woocommerce-paypal-payments' ) . $axo_smart_button_location_notice,
|
||||||
'options' => $container->get( 'wcgateway.button.locations' ),
|
'options' => $container->get( 'wcgateway.button.locations' ),
|
||||||
'screens' => array( State::STATE_START, State::STATE_ONBOARDED ),
|
'screens' => array( State::STATE_START, State::STATE_ONBOARDED ),
|
||||||
'requirements' => array(),
|
'requirements' => array(),
|
||||||
|
|
|
@ -10,8 +10,6 @@ declare(strict_types=1);
|
||||||
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
|
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
|
||||||
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message;
|
|
||||||
use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint;
|
||||||
|
@ -23,9 +21,7 @@ use WooCommerce\PayPalCommerce\Onboarding\Helper\OnboardingUrl;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
|
||||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
|
||||||
use WooCommerce\PayPalCommerce\Webhooks\WebhookRegistrar;
|
use WooCommerce\PayPalCommerce\Webhooks\WebhookRegistrar;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
|
||||||
use WooCommerce\WooCommerce\Logging\Logger\NullLogger;
|
use WooCommerce\WooCommerce\Logging\Logger\NullLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,13 +157,6 @@ class SettingsListener {
|
||||||
*/
|
*/
|
||||||
private $billing_agreements_endpoint;
|
private $billing_agreements_endpoint;
|
||||||
|
|
||||||
/**
|
|
||||||
* The subscription helper
|
|
||||||
*
|
|
||||||
* @var SubscriptionHelper
|
|
||||||
*/
|
|
||||||
protected $subscription_helper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
*
|
*
|
||||||
|
@ -193,7 +182,6 @@ class SettingsListener {
|
||||||
* @param string $partner_merchant_id_production Partner merchant ID production.
|
* @param string $partner_merchant_id_production Partner merchant ID production.
|
||||||
* @param string $partner_merchant_id_sandbox Partner merchant ID sandbox.
|
* @param string $partner_merchant_id_sandbox Partner merchant ID sandbox.
|
||||||
* @param BillingAgreementsEndpoint $billing_agreements_endpoint Billing Agreements endpoint.
|
* @param BillingAgreementsEndpoint $billing_agreements_endpoint Billing Agreements endpoint.
|
||||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
|
||||||
* @param ?LoggerInterface $logger The logger.
|
* @param ?LoggerInterface $logger The logger.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
@ -212,7 +200,6 @@ class SettingsListener {
|
||||||
string $partner_merchant_id_production,
|
string $partner_merchant_id_production,
|
||||||
string $partner_merchant_id_sandbox,
|
string $partner_merchant_id_sandbox,
|
||||||
BillingAgreementsEndpoint $billing_agreements_endpoint,
|
BillingAgreementsEndpoint $billing_agreements_endpoint,
|
||||||
SubscriptionHelper $subscription_helper,
|
|
||||||
LoggerInterface $logger = null
|
LoggerInterface $logger = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -231,7 +218,6 @@ class SettingsListener {
|
||||||
$this->partner_merchant_id_production = $partner_merchant_id_production;
|
$this->partner_merchant_id_production = $partner_merchant_id_production;
|
||||||
$this->partner_merchant_id_sandbox = $partner_merchant_id_sandbox;
|
$this->partner_merchant_id_sandbox = $partner_merchant_id_sandbox;
|
||||||
$this->billing_agreements_endpoint = $billing_agreements_endpoint;
|
$this->billing_agreements_endpoint = $billing_agreements_endpoint;
|
||||||
$this->subscription_helper = $subscription_helper;
|
|
||||||
$this->logger = $logger ?: new NullLogger();
|
$this->logger = $logger ?: new NullLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +380,18 @@ class SettingsListener {
|
||||||
|
|
||||||
if ( $reference_transaction_enabled !== true ) {
|
if ( $reference_transaction_enabled !== true ) {
|
||||||
$this->settings->set( 'vault_enabled', false );
|
$this->settings->set( 'vault_enabled', false );
|
||||||
$this->settings->set( 'subscriptions_mode', 'subscriptions_api' );
|
|
||||||
|
/**
|
||||||
|
* If Vaulting-API was previously enabled, then fall-back to the
|
||||||
|
* PayPal subscription mode, to ensure subscriptions are still
|
||||||
|
* possible on this shop.
|
||||||
|
*
|
||||||
|
* This can happen when switching to a different PayPal merchant account
|
||||||
|
*/
|
||||||
|
if ( 'vaulting_api' === $subscription_mode ) {
|
||||||
|
$this->settings->set( 'subscriptions_mode', 'subscriptions_api' );
|
||||||
|
}
|
||||||
|
|
||||||
$this->settings->persist();
|
$this->settings->persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,11 +400,6 @@ class SettingsListener {
|
||||||
$this->settings->persist();
|
$this->settings->persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $this->subscription_helper->plugin_is_active() ) {
|
|
||||||
$this->settings->set( 'blocks_final_review_enabled', true );
|
|
||||||
$this->settings->persist();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $subscription_mode === 'disable_paypal_subscriptions' && $vault_enabled === '1' ) {
|
if ( $subscription_mode === 'disable_paypal_subscriptions' && $vault_enabled === '1' ) {
|
||||||
$this->settings->set( 'vault_enabled', false );
|
$this->settings->set( 'vault_enabled', false );
|
||||||
$this->settings->persist();
|
$this->settings->persist();
|
||||||
|
@ -745,4 +737,28 @@ class SettingsListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter settings based on a condition.
|
||||||
|
*
|
||||||
|
* @param bool $condition The condition.
|
||||||
|
* @param string $setting_slug The setting slug.
|
||||||
|
* @param callable $filter_function The filter function.
|
||||||
|
* @param bool $persist Whether to persist the settings.
|
||||||
|
*/
|
||||||
|
public function filter_settings( bool $condition, string $setting_slug, callable $filter_function, bool $persist = true ): void {
|
||||||
|
if ( ! $this->is_valid_site_request() || State::STATE_ONBOARDED !== $this->state->current_state() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing_setting_value = $this->settings->has( $setting_slug ) ? $this->settings->get( $setting_slug ) : null;
|
||||||
|
|
||||||
|
if ( $condition ) {
|
||||||
|
$new_setting_value = $filter_function( $existing_setting_value );
|
||||||
|
$this->settings->set( $setting_slug, $new_setting_value );
|
||||||
|
|
||||||
|
if ( $persist ) {
|
||||||
|
$this->settings->persist();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "woocommerce-paypal-payments",
|
"name": "woocommerce-paypal-payments",
|
||||||
"version": "2.7.1",
|
"version": "2.8.0",
|
||||||
"description": "WooCommerce PayPal Payments",
|
"description": "WooCommerce PayPal Payments",
|
||||||
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
|
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
|
||||||
"license": "GPL-2.0",
|
"license": "GPL-2.0",
|
||||||
|
@ -94,6 +94,7 @@
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"playwright": "^1.43.0",
|
"playwright": "^1.43.0",
|
||||||
"run-s": "^0.0.0"
|
"run-s": "^0.0.0",
|
||||||
|
"uuid": "^9.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
18
readme.txt
18
readme.txt
|
@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple
|
||||||
Requires at least: 5.3
|
Requires at least: 5.3
|
||||||
Tested up to: 6.5
|
Tested up to: 6.5
|
||||||
Requires PHP: 7.2
|
Requires PHP: 7.2
|
||||||
Stable tag: 2.7.1
|
Stable tag: 2.8.0
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
|
||||||
|
@ -179,7 +179,21 @@ If you encounter issues with the PayPal buttons not appearing after an update, p
|
||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
= 2.7.1 - xxxx-xx-xx =
|
= 2.8.0 - 2024-06-11 =
|
||||||
|
* Fix - Calculate totals after adding shipping to include taxes #2296
|
||||||
|
* Fix - Package tracking integration throws error in 2.7.1 #2289
|
||||||
|
* Fix - Make PayPal Subscription products unique in cart #2265
|
||||||
|
* Fix - PayPal declares subscription support when merchant not enabled for Reference Transactions #2282
|
||||||
|
* Fix - Google Pay and Apple Pay Settings button from Connection tab have wrong links #2273
|
||||||
|
* Fix - Smart Buttons in Block Checkout not respecting the location setting (2830) #2278
|
||||||
|
* Fix - Disable Pay Upon Invoice if billing/shipping country not set #2281
|
||||||
|
* Fix - Critical error on pay for order page when we try to pay with ACDC gateway #2321
|
||||||
|
* Enhancement - Enable shipping callback for WC subscriptions #2259
|
||||||
|
* Enhancement - Disable the shipping callback for "venmo" when vaulting is active #2269
|
||||||
|
* Enhancement - Improve "Could not retrieve order" error message #2271
|
||||||
|
* Enhancement - Add block Checkout compatibility to Advanced Card Processing #2246
|
||||||
|
|
||||||
|
= 2.7.1 - 2024-05-28 =
|
||||||
* Fix - Ensure package tracking data is sent to original PayPal transaction #2180
|
* Fix - Ensure package tracking data is sent to original PayPal transaction #2180
|
||||||
* Fix - Set the 'Woo_PPCP' as a default value for data-partner-attribution-id #2188
|
* Fix - Set the 'Woo_PPCP' as a default value for data-partner-attribution-id #2188
|
||||||
* Fix - Allow PUI Gateway for refund processor #2192
|
* Fix - Allow PUI Gateway for refund processor #2192
|
||||||
|
|
|
@ -60,7 +60,6 @@ class SettingsListenerTest extends ModularTestCase
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
$billing_agreement_endpoint,
|
$billing_agreement_endpoint,
|
||||||
$subscription_helper,
|
|
||||||
$logger
|
$logger
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
* Plugin Name: WooCommerce PayPal Payments
|
* Plugin Name: WooCommerce PayPal Payments
|
||||||
* Plugin URI: https://woocommerce.com/products/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.
|
* 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.7.1
|
* Version: 2.8.0
|
||||||
* Author: WooCommerce
|
* Author: WooCommerce
|
||||||
* Author URI: https://woocommerce.com/
|
* Author URI: https://woocommerce.com/
|
||||||
* License: GPL-2.0
|
* License: GPL-2.0
|
||||||
* Requires PHP: 7.2
|
* Requires PHP: 7.2
|
||||||
* Requires Plugins: woocommerce
|
* Requires Plugins: woocommerce
|
||||||
* WC requires at least: 3.9
|
* WC requires at least: 3.9
|
||||||
* WC tested up to: 8.8
|
* WC tested up to: 8.9
|
||||||
* Text Domain: woocommerce-paypal-payments
|
* Text Domain: woocommerce-paypal-payments
|
||||||
*
|
*
|
||||||
* @package WooCommerce\PayPalCommerce
|
* @package WooCommerce\PayPalCommerce
|
||||||
|
@ -26,7 +26,7 @@ define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' );
|
||||||
define( 'PAYPAL_URL', 'https://www.paypal.com' );
|
define( 'PAYPAL_URL', 'https://www.paypal.com' );
|
||||||
define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' );
|
define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' );
|
||||||
define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' );
|
define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' );
|
||||||
define( 'PAYPAL_INTEGRATION_DATE', '2024-05-13' );
|
define( 'PAYPAL_INTEGRATION_DATE', '2024-06-03' );
|
||||||
|
|
||||||
! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' );
|
! 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_' );
|
! defined( 'CONNECT_WOO_SANDBOX_CLIENT_ID' ) && define( 'CONNECT_WOO_SANDBOX_CLIENT_ID', 'AYmOHbt1VHg-OZ_oihPdzKEVbU3qg0qXonBcAztuzniQRaKE0w1Hr762cSFwd4n8wxOl-TCWohEa0XM_' );
|
||||||
|
|
|
@ -598,6 +598,11 @@ unbox-primitive@^1.0.2:
|
||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
which-boxed-primitive "^1.0.2"
|
which-boxed-primitive "^1.0.2"
|
||||||
|
|
||||||
|
uuid@^9.0.1:
|
||||||
|
version "9.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
|
||||||
|
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
|
||||||
|
|
||||||
validate-npm-package-license@^3.0.1:
|
validate-npm-package-license@^3.0.1:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
|
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue