mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
init
This commit is contained in:
parent
ba97d7143d
commit
779eb31e4e
53 changed files with 8475 additions and 0 deletions
51
modules.local/ppcp-button/resources/js/button.js
Normal file
51
modules.local/ppcp-button/resources/js/button.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
import Renderer from './modules/Renderer';
|
||||
import SingleProductConfig from './modules/SingleProductConfig';
|
||||
import UpdateCart from './modules/UpdateCart';
|
||||
import ErrorHandler from './modules/ErrorHandler';
|
||||
|
||||
document.addEventListener(
|
||||
'DOMContentLoaded',
|
||||
() => {
|
||||
if (! typeof(PayPalCommerceGateway)) {
|
||||
console.error('PayPal button could not be configured.');
|
||||
return;
|
||||
}
|
||||
if (! document.querySelector(PayPalCommerceGateway.button.wrapper)) {
|
||||
console.error('No wrapper for PayPal button found.');
|
||||
return;
|
||||
}
|
||||
const context = PayPalCommerceGateway.context;
|
||||
if (context === 'product' && ! document.querySelector('form.cart') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const errorHandler = new ErrorHandler();
|
||||
const renderer = new Renderer({
|
||||
url: PayPalCommerceGateway.button.url,
|
||||
wrapper:PayPalCommerceGateway.button.wrapper
|
||||
});
|
||||
|
||||
|
||||
const updateCart = new UpdateCart(
|
||||
PayPalCommerceGateway.ajax.change_cart.endpoint,
|
||||
PayPalCommerceGateway.ajax.change_cart.nonce
|
||||
);
|
||||
let configurator = null;
|
||||
if (context === 'product') {
|
||||
configurator = new SingleProductConfig(
|
||||
PayPalCommerceGateway,
|
||||
updateCart,
|
||||
renderer.showButtons.bind(renderer),
|
||||
renderer.hideButtons.bind(renderer),
|
||||
document.querySelector('form.cart'),
|
||||
errorHandler
|
||||
);
|
||||
}
|
||||
if (! configurator) {
|
||||
console.error('No context for button found.');
|
||||
return;
|
||||
}
|
||||
renderer.render(configurator.configuration());
|
||||
|
||||
}
|
||||
);
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.observer.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
export default ButtonsToggleListener;
|
|
@ -0,0 +1,27 @@
|
|||
class ErrorHandler {
|
||||
|
||||
constructor() {
|
||||
this.wrapper = document.querySelector('.woocommerce-notices-wrapper');
|
||||
}
|
||||
|
||||
message(text) {
|
||||
this.wrapper.classList.add('woocommerce-error');
|
||||
this.wrapper.innerText = this.sanitize(text);
|
||||
}
|
||||
|
||||
sanitize(text) {
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.innerHTML = text;
|
||||
return textarea.value;
|
||||
}
|
||||
|
||||
clear() {
|
||||
if (! this.wrapper.classList.contains('woocommerce-error')) {
|
||||
return;
|
||||
}
|
||||
this.wrapper.classList.remove('woocommerce-error');
|
||||
this.wrapper.innerText = '';
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorHandler;
|
39
modules.local/ppcp-button/resources/js/modules/Renderer.js
Normal file
39
modules.local/ppcp-button/resources/js/modules/Renderer.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
class Renderer {
|
||||
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
render(buttonConfig) {
|
||||
|
||||
const script = document.createElement('script');
|
||||
|
||||
if (typeof paypal !== 'object') {
|
||||
script.setAttribute('src', this.config.url);
|
||||
script.addEventListener('load', (event) => {
|
||||
this.renderButtons(buttonConfig);
|
||||
})
|
||||
document.body.append(script);
|
||||
return;
|
||||
}
|
||||
|
||||
this.renderButtons(buttonConfig);
|
||||
}
|
||||
|
||||
renderButtons(buttonConfig) {
|
||||
|
||||
paypal.Buttons(
|
||||
buttonConfig
|
||||
).render(this.config.wrapper);
|
||||
}
|
||||
|
||||
hideButtons() {
|
||||
document.querySelector(this.config.wrapper).style.display = 'none';
|
||||
}
|
||||
|
||||
showButtons() {
|
||||
document.querySelector(this.config.wrapper).style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
export default Renderer;
|
|
@ -0,0 +1,95 @@
|
|||
import ButtonsToggleListener from "./ButtonsToggleListener";
|
||||
|
||||
class SingleProductConfig {
|
||||
|
||||
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();
|
||||
}
|
||||
const onApprove = (data, actions) => {
|
||||
return actions.redirect(this.config.redirect);
|
||||
}
|
||||
return {
|
||||
createOrder: this.createOrder(),
|
||||
onApprove,
|
||||
onError: (error) => {
|
||||
this.errorHandler.message(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createOrder() {
|
||||
const createOrder = (data, actions) => {
|
||||
this.errorHandler.clear();
|
||||
const product = document.querySelector('[name="add-to-cart"]').value;
|
||||
const qty = document.querySelector('[name="quantity"]').value;
|
||||
const variations = this.variations();
|
||||
|
||||
const onResolve = (purchase_units) => {
|
||||
return fetch(this.config.ajax.create_order.endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce:this.config.ajax.create_order.nonce,
|
||||
purchase_units
|
||||
})
|
||||
}).then(function(res) {
|
||||
return res.json();
|
||||
}).then(function(data) {
|
||||
if (! data.success) {
|
||||
//Todo: Error handling
|
||||
return;
|
||||
}
|
||||
return data.data.id;
|
||||
});
|
||||
};
|
||||
|
||||
const promise = this.updateCart.update(onResolve, product, qty, variations);
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
export default SingleProductConfig;
|
39
modules.local/ppcp-button/resources/js/modules/UpdateCart.js
Normal file
39
modules.local/ppcp-button/resources/js/modules/UpdateCart.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
class UpdateCart {
|
||||
|
||||
constructor(endpoint, nonce) {
|
||||
this.endpoint = endpoint;
|
||||
this.nonce = nonce;
|
||||
}
|
||||
|
||||
update(onResolve, product, qty, variations) {
|
||||
return new Promise( (resolve, reject) => {
|
||||
fetch(
|
||||
this.endpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
nonce: this.nonce,
|
||||
product,
|
||||
qty,
|
||||
variations
|
||||
})
|
||||
}
|
||||
).then(
|
||||
(result) => {
|
||||
return result.json();
|
||||
}
|
||||
).then( (result) => {
|
||||
if (! result.success) {
|
||||
reject(result.data);
|
||||
return;
|
||||
}
|
||||
|
||||
const resolved = onResolve(result.data);
|
||||
resolve(resolved);
|
||||
}
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default UpdateCart;
|
Loading…
Add table
Add a link
Reference in a new issue