mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 14:57:26 +08:00
Our current way of handling the checkout form via ajax does not match the WC behavior which submits them in urlencoded request instead of JSON. When it is submitted as JSON object PHP does not parse it for $_POST etc., and we do not get its handling of arrays, breaking some plugin. Now submitting the form as an urlencoded string inside JSON and parsing via `parse_str` which seems to handle it the same as $_POST. The parsing is handled in `RequestData` to avoid duplicating it in multiple places and to keep our weird sanitization here. Not sure if it's a good idea to sanitize so early, but for now keeping it like this to avoid major refactoring or introducing new vulnerabilities.
139 lines
5.5 KiB
JavaScript
139 lines
5.5 KiB
JavaScript
import 'formdata-polyfill';
|
|
import onApprove from '../OnApproveHandler/onApproveForPayNow.js';
|
|
import {payerData} from "../Helper/PayerData";
|
|
import {getCurrentPaymentMethod} from "../Helper/CheckoutMethodState";
|
|
|
|
class CheckoutActionHandler {
|
|
|
|
constructor(config, errorHandler, spinner) {
|
|
this.config = config;
|
|
this.errorHandler = errorHandler;
|
|
this.spinner = spinner;
|
|
}
|
|
|
|
subscriptionsConfiguration() {
|
|
return {
|
|
createSubscription: (data, actions) => {
|
|
return actions.subscription.create({
|
|
'plan_id': this.config.subscription_plan_id
|
|
});
|
|
},
|
|
onApprove: (data, actions) => {
|
|
fetch(this.config.ajax.approve_subscription.endpoint, {
|
|
method: 'POST',
|
|
credentials: 'same-origin',
|
|
body: JSON.stringify({
|
|
nonce: this.config.ajax.approve_subscription.nonce,
|
|
order_id: data.orderID,
|
|
subscription_id: data.subscriptionID
|
|
})
|
|
}).then((res)=>{
|
|
return res.json();
|
|
}).then((data) => {
|
|
document.querySelector('#place_order').click();
|
|
});
|
|
},
|
|
onError: (err) => {
|
|
console.error(err);
|
|
}
|
|
}
|
|
}
|
|
|
|
configuration() {
|
|
const spinner = this.spinner;
|
|
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 formSelector = this.config.context === 'checkout' ? 'form.checkout' : 'form#order_review';
|
|
const formData = new FormData(document.querySelector(formSelector));
|
|
|
|
const createaccount = jQuery('#createaccount').is(":checked") ? true : false;
|
|
|
|
const paymentMethod = getCurrentPaymentMethod();
|
|
const fundingSource = window.ppcpFundingSource;
|
|
|
|
return fetch(this.config.ajax.create_order.endpoint, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
credentials: 'same-origin',
|
|
body: JSON.stringify({
|
|
nonce: this.config.ajax.create_order.nonce,
|
|
payer,
|
|
bn_code:bnCode,
|
|
context:this.config.context,
|
|
order_id:this.config.order_id,
|
|
payment_method: paymentMethod,
|
|
funding_source: fundingSource,
|
|
// send as urlencoded string to handle complex fields via PHP functions the same as normal form submit
|
|
form_encoded: new URLSearchParams(formData).toString(),
|
|
createaccount: createaccount
|
|
})
|
|
}).then(function (res) {
|
|
return res.json();
|
|
}).then(function (data) {
|
|
if (!data.success) {
|
|
spinner.unblock();
|
|
//handle both messages sent from Woocommerce (data.messages) and this plugin (data.data.message)
|
|
if (typeof(data.messages) !== 'undefined' )
|
|
{
|
|
const domParser = new DOMParser();
|
|
errorHandler.appendPreparedErrorMessageElement(
|
|
domParser.parseFromString(data.messages, 'text/html')
|
|
.querySelector('ul')
|
|
);
|
|
} else {
|
|
errorHandler.clear();
|
|
|
|
if (data.data.refresh) {
|
|
jQuery( document.body ).trigger( 'update_checkout' );
|
|
}
|
|
|
|
if (data.data.errors?.length > 0) {
|
|
errorHandler.messages(data.data.errors);
|
|
} else if (data.data.details?.length > 0) {
|
|
errorHandler.message(data.data.details.map(d => `${d.issue} ${d.description}`).join('<br/>'));
|
|
} else {
|
|
errorHandler.message(data.data.message);
|
|
}
|
|
|
|
// fire WC event for other plugins
|
|
jQuery( document.body ).trigger( 'checkout_error' , [ errorHandler.currentHtml() ] );
|
|
}
|
|
|
|
throw {type: 'create-order-error', data: data.data};
|
|
}
|
|
const input = document.createElement('input');
|
|
input.setAttribute('type', 'hidden');
|
|
input.setAttribute('name', 'ppcp-resume-order');
|
|
input.setAttribute('value', data.data.custom_id);
|
|
document.querySelector(formSelector).appendChild(input);
|
|
return data.data.id;
|
|
});
|
|
}
|
|
return {
|
|
createOrder,
|
|
onApprove:onApprove(this, this.errorHandler, this.spinner),
|
|
onCancel: () => {
|
|
spinner.unblock();
|
|
},
|
|
onError: (err) => {
|
|
console.error(err);
|
|
spinner.unblock();
|
|
|
|
if (err && err.type === 'create-order-error') {
|
|
return;
|
|
}
|
|
|
|
this.errorHandler.genericError();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export default CheckoutActionHandler;
|