Add card fields (WIP)

This commit is contained in:
Emili Castells Guasch 2023-11-10 11:20:28 +01:00
parent 4edf9c1f46
commit 692d3672c4
11 changed files with 184 additions and 2516 deletions

View file

@ -1,6 +1,5 @@
import dccInputFactory from "../Helper/DccInputFactory"; import dccInputFactory from "../Helper/DccInputFactory";
import {show} from "../Helper/Hiding"; import {show} from "../Helper/Hiding";
import Product from "../Entity/Product";
class CreditCardRenderer { class CreditCardRenderer {
@ -25,141 +24,208 @@ class CreditCardRenderer {
) { ) {
return; return;
} }
if (
typeof paypal.HostedFields === 'undefined' if (typeof paypal.HostedFields !== 'undefined' && paypal.HostedFields.isEligible()) {
|| ! paypal.HostedFields.isEligible() const buttonSelector = wrapper + ' button';
) {
const wrapperElement = document.querySelector(wrapper); if (this.currentHostedFieldsInstance) {
wrapperElement.parentNode.removeChild(wrapperElement); this.currentHostedFieldsInstance.teardown()
.catch(err => console.error(`Hosted fields teardown error: ${err}`));
this.currentHostedFieldsInstance = null;
}
const gateWayBox = document.querySelector('.payment_box.payment_method_ppcp-credit-card-gateway');
if(! gateWayBox) {
return
}
const oldDisplayStyle = gateWayBox.style.display;
gateWayBox.style.display = 'block';
const hideDccGateway = document.querySelector('#ppcp-hide-dcc');
if (hideDccGateway) {
hideDccGateway.parentNode.removeChild(hideDccGateway);
}
const cardNumberField = document.querySelector('#ppcp-credit-card-gateway-card-number');
const stylesRaw = window.getComputedStyle(cardNumberField);
let styles = {};
Object.values(stylesRaw).forEach( (prop) => {
if (! stylesRaw[prop]) {
return;
}
styles[prop] = '' + stylesRaw[prop];
});
const cardNumber = dccInputFactory(cardNumberField);
cardNumberField.parentNode.replaceChild(cardNumber, cardNumberField);
const cardExpiryField = document.querySelector('#ppcp-credit-card-gateway-card-expiry');
const cardExpiry = dccInputFactory(cardExpiryField);
cardExpiryField.parentNode.replaceChild(cardExpiry, cardExpiryField);
const cardCodeField = document.querySelector('#ppcp-credit-card-gateway-card-cvc');
const cardCode = dccInputFactory(cardCodeField);
cardCodeField.parentNode.replaceChild(cardCode, cardCodeField);
gateWayBox.style.display = oldDisplayStyle;
const formWrapper = '.payment_box payment_method_ppcp-credit-card-gateway';
if (
this.defaultConfig.enforce_vault
&& document.querySelector(formWrapper + ' .ppcp-credit-card-vault')
) {
document.querySelector(formWrapper + ' .ppcp-credit-card-vault').checked = true;
document.querySelector(formWrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true);
}
paypal.HostedFields.render({
createOrder: contextConfig.createOrder,
styles: {
'input': styles
},
fields: {
number: {
selector: '#ppcp-credit-card-gateway-card-number',
placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number,
},
cvv: {
selector: '#ppcp-credit-card-gateway-card-cvc',
placeholder: this.defaultConfig.hosted_fields.labels.cvv,
},
expirationDate: {
selector: '#ppcp-credit-card-gateway-card-expiry',
placeholder: this.defaultConfig.hosted_fields.labels.mm_yy,
}
}
}).then(hostedFields => {
document.dispatchEvent(new CustomEvent("hosted_fields_loaded"));
this.currentHostedFieldsInstance = hostedFields;
hostedFields.on('inputSubmitRequest', () => {
this._submit(contextConfig);
});
hostedFields.on('cardTypeChange', (event) => {
if ( ! event.cards.length ) {
this.cardValid = false;
return;
}
const validCards = this.defaultConfig.hosted_fields.valid_cards;
this.cardValid = validCards.indexOf(event.cards[0].type) !== -1;
const className = this._cardNumberFiledCLassNameByCardType(event.cards[0].type);
this._recreateElementClassAttribute(cardNumber, cardNumberField.className);
if (event.cards.length === 1) {
cardNumber.classList.add(className);
}
})
hostedFields.on('validityChange', (event) => {
this.formValid = Object.keys(event.fields).every(function (key) {
return event.fields[key].isValid;
});
});
hostedFields.on('empty', (event) => {
this._recreateElementClassAttribute(cardNumber, cardNumberField.className);
this.emptyFields.add(event.emittedBy);
});
hostedFields.on('notEmpty', (event) => {
this.emptyFields.delete(event.emittedBy);
});
show(buttonSelector);
if (document.querySelector(wrapper).getAttribute('data-ppcp-subscribed') !== true) {
document.querySelector(buttonSelector).addEventListener(
'click',
event => {
event.preventDefault();
this._submit(contextConfig);
}
);
document.querySelector(wrapper).setAttribute('data-ppcp-subscribed', true);
}
});
document.querySelector('#payment_method_ppcp-credit-card-gateway').addEventListener(
'click',
() => {
document.querySelector('label[for=ppcp-credit-card-gateway-card-number]').click();
}
)
return; return;
} }
const buttonSelector = wrapper + ' button'; if (typeof paypal.CardFields !== 'undefined') {
const buttonSelector = wrapper + ' button';
if (this.currentHostedFieldsInstance) { const gateWayBox = document.querySelector('.payment_box.payment_method_ppcp-credit-card-gateway');
this.currentHostedFieldsInstance.teardown() if(! gateWayBox) {
.catch(err => console.error(`Hosted fields teardown error: ${err}`)); return
this.currentHostedFieldsInstance = null;
}
const gateWayBox = document.querySelector('.payment_box.payment_method_ppcp-credit-card-gateway');
if(! gateWayBox) {
return
}
const oldDisplayStyle = gateWayBox.style.display;
gateWayBox.style.display = 'block';
const hideDccGateway = document.querySelector('#ppcp-hide-dcc');
if (hideDccGateway) {
hideDccGateway.parentNode.removeChild(hideDccGateway);
}
const cardNumberField = document.querySelector('#ppcp-credit-card-gateway-card-number');
const stylesRaw = window.getComputedStyle(cardNumberField);
let styles = {};
Object.values(stylesRaw).forEach( (prop) => {
if (! stylesRaw[prop]) {
return;
} }
styles[prop] = '' + stylesRaw[prop]; const oldDisplayStyle = gateWayBox.style.display;
}); gateWayBox.style.display = 'block';
const cardNumber = dccInputFactory(cardNumberField); const hideDccGateway = document.querySelector('#ppcp-hide-dcc');
cardNumberField.parentNode.replaceChild(cardNumber, cardNumberField); if (hideDccGateway) {
hideDccGateway.parentNode.removeChild(hideDccGateway);
const cardExpiryField = document.querySelector('#ppcp-credit-card-gateway-card-expiry');
const cardExpiry = dccInputFactory(cardExpiryField);
cardExpiryField.parentNode.replaceChild(cardExpiry, cardExpiryField);
const cardCodeField = document.querySelector('#ppcp-credit-card-gateway-card-cvc');
const cardCode = dccInputFactory(cardCodeField);
cardCodeField.parentNode.replaceChild(cardCode, cardCodeField);
gateWayBox.style.display = oldDisplayStyle;
const formWrapper = '.payment_box payment_method_ppcp-credit-card-gateway';
if (
this.defaultConfig.enforce_vault
&& document.querySelector(formWrapper + ' .ppcp-credit-card-vault')
) {
document.querySelector(formWrapper + ' .ppcp-credit-card-vault').checked = true;
document.querySelector(formWrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true);
}
paypal.HostedFields.render({
createOrder: contextConfig.createOrder,
styles: {
'input': styles
},
fields: {
number: {
selector: '#ppcp-credit-card-gateway-card-number',
placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number,
},
cvv: {
selector: '#ppcp-credit-card-gateway-card-cvc',
placeholder: this.defaultConfig.hosted_fields.labels.cvv,
},
expirationDate: {
selector: '#ppcp-credit-card-gateway-card-expiry',
placeholder: this.defaultConfig.hosted_fields.labels.mm_yy,
}
} }
}).then(hostedFields => {
document.dispatchEvent(new CustomEvent("hosted_fields_loaded"));
this.currentHostedFieldsInstance = hostedFields;
hostedFields.on('inputSubmitRequest', () => { const cardNumberField = document.querySelector('#ppcp-credit-card-gateway-card-number');
this._submit(contextConfig); const stylesRaw = window.getComputedStyle(cardNumberField);
}); let styles = {};
hostedFields.on('cardTypeChange', (event) => { Object.values(stylesRaw).forEach( (prop) => {
if ( ! event.cards.length ) { if (! stylesRaw[prop]) {
this.cardValid = false;
return; return;
} }
const validCards = this.defaultConfig.hosted_fields.valid_cards; styles[prop] = '' + stylesRaw[prop];
this.cardValid = validCards.indexOf(event.cards[0].type) !== -1; });
const cardNumber = dccInputFactory(cardNumberField);
cardNumberField.parentNode.replaceChild(cardNumber, cardNumberField);
const className = this._cardNumberFiledCLassNameByCardType(event.cards[0].type); const cardExpiryField = document.querySelector('#ppcp-credit-card-gateway-card-expiry');
this._recreateElementClassAttribute(cardNumber, cardNumberField.className); const cardExpiry = dccInputFactory(cardExpiryField);
if (event.cards.length === 1) { cardExpiryField.parentNode.replaceChild(cardExpiry, cardExpiryField);
cardNumber.classList.add(className);
const cardCodeField = document.querySelector('#ppcp-credit-card-gateway-card-cvc');
const cardCode = dccInputFactory(cardCodeField);
cardCodeField.parentNode.replaceChild(cardCode, cardCodeField);
const cardField = paypal.CardFields({
createOrder: contextConfig.createOrder,
onApprove: function (data) {
return contextConfig.onApprove(data);
},
onError: function (error) {
console.error(error)
} }
})
hostedFields.on('validityChange', (event) => {
this.formValid = Object.keys(event.fields).every(function (key) {
return event.fields[key].isValid;
});
});
hostedFields.on('empty', (event) => {
this._recreateElementClassAttribute(cardNumber, cardNumberField.className);
this.emptyFields.add(event.emittedBy);
});
hostedFields.on('notEmpty', (event) => {
this.emptyFields.delete(event.emittedBy);
}); });
if (cardField.isEligible()) {
const numberField = cardField.NumberField();
numberField.render('#ppcp-credit-card-gateway-card-number');
const cvvField = cardField.CVVField();
cvvField.render('#ppcp-credit-card-gateway-card-cvc');
const expiryField = cardField.ExpiryField();
expiryField.render('#ppcp-credit-card-gateway-card-expiry');
}
gateWayBox.style.display = oldDisplayStyle;
show(buttonSelector); show(buttonSelector);
if (document.querySelector(wrapper).getAttribute('data-ppcp-subscribed') !== true) { document.querySelector(buttonSelector).addEventListener("click", (event) => {
document.querySelector(buttonSelector).addEventListener( event.preventDefault();
'click', cardField.submit();
event => { });
event.preventDefault();
this._submit(contextConfig);
}
);
document.querySelector(wrapper).setAttribute('data-ppcp-subscribed', true); return;
} }
});
document.querySelector('#payment_method_ppcp-credit-card-gateway').addEventListener( const wrapperElement = document.querySelector(wrapper);
'click', wrapperElement.parentNode.removeChild(wrapperElement);
() => {
document.querySelector('label[for=ppcp-credit-card-gateway-card-number]').click();
}
)
} }
disableFields() { disableFields() {

View file

@ -1,14 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": "3.25.0"
}
],
[
"@babel/preset-react"
]
]
}

View file

@ -1,3 +0,0 @@
node_modules
assets/js
assets/css

View file

@ -1,34 +0,0 @@
{
"name": "ppcp-card-fields",
"version": "1.0.0",
"license": "GPL-3.0-or-later",
"browserslist": [
"> 0.5%",
"Safari >= 8",
"Chrome >= 41",
"Firefox >= 43",
"Edge >= 14"
],
"dependencies": {
"@paypal/paypal-js": "^6.0.0",
"core-js": "^3.25.0"
},
"devDependencies": {
"@babel/core": "^7.19",
"@babel/preset-env": "^7.19",
"@babel/preset-react": "^7.18.6",
"@woocommerce/dependency-extraction-webpack-plugin": "^2.2.0",
"babel-loader": "^8.2",
"cross-env": "^7.0.3",
"file-loader": "^6.2.0",
"sass": "^1.42.1",
"sass-loader": "^12.1.0",
"webpack": "^5.76",
"webpack-cli": "^4.10"
},
"scripts": {
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
"watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch",
"dev": "cross-env BABEL_ENV=default webpack --watch"
}
}

View file

@ -1,27 +0,0 @@
class CardFieldsRenderer {
render(wrapper, contextConfig) {
const cardField = paypal.CardFields({
createOrder: function (data) {},
onApprove: function (data) {},
onError: function (error) {
console.error(error)
}
});
if (cardField.isEligible()) {
const numberField = cardField.NumberField();
numberField.render('#ppcp-credit-card-gateway-card-number');
const cvvField = cardField.CVVField();
cvvField.render('#ppcp-credit-card-gateway-card-cvc');
const expiryField = cardField.ExpiryField();
expiryField.render('#ppcp-credit-card-gateway-card-expiry');
};
}
enableFields() {}
}
export default CardFieldsRenderer;

View file

@ -41,15 +41,4 @@ return array(
) )
); );
}, },
'card-fields.module.url' => static function ( ContainerInterface $container ): string {
/**
* The path cannot be false.
*
* @psalm-suppress PossiblyFalseArgument
*/
return plugins_url(
'/modules/ppcp-card-fields/',
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
);
},
); );

View file

@ -28,20 +28,6 @@ class CardFieldsModule implements ModuleInterface {
return; return;
} }
add_action(
'wp_enqueue_scripts',
function () use ( $c ) {
$module_url = $c->get( 'card-fields.module.url' );
wp_enqueue_script(
'ppcp-card-fields-boot',
untrailingslashit( $module_url ) . '/assets/js/boot.js',
array( 'jquery' ),
$c->get( 'ppcp.asset-version' ),
true
);
}
);
/** /**
* Param types removed to avoid third-party issues. * Param types removed to avoid third-party issues.
* *

View file

@ -1,38 +0,0 @@
const path = require('path');
const isProduction = process.env.NODE_ENV === 'production';
const DependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' );
module.exports = {
devtool: isProduction ? 'source-map' : 'eval-source-map',
mode: isProduction ? 'production' : 'development',
target: 'web',
plugins: [ new DependencyExtractionWebpackPlugin() ],
entry: {
'boot': path.resolve('./resources/js/boot.js'),
},
output: {
path: path.resolve(__dirname, 'assets/'),
filename: 'js/[name].js',
},
module: {
rules: [{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{
loader: 'file-loader',
options: {
name: 'css/[name].css',
}
},
{loader:'sass-loader'}
]
}]
}
};

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,6 @@
"install:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn install", "install:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn install",
"install:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn install", "install:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn install",
"install:modules:ppcp-button": "cd modules/ppcp-button && yarn install", "install:modules:ppcp-button": "cd modules/ppcp-button && yarn install",
"install:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn install",
"install:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn install", "install:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn install",
"install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install", "install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install",
"install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install", "install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install",
@ -22,7 +21,6 @@
"build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build", "build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build",
"build:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run build", "build:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run build",
"build:modules:ppcp-button": "cd modules/ppcp-button && yarn run build", "build:modules:ppcp-button": "cd modules/ppcp-button && yarn run build",
"build:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn run build",
"build:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run build", "build:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run build",
"build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build", "build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build",
"build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build", "build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build",
@ -35,7 +33,6 @@
"watch:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run watch", "watch:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run watch",
"watch:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run watch", "watch:modules:ppcp-blocks": "cd modules/ppcp-blocks && yarn run watch",
"watch:modules:ppcp-button": "cd modules/ppcp-button && yarn run watch", "watch:modules:ppcp-button": "cd modules/ppcp-button && yarn run watch",
"watch:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn run watch",
"watch:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run watch", "watch:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run watch",
"watch:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run watch", "watch:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run watch",
"watch:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run watch", "watch:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run watch",