gapp-payment-method-flow
Version:
Mobile Gapp flow for Payment Method
499 lines (471 loc) • 21.7 kB
JavaScript
import { useCallback, useEffect, useState } from 'react';
import { httpRequest } from '../shared/httpRequest';
import axios from 'axios';
/** Initial value for payment method */
const paymentMethodInitialValues = {
id: 0,
text: '',
value: ''
};
/** view model of payment method gapp */
function useViewModel(_ref) {
var _dataIn$actions5;
let {
dataLoad,
dataIn,
dataOut
} = _ref;
const [paymentMethods, setPaymentMethods] = useState([]);
const [newDataLoad, setNewDataLoad] = useState([]);
const [tempSelectedPaymentMethod, setTempSelectedPaymentMethod] = useState(paymentMethodInitialValues);
const [paymentMethodDataOut, setPaymentMethodDataOut] = useState({
loading: false,
paymentMethod: {},
cardDetails: {},
errorResponse: {},
savedCard: {},
defaultCardId: 0,
savedCards: (dataLoad === null || dataLoad === void 0 ? void 0 : dataLoad.savedCards) || []
});
const {
data: dataLoadData,
axios: axiosInstance,
cardValidationToken,
endpoints,
token,
baseUrl,
validateCardUrl,
...resDataLoad
} = dataLoad || {};
const dataLoadType = dataIn.dataLoadType || 'json-stab';
const data = dataLoadType === 'json-stab' ? dataLoadData : [...paymentMethods];
const isCardValidate = (dataIn === null || dataIn === void 0 ? void 0 : dataIn.isCardValidate) || false;
const cardFormTrigger = (dataIn === null || dataIn === void 0 ? void 0 : dataIn.cardFormTrigger) || '';
const cardFormTriggerKey = (dataIn === null || dataIn === void 0 ? void 0 : dataIn.cardFormTriggerKey) || 'text';
/** dataIn function to reconstruct the list of payment method */
const constructedData = () => {
const newData = data.map(i => {
var _i$merchant_processor;
return {
id: i === null || i === void 0 ? void 0 : i.id,
text: i === null || i === void 0 ? void 0 : i.name,
value: i === null || i === void 0 ? void 0 : i.name,
subText: i.description,
descriptionText: '',
isExpanded: i.expanded || true,
child: (i.merchant_processors || []).length > 0 ? (_i$merchant_processor = i.merchant_processors) === null || _i$merchant_processor === void 0 ? void 0 : _i$merchant_processor.map(d => {
var _d$processors, _d$processors2, _d$processors3, _d$processors4;
return {
id: d === null || d === void 0 ? void 0 : d.id,
text: (_d$processors = d.processors) === null || _d$processors === void 0 ? void 0 : _d$processors.name,
value: (_d$processors2 = d.processors) === null || _d$processors2 === void 0 ? void 0 : _d$processors2.name,
subText: (_d$processors3 = d.processors) === null || _d$processors3 === void 0 ? void 0 : _d$processors3.description,
descriptionText: '',
imageUri: ((_d$processors4 = d.processors) === null || _d$processors4 === void 0 ? void 0 : _d$processors4.icon_url) || undefined
};
}) : undefined
};
});
const isNewDataLoad = Array.isArray(newDataLoad) && newDataLoad.length > 0;
const dLoad = isNewDataLoad ? newDataLoad : newData;
if (dataIn.constructData) {
return dataIn.constructData(dLoad, data);
} else {
return dLoad || [];
}
};
/** dataOut function of Payment Method MiniApp
* like MethodSelection, MethodSelectionAccordion
*/
const handleSelectPaymentMethod = values => {
const newPaymentMethod = (values === null || values === void 0 ? void 0 : values.type) === 'Selected' && values !== null && values !== void 0 && values.value ? values === null || values === void 0 ? void 0 : values.value : values;
const newPaymentMethods = (values === null || values === void 0 ? void 0 : values.type) === 'NewDataLoad' && values !== null && values !== void 0 && values.value ? values === null || values === void 0 ? void 0 : values.value : newDataLoad;
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: {},
paymentMethod: newPaymentMethod
});
setNewDataLoad(newPaymentMethods);
};
/** dataOut function of Payment Method MiniApp
* (MethodSelectionAccordionScreen)
*/
const handleSubmitPaymentMethodAccordion = async values => {
var _values$selectedSaved, _paymentMethodDataOut, _values$selectedSaved2, _values$selectedSaved3, _values$selectedSaved4;
const newPaymentMethod = values === null || values === void 0 ? void 0 : values.selectedMethod;
const newCardDetails = {
...((_values$selectedSaved = values.selectedSavedCard) === null || _values$selectedSaved === void 0 ? void 0 : _values$selectedSaved.value),
isSavedCard: true
};
const newSavedCard = values === null || values === void 0 ? void 0 : values.selectedSavedCard;
const newPaymentMethods = (values === null || values === void 0 ? void 0 : values.newData) || newDataLoad;
const hasTokenId = cardFormTrigger === newPaymentMethod[cardFormTriggerKey] && newSavedCard !== null && newSavedCard !== void 0 && newSavedCard.id && (_paymentMethodDataOut = paymentMethodDataOut.cardDetails) !== null && _paymentMethodDataOut !== void 0 && _paymentMethodDataOut.paymentTokenId ? true : false;
const validatedCard = hasTokenId ? {} : (values === null || values === void 0 ? void 0 : (_values$selectedSaved2 = values.selectedSavedCard) === null || _values$selectedSaved2 === void 0 ? void 0 : (_values$selectedSaved3 = _values$selectedSaved2.value) === null || _values$selectedSaved3 === void 0 ? void 0 : _values$selectedSaved3.cardNumber) && (await validateCreditDebitCard(values === null || values === void 0 ? void 0 : (_values$selectedSaved4 = values.selectedSavedCard) === null || _values$selectedSaved4 === void 0 ? void 0 : _values$selectedSaved4.value));
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: {},
cardDetails: Object.assign(newCardDetails, validatedCard),
paymentMethod: newPaymentMethod,
savedCard: newSavedCard
});
setNewDataLoad(newPaymentMethods);
};
const handleCardFormTrigger = methodValues => {
var _dataIn$actions;
setTempSelectedPaymentMethod(methodValues);
if (dataIn !== null && dataIn !== void 0 && (_dataIn$actions = dataIn.actions) !== null && _dataIn$actions !== void 0 && _dataIn$actions.handleCardFormTrigger && methodValues[cardFormTriggerKey] === cardFormTrigger) {
var _dataIn$actions2;
dataIn === null || dataIn === void 0 ? void 0 : (_dataIn$actions2 = dataIn.actions) === null || _dataIn$actions2 === void 0 ? void 0 : _dataIn$actions2.handleCardFormTrigger(methodValues);
}
};
const handleAddNewCard = methodValues => {
var _dataIn$actions3;
setTempSelectedPaymentMethod(methodValues);
if (dataIn !== null && dataIn !== void 0 && (_dataIn$actions3 = dataIn.actions) !== null && _dataIn$actions3 !== void 0 && _dataIn$actions3.handleAddNewCard) {
var _dataIn$actions4;
dataIn === null || dataIn === void 0 ? void 0 : (_dataIn$actions4 = dataIn.actions) === null || _dataIn$actions4 === void 0 ? void 0 : _dataIn$actions4.handleAddNewCard(methodValues);
}
};
const validateCreditDebitCard = async values => {
try {
var _values$cardNumber;
let validatedCard = {};
const cardPayload = {
card: {
number: values === null || values === void 0 ? void 0 : (_values$cardNumber = values.cardNumber) === null || _values$cardNumber === void 0 ? void 0 : _values$cardNumber.replace(/-/g, ''),
expMonth: values.mm,
expYear: values.yy,
cvc: values.cvv
}
};
setPaymentMethodDataOut({
...paymentMethodDataOut,
loading: true
});
const networkServiceCondition1 = dataLoadType === 'network-service-config' && validateCardUrl && cardValidationToken;
const networkServiceCondition2 = dataLoadType === 'network-service' && cardValidationToken && validateCardUrl;
if (isCardValidate) {
if (networkServiceCondition1) {
const validateRes = await httpRequest({
tokenType: 'Basic',
...resDataLoad,
url: `${validateCardUrl}`,
method: 'POST',
bearerToken: cardValidationToken,
requestPostData: cardPayload
});
const res = (validateRes === null || validateRes === void 0 ? void 0 : validateRes.data) || validateRes;
validatedCard = {
paymentTokenId: res === null || res === void 0 ? void 0 : res.paymentTokenId,
state: res === null || res === void 0 ? void 0 : res.state
};
} else if (networkServiceCondition2) {
const validateRes = await axios.post(validateCardUrl, cardPayload, {
headers: {
'Accept': 'application/json',
'Content-type': 'application/json;charset=utf-8',
'Authorization': `${(resDataLoad === null || resDataLoad === void 0 ? void 0 : resDataLoad.tokenType) || 'Basic'} ${cardValidationToken}`
}
});
const res = (validateRes === null || validateRes === void 0 ? void 0 : validateRes.data) || validateRes;
validatedCard = {
paymentTokenId: res === null || res === void 0 ? void 0 : res.paymentTokenId,
state: res === null || res === void 0 ? void 0 : res.state
};
}
}
return validatedCard;
} catch (err) {
var _err$response;
const error = (err === null || err === void 0 ? void 0 : (_err$response = err.response) === null || _err$response === void 0 ? void 0 : _err$response.data) || (err === null || err === void 0 ? void 0 : err.data) || err;
console.error('error at validating card form located on payment method gapp', error);
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: (err === null || err === void 0 ? void 0 : err.response) || err,
loading: false
});
}
};
// @ts-ignore
const verifyCardNumberType = numberCard => {
const cardTypes = {
'Electron': /^(4026|417500|4405|4508|4844|4913|4917)\d+$/,
'Maestro': /^(5018|5020|5038|5612|5893|6304|6759|6761|6762|6763|0604|6390)\d+$/,
'Dankort': /^(5019)\d+$/,
'Interpayment': /^(636)\d+$/,
'Union Pay': /^(62|88)\d+$/,
// Visa card numbers start with a 4.
'Visa': /^4[0-9]{6,}$/g,
// MasterCard numbers start with the numbers 51 through 55,
// but this will only detect MasterCard credit cards;
// there are other cards issued using the MasterCard system that
// do not fall into this IIN range. In 2016, they will add numbers
// in the range (222100-272099).
'Master Card': /^5[1-5][0-9]{5,}|222[1-9][0-9]{3,}|22[3-9][0-9]{4,}|2[3-6][0-9]{5,}|27[01][0-9]{4,}|2720[0-9]{3,}$/g,
// American Express card numbers start with 34 or 37.
'American Express': /^3[47][0-9]{5,}$/g,
// Diners Club card numbers begin with 300 through 305, 36 or 38. There are Diners Club cards that begin with 5 and have 16 digits. These are a joint venture between Diners Club and MasterCard and should be processed like a MasterCard.
'Diner Club': /^3(?:0[0-5]|[68][0-9])[0-9]{4,}$/g,
// Discover card numbers begin with 6011 or 65.
'Discover': /^6(?:011|5[0-9]{2})[0-9]{3,}$/g,
// JCB cards begin with 2131, 1800 or 35.
'JCB': /^(?:2131|1800|35[0-9]{3})[0-9]{3,}$/g
};
for (const nType in cardTypes) {
if (cardTypes[nType].test(numberCard)) {
return nType;
}
}
};
/** handle dataOut of CardForm */
const handleCardFormDataOut = async values => {
try {
const validatedCard = await validateCreditDebitCard(values);
// if (typeof values?.isSavedCard === 'boolean') {
setPaymentMethodDataOut({
...paymentMethodDataOut,
loading: false,
errorResponse: {},
paymentMethod: tempSelectedPaymentMethod,
cardDetails: Object.assign(values, validatedCard)
});
// } else {
// setPaymentMethodDataOut({
// ...paymentMethodDataOut,
// loading: false,
// errorResponse: {},
// cardDetails: Object.assign(values, validatedCard),
// });
// }
} catch (err) {
var _err$response2;
const error = (err === null || err === void 0 ? void 0 : (_err$response2 = err.response) === null || _err$response2 === void 0 ? void 0 : _err$response2.data) || (err === null || err === void 0 ? void 0 : err.data) || err;
console.error('error at submitting card details located on payment method gapp', error);
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: (err === null || err === void 0 ? void 0 : err.response) || err,
loading: false
});
}
};
/** handle dataOut of CardForm */
// const handleCardFormDataOut2 = async (values: any) => {
// try {
// setPaymentMethodDataOut({
// ...paymentMethodDataOut,
// loading: true,
// });
// const validatedCard: any = await validateCreditDebitCard(values);
// const numberCard: string = (values?.cardNumber || '')?.replace(
// /(-)*/g,
// ''
// );
// const cardDetailsValue = {
// cardNumber: numberCard, // '5123-4567-8901-2346',
// cvv: values?.cvv,
// mm: values?.mm,
// name: values?.name,
// yy: values?.yy,
// };
// if (typeof values?.isSavedCard === 'boolean') {
// const privacyCardNumber = numberCard?.replace(/.{12}/g, '**********');
// const savedCardsLength: number = (
// paymentMethodDataOut?.savedCards || []
// )?.length;
// // const hasSavedCards: boolean = savedCardsLength > 0;
// const savedCardNewId: number = savedCardsLength + 1;
// const savedCardDetails = {
// id: savedCardNewId,
// name: verifyCardNumberType(numberCard) || '',
// card_number: privacyCardNumber, // '**********2346',
// promo: '',
// value: cardDetailsValue,
// };
// const cards = paymentMethodDataOut?.savedCards?.concat([
// savedCardDetails,
// ]);
// setPaymentMethodDataOut({
// ...paymentMethodDataOut,
// loading: false,
// errorResponse: {},
// paymentMethod: tempSelectedPaymentMethod,
// cardDetails: Object.assign(values, cardDetailsValue, validatedCard),
// defaultCardId: values?.isSavedCard
// ? values.id
// : paymentMethodDataOut?.defaultCardId,
// savedCards: values?.isSavedCard
// ? cards
// : paymentMethodDataOut?.savedCards,
// });
// } else {
// setPaymentMethodDataOut({
// ...paymentMethodDataOut,
// loading: false,
// errorResponse: {},
// cardDetails: Object.assign(values, cardDetailsValue, validatedCard),
// });
// }
// } catch (err: any) {
// const error = err?.response?.data || err?.data || err;
// console.error(
// 'error at submitting card details located on payment method gapp',
// error
// );
// setPaymentMethodDataOut({
// ...paymentMethodDataOut,
// errorResponse: err?.response || err,
// loading: false,
// });
// }
// };
// const handleSavedCardScreenDataOut = async ({
// defaultId,
// newData,
// newSelected,
// }: {
// defaultId?: number | string;
// newData: any;
// newSelected: any;
// }) => {
// const cardDefaultID = newData.filter((n: any) => n.id === defaultId);
// const cardNotDefaultID = newData.filter((n: any) => n.id !== defaultId);
// setPaymentMethodDataOut({
// ...paymentMethodDataOut,
// defaultCardId: cardDefaultID?.length === 1 ? defaultId : 0,
// savedCards: cardDefaultID.concat(cardNotDefaultID),
// savedCard: newSelected,
// });
// };
// api request and set to state action (case 1 - network-service-config)
const fetchItems = useCallback(async () => {
try {
const networkServiceCondition1 = dataLoadType === 'network-service-config' && (endpoints === null || endpoints === void 0 ? void 0 : endpoints.getAll);
const networkServiceCondition2 = dataLoadType === 'network-service' && (endpoints === null || endpoints === void 0 ? void 0 : endpoints.getAll) && axiosInstance;
if (networkServiceCondition1) {
var _res$data;
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: {},
loading: true
});
const res = await httpRequest({
url: `${baseUrl}${endpoints === null || endpoints === void 0 ? void 0 : endpoints.getAll}`,
method: 'GET',
bearerToken: token,
tokenType: 'Bearer',
...resDataLoad
});
setPaymentMethods((res === null || res === void 0 ? void 0 : (_res$data = res.data) === null || _res$data === void 0 ? void 0 : _res$data.data) || (res === null || res === void 0 ? void 0 : res.data) || []);
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: {},
loading: false
});
} else if (networkServiceCondition2) {
var _res$data2;
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: {},
loading: true
});
const res = await axiosInstance.get(endpoints === null || endpoints === void 0 ? void 0 : endpoints.getAll);
setPaymentMethods((res === null || res === void 0 ? void 0 : (_res$data2 = res.data) === null || _res$data2 === void 0 ? void 0 : _res$data2.data) || (res === null || res === void 0 ? void 0 : res.data) || []);
setPaymentMethodDataOut({
...paymentMethodDataOut,
errorResponse: {},
loading: false
});
}
} catch (err) {
const error = (err === null || err === void 0 ? void 0 : err.response) || err;
console.error('error at fetching payment method list located on payment method gapp', error);
setPaymentMethodDataOut({
...paymentMethodDataOut,
loading: false,
errorResponse: error
});
}
}, []);
// life-cycle method to run api request
useEffect(() => {
fetchItems();
}, [endpoints === null || endpoints === void 0 ? void 0 : endpoints.getAll]);
// life-cycle method to dataOut (your GApp)
useEffect(() => {
dataOut(paymentMethodDataOut);
}, [paymentMethodDataOut]);
// useEffect(() => {
// if (Array.isArray(dataLoad?.savedCards)) {
// setPaymentMethodDataOut({
// ...paymentMethodDataOut,
// savedCards: dataLoad?.savedCards,
// });
// console.log('render dataLoad Saved cards', dataLoad?.savedCards);
// }
// }, [JSON.stringify(dataLoad?.savedCards)]);
return {
/** mini-app/screen key (compatible to: MethodSelection) */
'payment-method': {
dataLoad: constructedData()
},
/** mini-app/screen key (compatible to: MethodSelectionAccordion) */
'payment-method-accordion-list': {
dataLoad: constructedData(),
dataIn: {
selectedPaymentMethod: paymentMethodDataOut.paymentMethod[cardFormTriggerKey] === cardFormTrigger ? paymentMethodInitialValues : paymentMethodDataOut.paymentMethod
},
dataOut: handleSelectPaymentMethod
},
/** mini-app/screen key (compatible to: MethodSelectionAccordionScreen) */
'payment-method-accordion-screen': {
dataLoad: constructedData(),
dataIn: {
selectedPaymentMethod: paymentMethodDataOut.paymentMethod[cardFormTriggerKey] === cardFormTrigger ? paymentMethodInitialValues : paymentMethodDataOut.paymentMethod,
cardFormTrigger,
handleCardFormTrigger,
savedCards: dataLoad === null || dataLoad === void 0 ? void 0 : dataLoad.savedCards,
onPressNewCard: handleAddNewCard,
onPressManageCard: dataIn === null || dataIn === void 0 ? void 0 : (_dataIn$actions5 = dataIn.actions) === null || _dataIn$actions5 === void 0 ? void 0 : _dataIn$actions5.handleManageCard
},
dataOut: handleSubmitPaymentMethodAccordion
},
/** mini-app/screen key (compatible to: MethodSelectionAccordionScreen) */
// 'payment-method-accordion-screen2': {
// dataLoad: constructedData(),
// dataIn: {
// selectedPaymentMethod:
// paymentMethodDataOut.paymentMethod?.text === cardFormTrigger
// ? paymentMethodInitialValues
// : paymentMethodDataOut.paymentMethod,
// cardFormTrigger,
// handleCardFormTrigger,
// savedCards: paymentMethodDataOut?.savedCards,
// onPressNewCard: handleAddNewCard,
// onPressManageCard: dataIn?.actions?.handleManageCard,
// },
// dataOut: handleSubmitPaymentMethodAccordion,
// },
/** mini-app/screen key (compatible to: CardForm) */
'card-form-details': {
dataOut: handleCardFormDataOut
},
/** mini-app/screen key (compatible to: CardForm) */
// 'card-form-details2': {
// dataOut: handleCardFormDataOut2,
// },
/** mini-app/screen key (compatible to: SavedCardScreen) */
'saved-card-screen': {
dataLoad: {
data: dataLoad === null || dataLoad === void 0 ? void 0 : dataLoad.savedCards
}
}
// 'saved-card-screen-2': {
// dataLoad: {
// data: paymentMethodDataOut?.savedCards,
// },
// dataOut: handleSavedCardScreenDataOut,
// },
};
}
export default useViewModel;
//# sourceMappingURL=useViewModel.js.map