mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
🔀 Merge branch 'PCP-3380’
# Conflicts: # modules/ppcp-axo-block/resources/js/index.js
This commit is contained in:
commit
50711fb37d
47 changed files with 924 additions and 748 deletions
|
@ -5,10 +5,8 @@
|
|||
* @package WooCommerce\PayPalCommerce\AxoBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\AxoBlock;
|
||||
|
||||
|
||||
return array(
|
||||
);
|
||||
return array();
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
* @package WooCommerce\PayPalCommerce\AxoBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\AxoBlock;
|
||||
|
||||
return static function (): AxoBlockModule {
|
||||
return static function () : AxoBlockModule {
|
||||
return new AxoBlockModule();
|
||||
};
|
||||
|
|
|
@ -1,91 +1,102 @@
|
|||
#ppcp-axo-block-radio-label {
|
||||
// Variables
|
||||
$border-color: hsla(0, 0%, 7%, 0.11);
|
||||
$transition-duration: 0.3s;
|
||||
$fast-transition-duration: 0.5s;
|
||||
|
||||
// Mixins
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@mixin flex-space-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// 1. AXO Block Radio Label
|
||||
#ppcp-axo-block-radio-label {
|
||||
@include flex-space-between;
|
||||
width: 100%;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
// 2. AXO Block Card
|
||||
.wc-block-checkout-axo-block-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@include flex-center;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.wc-block-checkout-axo-block-card__inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-width: 300px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wc-block-checkout-axo-block-card__content {
|
||||
box-sizing: border-box;
|
||||
aspect-ratio: 1.586;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
border: 1px solid hsla(0,0%,7%,.11);
|
||||
font-size: .875em;
|
||||
font-family: monospace;
|
||||
padding: 1em;
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1em;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wc-block-checkout-axo-block-card__meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wc-block-checkout-axo-block-card__meta-digits {
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.wc-block-checkout-axo-block-card__watermark {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.wc-block-checkout-axo-block-card__edit {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-family: inherit;
|
||||
margin: 0 0 0 auto;
|
||||
font-size: .875em;
|
||||
font-weight: normal;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
&__inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-width: 300px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-axo-block-card__meta:last-child {
|
||||
align-self: flex-end;
|
||||
&__content {
|
||||
box-sizing: border-box;
|
||||
aspect-ratio: 1.586;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
border: 1px solid $border-color;
|
||||
font-size: 0.875em;
|
||||
font-family: monospace;
|
||||
padding: 1em;
|
||||
margin: 1em 0;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__meta {
|
||||
@include flex-space-between;
|
||||
width: 100%;
|
||||
|
||||
&-digits {
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
align-self: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
&__watermark {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
&__edit {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-family: inherit;
|
||||
margin: 0 0 0 auto;
|
||||
font-size: 0.875em;
|
||||
font-weight: normal;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-axo-block-card__meta-icon {
|
||||
max-height: 25px;
|
||||
}
|
||||
|
||||
// 3. Express Payment Block
|
||||
.wp-block-woocommerce-checkout-express-payment-block {
|
||||
transition: opacity .3s ease-in,
|
||||
scale .3s ease-in,
|
||||
display .3s ease-in;
|
||||
/* key to transitioning out */
|
||||
transition: opacity $transition-duration ease-in,
|
||||
scale $transition-duration ease-in,
|
||||
display $transition-duration ease-in;
|
||||
transition-behavior: allow-discrete;
|
||||
|
||||
/* stage enter */
|
||||
/* key to transitioning in */
|
||||
@starting-style {
|
||||
opacity: 0;
|
||||
scale: 1.1;
|
||||
|
@ -93,80 +104,85 @@
|
|||
|
||||
&.wc-block-axo-is-authenticated {
|
||||
opacity: 0;
|
||||
scale: .9;
|
||||
|
||||
/* hidden sets display: none, but loses easily */
|
||||
scale: 0.9;
|
||||
display: none !important;
|
||||
|
||||
/* faster leaving the stage then entering */
|
||||
transition-duration: .5s;
|
||||
transition-duration: $fast-transition-duration;
|
||||
transition-timing-function: var(--ease-out-5);
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-axo-is-loaded .wc-block-components-text-input {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.wc-block-axo-is-loaded .wc-block-components-text-input {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.wc-block-checkout-axo-block-watermark-container {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
// 4. AXO Loaded State
|
||||
.wc-block-axo-is-loaded {
|
||||
// 4.1 Text Input
|
||||
.wc-block-components-text-input {
|
||||
display: flex;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
// 4.2 Hidden Fields
|
||||
&:not(.wc-block-axo-email-lookup-completed) {
|
||||
#shipping-fields,
|
||||
#billing-fields,
|
||||
#shipping-option,
|
||||
#order-notes {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 4.3 Authenticated State
|
||||
&.wc-block-axo-is-authenticated .wc-block-components-text-input {
|
||||
gap: 14px 0;
|
||||
}
|
||||
|
||||
// 4.4 Contact Information Block
|
||||
.wp-block-woocommerce-checkout-contact-information-block .wc-block-components-text-input {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"input button"
|
||||
"watermark watermark"
|
||||
"error error";
|
||||
"input button"
|
||||
"watermark watermark"
|
||||
"error error";
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 6px 8px;
|
||||
align-items: start;
|
||||
|
||||
input[type="email"] {
|
||||
grid-area: input;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
#email {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&.wc-block-axo-is-authenticated .wc-block-components-text-input {
|
||||
gap: 14px 0;
|
||||
}
|
||||
|
||||
.wc-block-components-text-input input[type="email"] {
|
||||
grid-area: input;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// 4.5 Email Submit Button
|
||||
.wc-block-axo-email-submit-button-container {
|
||||
grid-area: button;
|
||||
align-self: center;
|
||||
|
||||
.wc-block-components-button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
// 4.6 Watermark Container
|
||||
.wc-block-checkout-axo-block-watermark-container {
|
||||
grid-area: watermark;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// 4.7 Validation Error
|
||||
.wc-block-components-validation-error {
|
||||
grid-area: error;
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.wc-block-axo-email-submit-button-container .wc-block-components-button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Shipping/Card Change Link
|
||||
a.wc-block-axo-change-link {
|
||||
& {
|
||||
color: var(--wp--preset--color--secondary);
|
||||
text-decoration: underline;
|
||||
}
|
||||
color: var(--wp--preset--color--secondary);
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
|
@ -182,29 +198,36 @@ a.wc-block-axo-change-link {
|
|||
}
|
||||
}
|
||||
|
||||
// 6. Watermark Container
|
||||
.wc-block-checkout-axo-block-watermark-container {
|
||||
height: 25px;
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.wp-block-woocommerce-checkout-contact-information-block:not( .wc-block-axo-is-loaded ) .wc-block-checkout-axo-block-watermark-container {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
margin-left: 10px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.wc-block-components-spinner {
|
||||
box-sizing: content-box;
|
||||
color: inherit;
|
||||
font-size: 1em;
|
||||
height: auto;
|
||||
width: auto;
|
||||
// 7. Checkout Fields Block (AXO Not Loaded)
|
||||
.wp-block-woocommerce-checkout-fields-block:not(.wc-block-axo-is-loaded) {
|
||||
.wc-block-checkout-axo-block-watermark-container {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
margin-left: 10px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
margin-top: 12px;
|
||||
|
||||
.wc-block-components-spinner {
|
||||
box-sizing: content-box;
|
||||
color: inherit;
|
||||
font-size: 1em;
|
||||
height: auto;
|
||||
width: auto;
|
||||
position: relative;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wp-block-woocommerce-checkout-contact-information-block.wc-block-axo-is-loaded {
|
||||
// 8. AXO Loaded Contact Information Block
|
||||
.wc-block-axo-is-loaded .wp-block-woocommerce-checkout-contact-information-block {
|
||||
.wc-block-checkout-axo-block-watermark-container .wc-block-components-spinner {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
|
@ -212,19 +235,19 @@ a.wc-block-axo-change-link {
|
|||
}
|
||||
}
|
||||
|
||||
// 9. Transitions
|
||||
.wc-block-axo-email-submit-button-container,
|
||||
.wc-block-checkout-axo-block-watermark-container #fastlane-watermark-email,
|
||||
a.wc-block-axo-change-link{
|
||||
a.wc-block-axo-change-link {
|
||||
transition: opacity 0.5s ease-in-out;
|
||||
|
||||
/* stage enter */
|
||||
/* key to transitioning in */
|
||||
@starting-style {
|
||||
opacity: 0;
|
||||
scale: 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
// 10. Shipping Fields
|
||||
#shipping-fields .wc-block-components-checkout-step__heading {
|
||||
display: flex;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useMemo } from '@wordpress/element';
|
||||
import { Watermark } from '../watermark';
|
||||
import { Watermark } from '../Watermark';
|
||||
|
||||
const cardIcons = {
|
||||
VISA: 'visa-light.svg',
|
||||
|
@ -11,7 +11,7 @@ const cardIcons = {
|
|||
UNIONPAY: 'unionpay-light.svg',
|
||||
};
|
||||
|
||||
export const Card = ( { card, fastlaneSdk, showWatermark = true } ) => {
|
||||
const Card = ( { card, fastlaneSdk, showWatermark = true } ) => {
|
||||
const { brand, lastDigits, expiry, name } = card?.paymentSource?.card ?? {};
|
||||
|
||||
const cardLogo = useMemo( () => {
|
||||
|
@ -59,3 +59,5 @@ export const Card = ( { card, fastlaneSdk, showWatermark = true } ) => {
|
|||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Card;
|
|
@ -0,0 +1,18 @@
|
|||
import { createElement } from '@wordpress/element';
|
||||
|
||||
const CardChangeButton = ( { onChangeButtonClick } ) =>
|
||||
createElement(
|
||||
'a',
|
||||
{
|
||||
className:
|
||||
'wc-block-checkout-axo-block-card__edit wc-block-axo-change-link',
|
||||
role: 'button',
|
||||
onClick: ( event ) => {
|
||||
event.preventDefault();
|
||||
onChangeButtonClick();
|
||||
},
|
||||
},
|
||||
'Choose a different card'
|
||||
);
|
||||
|
||||
export default CardChangeButton;
|
|
@ -1,19 +1,5 @@
|
|||
import { createElement, useEffect, createRoot } from '@wordpress/element';
|
||||
|
||||
const CardChangeButton = ( { onChangeButtonClick } ) =>
|
||||
createElement(
|
||||
'a',
|
||||
{
|
||||
className:
|
||||
'wc-block-checkout-axo-block-card__edit wc-block-axo-change-link',
|
||||
role: 'button',
|
||||
onClick: ( event ) => {
|
||||
event.preventDefault();
|
||||
onChangeButtonClick();
|
||||
},
|
||||
},
|
||||
'Choose a different card'
|
||||
);
|
||||
import { createElement, createRoot, useEffect } from '@wordpress/element';
|
||||
import CardChangeButton from './CardChangeButton';
|
||||
|
||||
const CardChangeButtonManager = ( { onChangeButtonClick } ) => {
|
||||
useEffect( () => {
|
||||
|
@ -50,21 +36,4 @@ const CardChangeButtonManager = ( { onChangeButtonClick } ) => {
|
|||
return null;
|
||||
};
|
||||
|
||||
export const injectCardChangeButton = ( onChangeButtonClick ) => {
|
||||
const container = document.createElement( 'div' );
|
||||
document.body.appendChild( container );
|
||||
createRoot( container ).render(
|
||||
createElement( CardChangeButtonManager, { onChangeButtonClick } )
|
||||
);
|
||||
};
|
||||
|
||||
export const removeCardChangeButton = () => {
|
||||
const button = document.querySelector(
|
||||
'.wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
if ( button && button.parentNode ) {
|
||||
button.parentNode.remove();
|
||||
}
|
||||
};
|
||||
|
||||
export default CardChangeButtonManager;
|
|
@ -0,0 +1,4 @@
|
|||
export { default as Card } from './Card';
|
||||
export { default as CardChangeButton } from './CardChangeButton';
|
||||
export { default as CardChangeButtonManager } from './CardChangeButtonManager';
|
||||
export { injectCardChangeButton, removeCardChangeButton } from './utils';
|
19
modules/ppcp-axo-block/resources/js/components/Card/utils.js
Normal file
19
modules/ppcp-axo-block/resources/js/components/Card/utils.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { createElement, createRoot } from '@wordpress/element';
|
||||
import CardChangeButtonManager from './CardChangeButtonManager';
|
||||
|
||||
export const injectCardChangeButton = ( onChangeButtonClick ) => {
|
||||
const container = document.createElement( 'div' );
|
||||
document.body.appendChild( container );
|
||||
createRoot( container ).render(
|
||||
createElement( CardChangeButtonManager, { onChangeButtonClick } )
|
||||
);
|
||||
};
|
||||
|
||||
export const removeCardChangeButton = () => {
|
||||
const button = document.querySelector(
|
||||
'.wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
if ( button && button.parentNode ) {
|
||||
button.parentNode.remove();
|
||||
}
|
||||
};
|
|
@ -1,12 +1,12 @@
|
|||
import { STORE_NAME } from '../../stores/axoStore';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
|
||||
export const EmailButton = ( { handleSubmit } ) => {
|
||||
const EmailButton = ( { handleSubmit } ) => {
|
||||
const { isGuest, isAxoActive, isEmailSubmitted } = useSelect(
|
||||
( select ) => ( {
|
||||
isGuest: select( STORE_NAME ).getIsGuest(),
|
||||
isAxoActive: select( STORE_NAME ).getIsAxoActive(),
|
||||
isEmailSubmitted: select( STORE_NAME ).isEmailSubmitted(),
|
||||
isEmailSubmitted: select( STORE_NAME ).getIsEmailSubmitted(),
|
||||
} )
|
||||
);
|
||||
|
||||
|
@ -46,3 +46,5 @@ export const EmailButton = ( { handleSubmit } ) => {
|
|||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmailButton;
|
|
@ -0,0 +1,6 @@
|
|||
export { default as EmailButton } from './EmailButton';
|
||||
export {
|
||||
setupEmailFunctionality,
|
||||
removeEmailFunctionality,
|
||||
isEmailFunctionalitySetup,
|
||||
} from './utils';
|
|
@ -1,6 +1,6 @@
|
|||
import { createElement, createRoot } from '@wordpress/element';
|
||||
import { STORE_NAME } from '../../stores/axoStore';
|
||||
import { EmailButton } from './EmailButton';
|
||||
import EmailButton from './EmailButton';
|
||||
|
||||
let emailInput = null;
|
||||
let submitButtonReference = {
|
||||
|
@ -17,7 +17,7 @@ const getEmailInput = () => {
|
|||
return emailInput;
|
||||
};
|
||||
|
||||
const setupEmailFunctionality = ( onEmailSubmit ) => {
|
||||
export const setupEmailFunctionality = ( onEmailSubmit ) => {
|
||||
const input = getEmailInput();
|
||||
if ( ! input ) {
|
||||
console.warn(
|
||||
|
@ -29,7 +29,7 @@ const setupEmailFunctionality = ( onEmailSubmit ) => {
|
|||
const handleEmailSubmit = async () => {
|
||||
const isEmailSubmitted = wp.data
|
||||
.select( STORE_NAME )
|
||||
.isEmailSubmitted();
|
||||
.getIsEmailSubmitted();
|
||||
|
||||
if ( isEmailSubmitted || ! input.value ) {
|
||||
return;
|
||||
|
@ -96,7 +96,7 @@ const setupEmailFunctionality = ( onEmailSubmit ) => {
|
|||
} );
|
||||
};
|
||||
|
||||
const removeEmailFunctionality = () => {
|
||||
export const removeEmailFunctionality = () => {
|
||||
const input = getEmailInput();
|
||||
if ( input && keydownHandler ) {
|
||||
input.removeEventListener( 'keydown', keydownHandler );
|
||||
|
@ -120,12 +120,6 @@ const removeEmailFunctionality = () => {
|
|||
keydownHandler = null;
|
||||
};
|
||||
|
||||
const isEmailFunctionalitySetup = () => {
|
||||
export const isEmailFunctionalitySetup = () => {
|
||||
return !! submitButtonReference.root;
|
||||
};
|
||||
|
||||
export {
|
||||
setupEmailFunctionality,
|
||||
removeEmailFunctionality,
|
||||
isEmailFunctionalitySetup,
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import { useEffect, useCallback } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { Card } from './card/Card';
|
||||
import { STORE_NAME } from '../stores/axoStore';
|
||||
import { Card } from '../Card';
|
||||
import { STORE_NAME } from '../../stores/axoStore';
|
||||
|
||||
export const Payment = ( { fastlaneSdk, card, onPaymentLoad } ) => {
|
||||
const isGuest = useSelect( ( select ) =>
|
|
@ -1,9 +1,6 @@
|
|||
export { default as ShippingChangeButton } from './ShippingChangeButton';
|
||||
export { default as ShippingChangeButtonManager } from './ShippingChangeButtonManager';
|
||||
export {
|
||||
snapshotFields,
|
||||
restoreOriginalFields,
|
||||
populateWooFields,
|
||||
injectShippingChangeButton,
|
||||
removeShippingChangeButton,
|
||||
} from './utils';
|
|
@ -0,0 +1,32 @@
|
|||
import { createRoot } from '@wordpress/element';
|
||||
import ShippingChangeButtonManager from './ShippingChangeButtonManager';
|
||||
|
||||
export const injectShippingChangeButton = ( onChangeShippingAddressClick ) => {
|
||||
const existingButton = document.querySelector(
|
||||
'#shipping-fields .wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
|
||||
if ( ! existingButton ) {
|
||||
const container = document.createElement( 'div' );
|
||||
document.body.appendChild( container );
|
||||
createRoot( container ).render(
|
||||
<ShippingChangeButtonManager
|
||||
onChangeShippingAddressClick={ onChangeShippingAddressClick }
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
'Shipping change button already exists. Skipping injection.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const removeShippingChangeButton = () => {
|
||||
const span = document.querySelector(
|
||||
'#shipping-fields .wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
if ( span ) {
|
||||
createRoot( span ).unmount();
|
||||
span.remove();
|
||||
}
|
||||
};
|
|
@ -19,7 +19,7 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
|
|||
select( STORE_NAME ).getIsAxoActive()
|
||||
);
|
||||
const isAxoScriptLoaded = useSelect( ( select ) =>
|
||||
select( STORE_NAME ).isAxoScriptLoaded()
|
||||
select( STORE_NAME ).getIsAxoScriptLoaded()
|
||||
);
|
||||
|
||||
console.log( 'WatermarkManager state', {
|
|
@ -1,5 +1,5 @@
|
|||
import { createElement, createRoot } from '@wordpress/element';
|
||||
import { Watermark, WatermarkManager } from '../watermark';
|
||||
import { Watermark, WatermarkManager } from '../Watermark';
|
||||
|
||||
const watermarkReference = {
|
||||
container: null,
|
|
@ -1,15 +0,0 @@
|
|||
import { EmailButton } from './EmailButton';
|
||||
import {
|
||||
setupEmailFunctionality,
|
||||
removeEmailFunctionality,
|
||||
isEmailFunctionalitySetup,
|
||||
} from './utils';
|
||||
|
||||
export {
|
||||
EmailButton,
|
||||
setupEmailFunctionality,
|
||||
removeEmailFunctionality,
|
||||
isEmailFunctionalitySetup,
|
||||
};
|
||||
|
||||
export default EmailButton;
|
|
@ -1,149 +0,0 @@
|
|||
import { createRoot } from '@wordpress/element';
|
||||
import ShippingChangeButtonManager from './ShippingChangeButtonManager';
|
||||
|
||||
export const snapshotFields = ( shippingAddress, billingAddress ) => {
|
||||
console.log( 'Attempting to snapshot fields' );
|
||||
if ( ! shippingAddress || ! billingAddress ) {
|
||||
console.warn( 'Shipping or billing address is missing:', {
|
||||
shippingAddress,
|
||||
billingAddress,
|
||||
} );
|
||||
}
|
||||
|
||||
const originalData = { shippingAddress, billingAddress };
|
||||
console.log( 'Snapshot data:', originalData );
|
||||
try {
|
||||
localStorage.setItem(
|
||||
'axoOriginalCheckoutFields',
|
||||
JSON.stringify( originalData )
|
||||
);
|
||||
console.log( 'Original fields saved to localStorage', originalData );
|
||||
} catch ( error ) {
|
||||
console.error( 'Error saving to localStorage:', error );
|
||||
}
|
||||
};
|
||||
|
||||
export const restoreOriginalFields = (
|
||||
updateShippingAddress,
|
||||
updateBillingAddress
|
||||
) => {
|
||||
console.log( 'Attempting to restore original fields' );
|
||||
let savedData;
|
||||
try {
|
||||
savedData = localStorage.getItem( 'axoOriginalCheckoutFields' );
|
||||
console.log( 'Data retrieved from localStorage:', savedData );
|
||||
} catch ( error ) {
|
||||
console.error( 'Error retrieving from localStorage:', error );
|
||||
}
|
||||
|
||||
if ( savedData ) {
|
||||
try {
|
||||
const parsedData = JSON.parse( savedData );
|
||||
console.log( 'Parsed data:', parsedData );
|
||||
if ( parsedData.shippingAddress ) {
|
||||
console.log(
|
||||
'Restoring shipping address:',
|
||||
parsedData.shippingAddress
|
||||
);
|
||||
updateShippingAddress( parsedData.shippingAddress );
|
||||
} else {
|
||||
console.warn( 'No shipping address found in saved data' );
|
||||
}
|
||||
if ( parsedData.billingAddress ) {
|
||||
console.log(
|
||||
'Restoring billing address:',
|
||||
parsedData.billingAddress
|
||||
);
|
||||
updateBillingAddress( parsedData.billingAddress );
|
||||
} else {
|
||||
console.warn( 'No billing address found in saved data' );
|
||||
}
|
||||
console.log(
|
||||
'Original fields restored from localStorage',
|
||||
parsedData
|
||||
);
|
||||
} catch ( error ) {
|
||||
console.error( 'Error parsing saved data:', error );
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
'No data found in localStorage under axoOriginalCheckoutFields'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const populateWooFields = (
|
||||
profileData,
|
||||
setWooShippingAddress,
|
||||
setWooBillingAddress
|
||||
) => {
|
||||
console.log(
|
||||
'Populating WooCommerce fields with profile data:',
|
||||
profileData
|
||||
);
|
||||
|
||||
// Save shipping address
|
||||
const { address, name, phoneNumber } = profileData.shippingAddress;
|
||||
|
||||
const shippingAddress = {
|
||||
first_name: name.firstName,
|
||||
last_name: name.lastName,
|
||||
address_1: address.addressLine1,
|
||||
address_2: address.addressLine2 || '',
|
||||
city: address.adminArea2,
|
||||
state: address.adminArea1,
|
||||
postcode: address.postalCode,
|
||||
country: address.countryCode,
|
||||
phone: phoneNumber.nationalNumber,
|
||||
};
|
||||
|
||||
console.log( 'Setting WooCommerce shipping address:', shippingAddress );
|
||||
setWooShippingAddress( shippingAddress );
|
||||
|
||||
// Save billing address
|
||||
const billingData = profileData.card.paymentSource.card.billingAddress;
|
||||
|
||||
const billingAddress = {
|
||||
first_name: profileData.name.firstName,
|
||||
last_name: profileData.name.lastName,
|
||||
address_1: billingData.addressLine1,
|
||||
address_2: billingData.addressLine2 || '',
|
||||
city: billingData.adminArea2,
|
||||
state: billingData.adminArea1,
|
||||
postcode: billingData.postalCode,
|
||||
country: billingData.countryCode,
|
||||
};
|
||||
|
||||
console.log( 'Setting WooCommerce billing address:', billingAddress );
|
||||
setWooBillingAddress( billingAddress );
|
||||
};
|
||||
|
||||
export const injectShippingChangeButton = ( onChangeShippingAddressClick ) => {
|
||||
const existingButton = document.querySelector(
|
||||
'#shipping-fields .wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
|
||||
if ( ! existingButton ) {
|
||||
const container = document.createElement( 'div' );
|
||||
document.body.appendChild( container );
|
||||
createRoot( container ).render(
|
||||
<ShippingChangeButtonManager
|
||||
onChangeShippingAddressClick={ onChangeShippingAddressClick }
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
'Shipping change button already exists. Skipping injection.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const removeShippingChangeButton = () => {
|
||||
const span = document.querySelector(
|
||||
'#shipping-fields .wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
if ( span ) {
|
||||
createRoot( span ).unmount();
|
||||
span.remove();
|
||||
}
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import { populateWooFields } from '../helpers/fieldHelpers';
|
||||
import { injectShippingChangeButton } from '../components/shipping';
|
||||
import { injectCardChangeButton } from '../helpers/cardChangeButtonManager';
|
||||
import { setIsGuest } from '../stores/axoStore';
|
||||
import { injectShippingChangeButton } from '../components/Shipping';
|
||||
import { injectCardChangeButton } from '../components/Card';
|
||||
import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';
|
||||
|
||||
export const createEmailLookupHandler = (
|
||||
fastlaneSdk,
|
||||
|
@ -34,6 +34,11 @@ export const createEmailLookupHandler = (
|
|||
|
||||
console.log( 'Lookup response:', lookup );
|
||||
|
||||
// Gary flow
|
||||
if ( lookup && lookup.customerContextId === '' ) {
|
||||
setIsEmailLookupCompleted( true );
|
||||
}
|
||||
|
||||
if ( ! lookup || ! lookup.customerContextId ) {
|
||||
console.warn( 'No customerContextId found in the response' );
|
||||
return;
|
||||
|
@ -50,9 +55,13 @@ export const createEmailLookupHandler = (
|
|||
|
||||
const { authenticationState, profileData } = authResponse;
|
||||
|
||||
// OTP success/fail/cancel flow
|
||||
if ( authResponse ) {
|
||||
setIsEmailLookupCompleted( true );
|
||||
}
|
||||
|
||||
if ( authenticationState === 'succeeded' ) {
|
||||
snapshotFields( wooShippingAddress, wooBillingAddress );
|
||||
|
||||
setIsGuest( false );
|
||||
|
||||
if ( profileData && profileData.shippingAddress ) {
|
||||
|
|
|
@ -37,17 +37,49 @@ export const setupAuthenticationClassToggle = () => {
|
|||
return unsubscribe;
|
||||
};
|
||||
|
||||
export const setupEmailLookupCompletedClassToggle = () => {
|
||||
const targetSelector = '.wp-block-woocommerce-checkout-fields-block';
|
||||
const emailLookupCompletedClass = 'wc-block-axo-email-lookup-completed';
|
||||
|
||||
const updateEmailLookupCompletedClass = () => {
|
||||
const targetElement = document.querySelector( targetSelector );
|
||||
if ( ! targetElement ) {
|
||||
console.warn( `Target element not found: ${ targetSelector }` );
|
||||
return;
|
||||
}
|
||||
|
||||
const isEmailLookupCompleted =
|
||||
select( STORE_NAME ).getIsEmailLookupCompleted();
|
||||
|
||||
if ( isEmailLookupCompleted ) {
|
||||
targetElement.classList.add( emailLookupCompletedClass );
|
||||
} else {
|
||||
targetElement.classList.remove( emailLookupCompletedClass );
|
||||
}
|
||||
};
|
||||
|
||||
// Initial update
|
||||
updateEmailLookupCompletedClass();
|
||||
|
||||
// Subscribe to state changes
|
||||
const unsubscribe = subscribe( () => {
|
||||
updateEmailLookupCompletedClass();
|
||||
} );
|
||||
|
||||
return unsubscribe;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets up class toggles for the contact information block based on isAxoActive and isGuest states.
|
||||
* @return {Function} Unsubscribe function for cleanup.
|
||||
*/
|
||||
export const setupContactInfoClassToggles = () => {
|
||||
const targetSelector =
|
||||
'.wp-block-woocommerce-checkout-contact-information-block';
|
||||
export const setupCheckoutBlockClassToggles = () => {
|
||||
const targetSelector = '.wp-block-woocommerce-checkout-fields-block';
|
||||
const axoLoadedClass = 'wc-block-axo-is-loaded';
|
||||
const authClass = 'wc-block-axo-is-authenticated';
|
||||
const emailLookupCompletedClass = 'wc-block-axo-email-lookup-completed';
|
||||
|
||||
const updateContactInfoClasses = () => {
|
||||
const updateCheckoutBlockClassToggles = () => {
|
||||
const targetElement = document.querySelector( targetSelector );
|
||||
if ( ! targetElement ) {
|
||||
console.warn( `Target element not found: ${ targetSelector }` );
|
||||
|
@ -56,6 +88,8 @@ export const setupContactInfoClassToggles = () => {
|
|||
|
||||
const isAxoActive = select( STORE_NAME ).getIsAxoActive();
|
||||
const isGuest = select( STORE_NAME ).getIsGuest();
|
||||
const isEmailLookupCompleted =
|
||||
select( STORE_NAME ).getIsEmailLookupCompleted();
|
||||
|
||||
if ( isAxoActive ) {
|
||||
targetElement.classList.add( axoLoadedClass );
|
||||
|
@ -68,14 +102,20 @@ export const setupContactInfoClassToggles = () => {
|
|||
} else {
|
||||
targetElement.classList.remove( authClass );
|
||||
}
|
||||
|
||||
if ( isEmailLookupCompleted ) {
|
||||
targetElement.classList.add( emailLookupCompletedClass );
|
||||
} else {
|
||||
targetElement.classList.remove( emailLookupCompletedClass );
|
||||
}
|
||||
};
|
||||
|
||||
// Initial update
|
||||
updateContactInfoClasses();
|
||||
updateCheckoutBlockClassToggles();
|
||||
|
||||
// Subscribe to state changes
|
||||
const unsubscribe = subscribe( () => {
|
||||
updateContactInfoClasses();
|
||||
updateCheckoutBlockClassToggles();
|
||||
} );
|
||||
|
||||
return unsubscribe;
|
||||
|
@ -87,12 +127,17 @@ export const setupContactInfoClassToggles = () => {
|
|||
*/
|
||||
export const initializeClassToggles = () => {
|
||||
const unsubscribeAuth = setupAuthenticationClassToggle();
|
||||
const unsubscribeContactInfo = setupContactInfoClassToggles();
|
||||
const unsubscribeEmailLookupCompleted =
|
||||
setupEmailLookupCompletedClassToggle();
|
||||
const unsubscribeContactInfo = setupCheckoutBlockClassToggles();
|
||||
|
||||
return () => {
|
||||
if ( unsubscribeAuth ) {
|
||||
unsubscribeAuth();
|
||||
}
|
||||
if ( unsubscribeEmailLookupCompleted ) {
|
||||
unsubscribeEmailLookupCompleted();
|
||||
}
|
||||
if ( unsubscribeContactInfo ) {
|
||||
unsubscribeContactInfo();
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { dispatch } from '@wordpress/data';
|
||||
|
||||
export const snapshotFields = ( shippingAddress, billingAddress ) => {
|
||||
console.log( 'Attempting to snapshot fields' );
|
||||
if ( ! shippingAddress || ! billingAddress ) {
|
||||
|
@ -74,11 +76,16 @@ export const populateWooFields = (
|
|||
setWooShippingAddress,
|
||||
setWooBillingAddress
|
||||
) => {
|
||||
const CHECKOUT_STORE_KEY = 'wc/store/checkout';
|
||||
|
||||
console.log(
|
||||
'Populating WooCommerce fields with profile data:',
|
||||
profileData
|
||||
);
|
||||
|
||||
// Disable the 'Use same address for billing' checkbox
|
||||
dispatch( CHECKOUT_STORE_KEY ).__internalSetUseShippingAsBilling( false );
|
||||
|
||||
// Save shipping address
|
||||
const { address, name, phoneNumber } = profileData.shippingAddress;
|
||||
|
||||
|
@ -113,4 +120,7 @@ export const populateWooFields = (
|
|||
|
||||
console.log( 'Setting WooCommerce billing address:', billingAddress );
|
||||
setWooBillingAddress( billingAddress );
|
||||
|
||||
dispatch( CHECKOUT_STORE_KEY ).setEditingShippingAddress( false );
|
||||
dispatch( CHECKOUT_STORE_KEY ).setEditingBillingAddress( false );
|
||||
};
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
import { useEffect, createRoot } from '@wordpress/element';
|
||||
|
||||
const ShippingChangeButton = ( { onChangeShippingAddressClick } ) => (
|
||||
<a
|
||||
className="wc-block-axo-change-link"
|
||||
role="button"
|
||||
onClick={ ( event ) => {
|
||||
event.preventDefault();
|
||||
onChangeShippingAddressClick();
|
||||
} }
|
||||
>
|
||||
Choose a different shipping address
|
||||
</a>
|
||||
);
|
||||
|
||||
const ShippingChangeButtonManager = ( { onChangeShippingAddressClick } ) => {
|
||||
useEffect( () => {
|
||||
const shippingHeading = document.querySelector(
|
||||
'#shipping-fields .wc-block-components-checkout-step__heading'
|
||||
);
|
||||
|
||||
if (
|
||||
shippingHeading &&
|
||||
! shippingHeading.querySelector(
|
||||
'.wc-block-checkout-axo-block-card__edit'
|
||||
)
|
||||
) {
|
||||
const spanElement = document.createElement( 'span' );
|
||||
spanElement.className = 'wc-block-checkout-axo-block-card__edit';
|
||||
shippingHeading.appendChild( spanElement );
|
||||
|
||||
const root = createRoot( spanElement );
|
||||
root.render(
|
||||
<ShippingChangeButton
|
||||
onChangeShippingAddressClick={
|
||||
onChangeShippingAddressClick
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
return () => {
|
||||
root.unmount();
|
||||
spanElement.remove();
|
||||
};
|
||||
}
|
||||
}, [ onChangeShippingAddressClick ] );
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const injectShippingChangeButton = ( onChangeShippingAddressClick ) => {
|
||||
const existingButton = document.querySelector(
|
||||
'#shipping-fields .wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
|
||||
if ( ! existingButton ) {
|
||||
const container = document.createElement( 'div' );
|
||||
document.body.appendChild( container );
|
||||
createRoot( container ).render(
|
||||
<ShippingChangeButtonManager
|
||||
onChangeShippingAddressClick={ onChangeShippingAddressClick }
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
'Shipping change button already exists. Skipping injection.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const removeShippingChangeButton = () => {
|
||||
const span = document.querySelector(
|
||||
'#shipping-fields .wc-block-checkout-axo-block-card__edit'
|
||||
);
|
||||
if ( span ) {
|
||||
createRoot( span ).unmount();
|
||||
span.remove();
|
||||
}
|
||||
};
|
||||
|
||||
export default ShippingChangeButtonManager;
|
|
@ -0,0 +1,43 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
import { useDispatch, useSelect } from '@wordpress/data';
|
||||
|
||||
const CHECKOUT_STORE_KEY = 'wc/store/checkout';
|
||||
|
||||
export const useAddressEditing = () => {
|
||||
const { isEditingShippingAddress, isEditingBillingAddress } = useSelect(
|
||||
( select ) => {
|
||||
const store = select( CHECKOUT_STORE_KEY );
|
||||
return {
|
||||
isEditingShippingAddress: store.getEditingShippingAddress(),
|
||||
isEditingBillingAddress: store.getEditingBillingAddress(),
|
||||
};
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const { setEditingShippingAddress, setEditingBillingAddress } =
|
||||
useDispatch( CHECKOUT_STORE_KEY );
|
||||
|
||||
const setShippingAddressEditing = useCallback(
|
||||
( isEditing ) => {
|
||||
setEditingShippingAddress( isEditing );
|
||||
},
|
||||
[ setEditingShippingAddress ]
|
||||
);
|
||||
|
||||
const setBillingAddressEditing = useCallback(
|
||||
( isEditing ) => {
|
||||
setEditingBillingAddress( isEditing );
|
||||
},
|
||||
[ setEditingBillingAddress ]
|
||||
);
|
||||
|
||||
return {
|
||||
isEditingShippingAddress,
|
||||
isEditingBillingAddress,
|
||||
setShippingAddressEditing,
|
||||
setBillingAddressEditing,
|
||||
};
|
||||
};
|
||||
|
||||
export default useAddressEditing;
|
49
modules/ppcp-axo-block/resources/js/hooks/useAxoCleanup.js
Normal file
49
modules/ppcp-axo-block/resources/js/hooks/useAxoCleanup.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
import { useEffect } from '@wordpress/element';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { STORE_NAME } from '../stores/axoStore';
|
||||
import { removeShippingChangeButton } from '../components/Shipping';
|
||||
import { removeCardChangeButton } from '../components/Card';
|
||||
import { removeWatermark } from '../components/Watermark';
|
||||
import {
|
||||
removeEmailFunctionality,
|
||||
isEmailFunctionalitySetup,
|
||||
} from '../components/EmailButton';
|
||||
import { restoreOriginalFields } from '../helpers/fieldHelpers';
|
||||
import useCustomerData from './useCustomerData';
|
||||
|
||||
const useAxoCleanup = () => {
|
||||
const { setIsAxoActive, setIsGuest } = useDispatch( STORE_NAME );
|
||||
const {
|
||||
setShippingAddress: updateWooShippingAddress,
|
||||
setBillingAddress: updateWooBillingAddress,
|
||||
} = useCustomerData();
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Setting up cleanup for WooCommerce fields' );
|
||||
return () => {
|
||||
console.log( 'Cleaning up: Restoring WooCommerce fields' );
|
||||
restoreOriginalFields(
|
||||
updateWooShippingAddress,
|
||||
updateWooBillingAddress
|
||||
);
|
||||
};
|
||||
}, [ updateWooShippingAddress, updateWooBillingAddress ] );
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Setting up cleanup for Axo component' );
|
||||
return () => {
|
||||
console.log( 'Cleaning up Axo component' );
|
||||
setIsAxoActive( false );
|
||||
setIsGuest( true );
|
||||
removeShippingChangeButton();
|
||||
removeCardChangeButton();
|
||||
removeWatermark();
|
||||
if ( isEmailFunctionalitySetup() ) {
|
||||
console.log( 'Removing email functionality' );
|
||||
removeEmailFunctionality();
|
||||
}
|
||||
};
|
||||
}, [] );
|
||||
};
|
||||
|
||||
export default useAxoCleanup;
|
81
modules/ppcp-axo-block/resources/js/hooks/useAxoSetup.js
Normal file
81
modules/ppcp-axo-block/resources/js/hooks/useAxoSetup.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
import { useEffect } from '@wordpress/element';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { STORE_NAME } from '../stores/axoStore';
|
||||
import usePayPalScript from './usePayPalScript';
|
||||
import { setupWatermark } from '../components/Watermark';
|
||||
import { setupEmailFunctionality } from '../components/EmailButton';
|
||||
import { createEmailLookupHandler } from '../events/emailLookupManager';
|
||||
import { initializeClassToggles } from '../helpers/classnamesManager';
|
||||
import { snapshotFields } from '../helpers/fieldHelpers';
|
||||
import useCustomerData from './useCustomerData';
|
||||
import useShippingAddressChange from './useShippingAddressChange';
|
||||
|
||||
const useAxoSetup = (
|
||||
ppcpConfig,
|
||||
fastlaneSdk,
|
||||
onChangeCardButtonClick,
|
||||
setShippingAddress,
|
||||
setCard
|
||||
) => {
|
||||
const { setIsAxoActive, setIsAxoScriptLoaded } = useDispatch( STORE_NAME );
|
||||
const paypalLoaded = usePayPalScript( ppcpConfig );
|
||||
|
||||
const onChangeShippingAddressClick = useShippingAddressChange(
|
||||
fastlaneSdk,
|
||||
setShippingAddress
|
||||
);
|
||||
|
||||
const {
|
||||
shippingAddress: wooShippingAddress,
|
||||
billingAddress: wooBillingAddress,
|
||||
setShippingAddress: setWooShippingAddress,
|
||||
setBillingAddress: setWooBillingAddress,
|
||||
} = useCustomerData();
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Initializing class toggles' );
|
||||
initializeClassToggles();
|
||||
}, [] );
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Setting up Axo functionality' );
|
||||
setupWatermark( fastlaneSdk );
|
||||
if ( paypalLoaded && fastlaneSdk ) {
|
||||
console.log(
|
||||
'PayPal loaded and FastlaneSDK available, setting up email functionality'
|
||||
);
|
||||
setIsAxoScriptLoaded( true );
|
||||
setIsAxoActive( true );
|
||||
const emailLookupHandler = createEmailLookupHandler(
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
snapshotFields,
|
||||
wooShippingAddress,
|
||||
wooBillingAddress,
|
||||
setWooShippingAddress,
|
||||
setWooBillingAddress,
|
||||
onChangeShippingAddressClick,
|
||||
onChangeCardButtonClick
|
||||
);
|
||||
setupEmailFunctionality( emailLookupHandler );
|
||||
}
|
||||
}, [
|
||||
paypalLoaded,
|
||||
fastlaneSdk,
|
||||
setIsAxoActive,
|
||||
setIsAxoScriptLoaded,
|
||||
wooShippingAddress,
|
||||
wooBillingAddress,
|
||||
setWooShippingAddress,
|
||||
setWooBillingAddress,
|
||||
onChangeShippingAddressClick,
|
||||
onChangeCardButtonClick,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
] );
|
||||
|
||||
return paypalLoaded;
|
||||
};
|
||||
|
||||
export default useAxoSetup;
|
|
@ -1,7 +1,11 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
import useFastlaneSdk from "./useFastlaneSdk";
|
||||
import { useAddressEditing } from './useAddressEditing';
|
||||
import useCustomerData from './useCustomerData';
|
||||
|
||||
export const useCardChange = ( fastlaneSdk, setCard ) => {
|
||||
const { setBillingAddressEditing } = useAddressEditing();
|
||||
const { setBillingAddress: setWooBillingAddress } = useCustomerData();
|
||||
|
||||
export const useCardChange = ( fastlaneSdk, setCard, setWooBillingAddress ) => {
|
||||
return useCallback( async () => {
|
||||
if ( fastlaneSdk ) {
|
||||
const { selectionChanged, selectedCard } =
|
||||
|
@ -18,7 +22,7 @@ export const useCardChange = ( fastlaneSdk, setCard, setWooBillingAddress ) => {
|
|||
const firstName = nameParts[ 0 ];
|
||||
const lastName = nameParts.slice( 1 ).join( ' ' );
|
||||
|
||||
setWooBillingAddress( {
|
||||
const newBillingAddress = {
|
||||
first_name: firstName,
|
||||
last_name: lastName,
|
||||
address_1: billingAddress.addressLine1,
|
||||
|
@ -27,12 +31,25 @@ export const useCardChange = ( fastlaneSdk, setCard, setWooBillingAddress ) => {
|
|||
state: billingAddress.adminArea1,
|
||||
postcode: billingAddress.postalCode,
|
||||
country: billingAddress.countryCode,
|
||||
};
|
||||
|
||||
await new Promise( ( resolve ) => {
|
||||
setWooBillingAddress( newBillingAddress );
|
||||
resolve();
|
||||
} );
|
||||
|
||||
console.log( 'Billing address updated:', billingAddress );
|
||||
await new Promise( ( resolve ) => {
|
||||
setBillingAddressEditing( false );
|
||||
resolve();
|
||||
} );
|
||||
}
|
||||
}
|
||||
}, [ fastlaneSdk, setCard ] );
|
||||
}, [
|
||||
fastlaneSdk,
|
||||
setCard,
|
||||
setWooBillingAddress,
|
||||
setBillingAddressEditing,
|
||||
] );
|
||||
};
|
||||
|
||||
export default useCardChange;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { useCallback, useMemo } from '@wordpress/element';
|
||||
import { useDispatch, useSelect } from '@wordpress/data';
|
||||
import useFastlaneSdk from "./useFastlaneSdk";
|
||||
|
||||
export const useCustomerData = () => {
|
||||
const customerData = useSelect( ( select ) =>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
|
||||
const useHandlePaymentSetup = (
|
||||
emitResponse,
|
||||
card,
|
||||
paymentComponent,
|
||||
tokenizedCustomerData
|
||||
) => {
|
||||
return useCallback( async () => {
|
||||
const isRyanFlow = !! card?.id;
|
||||
let cardToken = card?.id;
|
||||
|
||||
if ( ! cardToken && paymentComponent ) {
|
||||
cardToken = await paymentComponent
|
||||
.getPaymentToken( tokenizedCustomerData )
|
||||
.then( ( response ) => response.id );
|
||||
}
|
||||
|
||||
if ( ! cardToken ) {
|
||||
return {
|
||||
type: emitResponse.responseTypes.ERROR,
|
||||
message: 'Could not process the payment (tokenization error)',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: emitResponse.responseTypes.SUCCESS,
|
||||
meta: {
|
||||
paymentMethodData: {
|
||||
fastlane_member: isRyanFlow,
|
||||
axo_nonce: cardToken,
|
||||
},
|
||||
},
|
||||
};
|
||||
}, [
|
||||
card,
|
||||
paymentComponent,
|
||||
tokenizedCustomerData,
|
||||
] );
|
||||
};
|
||||
|
||||
export default useHandlePaymentSetup;
|
20
modules/ppcp-axo-block/resources/js/hooks/usePayPalScript.js
Normal file
20
modules/ppcp-axo-block/resources/js/hooks/usePayPalScript.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { loadPaypalScript } from '../../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
|
||||
|
||||
const usePayPalScript = ( ppcpConfig ) => {
|
||||
const [ isLoaded, setIsLoaded ] = useState( false );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! isLoaded ) {
|
||||
console.log( 'Loading PayPal script' );
|
||||
loadPaypalScript( ppcpConfig, () => {
|
||||
console.log( 'PayPal script loaded' );
|
||||
setIsLoaded( true );
|
||||
} );
|
||||
}
|
||||
}, [ ppcpConfig, isLoaded ] );
|
||||
|
||||
return isLoaded;
|
||||
};
|
||||
|
||||
export default usePayPalScript;
|
27
modules/ppcp-axo-block/resources/js/hooks/usePaymentSetup.js
Normal file
27
modules/ppcp-axo-block/resources/js/hooks/usePaymentSetup.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { useEffect } from '@wordpress/element';
|
||||
|
||||
const usePaymentSetup = ( onPaymentSetup, emitResponse, card ) => {
|
||||
useEffect( () => {
|
||||
const unsubscribe = onPaymentSetup( async () => {
|
||||
return {
|
||||
type: emitResponse.responseTypes.SUCCESS,
|
||||
meta: {
|
||||
paymentMethodData: {
|
||||
axo_nonce: card?.id,
|
||||
},
|
||||
},
|
||||
};
|
||||
} );
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [
|
||||
emitResponse.responseTypes.ERROR,
|
||||
emitResponse.responseTypes.SUCCESS,
|
||||
onPaymentSetup,
|
||||
card,
|
||||
] );
|
||||
};
|
||||
|
||||
export default usePaymentSetup;
|
|
@ -0,0 +1,24 @@
|
|||
import { useEffect, useCallback } from '@wordpress/element';
|
||||
|
||||
const usePaymentSetupEffect = ( onPaymentSetup, handlePaymentSetup ) => {
|
||||
/**
|
||||
* `onPaymentSetup()` fires when we enter the "PROCESSING" state in the checkout flow.
|
||||
* It pre-processes the payment details and returns data for server-side processing.
|
||||
*/
|
||||
useEffect( () => {
|
||||
const unsubscribe = onPaymentSetup( handlePaymentSetup );
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [ onPaymentSetup, handlePaymentSetup ] );
|
||||
|
||||
const handlePaymentLoad = useCallback( ( component ) => {
|
||||
// We'll return this function instead of calling setPaymentComponent directly
|
||||
return component;
|
||||
}, [] );
|
||||
|
||||
return { handlePaymentLoad };
|
||||
};
|
||||
|
||||
export default usePaymentSetupEffect;
|
|
@ -1,24 +1,21 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
import { useAddressEditing } from './useAddressEditing';
|
||||
import useCustomerData from './useCustomerData';
|
||||
|
||||
export const useShippingAddressChange = ( fastlaneSdk, setShippingAddress ) => {
|
||||
const { setShippingAddressEditing } = useAddressEditing();
|
||||
const { setShippingAddress: setWooShippingAddress } = useCustomerData();
|
||||
|
||||
export const useShippingAddressChange = (
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setWooShippingAddress
|
||||
) => {
|
||||
return useCallback( async () => {
|
||||
if ( fastlaneSdk ) {
|
||||
const { selectionChanged, selectedAddress } =
|
||||
await fastlaneSdk.profile.showShippingAddressSelector();
|
||||
if ( selectionChanged ) {
|
||||
setShippingAddress( selectedAddress );
|
||||
console.log(
|
||||
'Selected shipping address changed:',
|
||||
selectedAddress
|
||||
);
|
||||
|
||||
const { address, name, phoneNumber } = selectedAddress;
|
||||
|
||||
setWooShippingAddress( {
|
||||
const newShippingAddress = {
|
||||
first_name: name.firstName,
|
||||
last_name: name.lastName,
|
||||
address_1: address.addressLine1,
|
||||
|
@ -28,10 +25,25 @@ export const useShippingAddressChange = (
|
|||
postcode: address.postalCode,
|
||||
country: address.countryCode,
|
||||
phone: phoneNumber.nationalNumber,
|
||||
};
|
||||
|
||||
await new Promise( ( resolve ) => {
|
||||
setWooShippingAddress( newShippingAddress );
|
||||
resolve();
|
||||
} );
|
||||
|
||||
await new Promise( ( resolve ) => {
|
||||
setShippingAddressEditing( false );
|
||||
resolve();
|
||||
} );
|
||||
}
|
||||
}
|
||||
}, [ fastlaneSdk, setShippingAddress, setWooShippingAddress ] );
|
||||
}, [
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setWooShippingAddress,
|
||||
setShippingAddressEditing,
|
||||
] );
|
||||
};
|
||||
|
||||
export default useShippingAddressChange;
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import { useMemo } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
|
||||
export const useTokenizeCustomerData = () => {
|
||||
const customerData = useSelect( ( select ) =>
|
||||
select( 'wc/store/cart' ).getCustomerData()
|
||||
);
|
||||
|
||||
const isValidAddress = ( address ) => {
|
||||
// At least one name must be present.
|
||||
if ( ! address.first_name && ! address.last_name ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Street, city, postcode, country are mandatory; state is optional.
|
||||
return (
|
||||
address.address_1 &&
|
||||
address.city &&
|
||||
address.postcode &&
|
||||
address.country
|
||||
);
|
||||
};
|
||||
|
||||
// Memoize the customer data to avoid unnecessary re-renders (and potential infinite loops).
|
||||
return useMemo( () => {
|
||||
const { billingAddress, shippingAddress } = customerData;
|
||||
|
||||
// Prefer billing address, but fallback to shipping address if billing address is not valid.
|
||||
const mainAddress = isValidAddress( billingAddress )
|
||||
? billingAddress
|
||||
: shippingAddress;
|
||||
|
||||
return {
|
||||
cardholderName: {
|
||||
fullName: `${ mainAddress.first_name } ${ mainAddress.last_name }`,
|
||||
},
|
||||
billingAddress: {
|
||||
addressLine1: mainAddress.address_1,
|
||||
addressLine2: mainAddress.address_2,
|
||||
adminArea1: mainAddress.state,
|
||||
adminArea2: mainAddress.city,
|
||||
postalCode: mainAddress.postcode,
|
||||
countryCode: mainAddress.country,
|
||||
},
|
||||
};
|
||||
}, [ customerData ] );
|
||||
};
|
||||
|
||||
export default useTokenizeCustomerData;
|
|
@ -1,39 +1,21 @@
|
|||
import { useCallback, useEffect, useState } from '@wordpress/element';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
|
||||
import { useState } from '@wordpress/element';
|
||||
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||
|
||||
import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
|
||||
|
||||
// Hooks
|
||||
import useFastlaneSdk from './hooks/useFastlaneSdk';
|
||||
import useCustomerData from './hooks/useCustomerData';
|
||||
import useShippingAddressChange from './hooks/useShippingAddressChange';
|
||||
import useTokenizeCustomerData from './hooks/useTokenizeCustomerData';
|
||||
import useCardChange from './hooks/useCardChange';
|
||||
import useAxoSetup from './hooks/useAxoSetup';
|
||||
import usePaymentSetup from './hooks/usePaymentSetup';
|
||||
import useAxoCleanup from './hooks/useAxoCleanup';
|
||||
import useHandlePaymentSetup from './hooks/useHandlePaymentSetup';
|
||||
|
||||
// Components
|
||||
import { Payment } from './components/Payment';
|
||||
import { Payment } from './components/Payment/Payment';
|
||||
import usePaymentSetupEffect from './hooks/usePaymentSetupEffect';
|
||||
|
||||
// Helpers
|
||||
import { snapshotFields, restoreOriginalFields } from './helpers/fieldHelpers';
|
||||
import { removeWatermark, setupWatermark } from './components/watermark';
|
||||
import { removeCardChangeButton } from './helpers/cardChangeButtonManager';
|
||||
import { removeShippingChangeButton } from './components/shipping';
|
||||
import { initializeClassToggles } from './helpers/classnamesManager';
|
||||
|
||||
// Stores
|
||||
import { STORE_NAME } from './stores/axoStore';
|
||||
|
||||
// Event handlers
|
||||
import { createEmailLookupHandler } from './events/emailLookupManager';
|
||||
import { usePhoneSyncHandler } from './events/phoneSyncManager';
|
||||
import {
|
||||
setupEmailFunctionality,
|
||||
removeEmailFunctionality,
|
||||
isEmailFunctionalitySetup,
|
||||
} from './components/email-button';
|
||||
|
||||
const ppcpConfig = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' );
|
||||
const gatewayHandle = 'ppcp-axo-gateway';
|
||||
const ppcpConfig = wc.wcSettings.getSetting( `${ gatewayHandle }_data` );
|
||||
|
||||
if ( typeof window.PayPalCommerceGateway === 'undefined' ) {
|
||||
window.PayPalCommerceGateway = ppcpConfig;
|
||||
|
@ -44,151 +26,37 @@ const axoConfig = window.wc_ppcp_axo;
|
|||
const Axo = ( props ) => {
|
||||
const { eventRegistration, emitResponse } = props;
|
||||
const { onPaymentSetup } = eventRegistration;
|
||||
const [ paypalLoaded, setPaypalLoaded ] = useState( false );
|
||||
const [ shippingAddress, setShippingAddress ] = useState( null );
|
||||
const [ card, setCard ] = useState( null );
|
||||
const [ wooPhone, setWooPhone ] = useState( '' );
|
||||
const [ paymentComponent, setPaymentComponent ] = useState( null );
|
||||
|
||||
const fastlaneSdk = useFastlaneSdk( axoConfig, ppcpConfig );
|
||||
|
||||
console.log( 'Axo component rendering' );
|
||||
|
||||
useEffect( () => {
|
||||
const unsubscribe = onPaymentSetup( async () => {
|
||||
// Validate payment options and emit response.
|
||||
|
||||
// Note: This response supports the Ryan flow (payment via saved card-token)
|
||||
return {
|
||||
type: emitResponse.responseTypes.SUCCESS,
|
||||
meta: {
|
||||
paymentMethodData: {
|
||||
axo_nonce: card?.id,
|
||||
},
|
||||
},
|
||||
};
|
||||
} );
|
||||
|
||||
// Unsubscribes when this component is unmounted.
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [
|
||||
emitResponse.responseTypes.ERROR,
|
||||
emitResponse.responseTypes.SUCCESS,
|
||||
onPaymentSetup,
|
||||
const tokenizedCustomerData = useTokenizeCustomerData();
|
||||
const onChangeCardButtonClick = useCardChange( fastlaneSdk, setCard );
|
||||
const handlePaymentSetup = useHandlePaymentSetup(
|
||||
emitResponse,
|
||||
card,
|
||||
] );
|
||||
|
||||
const { setIsAxoActive, setIsGuest, setIsAxoScriptLoaded } =
|
||||
useDispatch( STORE_NAME );
|
||||
|
||||
const {
|
||||
shippingAddress: wooShippingAddress,
|
||||
billingAddress: wooBillingAddress,
|
||||
setShippingAddress: updateWooShippingAddress,
|
||||
setBillingAddress: updateWooBillingAddress,
|
||||
} = useCustomerData();
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Initializing class toggles' );
|
||||
initializeClassToggles();
|
||||
}, [] );
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Setting up cleanup for WooCommerce fields' );
|
||||
return () => {
|
||||
console.log( 'Cleaning up: Restoring WooCommerce fields' );
|
||||
restoreOriginalFields(
|
||||
updateWooShippingAddress,
|
||||
updateWooBillingAddress
|
||||
);
|
||||
};
|
||||
}, [ updateWooShippingAddress, updateWooBillingAddress ] );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! paypalLoaded ) {
|
||||
console.log( 'Loading PayPal script' );
|
||||
loadPaypalScript( ppcpConfig, () => {
|
||||
console.log( 'PayPal script loaded' );
|
||||
setPaypalLoaded( true );
|
||||
} );
|
||||
}
|
||||
}, [ paypalLoaded, ppcpConfig ] );
|
||||
|
||||
const {
|
||||
setShippingAddress: setWooShippingAddress,
|
||||
setBillingAddress: setWooBillingAddress,
|
||||
} = useCustomerData();
|
||||
|
||||
const onChangeShippingAddressClick = useShippingAddressChange(
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
updateWooShippingAddress
|
||||
);
|
||||
const onChangeCardButtonClick = useCardChange(
|
||||
fastlaneSdk,
|
||||
setCard,
|
||||
updateWooBillingAddress
|
||||
paymentComponent,
|
||||
tokenizedCustomerData
|
||||
);
|
||||
|
||||
usePhoneSyncHandler( setWooPhone );
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Setting up Axo functionality' );
|
||||
setupWatermark( fastlaneSdk );
|
||||
if ( paypalLoaded && fastlaneSdk ) {
|
||||
console.log(
|
||||
'PayPal loaded and FastlaneSDK available, setting up email functionality'
|
||||
);
|
||||
setIsAxoScriptLoaded( true );
|
||||
setIsAxoActive( true );
|
||||
const emailLookupHandler = createEmailLookupHandler(
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
snapshotFields,
|
||||
wooShippingAddress,
|
||||
wooBillingAddress,
|
||||
setWooShippingAddress,
|
||||
setWooBillingAddress,
|
||||
onChangeShippingAddressClick,
|
||||
onChangeCardButtonClick
|
||||
);
|
||||
setupEmailFunctionality( emailLookupHandler );
|
||||
}
|
||||
}, [
|
||||
paypalLoaded,
|
||||
useAxoSetup(
|
||||
ppcpConfig,
|
||||
fastlaneSdk,
|
||||
setIsAxoActive,
|
||||
setIsAxoScriptLoaded,
|
||||
wooShippingAddress,
|
||||
wooBillingAddress,
|
||||
setWooShippingAddress,
|
||||
setWooBillingAddress,
|
||||
onChangeShippingAddressClick,
|
||||
onChangeCardButtonClick,
|
||||
] );
|
||||
setShippingAddress,
|
||||
setCard
|
||||
);
|
||||
usePaymentSetup( onPaymentSetup, emitResponse, card );
|
||||
|
||||
useEffect( () => {
|
||||
console.log( 'Setting up cleanup for Axo component' );
|
||||
return () => {
|
||||
console.log( 'Cleaning up Axo component' );
|
||||
setIsAxoActive( false );
|
||||
setIsGuest( true );
|
||||
removeShippingChangeButton();
|
||||
removeCardChangeButton();
|
||||
removeWatermark();
|
||||
if ( isEmailFunctionalitySetup() ) {
|
||||
console.log( 'Removing email functionality' );
|
||||
removeEmailFunctionality();
|
||||
}
|
||||
};
|
||||
}, [] );
|
||||
const { handlePaymentLoad } = usePaymentSetupEffect(
|
||||
onPaymentSetup,
|
||||
handlePaymentSetup
|
||||
);
|
||||
|
||||
const handlePaymentLoad = useCallback( ( paymentComponent ) => {
|
||||
console.log( 'Payment component loaded', paymentComponent );
|
||||
}, [] );
|
||||
useAxoCleanup();
|
||||
|
||||
const handleChange = ( selectedCard ) => {
|
||||
const handleCardChange = ( selectedCard ) => {
|
||||
console.log( 'Card selection changed', selectedCard );
|
||||
setCard( selectedCard );
|
||||
};
|
||||
|
@ -203,7 +71,7 @@ const Axo = ( props ) => {
|
|||
<Payment
|
||||
fastlaneSdk={ fastlaneSdk }
|
||||
card={ card }
|
||||
onChange={ handleChange }
|
||||
onChange={ handleCardChange }
|
||||
onPaymentLoad={ handlePaymentLoad }
|
||||
onChangeButtonClick={ onChangeCardButtonClick }
|
||||
/>
|
||||
|
@ -212,7 +80,6 @@ const Axo = ( props ) => {
|
|||
);
|
||||
};
|
||||
|
||||
// Register the payment method
|
||||
registerPaymentMethod( {
|
||||
name: ppcpConfig.id,
|
||||
label: (
|
||||
|
@ -224,15 +91,11 @@ registerPaymentMethod( {
|
|||
content: <Axo />,
|
||||
edit: <h1>This is Axo Blocks in the editor</h1>,
|
||||
ariaLabel: ppcpConfig.title,
|
||||
canMakePayment: () => {
|
||||
return true;
|
||||
},
|
||||
canMakePayment: () => true,
|
||||
supports: {
|
||||
showSavedCards: true,
|
||||
features: ppcpConfig.supports,
|
||||
},
|
||||
} );
|
||||
|
||||
console.log( 'Axo module loaded' );
|
||||
|
||||
export default Axo;
|
||||
|
|
|
@ -10,6 +10,7 @@ const DEFAULT_STATE = {
|
|||
isAxoActive: false,
|
||||
isAxoScriptLoaded: false,
|
||||
isEmailSubmitted: false,
|
||||
isEmailLookupCompleted: false,
|
||||
};
|
||||
|
||||
// Actions
|
||||
|
@ -30,6 +31,10 @@ const actions = {
|
|||
type: 'SET_IS_EMAIL_SUBMITTED',
|
||||
payload: isEmailSubmitted,
|
||||
} ),
|
||||
setIsEmailLookupCompleted: ( isEmailLookupCompleted ) => ( {
|
||||
type: 'SET_IS_EMAIL_LOOKUP_COMPLETED',
|
||||
payload: isEmailLookupCompleted,
|
||||
} ),
|
||||
};
|
||||
|
||||
// Reducer
|
||||
|
@ -43,6 +48,8 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
|
|||
return { ...state, isAxoScriptLoaded: action.payload };
|
||||
case 'SET_IS_EMAIL_SUBMITTED':
|
||||
return { ...state, isEmailSubmitted: action.payload };
|
||||
case 'SET_IS_EMAIL_LOOKUP_COMPLETED':
|
||||
return { ...state, isEmailLookupCompleted: action.payload };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -52,8 +59,9 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
|
|||
const selectors = {
|
||||
getIsGuest: ( state ) => state.isGuest,
|
||||
getIsAxoActive: ( state ) => state.isAxoActive,
|
||||
isAxoScriptLoaded: ( state ) => state.isAxoScriptLoaded,
|
||||
isEmailSubmitted: ( state ) => state.isEmailSubmitted,
|
||||
getIsAxoScriptLoaded: ( state ) => state.isAxoScriptLoaded,
|
||||
getIsEmailSubmitted: ( state ) => state.isEmailSubmitted,
|
||||
getIsEmailLookupCompleted: ( state ) => state.isEmailLookupCompleted,
|
||||
};
|
||||
|
||||
// Create and register the store
|
||||
|
@ -65,7 +73,6 @@ const store = createReduxStore( STORE_NAME, {
|
|||
|
||||
register( store );
|
||||
|
||||
// Utility functions
|
||||
export const setIsGuest = ( isGuest ) => {
|
||||
try {
|
||||
dispatch( STORE_NAME ).setIsGuest( isGuest );
|
||||
|
@ -73,3 +80,13 @@ export const setIsGuest = ( isGuest ) => {
|
|||
console.error( 'Error updating isGuest state:', error );
|
||||
}
|
||||
};
|
||||
|
||||
export const setIsEmailLookupCompleted = ( isEmailLookupCompleted ) => {
|
||||
try {
|
||||
dispatch( STORE_NAME ).setIsEmailLookupCompleted(
|
||||
isEmailLookupCompleted
|
||||
);
|
||||
} catch ( error ) {
|
||||
console.error( 'Error updating isEmailLookupCompleted state:', error );
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* @package WooCommerce\PayPalCommerce\Axo
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\AxoBlock;
|
||||
|
||||
|
@ -14,10 +14,10 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
|||
|
||||
return array(
|
||||
// If AXO Block is configured and onboarded.
|
||||
'axoblock.available' => static function ( ContainerInterface $container ): bool {
|
||||
'axoblock.available' => static function ( ContainerInterface $container ) : bool {
|
||||
return true;
|
||||
},
|
||||
'axoblock.url' => static function ( ContainerInterface $container ): string {
|
||||
'axoblock.url' => static function ( ContainerInterface $container ) : string {
|
||||
/**
|
||||
* The path cannot be false.
|
||||
*
|
||||
|
@ -28,14 +28,12 @@ return array(
|
|||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'axoblock.method' => static function( ContainerInterface $container ): AxoBlockPaymentMethod {
|
||||
'axoblock.method' => static function ( ContainerInterface $container ) : AxoBlockPaymentMethod {
|
||||
return new AxoBlockPaymentMethod(
|
||||
$container->get( 'axoblock.url' ),
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
$container->get( 'wcgateway.credit-card-gateway' ),
|
||||
function () use ( $container ): SmartButtonInterface {
|
||||
return $container->get( 'button.smart-button' );
|
||||
},
|
||||
$container->get( 'axo.gateway' ),
|
||||
fn() : SmartButtonInterface => $container->get( 'button.smart-button' ),
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'onboarding.environment' ),
|
||||
$container->get( 'wcgateway.url' )
|
||||
|
|
|
@ -5,15 +5,16 @@
|
|||
* @package WooCommerce\PayPalCommerce\AxoBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\AxoBlock;
|
||||
|
||||
use WC_Payment_Gateway;
|
||||
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||
use WooCommerce\PayPalCommerce\Axo\FrontendLoggerEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +39,7 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
|||
/**
|
||||
* Credit card gateway.
|
||||
*
|
||||
* @var CreditCardGateway
|
||||
* @var WC_Payment_Gateway
|
||||
*/
|
||||
private $gateway;
|
||||
|
||||
|
@ -73,29 +74,30 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
|||
/**
|
||||
* AdvancedCardPaymentMethod constructor.
|
||||
*
|
||||
* @param string $module_url The URL of this module.
|
||||
* @param string $version The assets version.
|
||||
* @param CreditCardGateway $gateway Credit card gateway.
|
||||
* @param SmartButtonInterface|callable $smart_button The smart button script loading handler.
|
||||
* @param Settings $settings The settings.
|
||||
* @param Environment $environment The environment object.
|
||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||
* @param string $module_url The URL of this module.
|
||||
* @param string $version The assets version.
|
||||
* @param WC_Payment_Gateway $gateway Credit card gateway.
|
||||
* @param SmartButtonInterface|callable $smart_button The smart button script loading
|
||||
* handler.
|
||||
* @param Settings $settings The settings.
|
||||
* @param Environment $environment The environment object.
|
||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
string $version,
|
||||
CreditCardGateway $gateway,
|
||||
WC_Payment_Gateway $gateway,
|
||||
$smart_button,
|
||||
Settings $settings,
|
||||
Environment $environment,
|
||||
string $wcgateway_module_url
|
||||
) {
|
||||
$this->name = CreditCardGateway::ID;
|
||||
$this->module_url = $module_url;
|
||||
$this->version = $version;
|
||||
$this->gateway = $gateway;
|
||||
$this->smart_button = $smart_button;
|
||||
$this->settings = $settings;
|
||||
$this->name = AxoGateway::ID;
|
||||
$this->module_url = $module_url;
|
||||
$this->version = $version;
|
||||
$this->gateway = $gateway;
|
||||
$this->smart_button = $smart_button;
|
||||
$this->settings = $settings;
|
||||
$this->environment = $environment;
|
||||
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||
|
||||
|
@ -110,29 +112,29 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function is_active() {
|
||||
return true;
|
||||
public function is_active() : bool {
|
||||
return $this->gateway->is_available();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_payment_method_script_handles() {
|
||||
public function get_payment_method_script_handles() : array {
|
||||
$script_path = 'assets/js/index.js';
|
||||
$script_asset_path = trailingslashit( $this->module_url ) . 'assets/js/index.asset.php';
|
||||
$script_asset = file_exists( $script_asset_path )
|
||||
? require( $script_asset_path )
|
||||
? require $script_asset_path
|
||||
: array(
|
||||
'dependencies' => array(),
|
||||
'version' => '1.0.0'
|
||||
'version' => '1.0.0',
|
||||
);
|
||||
$script_url = trailingslashit( $this->module_url ) . $script_path;
|
||||
|
||||
wp_register_script(
|
||||
'ppcp-axo-block',
|
||||
$script_url,
|
||||
$script_asset[ 'dependencies' ],
|
||||
$script_asset[ 'version' ],
|
||||
$script_asset['dependencies'],
|
||||
$script_asset['version'],
|
||||
true
|
||||
);
|
||||
|
||||
|
@ -142,19 +144,25 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
|||
$this->script_data()
|
||||
);
|
||||
|
||||
return [ 'ppcp-axo-block' ];
|
||||
return array( 'ppcp-axo-block' );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_payment_method_data() {
|
||||
return [
|
||||
'id' => $this->name,
|
||||
return array(
|
||||
'id' => $this->name,
|
||||
'title' => 'Debit & Credit Cards',
|
||||
'description' => 'Axo Description',
|
||||
'supports' => array_filter( $this->gateway->supports, [ $this->gateway, 'supports' ] ),
|
||||
];
|
||||
'supports' => array_filter(
|
||||
$this->gateway->supports,
|
||||
array(
|
||||
$this->gateway,
|
||||
'supports',
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,8 +170,11 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
private function script_data(): array
|
||||
{ if(is_admin()) { return array(); }
|
||||
private function script_data() : array {
|
||||
if ( is_admin() ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return array(
|
||||
'environment' => array(
|
||||
'is_sandbox' => $this->environment->current_environment() === 'sandbox',
|
||||
|
@ -175,14 +186,14 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
|||
'enabled' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
||||
'client_id' => ( $this->settings->has( 'client_id' ) ? $this->settings->get( 'client_id' ) : null ),
|
||||
'session_id' =>
|
||||
(WC()->session && method_exists(WC()->session, 'get_customer_unique_id'))
|
||||
? substr(md5(WC()->session->get_customer_unique_id()), 0, 16)
|
||||
( WC()->session && method_exists( WC()->session, 'get_customer_unique_id' ) )
|
||||
? substr( md5( WC()->session->get_customer_unique_id() ), 0, 16 )
|
||||
: '',
|
||||
'amount' => array(
|
||||
'amount' => array(
|
||||
'currency_code' => get_woocommerce_currency(),
|
||||
'value' => (WC()->cart && method_exists(WC()->cart, 'get_total'))
|
||||
? WC()->cart->get_total('numeric')
|
||||
: null, // Set to null if WC()->cart is null or get_total doesn't exist
|
||||
'value' => ( WC()->cart && method_exists( WC()->cart, 'get_total' ) )
|
||||
? WC()->cart->get_total( 'numeric' )
|
||||
: null, // Set to null if WC()->cart is null or get_total doesn't exist.
|
||||
),
|
||||
),
|
||||
'style_options' => array(
|
||||
|
@ -224,5 +235,4 @@ class AxoBlockPaymentMethod extends AbstractPaymentMethodType {
|
|||
'billing_email_button_text' => __( 'Continue', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ return array(
|
|||
$container->get( 'wcgateway.settings.render' ),
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'wcgateway.url' ),
|
||||
$container->get( 'session.handler' ),
|
||||
$container->get( 'wcgateway.order-processor' ),
|
||||
$container->get( 'axo.card_icons' ),
|
||||
$container->get( 'axo.card_icons.axo' ),
|
||||
|
|
|
@ -28,6 +28,8 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WC_Payment_Gateways;
|
||||
|
||||
/**
|
||||
* Class AxoModule
|
||||
*/
|
||||
|
@ -130,6 +132,23 @@ class AxoModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
|||
}
|
||||
);
|
||||
|
||||
// Enforce Fastlane to always be the first payment method in the list.
|
||||
add_action(
|
||||
'wc_payment_gateways_initialized',
|
||||
function ( WC_Payment_Gateways $gateways ) {
|
||||
if ( is_admin() ) {
|
||||
return;
|
||||
}
|
||||
foreach ( $gateways->payment_gateways as $key => $gateway ) {
|
||||
if ( $gateway->id === AxoGateway::ID ) {
|
||||
unset( $gateways->payment_gateways[ $key ] );
|
||||
array_unshift( $gateways->payment_gateways, $gateway );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Force 'cart-block' and 'cart' Smart Button locations in the settings.
|
||||
add_action(
|
||||
'admin_init',
|
||||
|
|
|
@ -5,20 +5,20 @@
|
|||
* @package WooCommerce\PayPalCommerce\WcGateway\Gateway
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo\Gateway;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Exception;
|
||||
use WC_Order;
|
||||
use WC_Payment_Gateway;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\GatewaySettingsRendererTrait;
|
||||
|
@ -26,12 +26,15 @@ use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\ProcessPaymentTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
|
||||
/**
|
||||
* Class AXOGateway.
|
||||
*/
|
||||
class AxoGateway extends WC_Payment_Gateway {
|
||||
use OrderMetaTrait, GatewaySettingsRendererTrait;
|
||||
use OrderMetaTrait, GatewaySettingsRendererTrait, ProcessPaymentTrait;
|
||||
|
||||
const ID = 'ppcp-axo-gateway';
|
||||
|
||||
|
@ -119,26 +122,35 @@ class AxoGateway extends WC_Payment_Gateway {
|
|||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* The Session Handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
protected $session_handler;
|
||||
|
||||
/**
|
||||
* AXOGateway constructor.
|
||||
*
|
||||
* @param SettingsRenderer $settings_renderer The settings renderer.
|
||||
* @param ContainerInterface $ppcp_settings The settings.
|
||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||
* @param OrderProcessor $order_processor The Order processor.
|
||||
* @param array $card_icons The card icons.
|
||||
* @param array $card_icons_axo The card icons.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
|
||||
* @param ShippingPreferenceFactory $shipping_preference_factory The shipping preference factory.
|
||||
* @param TransactionUrlProvider $transaction_url_provider The transaction url provider.
|
||||
* @param Environment $environment The environment.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param SettingsRenderer $settings_renderer The settings renderer.
|
||||
* @param ContainerInterface $ppcp_settings The settings.
|
||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||
* @param SessionHandler $session_handler The session handler.
|
||||
* @param OrderProcessor $order_processor The Order processor.
|
||||
* @param array $card_icons The card icons.
|
||||
* @param array $card_icons_axo The card icons.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
|
||||
* @param ShippingPreferenceFactory $shipping_preference_factory Shipping preference factory.
|
||||
* @param TransactionUrlProvider $transaction_url_provider The transaction url provider.
|
||||
* @param Environment $environment The environment.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
SettingsRenderer $settings_renderer,
|
||||
ContainerInterface $ppcp_settings,
|
||||
string $wcgateway_module_url,
|
||||
SessionHandler $session_handler,
|
||||
OrderProcessor $order_processor,
|
||||
array $card_icons,
|
||||
array $card_icons_axo,
|
||||
|
@ -154,6 +166,7 @@ class AxoGateway extends WC_Payment_Gateway {
|
|||
$this->settings_renderer = $settings_renderer;
|
||||
$this->ppcp_settings = $ppcp_settings;
|
||||
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->order_processor = $order_processor;
|
||||
$this->card_icons = $card_icons;
|
||||
$this->card_icons_axo = $card_icons_axo;
|
||||
|
@ -213,80 +226,83 @@ class AxoGateway extends WC_Payment_Gateway {
|
|||
* Processes the order.
|
||||
*
|
||||
* @param int $order_id The WC order ID.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function process_payment( $order_id ) {
|
||||
$wc_order = wc_get_order( $order_id );
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$fastlane_member = wc_clean( wp_unslash( $_POST['fastlane_member'] ?? '' ) );
|
||||
if ( $fastlane_member ) {
|
||||
$payment_method_title = __( 'Debit & Credit Cards (via Fastlane by PayPal)', 'woocommerce-paypal-payments' );
|
||||
$wc_order->set_payment_method_title( $payment_method_title );
|
||||
$wc_order->save();
|
||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||
return $this->handle_payment_failure(
|
||||
null,
|
||||
new GatewayGenericException( new Exception( 'WC order was not found.' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$nonce = wc_clean( wp_unslash( $_POST['axo_nonce'] ?? '' ) );
|
||||
|
||||
try {
|
||||
$shipping_preference = $this->shipping_preference_factory->from_state(
|
||||
$purchase_unit,
|
||||
'checkout'
|
||||
);
|
||||
|
||||
$payment_source_properties = new \stdClass();
|
||||
$payment_source_properties->single_use_token = $nonce;
|
||||
|
||||
$payment_source = new PaymentSource(
|
||||
'card',
|
||||
$payment_source_properties
|
||||
);
|
||||
|
||||
$order = $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$shipping_preference,
|
||||
null,
|
||||
null,
|
||||
'',
|
||||
ApplicationContext::USER_ACTION_CONTINUE,
|
||||
'',
|
||||
array(),
|
||||
$payment_source
|
||||
);
|
||||
|
||||
$this->order_processor->process_captured_and_authorized( $wc_order, $order );
|
||||
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$fastlane_member = wc_clean( wp_unslash( $_POST['fastlane_member'] ?? '' ) );
|
||||
if ( $fastlane_member ) {
|
||||
$payment_method_title = __( 'Debit & Credit Cards (via Fastlane by PayPal)', 'woocommerce-paypal-payments' );
|
||||
$wc_order->set_payment_method_title( $payment_method_title );
|
||||
$wc_order->save();
|
||||
}
|
||||
|
||||
$this->logger->error( $error );
|
||||
wc_add_notice( $error, 'error' );
|
||||
// The `axo_nonce` is not a WP nonce, but a card-token generated by the JS SDK.
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$token = wc_clean( wp_unslash( $_POST['axo_nonce'] ?? '' ) );
|
||||
|
||||
$wc_order->update_status(
|
||||
'failed',
|
||||
$error
|
||||
);
|
||||
$order = $this->create_paypal_order( $wc_order, $token );
|
||||
|
||||
return array(
|
||||
'result' => 'failure',
|
||||
'redirect' => wc_get_checkout_url(),
|
||||
);
|
||||
$this->order_processor->process_captured_and_authorized( $wc_order, $order );
|
||||
} catch ( Exception $exception ) {
|
||||
return $this->handle_payment_failure( $wc_order, $exception );
|
||||
}
|
||||
|
||||
WC()->cart->empty_cart();
|
||||
|
||||
$result = array(
|
||||
return array(
|
||||
'result' => 'success',
|
||||
'redirect' => $this->get_return_url( $wc_order ),
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
/**
|
||||
* Create a new PayPal order from the existing WC_Order instance.
|
||||
*
|
||||
* @param WC_Order $wc_order The WooCommerce order to use as a base.
|
||||
* @param string $payment_token The payment token, generated by the JS SDK.
|
||||
*
|
||||
* @return Order The PayPal order.
|
||||
*/
|
||||
protected function create_paypal_order( WC_Order $wc_order, string $payment_token ) : Order {
|
||||
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||
|
||||
$shipping_preference = $this->shipping_preference_factory->from_state(
|
||||
$purchase_unit,
|
||||
'checkout'
|
||||
);
|
||||
|
||||
$payment_source_properties = (object) array(
|
||||
'single_use_token' => $payment_token,
|
||||
);
|
||||
|
||||
$payment_source = new PaymentSource(
|
||||
'card',
|
||||
$payment_source_properties
|
||||
);
|
||||
|
||||
return $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$shipping_preference,
|
||||
null,
|
||||
null,
|
||||
'',
|
||||
ApplicationContext::USER_ACTION_CONTINUE,
|
||||
'',
|
||||
array(),
|
||||
$payment_source
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -328,7 +344,7 @@ class AxoGateway extends WC_Payment_Gateway {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_transaction_url( $order ): string {
|
||||
public function get_transaction_url( $order ) : string {
|
||||
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||
|
||||
return parent::get_transaction_url( $order );
|
||||
|
@ -362,7 +378,7 @@ class AxoGateway extends WC_Payment_Gateway {
|
|||
*
|
||||
* @return SettingsRenderer
|
||||
*/
|
||||
protected function settings_renderer(): SettingsRenderer {
|
||||
protected function settings_renderer() : SettingsRenderer {
|
||||
return $this->settings_renderer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use Exception;
|
|||
use Throwable;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
|
||||
/**
|
||||
* Trait ProcessPaymentTrait
|
||||
|
@ -74,8 +75,13 @@ trait ProcessPaymentTrait {
|
|||
* @param Throwable $exception The exception to format.
|
||||
* @return string
|
||||
*/
|
||||
protected function format_exception( Throwable $exception ): string {
|
||||
$output = $exception->getMessage() . ' ' . basename( $exception->getFile() ) . ':' . $exception->getLine();
|
||||
protected function format_exception( Throwable $exception ) : string {
|
||||
$message = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$message = $exception->get_details( $message );
|
||||
}
|
||||
|
||||
$output = $message . ' ' . basename( $exception->getFile() ) . ':' . $exception->getLine();
|
||||
$prev = $exception->getPrevious();
|
||||
if ( ! $prev ) {
|
||||
return $output;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue