mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
🔀 Merge branch 'trunk' into PCP-3179-apple-pay-google-pay-buttons-no-longer-visible-in-standard-payments-button-previews-after-moving-them-to-advanced-card-processing-tab
This commit is contained in:
commit
202f308850
38 changed files with 820 additions and 251 deletions
|
@ -1,5 +1,18 @@
|
||||||
*** Changelog ***
|
*** Changelog ***
|
||||||
|
|
||||||
|
= 2.8.0 - xxxx-xx-xx =
|
||||||
|
* 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
|
||||||
|
* 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 =
|
= 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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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,15 @@
|
||||||
.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-payment-container {
|
.ppcp-axo-payment-container {
|
||||||
|
@ -28,6 +37,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 +54,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;
|
||||||
|
|
|
@ -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,9 +165,8 @@ 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);
|
|
||||||
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) {
|
||||||
await this.onChangeEmail();
|
await this.onChangeEmail();
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ class AxoManager {
|
||||||
|
|
||||||
// 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,7 +212,7 @@ 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();
|
||||||
|
@ -231,6 +231,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();
|
||||||
}
|
}
|
||||||
|
@ -248,7 +249,6 @@ class AxoManager {
|
||||||
this.$(this.el.fieldBillingEmail.selector).append(
|
this.$(this.el.fieldBillingEmail.selector).append(
|
||||||
this.$(this.el.watermarkContainer.selector)
|
this.$(this.el.watermarkContainer.selector)
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.el.emailWidgetContainer.hide();
|
this.el.emailWidgetContainer.hide();
|
||||||
if (!scenario.defaultEmailField) {
|
if (!scenario.defaultEmailField) {
|
||||||
|
@ -257,12 +257,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)
|
||||||
|
@ -372,7 +374,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 +386,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();
|
||||||
}
|
}
|
||||||
|
@ -496,6 +497,8 @@ 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');
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEmail() {
|
watchEmail() {
|
||||||
|
@ -506,17 +509,15 @@ 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.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 +537,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('');
|
||||||
|
@ -565,12 +566,16 @@ class AxoManager {
|
||||||
page_type: 'checkout'
|
page_type: 'checkout'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.disableGatewaySelection();
|
||||||
await this.lookupCustomerByEmail();
|
await this.lookupCustomerByEmail();
|
||||||
|
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 +583,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 +619,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 +656,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 +692,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 +703,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 +737,7 @@ class AxoManager {
|
||||||
|
|
||||||
tokenizeData() {
|
tokenizeData() {
|
||||||
return {
|
return {
|
||||||
name: {
|
cardholderName: {
|
||||||
fullName: this.billingView.fullName()
|
fullName: this.billingView.fullName()
|
||||||
},
|
},
|
||||||
billingAddress: {
|
billingAddress: {
|
||||||
|
@ -776,7 +799,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 +810,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 +866,28 @@ 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AxoManager;
|
export default AxoManager;
|
||||||
|
|
|
@ -20,7 +20,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({
|
||||||
|
|
|
@ -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' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -191,6 +195,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,21 @@ 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() ),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
|
@ -108,9 +108,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 +145,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 +243,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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -292,4 +330,47 @@ class AxoModule implements ModuleInterface {
|
||||||
&& CartCheckoutDetector::has_classic_checkout()
|
&& CartCheckoutDetector::has_classic_checkout()
|
||||||
&& $is_axo_enabled;
|
&& $is_axo_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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' )
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -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';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -360,7 +360,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
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -114,7 +114,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 +124,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,14 +220,9 @@ class OrderProcessor {
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new PayPalOrderMissingException(
|
throw new PayPalOrderMissingException(
|
||||||
sprintf(
|
esc_attr__(
|
||||||
// translators: %s: Order history URL on My Account section.
|
'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.',
|
||||||
esc_attr__(
|
'woocommerce-paypal-payments'
|
||||||
'There was an error processing your order. Please check for any charges in your payment method and review your <a href="%s">order history</a> before placing the order again.',
|
|
||||||
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Intentionally "woocommerce" to reflect the original message.
|
|
||||||
'woocommerce'
|
|
||||||
),
|
|
||||||
esc_url( wc_get_account_endpoint_url( 'orders' ) )
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
readme.txt
15
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,6 +179,19 @@ If you encounter issues with the PayPal buttons not appearing after an update, p
|
||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 2.8.0 - xxxx-xx-xx =
|
||||||
|
* 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
|
||||||
|
* 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 =
|
= 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
|
||||||
|
|
|
@ -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