react-native-moyasar-sdk
Version:
Official React Native Moyasar SDK - Integrate Credit Cards, Apple Pay, Samsung Pay, and STC Pay with simple interfaces for a seamless payment experience in your React Native app
176 lines (145 loc) • 8.05 kB
JavaScript
;
import { Platform } from 'react-native';
import { MODULE_SCOPING, SHIPPING_ADDRESS_CHANGE_EVENT, SHIPPING_OPTION_CHANGE_EVENT, INTERNAL_SHIPPING_ADDRESS_CHANGE_EVENT, INTERNAL_SHIPPING_OPTION_CHANGE_EVENT, USER_DISMISS_EVENT, USER_ACCEPT_EVENT, SUPPORTED_METHOD_NAME } from "./constants.js";
const noop = () => {};
import PaymentRequest from "./index.js";
import NativePayments from "../NativeBridge/index.js";
// Helpers
import { validateTotal, validateDisplayItems, validateShippingOptions, convertDetailAmountsToString } from "./helpers/index.js";
// Errors
import { DOMException } from "./errors/index.js";
export default class PaymentRequestUpdateEvent {
constructor(name, target) {
if (name !== SHIPPING_ADDRESS_CHANGE_EVENT && name !== SHIPPING_OPTION_CHANGE_EVENT) {
throw new Error(`Only "${SHIPPING_ADDRESS_CHANGE_EVENT}" and "${SHIPPING_OPTION_CHANGE_EVENT}" event listeners are supported.`);
}
this.name = name;
this.target = target;
this._waitForUpdate = false;
this._handleDetailsChange = this._handleDetailsChange.bind(this);
this._resetEvent = this._resetEvent.bind(this);
}
_handleDetailsChange(value) {
const target = this.target;
validateTotal(value.total, DOMException);
validateDisplayItems(value.displayItems, DOMException);
validateShippingOptions(value.shippingOptions, DOMException);
// 1. Let details be the result of converting value to a PaymentDetailsUpdate dictionary. If this throws an exception, abort the update with the thrown exception.
const details = Object.assign(target._details, value);
// 2. Let serializedModifierData be an empty list.
let serializedModifierData = [];
// 3. Let selectedShippingOption be null.
let selectedShippingOption = null;
// 4. Let shippingOptions be an empty sequence<PaymentShippingOption>.
let shippingOptions = [];
// 5. Validate and canonicalize the details:
// TODO: implmentation
// 6. Update the PaymentRequest using the new details:
target._details = details;
// 6.1 If the total member of details is present, then:
// if (details.total) {
// target._details = Object.assign({}, target._details, { total: details.total });
// }
// // 6.2 If the displayItems member of details is present, then:
// if (details.displayItems) {
// target._details = Object.assign({}, target._details, { displayItems: details.displayItems });
// }
// // 6.3 If the shippingOptions member of details is present, and target.[[options]].requestShipping is true, then:
// if (details.shippingOptions && target._options.requestShipping === true) {
// // 6.3.1 Set target.[[details]].shippingOptions to shippingOptions.
// shippingOptions = details.shippingOptions;
// target._details = Object.assign({}, target._details, { shippingOptions });
// // 6.3.2 Set the value of target's shippingOption attribute to selectedShippingOption.
// selectedShippingOption = target.shippingOption;
// }
// // 6.4 If the modifiers member of details is present, then:
// if (details.modifiers) {
// // 6.4.1 Set target.[[details]].modifiers to details.modifiers.
// target._details = Object.assign({}, target._details, { modifiers: details.modifiers });
// // 6.4.2 Set target.[[serializedModifierData]] to serializedModifierData.
// target._serializedModifierData = serializedModifierData;
// }
// 6.5 If target.[[options]].requestShipping is true, and target.[[details]].shippingOptions is empty,
// then the developer has signified that there are no valid shipping options for the currently-chosen shipping address (given by target's shippingAddress).
// In this case, the user agent should display an error indicating this, and may indicate that that the currently-chosen shipping address is invalid in some way.
// The user agent should use the error member of details, if it is present, to give more information about why there are no valid shipping options for that address.
// React Native Payments specific 👇
// ---------------------------------
const normalizedDetails = convertDetailAmountsToString(target._details);
return NativePayments.handleDetailsUpdate(normalizedDetails, DOMException)
// 14. Upon fulfillment of detailsPromise with value value
.then(this._resetEvent())
// On iOS the `selectedShippingMethod` defaults back to the first option
// when updating shippingMethods. So we call the `_handleShippingOptionChange`
// method with the first shippingOption id so that JS is in sync with Apple Pay.
.then(() => {
if (Platform.OS !== 'ios') {
return;
}
if (target._details.shippingOptions && target._details.shippingOptions.length > 0 && value.shippingOptions && ((value.shippingOptions.find(op => op.selected) || {}).id || null) !== target._shippingOption) {
target._handleShippingOptionChange({
selectedShippingOptionId: target._details.shippingOptions[0].id
});
}
})
// 13. Upon rejection of detailsPromise:
.catch(e => {
this._resetEvent();
throw new Error('AbortError');
});
}
_resetEvent() {
// 1. Set event.[[waitForUpdate]] to false.
this._waitForUpdate = false;
// 2. Set target.[[updating]] to false.
this.target._updating = false;
// 3. The user agent should update the user interface based on any changed values in target.
// The user agent should re-enable user interface elements that might have been disabled in the steps above if appropriate.
noop();
}
async updateWith(PaymentDetailsModifierOrPromise) {
// 1. Let event be this PaymentRequestUpdateEvent instance.
let event = this;
// 2. Let target be the value of event's target attribute.
let target = this.target;
// 3. If target is not a PaymentRequest object, then throw a TypeError.
if (!(target instanceof PaymentRequest)) {
throw new Error('TypeError');
}
// 5. If event.[[waitForUpdate]] is true, then throw an "InvalidStateError" DOMException.
if (event._waitForUpdate === true) {
throw new Error('InvalidStateError');
}
// 6. If target.[[state]] is not " interactive", then throw an " InvalidStateError" DOMException.
if (target._state !== 'interactive') {
throw new Error('InvalidStateError');
}
// 7. If target.[[updating]] is true, then throw an "InvalidStateError" DOMException.
if (target._updating === true) {
throw new Error('InvalidStateError');
}
// 8. Set event's stop propagation flag and stop immediate propagation flag.
noop();
// 9. Set event.[[waitForUpdate]] to true.
event._waitForUpdate = true;
// 10. Set target.[[updating]] to true.
target._updating = true;
// 11. The user agent should disable the user interface that allows the user to accept the payment request.
// This is to ensure that the payment is not accepted until the web page has made changes required by the change.
// The web page must settle the detailsPromise to indicate that the payment request is valid again.
// The user agent should disable any part of the user interface that could cause another update event to be fired.
// Only one update may be processed at a time.
noop(); // NativePayments does this for us (iOS does at the time of this comment)
// 12. Return from the method and perform the remaining steps in parallel.
if (typeof PaymentDetailsModifierOrPromise === 'object') {
const paymentDetailsModifier = PaymentDetailsModifierOrPromise;
return this._handleDetailsChange(paymentDetailsModifier);
}
if (typeof PaymentDetailsModifierOrPromise === 'function') {
const detailsFromPromise = await PaymentDetailsModifierOrPromise();
this._handleDetailsChange(detailsFromPromise);
}
// 13 & 14 happen in `this._handleDetailsChange`.
}
}
//# sourceMappingURL=PaymentRequestUpdateEvent.js.map