@salla.sa/applepay
Version:
Salla Apple Pay light
232 lines (190 loc) • 8.06 kB
JavaScript
import http from "./http";
/**
* @typedef {Object} ApplePayPaymentContact
* @property {string} phoneNumber
* @property {string} emailAddress
* @property {string} givenName
* @property {string} familyName
* @property {string} [phoneticGivenName]
* @property {string} [phoneticFamilyName]
* @property {string[]} addressLines
* @property {string} [subLocality]
* @property {string} locality
* @property {string} postalCode
* @property {string} [subAdministrativeArea]
* @property {string} administrativeArea
* @property {string} country
* @property {string} countryCode
*/
/**
*
* @param {SallaApplePay} SallaApplePay
* @param {boolean} isAuthorized
* @param {ApplePayPaymentContact} shippingContact
*
*/
export async function mutateShippingContact(SallaApplePay, shippingContact, isAuthorized = false) {
salla.logger.log('🍏 Pay: mutateShippingContact called', shippingContact, isAuthorized);
if (!SallaApplePay.detail.requiredShippingContactFields || SallaApplePay.detail.requiredShippingContactFields.length == 0) {
return;
}
if (isAuthorized) {
if (isGuestCheckout()) {
if (
!shippingContact.emailAddress ||
!shippingContact.givenName ||
!shippingContact.familyName ||
!shippingContact.phoneNumber
) {
salla.logger.warn('🍏 Pay: Guest contact fields are required', shippingContact);
const errors = [];
if (!shippingContact.emailAddress) {
errors.push(new window.ApplePayError('shippingContactInvalid', 'emailAddress', 'Email address is required'));
}
if (!shippingContact.phoneNumber) {
errors.push(new window.ApplePayError('shippingContactInvalid', 'phoneNumber', 'Phone number is required'));
}
if (!shippingContact.givenName || !shippingContact.familyName) {
errors.push(new window.ApplePayError('shippingContactInvalid', 'name', 'Name is required'));
}
SallaApplePay.session.completePayment({
status: SallaApplePay.session.STATUS_INVALID_SHIPPING_CONTACT,
errors: errors
});
return;
}
await updateGuestContact(SallaApplePay, shippingContact);
}
// if authorized and not guest checkout, do nothing address already added
return;
}
if (!SallaApplePay.detail.requiredShippingContactFields.includes('postalAddress')) {
return;
}
return http.post(
SallaApplePay.detail.shippingContactSelected.url.replace('{id}', SallaApplePay.id),
{
'country': shippingContact.country,
'city': shippingContact.locality,
'local': shippingContact.subLocality || shippingContact.administrativeArea || shippingContact.locality,
'description': shippingContact.subAdministrativeArea,
'street': shippingContact.addressLines?.join(", ") || shippingContact.administrativeArea,
'country_code': shippingContact.countryCode,
'postal_code': shippingContact.postalCode,
},
async ({ data }) => {
if (typeof SallaApplePay.detail.shippingContactSelected.onSuccess === 'function') {
SallaApplePay.detail.shippingContactSelected.onSuccess(data);
}
SallaApplePay.address_id = data.data.address_id;
SallaApplePay.shipping_methods = data.data.shipping_methods;
if (!SallaApplePay.shipping_methods || (SallaApplePay.shipping_methods && !SallaApplePay.shipping_methods.length)) {
salla.logger.warn('🍏 Pay: We dont found any supported methods', data);
SallaApplePay.session.completeShippingContactSelection({
status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
errors: [
new window.ApplePayError('addressUnserviceable')
]
});
return
}
try {
await SallaApplePay.selectApplePayShippingMethod(SallaApplePay.shipping_methods[0]);
} catch (error) {
salla.logger.warn('Failed set the shipping details to api', error);
SallaApplePay.session.completeShippingContactSelection({
status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
errors: [
new window.ApplePayError('addressUnserviceable')
]
});
return;
}
try {
await SallaApplePay.recalculateTotal();
} catch (error) {
salla.logger.warn('🍏 Pay: Failed recalculate total', error);
SallaApplePay.session.completeShippingContactSelection({
status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
errors: [
new window.ApplePayError('addressUnserviceable')
]
});
return;
}
const updatedShippingContactSelection = {
newTotal: SallaApplePay.prepareTotal(),
newLineItems: SallaApplePay.prepareLineItems(),
newShippingMethods: SallaApplePay.mappingShippingMethods(SallaApplePay.shipping_methods)
};
salla.logger.log('🍏 Pay: completeShippingContactSelection', updatedShippingContactSelection);
SallaApplePay.session.completeShippingContactSelection(updatedShippingContactSelection);
},
({ response }) => {
salla.logger.warn('🍏 Pay: Failed add address via api', response);
if (typeof SallaApplePay.detail.shippingContactSelected.onFailed === 'function') {
SallaApplePay.detail.shippingContactSelected.onFailed(response);
}
// parse 422 errors
let fields = response?.data?.error?.fields;
let errors = getApplePayErrors({
countryCode: fields?.country_code && fields.country_code.length > 0 ? fields.country_code[0] : null,
locality: fields?.city && fields.city.length > 0 ? fields.city[0] : null,
country: fields?.country && fields.country.length > 0 ? fields.country[0] : null,
});
if (errors.length === 0 && response?.data?.error?.message) {
errors.push(new window.ApplePayError('shippingContactInvalid', 'locality', response?.data?.error?.message))
}
SallaApplePay.session.completeShippingContactSelection({
newTotal: SallaApplePay.prepareTotal(),
newLineItems: SallaApplePay.prepareLineItems(),
status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
errors: errors
});
}
);
}
function isGuestCheckout() {
return salla.config.isGuest() && salla.config.get('store.features').includes('guest-checkout');
}
/**
* Update guest contact
*
* @param {SallaApplePay} SallaApplePay
* @param {ApplePayPaymentContact} shippingContact
*
*/
async function updateGuestContact(SallaApplePay, shippingContact) {
salla.logger.log('🍏 Pay: Updating guest contact', shippingContact);
return new Promise((resolve, reject) => {
http.post(
SallaApplePay.detail.guestContactSelected.url.replace('{id}', SallaApplePay.id),
{
'email': shippingContact.emailAddress || null,
'first_name': shippingContact.givenName || null,
'last_name': shippingContact.familyName || null,
'phone_number': shippingContact.phoneNumber || null,
'country_code': shippingContact.countryCode || null,
},
async ({ data }) => {
if (typeof SallaApplePay.detail.guestContactSelected?.onSuccess === 'function') {
SallaApplePay.detail.guestContactSelected.onSuccess(data);
}
resolve(data);
},
({ response }) => {
salla.logger.warn('🍏 Pay: Failed to update guest contact via api', response);
if (typeof SallaApplePay.detail.guestContactSelected?.onFailed === 'function') {
SallaApplePay.detail.guestContactSelected.onFailed(response);
}
// Reject the promise so it can be caught in onPaymentAuthorized
reject({ response });
}
);
});
}
function getApplePayErrors(fields) {
return Object.entries(fields)
.filter(([field, messages]) => messages && messages.length > 0)
.map(([field, messages]) => new window.ApplePayError('shippingContactInvalid', field, messages[0]));
}