mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
move module.local to module
This commit is contained in:
parent
c443e4053c
commit
f8e82bdfaf
217 changed files with 8 additions and 2 deletions
50
modules/ppcp-button/resources/css/hosted-fields.scss
Normal file
50
modules/ppcp-button/resources/css/hosted-fields.scss
Normal file
|
@ -0,0 +1,50 @@
|
|||
.ppcp-card-icon {
|
||||
max-width: 50px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#ppcp-hosted-fields {
|
||||
|
||||
.ppcp-dcc-credit-card-wrapper {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 55% 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr auto;
|
||||
grid-column-gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
|
||||
label, span {
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
vertical-align: bottom;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
label {
|
||||
grid-row: 1/2;
|
||||
}
|
||||
span {
|
||||
grid-row: 2/3;
|
||||
background:white;
|
||||
border: 1px #666;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
grid-row: 3/4;
|
||||
grid-column: 1/4;
|
||||
}
|
||||
|
||||
label {
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
85
modules/ppcp-button/resources/js/button.js
Normal file
85
modules/ppcp-button/resources/js/button.js
Normal file
|
@ -0,0 +1,85 @@
|
|||
import MiniCartBootstap from './modules/ContextBootstrap/MiniCartBootstap';
|
||||
import SingleProductBootstap from './modules/ContextBootstrap/SingleProductBootstap';
|
||||
import CartBootstrap from './modules/ContextBootstrap/CartBootstap';
|
||||
import CheckoutBootstap from './modules/ContextBootstrap/CheckoutBootstap';
|
||||
import Renderer from './modules/Renderer/Renderer';
|
||||
import ErrorHandler from './modules/ErrorHandler';
|
||||
import CreditCardRenderer from "./modules/Renderer/CreditCardRenderer";
|
||||
import dataClientIdAttributeHandler from "./modules/DataClientIdAttributeHandler";
|
||||
import MessageRenderer from "./modules/Renderer/MessageRenderer";
|
||||
|
||||
const bootstrap = () => {
|
||||
const errorHandler = new ErrorHandler(PayPalCommerceGateway.labels.error.generic);
|
||||
const creditCardRenderer = new CreditCardRenderer(PayPalCommerceGateway, errorHandler);
|
||||
const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway);
|
||||
const messageRenderer = new MessageRenderer(PayPalCommerceGateway.messages);
|
||||
const context = PayPalCommerceGateway.context;
|
||||
if (context === 'mini-cart' || context === 'product') {
|
||||
const miniCartBootstrap = new MiniCartBootstap(
|
||||
PayPalCommerceGateway,
|
||||
renderer
|
||||
);
|
||||
|
||||
miniCartBootstrap.init();
|
||||
}
|
||||
|
||||
if (context === 'product') {
|
||||
const singleProductBootstrap = new SingleProductBootstap(
|
||||
PayPalCommerceGateway,
|
||||
renderer,
|
||||
messageRenderer,
|
||||
);
|
||||
|
||||
singleProductBootstrap.init();
|
||||
}
|
||||
|
||||
if (context === 'cart') {
|
||||
const cartBootstrap = new CartBootstrap(
|
||||
PayPalCommerceGateway,
|
||||
renderer,
|
||||
);
|
||||
|
||||
cartBootstrap.init();
|
||||
}
|
||||
|
||||
if (context === 'checkout') {
|
||||
const checkoutBootstap = new CheckoutBootstap(
|
||||
PayPalCommerceGateway,
|
||||
renderer,
|
||||
messageRenderer
|
||||
);
|
||||
|
||||
checkoutBootstap.init();
|
||||
}
|
||||
|
||||
if (context !== 'checkout') {
|
||||
messageRenderer.render();
|
||||
}
|
||||
};
|
||||
document.addEventListener(
|
||||
'DOMContentLoaded',
|
||||
() => {
|
||||
if (!typeof (PayPalCommerceGateway)) {
|
||||
console.error('PayPal button could not be configured.');
|
||||
return;
|
||||
}
|
||||
const script = document.createElement('script');
|
||||
|
||||
script.addEventListener('load', (event) => {
|
||||
bootstrap();
|
||||
});
|
||||
script.setAttribute('src', PayPalCommerceGateway.button.url);
|
||||
Object.entries(PayPalCommerceGateway.script_attributes).forEach(
|
||||
(keyValue) => {
|
||||
script.setAttribute(keyValue[0], keyValue[1]);
|
||||
}
|
||||
);
|
||||
|
||||
if (PayPalCommerceGateway.data_client_id.set_attribute) {
|
||||
dataClientIdAttributeHandler(script, PayPalCommerceGateway.data_client_id);
|
||||
return;
|
||||
}
|
||||
|
||||
document.body.append(script);
|
||||
},
|
||||
);
|
|
@ -0,0 +1,46 @@
|
|||
import onApprove from '../OnApproveHandler/onApproveForContinue.js';
|
||||
import {payerData} from "../Helper/PayerData";
|
||||
|
||||
class CartActionHandler {
|
||||
|
||||
constructor(config, errorHandler) {
|
||||
this.config = config;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
configuration() {
|
||||
const createOrder = (data, actions) => {
|
||||
const payer = payerData();
|
||||
const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ?
|
||||
this.config.bn_codes[this.config.context] : '';
|
||||
return fetch(this.config.ajax.create_order.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.create_order.nonce,
|
||||
purchase_units: [],
|
||||
bn_code:bnCode,
|
||||
payer,
|
||||
context:this.config.context
|
||||
}),
|
||||
}).then(function(res) {
|
||||
return res.json();
|
||||
}).then(function(data) {
|
||||
if (!data.success) {
|
||||
console.error(data);
|
||||
throw Error(data.data.message);
|
||||
}
|
||||
return data.data.id;
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
createOrder,
|
||||
onApprove: onApprove(this, this.errorHandler),
|
||||
onError: (error) => {
|
||||
this.errorHandler.genericError();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default CartActionHandler;
|
|
@ -0,0 +1,55 @@
|
|||
import onApprove from '../OnApproveHandler/onApproveForPayNow.js';
|
||||
import {payerData} from "../Helper/PayerData";
|
||||
|
||||
class CheckoutActionHandler {
|
||||
|
||||
constructor(config, errorHandler) {
|
||||
this.config = config;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
configuration() {
|
||||
const createOrder = (data, actions) => {
|
||||
const payer = payerData();
|
||||
const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ?
|
||||
this.config.bn_codes[this.config.context] : '';
|
||||
|
||||
|
||||
const errorHandler = this.errorHandler;
|
||||
const formValues = jQuery('form.checkout').serialize();
|
||||
|
||||
return fetch(this.config.ajax.create_order.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.create_order.nonce,
|
||||
payer,
|
||||
bn_code:bnCode,
|
||||
context:this.config.context,
|
||||
form:formValues
|
||||
})
|
||||
}).then(function (res) {
|
||||
return res.json();
|
||||
}).then(function (data) {
|
||||
if (!data.success) {
|
||||
errorHandler.message(data.data.message, true);
|
||||
return;
|
||||
}
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('type', 'hidden');
|
||||
input.setAttribute('name', 'ppcp-resume-order');
|
||||
input.setAttribute('value', data.data.purchase_units[0].custom_id);
|
||||
document.querySelector('form.checkout').append(input);
|
||||
return data.data.id;
|
||||
});
|
||||
}
|
||||
return {
|
||||
createOrder,
|
||||
onApprove:onApprove(this, this.errorHandler),
|
||||
onError: (error) => {
|
||||
this.errorHandler.genericError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default CheckoutActionHandler;
|
|
@ -0,0 +1,133 @@
|
|||
import ButtonsToggleListener from '../Helper/ButtonsToggleListener';
|
||||
import Product from '../Entity/Product';
|
||||
import onApprove from '../OnApproveHandler/onApproveForContinue';
|
||||
import {payerData} from "../Helper/PayerData";
|
||||
|
||||
class SingleProductActionHandler {
|
||||
|
||||
constructor(
|
||||
config,
|
||||
updateCart,
|
||||
showButtonCallback,
|
||||
hideButtonCallback,
|
||||
formElement,
|
||||
errorHandler
|
||||
) {
|
||||
this.config = config;
|
||||
this.updateCart = updateCart;
|
||||
this.showButtonCallback = showButtonCallback;
|
||||
this.hideButtonCallback = hideButtonCallback;
|
||||
this.formElement = formElement;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
configuration()
|
||||
{
|
||||
|
||||
if ( this.hasVariations() ) {
|
||||
const observer = new ButtonsToggleListener(
|
||||
this.formElement.querySelector('.single_add_to_cart_button'),
|
||||
this.showButtonCallback,
|
||||
this.hideButtonCallback
|
||||
);
|
||||
observer.init();
|
||||
}
|
||||
|
||||
return {
|
||||
createOrder: this.createOrder(),
|
||||
onApprove: onApprove(this, this.errorHandler),
|
||||
onError: (error) => {
|
||||
this.errorHandler.genericError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createOrder()
|
||||
{
|
||||
var getProducts = null;
|
||||
if (! this.isGroupedProduct() ) {
|
||||
getProducts = () => {
|
||||
const id = document.querySelector('[name="add-to-cart"]').value;
|
||||
const qty = document.querySelector('[name="quantity"]').value;
|
||||
const variations = this.variations();
|
||||
return [new Product(id, qty, variations)];
|
||||
}
|
||||
} else {
|
||||
getProducts = () => {
|
||||
const products = [];
|
||||
this.formElement.querySelectorAll('input[type="number"]').forEach((element) => {
|
||||
if (! element.value) {
|
||||
return;
|
||||
}
|
||||
const elementName = element.getAttribute('name').match(/quantity\[([\d]*)\]/);
|
||||
if (elementName.length !== 2) {
|
||||
return;
|
||||
}
|
||||
const id = parseInt(elementName[1]);
|
||||
const quantity = parseInt(element.value);
|
||||
products.push(new Product(id, quantity, null));
|
||||
})
|
||||
return products;
|
||||
}
|
||||
}
|
||||
const createOrder = (data, actions) => {
|
||||
this.errorHandler.clear();
|
||||
|
||||
const onResolve = (purchase_units) => {
|
||||
const payer = payerData();
|
||||
const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ?
|
||||
this.config.bn_codes[this.config.context] : '';
|
||||
return fetch(this.config.ajax.create_order.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: this.config.ajax.create_order.nonce,
|
||||
purchase_units,
|
||||
payer,
|
||||
bn_code:bnCode,
|
||||
context:this.config.context
|
||||
})
|
||||
}).then(function (res) {
|
||||
return res.json();
|
||||
}).then(function (data) {
|
||||
if (!data.success) {
|
||||
console.error(data);
|
||||
throw Error(data.data.message);
|
||||
}
|
||||
return data.data.id;
|
||||
});
|
||||
};
|
||||
|
||||
const promise = this.updateCart.update(onResolve, getProducts());
|
||||
return promise;
|
||||
};
|
||||
return createOrder;
|
||||
}
|
||||
|
||||
variations()
|
||||
{
|
||||
|
||||
if (! this.hasVariations()) {
|
||||
return null;
|
||||
}
|
||||
const attributes = [...this.formElement.querySelectorAll("[name^='attribute_']")].map(
|
||||
(element) => {
|
||||
return {
|
||||
value:element.value,
|
||||
name:element.name
|
||||
}
|
||||
}
|
||||
);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
hasVariations()
|
||||
{
|
||||
return this.formElement.classList.contains('variations_form');
|
||||
}
|
||||
|
||||
isGroupedProduct()
|
||||
{
|
||||
return this.formElement.classList.contains('grouped_form');
|
||||
}
|
||||
}
|
||||
export default SingleProductActionHandler;
|
|
@ -0,0 +1,42 @@
|
|||
import CartActionHandler from '../ActionHandler/CartActionHandler';
|
||||
import ErrorHandler from '../ErrorHandler';
|
||||
|
||||
class CartBootstrap {
|
||||
constructor(gateway, renderer) {
|
||||
this.gateway = gateway;
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
init() {
|
||||
if (!this.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.render();
|
||||
|
||||
jQuery(document.body).on('updated_cart_totals updated_checkout', () => {
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
return document.querySelector(this.gateway.button.wrapper) !==
|
||||
null || document.querySelector(this.gateway.hosted_fields.wrapper) !==
|
||||
null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const actionHandler = new CartActionHandler(
|
||||
PayPalCommerceGateway,
|
||||
new ErrorHandler(this.gateway.labels.error.generic),
|
||||
);
|
||||
|
||||
this.renderer.render(
|
||||
this.gateway.button.wrapper,
|
||||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CartBootstrap;
|
|
@ -0,0 +1,80 @@
|
|||
import ErrorHandler from '../ErrorHandler';
|
||||
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
|
||||
|
||||
class CheckoutBootstap {
|
||||
constructor(gateway, renderer, messages) {
|
||||
this.gateway = gateway;
|
||||
this.renderer = renderer;
|
||||
this.messages = messages
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
this.render();
|
||||
|
||||
jQuery(document.body).on('updated_checkout', () => {
|
||||
this.render();
|
||||
});
|
||||
|
||||
jQuery(document.body).
|
||||
on('updated_checkout payment_method_selected', () => {
|
||||
this.switchBetweenPayPalandOrderButton();
|
||||
});
|
||||
this.switchBetweenPayPalandOrderButton();
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
if (document.querySelector(this.gateway.button.cancel_wrapper)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
if (document.querySelector(this.gateway.hosted_fields.wrapper + '>div')) {
|
||||
document.querySelector(this.gateway.hosted_fields.wrapper + '>div').setAttribute('style', '');
|
||||
}
|
||||
const actionHandler = new CheckoutActionHandler(
|
||||
PayPalCommerceGateway,
|
||||
new ErrorHandler(this.gateway.labels.error.generic),
|
||||
);
|
||||
|
||||
this.renderer.render(
|
||||
this.gateway.button.wrapper,
|
||||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
}
|
||||
|
||||
switchBetweenPayPalandOrderButton() {
|
||||
const currentPaymentMethod = jQuery(
|
||||
'input[name="payment_method"]:checked').val();
|
||||
|
||||
if (currentPaymentMethod !== 'ppcp-gateway' && currentPaymentMethod !== 'ppcp-credit-card-gateway') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
jQuery('#place_order').show();
|
||||
}
|
||||
else {
|
||||
jQuery('#place_order').hide();
|
||||
if (currentPaymentMethod === 'ppcp-gateway') {
|
||||
this.renderer.showButtons(this.gateway.button.wrapper);
|
||||
this.renderer.showButtons(this.gateway.messages.wrapper);
|
||||
this.messages.render();
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
}
|
||||
if (currentPaymentMethod === 'ppcp-credit-card-gateway') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.messages.wrapper);
|
||||
this.renderer.showButtons(this.gateway.hosted_fields.wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default CheckoutBootstap;
|
|
@ -0,0 +1,43 @@
|
|||
import ErrorHandler from '../ErrorHandler';
|
||||
import CartActionHandler from '../ActionHandler/CartActionHandler';
|
||||
|
||||
class MiniCartBootstap {
|
||||
constructor(gateway, renderer) {
|
||||
this.gateway = gateway;
|
||||
this.renderer = renderer;
|
||||
this.actionHandler = null;
|
||||
}
|
||||
|
||||
init() {
|
||||
|
||||
this.actionHandler = new CartActionHandler(
|
||||
PayPalCommerceGateway,
|
||||
new ErrorHandler(this.gateway.labels.error.generic),
|
||||
);
|
||||
this.render();
|
||||
|
||||
jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => {
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
return document.querySelector(this.gateway.button.mini_cart_wrapper) !==
|
||||
null || document.querySelector(this.gateway.hosted_fields.mini_cart_wrapper) !==
|
||||
null;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderer.render(
|
||||
this.gateway.button.mini_cart_wrapper,
|
||||
this.gateway.hosted_fields.mini_cart_wrapper,
|
||||
this.actionHandler.configuration()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MiniCartBootstap;
|
|
@ -0,0 +1,65 @@
|
|||
import ErrorHandler from '../ErrorHandler';
|
||||
import UpdateCart from "../Helper/UpdateCart";
|
||||
import SingleProductActionHandler from "../ActionHandler/SingleProductActionHandler";
|
||||
|
||||
class SingleProductBootstap {
|
||||
constructor(gateway, renderer, messages) {
|
||||
this.gateway = gateway;
|
||||
this.renderer = renderer;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
init() {
|
||||
if (!this.shouldRender()) {
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
return;
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
if (document.querySelector('form.cart') === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const actionHandler = new SingleProductActionHandler(
|
||||
this.gateway,
|
||||
new UpdateCart(
|
||||
this.gateway.ajax.change_cart.endpoint,
|
||||
this.gateway.ajax.change_cart.nonce,
|
||||
),
|
||||
() => {
|
||||
this.renderer.showButtons(this.gateway.button.wrapper);
|
||||
this.renderer.showButtons(this.gateway.hosted_fields.wrapper);
|
||||
let priceText = "0";
|
||||
if (document.querySelector('form.cart ins .woocommerce-Price-amount')) {
|
||||
priceText = document.querySelector('form.cart ins .woocommerce-Price-amount').innerText;
|
||||
}
|
||||
else if (document.querySelector('form.cart .woocommerce-Price-amount')) {
|
||||
priceText = document.querySelector('form.cart .woocommerce-Price-amount').innerText;
|
||||
}
|
||||
const amount = parseInt(priceText.replace(/([^\d,\.\s]*)/g, ''));
|
||||
this.messages.renderWithAmount(amount)
|
||||
},
|
||||
() => {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
},
|
||||
document.querySelector('form.cart'),
|
||||
new ErrorHandler(this.gateway.labels.error.generic),
|
||||
);
|
||||
|
||||
this.renderer.render(
|
||||
this.gateway.button.wrapper,
|
||||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SingleProductBootstap;
|
|
@ -0,0 +1,52 @@
|
|||
const storageKey = 'ppcp-data-client-id';
|
||||
|
||||
const validateToken = (token, user) => {
|
||||
if (! token) {
|
||||
return false;
|
||||
}
|
||||
if (token.user !== user) {
|
||||
return false;
|
||||
}
|
||||
const currentTime = new Date().getTime();
|
||||
const isExpired = currentTime >= token.expiration * 1000;
|
||||
return ! isExpired;
|
||||
}
|
||||
|
||||
const storedTokenForUser = (user) => {
|
||||
const token = JSON.parse(sessionStorage.getItem(storageKey));
|
||||
if (validateToken(token, user)) {
|
||||
return token.token;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const storeToken = (token) => {
|
||||
sessionStorage.setItem(storageKey, JSON.stringify(token));
|
||||
}
|
||||
|
||||
const dataClientIdAttributeHandler = (script, config) => {
|
||||
const token = storedTokenForUser(config.user);
|
||||
if (token) {
|
||||
script.setAttribute('data-client-token', token);
|
||||
document.body.append(script);
|
||||
return;
|
||||
}
|
||||
fetch(config.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: config.nonce
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
}).then((data)=>{
|
||||
const isValid = validateToken(data, config.user);
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
storeToken(data);
|
||||
script.setAttribute('data-client-token', data.token);
|
||||
document.body.append(script);
|
||||
});
|
||||
}
|
||||
|
||||
export default dataClientIdAttributeHandler;
|
18
modules/ppcp-button/resources/js/modules/Entity/Product.js
Normal file
18
modules/ppcp-button/resources/js/modules/Entity/Product.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
class Product {
|
||||
|
||||
constructor(id, quantity, variations) {
|
||||
this.id = id;
|
||||
this.quantity = quantity;
|
||||
this.variations = variations;
|
||||
}
|
||||
|
||||
data() {
|
||||
return {
|
||||
id:this.id,
|
||||
quantity:this.quantity,
|
||||
variations:this.variations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Product;
|
46
modules/ppcp-button/resources/js/modules/ErrorHandler.js
Normal file
46
modules/ppcp-button/resources/js/modules/ErrorHandler.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
class ErrorHandler {
|
||||
|
||||
constructor(genericErrorText)
|
||||
{
|
||||
this.genericErrorText = genericErrorText;
|
||||
this.wrapper = document.querySelector('.woocommerce-notices-wrapper');
|
||||
}
|
||||
|
||||
genericError() {
|
||||
if (this.wrapper.classList.contains('ppcp-persist')) {
|
||||
return;
|
||||
}
|
||||
this.clear();
|
||||
this.message(this.genericErrorText)
|
||||
}
|
||||
|
||||
message(text, persist = false)
|
||||
{
|
||||
this.wrapper.classList.add('woocommerce-error');
|
||||
if (persist) {
|
||||
this.wrapper.classList.add('ppcp-persist');
|
||||
} else {
|
||||
this.wrapper.classList.remove('ppcp-persist');
|
||||
}
|
||||
this.wrapper.innerText = this.sanitize(text);
|
||||
jQuery.scroll_to_notices(jQuery('.woocommerce-notices-wrapper'))
|
||||
}
|
||||
|
||||
sanitize(text)
|
||||
{
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.innerHTML = text;
|
||||
return textarea.value.replace('Error: ', '');
|
||||
}
|
||||
|
||||
clear()
|
||||
{
|
||||
if (! this.wrapper.classList.contains('woocommerce-error')) {
|
||||
return;
|
||||
}
|
||||
this.wrapper.classList.remove('woocommerce-error');
|
||||
this.wrapper.innerText = '';
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorHandler;
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* When you can't add something to the cart, the PayPal buttons should not show.
|
||||
* Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly.
|
||||
*/
|
||||
|
||||
class ButtonsToggleListener {
|
||||
constructor(element, showCallback, hideCallback)
|
||||
{
|
||||
this.element = element;
|
||||
this.showCallback = showCallback;
|
||||
this.hideCallback = hideCallback;
|
||||
this.observer = null;
|
||||
}
|
||||
|
||||
init()
|
||||
{
|
||||
const config = { attributes : true };
|
||||
const callback = () => {
|
||||
if (this.element.classList.contains('disabled')) {
|
||||
this.hideCallback();
|
||||
return;
|
||||
}
|
||||
this.showCallback();
|
||||
}
|
||||
this.observer = new MutationObserver(callback);
|
||||
this.observer.observe(this.element, config);
|
||||
callback();
|
||||
}
|
||||
|
||||
disconnect()
|
||||
{
|
||||
this.observer.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
export default ButtonsToggleListener;
|
34
modules/ppcp-button/resources/js/modules/Helper/PayerData.js
Normal file
34
modules/ppcp-button/resources/js/modules/Helper/PayerData.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
export const payerData = () => {
|
||||
const payer = PayPalCommerceGateway.payer;
|
||||
if (! payer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const phone = (document.querySelector('#billing_phone') || typeof payer.phone !== 'undefined') ?
|
||||
{
|
||||
phone_type:"HOME",
|
||||
phone_number:{
|
||||
national_number : (document.querySelector('#billing_phone')) ? document.querySelector('#billing_phone').value : payer.phone.phone_number.national_number
|
||||
}
|
||||
} : null;
|
||||
const payerData = {
|
||||
email_address:(document.querySelector('#billing_email')) ? document.querySelector('#billing_email').value : payer.email_address,
|
||||
name : {
|
||||
surname: (document.querySelector('#billing_last_name')) ? document.querySelector('#billing_last_name').value : payer.name.surname,
|
||||
given_name: (document.querySelector('#billing_first_name')) ? document.querySelector('#billing_first_name').value : payer.name.given_name
|
||||
},
|
||||
address : {
|
||||
country_code : (document.querySelector('#billing_country')) ? document.querySelector('#billing_country').value : payer.address.country_code,
|
||||
address_line_1 : (document.querySelector('#billing_address_1')) ? document.querySelector('#billing_address_1').value : payer.address.address_line_1,
|
||||
address_line_2 : (document.querySelector('#billing_address_2')) ? document.querySelector('#billing_address_2').value : payer.address.address_line_2,
|
||||
admin_area_1 : (document.querySelector('#billing_city')) ? document.querySelector('#billing_city').value : payer.address.admin_area_1,
|
||||
admin_area_2 : (document.querySelector('#billing_state')) ? document.querySelector('#billing_state').value : payer.address.admin_area_2,
|
||||
postal_code : (document.querySelector('#billing_postcode')) ? document.querySelector('#billing_postcode').value : payer.address.postal_code
|
||||
}
|
||||
};
|
||||
|
||||
if (phone) {
|
||||
payerData.phone = phone;
|
||||
}
|
||||
return payerData;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import Product from "../Entity/Product";
|
||||
class UpdateCart {
|
||||
|
||||
constructor(endpoint, nonce)
|
||||
{
|
||||
this.endpoint = endpoint;
|
||||
this.nonce = nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param onResolve
|
||||
* @param {Product[]} products
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
update(onResolve, products)
|
||||
{
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(
|
||||
this.endpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: this.nonce,
|
||||
products,
|
||||
})
|
||||
}
|
||||
).then(
|
||||
(result) => {
|
||||
return result.json();
|
||||
}
|
||||
).then((result) => {
|
||||
if (! result.success) {
|
||||
reject(result.data);
|
||||
return;
|
||||
}
|
||||
|
||||
const resolved = onResolve(result.data);
|
||||
resolve(resolved);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default UpdateCart;
|
|
@ -0,0 +1,24 @@
|
|||
const onApprove = (context, errorHandler) => {
|
||||
return (data, actions) => {
|
||||
return fetch(context.config.ajax.approve_order.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: context.config.ajax.approve_order.nonce,
|
||||
order_id:data.orderID
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
}).then((data)=>{
|
||||
if (!data.success) {
|
||||
errorHandler.genericError();
|
||||
return actions.restart().catch(err => {
|
||||
errorHandler.genericError();
|
||||
});;
|
||||
}
|
||||
location.href = context.config.redirect;
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default onApprove;
|
|
@ -0,0 +1,26 @@
|
|||
const onApprove = (context, errorHandler) => {
|
||||
return (data, actions) => {
|
||||
return fetch(context.config.ajax.approve_order.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: context.config.ajax.approve_order.nonce,
|
||||
order_id:data.orderID
|
||||
})
|
||||
}).then((res)=>{
|
||||
return res.json();
|
||||
}).then((data)=>{
|
||||
if (!data.success) {
|
||||
errorHandler.genericError();
|
||||
console.error(data);
|
||||
if (typeof actions.restart !== 'undefined') {
|
||||
return actions.restart();
|
||||
}
|
||||
throw new Error(data.data.message);
|
||||
}
|
||||
document.querySelector('#place_order').click()
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default onApprove;
|
|
@ -0,0 +1,86 @@
|
|||
class CreditCardRenderer {
|
||||
|
||||
constructor(defaultConfig, errorHandler) {
|
||||
this.defaultConfig = defaultConfig;
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
render(wrapper, contextConfig) {
|
||||
|
||||
if (
|
||||
this.defaultConfig.context !== 'checkout'
|
||||
|| wrapper === null
|
||||
|| document.querySelector(wrapper) === null
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
typeof paypal.HostedFields === 'undefined'
|
||||
|| ! paypal.HostedFields.isEligible()
|
||||
) {
|
||||
const wrapperElement = document.querySelector(wrapper);
|
||||
wrapperElement.parentNode.removeChild(wrapperElement);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.defaultConfig.enforce_vault
|
||||
&& document.querySelector(wrapper + ' .ppcp-credit-card-vault')
|
||||
) {
|
||||
document.querySelector(wrapper + ' .ppcp-credit-card-vault').checked = true;
|
||||
document.querySelector(wrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true);
|
||||
}
|
||||
paypal.HostedFields.render({
|
||||
createOrder: contextConfig.createOrder,
|
||||
fields: {
|
||||
number: {
|
||||
selector: wrapper + ' .ppcp-credit-card',
|
||||
placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number,
|
||||
},
|
||||
cvv: {
|
||||
selector: wrapper + ' .ppcp-cvv',
|
||||
placeholder: this.defaultConfig.hosted_fields.labels.cvv,
|
||||
},
|
||||
expirationDate: {
|
||||
selector: wrapper + ' .ppcp-expiration-date',
|
||||
placeholder: this.defaultConfig.hosted_fields.labels.mm_yyyy,
|
||||
}
|
||||
}
|
||||
}).then(hostedFields => {
|
||||
const submitEvent = (event) => {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
this.errorHandler.clear();
|
||||
const state = hostedFields.getState();
|
||||
const formValid = Object.keys(state.fields).every(function (key) {
|
||||
return state.fields[key].isValid;
|
||||
});
|
||||
|
||||
if (formValid) {
|
||||
|
||||
let vault = document.querySelector(wrapper + ' .ppcp-credit-card-vault') ?
|
||||
document.querySelector(wrapper + ' .ppcp-credit-card-vault').checked : false;
|
||||
vault = this.defaultConfig.enforce_vault || vault;
|
||||
|
||||
hostedFields.submit({
|
||||
contingencies: ['3D_SECURE'],
|
||||
vault
|
||||
}).then((payload) => {
|
||||
payload.orderID = payload.orderId;
|
||||
return contextConfig.onApprove(payload);
|
||||
});
|
||||
} else {
|
||||
this.errorHandler.message(this.defaultConfig.hosted_fields.labels.fields_not_valid);
|
||||
}
|
||||
}
|
||||
hostedFields.on('inputSubmitRequest', function () {
|
||||
submitEvent(null);
|
||||
});
|
||||
document.querySelector(wrapper).addEventListener(
|
||||
'submit',
|
||||
submitEvent
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
export default CreditCardRenderer;
|
|
@ -0,0 +1,49 @@
|
|||
class MessageRenderer {
|
||||
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
render() {
|
||||
if (! this.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
paypal.Messages({
|
||||
amount: this.config.amount,
|
||||
placement: this.config.placement,
|
||||
style: this.config.style
|
||||
}).render(this.config.wrapper);
|
||||
}
|
||||
|
||||
renderWithAmount(amount) {
|
||||
|
||||
if (! this.shouldRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newWrapper = document.createElement('div');
|
||||
newWrapper.setAttribute('id', this.config.wrapper.replace('#', ''));
|
||||
|
||||
const sibling = document.querySelector(this.config.wrapper).nextSibling;
|
||||
document.querySelector(this.config.wrapper).parentElement.removeChild(document.querySelector(this.config.wrapper));
|
||||
sibling.parentElement.insertBefore(newWrapper, sibling);
|
||||
paypal.Messages({
|
||||
amount,
|
||||
placement: this.config.placement,
|
||||
style: this.config.style
|
||||
}).render(this.config.wrapper);
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
|
||||
if (typeof paypal.Messages === 'undefined' || typeof this.config.wrapper === 'undefined' ) {
|
||||
return false;
|
||||
}
|
||||
if (! document.querySelector(this.config.wrapper)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
export default MessageRenderer;
|
|
@ -0,0 +1,48 @@
|
|||
class Renderer {
|
||||
constructor(creditCardRenderer, defaultConfig) {
|
||||
this.defaultConfig = defaultConfig;
|
||||
this.creditCardRenderer = creditCardRenderer;
|
||||
}
|
||||
|
||||
render(wrapper, hostedFieldsWrapper, contextConfig) {
|
||||
|
||||
this.renderButtons(wrapper, contextConfig);
|
||||
this.creditCardRenderer.render(hostedFieldsWrapper, contextConfig);
|
||||
}
|
||||
|
||||
renderButtons(wrapper, contextConfig) {
|
||||
if (! document.querySelector(wrapper) || this.isAlreadyRendered(wrapper)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const style = wrapper === this.defaultConfig.button.wrapper ? this.defaultConfig.button.style : this.defaultConfig.button.mini_cart_style;
|
||||
paypal.Buttons({
|
||||
style,
|
||||
...contextConfig,
|
||||
}).render(wrapper);
|
||||
}
|
||||
|
||||
isAlreadyRendered(wrapper) {
|
||||
return document.querySelector(wrapper).hasChildNodes();
|
||||
}
|
||||
|
||||
hideButtons(element) {
|
||||
const domElement = document.querySelector(element);
|
||||
if (! domElement ) {
|
||||
return false;
|
||||
}
|
||||
domElement.style.display = 'none';
|
||||
return true;
|
||||
}
|
||||
|
||||
showButtons(element) {
|
||||
const domElement = document.querySelector(element);
|
||||
if (! domElement ) {
|
||||
return false;
|
||||
}
|
||||
domElement.style.display = 'block';
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default Renderer;
|
Loading…
Add table
Add a link
Reference in a new issue