1.0.12 • Published 2 years ago
gapp-payment-method v1.0.12
Payment Method GApp Flow
Mobile GApp Flow for Payment Method
Installation
npm install serino-mobile-gapp-payment-method-flow --registry http://miniapp.serino.com:4873/
Changelogs
See the Change logs
Dependecies
- npm install axios
(PaymentMethodGAppFlow) DataLoad Props
Prop | Required | Type | Description |
---|---|---|---|
data | No | array of object | list of payment method data. Applicable for dataloadType=json-stab |
axios | No | AxiosInstance | set axios instance. Applicable for dataloadType=network-service |
endpoints | No | object | list of endpoints. Applicable for dataloadType=network-service or network-service-config |
baseUrl | No | string | baseurl for getAll endpoint. Applicable for dataloadType=network-service-config |
method | No | GET ,POST ,PUT ,DELETE | Applicable for dataloadType=network-service-config |
requestParams | No | object | Applicable for dataloadType=network-service-config |
requestPostData | No | object | Applicable for dataloadType=network-service-config |
cancelRequest | No | Applicable for dataloadType=network-service-config | |
timeout | No | Applicable for dataloadType=network-service-config | |
AppKey | No | Applicable for dataloadType=network-service-config | |
token | No | Applicable for dataloadType=network-service-config | |
tokenType | No | Applicable for dataloadType=network-service-config | |
header | No | object | Applicable for dataloadType=network-service-config |
validateCardUrl | No | string | Applicable for dataloadType=network-service or network-service-config |
cardValidationtoken | No | string | Applicable for dataloadType=network-service ornetwork-service-config |
(PaymentMethodGAppFlow) DataIn Props
Prop | Required | Type | Description |
---|---|---|---|
dataLoadType | Yes | json-stab ,network-service ,network-service-config | choices what dataLoad should be apply |
constructData | No | function | function that reconstruct payment method list. should return list. |
initialRouteName | No | string | initialRouteName for StackNavigator |
screens | No | array of objects | modify mini-app and gapp. able to use with the combination of Stack |
isCardValidate | No | boolean | activating server request to validate card form. |
(dataLoad > endpoints) Props
Prop | Required | Type | Description |
---|---|---|---|
getAll | No | string | endpoint for payment method list api |
(dataIn > screens) Props
Prop | Required | Type | Description |
---|---|---|---|
key | No | string | mini-app key |
stackName | No | string | Stack name |
stackOptions | No | object | Stack options |
dataLoad | No | object | mini-app dataLoad. to modify initial and gapp dataLoad |
dataIn | No | object | mini-app dataIn. to modify initial and gapp dataIn |
dataOut | No | function | mini-app dataOut. to modify initial and gapp dataOut |
Example
Run the following commands
npm run boostrap
:setup project by installing all dependencies and pods.
npm run example run start
: start the Metro server for the example app.
npm run example run android
: run the example app on Android.
npm run example run ios
: run the example app on iOS.
Example (dataLoad='json-stab')
gateway-payment-list.json
{
"status": 200,
"message": "Success",
"data": [
{
"id": 1,
"name": "Credit/Debit Card",
"description": "Pay using your Visa or Master Debit/Credit Cards",
"type": "online",
"merchant_processors": [
{
"id": 2,
"priority_level": 0,
"processor": {
"name": "Maya - Credit/Debit Card",
"description": "Pay using Credit/Debit Card via Maya",
"type": "checkout",
"icon_url": "https://someimage.com/maya_icon.png",
"banner_url": "https://someimage.com/maya_banner.png"
}
},
{
"id": 3,
"priority_level": 1,
"processor": {
"name": "MetroBank - MasterCard",
"description": "Pay using Credit/Debit Master Card",
"type": "checkout",
"icon_url": "https://someimage.com/maya_icon.png",
"banner_url": "https://someimage.com/maya_banner.png"
}
}
]
},
{
"id": 2,
"name": "E-Wallets",
"description": "Pay using your E-Wallet accounts in partner banks",
"type": "online",
"merchant_processors": [
{
"id": 4,
"priority_level": 0,
"processor": {
"name": "Maya - eWallet",
"description": "Pay using Maya Account",
"type": "checkout",
"icon_url": "https://someimage.com/maya_icon.png",
"banner_url": "https://someimage.com/maya_banner.png"
}
},
{
"id": 5,
"priority_level": 1,
"processor": {
"name": "BDO",
"description": "Pay using BDO",
"type": "checkout",
"icon_url": "https://someimage.com/bdo_icon.png",
"banner_url": "https://someimage.com/bdo_banner.png"
}
}
]
},
{
"id": 3,
"name": "Cash",
"description": "Pay using Cash on Delivery",
"type": "cash",
"merchant_processors": []
}
]
}
Payment Method Screen
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { Button, Text } from 'react-native-paper';
import { PaymentMethodGAppFlow } from 'serino-mobile-gapp-payment-method-flow';
import { MyNavigator } from '../App';
/*
* from App.tsx:
* import { createNativeStackNavigator } from '@react-navigation/native-stack'
* export const MyNavigator = createNativeStackNavigator();
*/
import { GlobalContext } from '../context/GlobalContext';
import { MethodSelectionAccordion } from 'serino-mapp-payment-method';
import JSONStab from '../json-stab/gateway-payment-list.json';
const PaymentMethodFlow = ({ navigation }: any) => {
const context: any = React.useContext(GlobalContext);
const [selectedPaymentMethod, setSelectedPaymentMethod] = React.useState(
Boolean(context.paymentMethod)
? context.paymentMethod
: {
id: 1,
text: 'Credit/Debit Card',
value: 'Credit/Debit Card',
}
);
const dataLoadType = 'json-stab';
const data = JSONStab.data;
const screens = [
// mini-app index 0
{
stackName: 'PaymentMethod',
stackOptions: {
title: 'Payment Method',
},
},
// mini-app index 1
{
stackName: 'CardDetails',
stackOptions: {
title: 'Debit/Credit Card Details',
},
},
];
const constructData = (item: any) => {
return item.map((i: any) => ({
id: i.id,
text: i.name,
value: i.name,
subText: i.description,
descriptionText: '', // i.description,
isExpanded: i.expanded || false,
child:
(i.merchant_processors || []).length > 0
? i.merchant_processors?.map((d: any) => ({
id: d.id,
text: d.processor.name,
value: d.processor.name,
subText: d.processor.description,
descriptionText: '', //d.description,
imageUri: d.processor.icon_url || undefined,
}))
: undefined,
}));
};
const handleDataOut = (values: any) => {
const paymentMethodDetails = values.paymentMethod?.id
? values.paymentMethod
: selectedPaymentMethod;
// set selected payment method
setSelectedPaymentMethod(paymentMethodDetails);
// If selected payment method is debit or credit card
if (values.paymentMethod.id === 1) {
console.log('values.paymentMethod.id', values.paymentMethod.id);
// navigation.navigate('CardDetails');
navigation.navigate('PaymentMethodFlow', { screen: 'CardDetails' });
}
};
React.useLayoutEffect(() => {
navigation.setOptions({
headerShown: false,
});
}, [navigation]);
return (
<View style={styles.container}>
<PaymentMethodGAppFlow
dataLoad={{ data }}
dataIn={{
dataLoadType,
constructData,
StackNavigator: MyNavigator,
initialRouteName: 'PaymentMethod',
screens,
}}
dataOut={handleDataOut}
>
{/* mini-app index 0 */}
<MethodSelectionAccordion
key="payment-method-accordion-list"
dataLoad={[]}
dataIn={{
selectedPaymentMethod,
}}
dataOut={() => {}}
/>
{/* mini-app index 1 */}
<MApp2 key="card-form-details" dataOut={() => {}} />
</PaymentMethodGAppFlow>
<Button
mode="contained"
onPress={() => {
// context purpose: (simulate checkout gapp flow)
context.setContext &&
context.setContext({
...context,
paymentMethod: selectedPaymentMethod,
});
navigation.goBack();
}}
>
Confirm
</Button>
</View>
);
};
export default PaymentMethodFlow;
const MApp2 = (props: any) => {
return (
<View>
<Text>Card Details</Text>
<Button
onPress={() =>
props?.dataOut({
cardNumber:
'************' +
'4012001037167778'.replace(/-/g, '').substring(12),
paymentTokenId: '1234',
})
}
>
Send Card details
</Button>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
box: {
width: 60,
height: 60,
marginVertical: 20,
},
});
Example (dataLoad='network-service')
axiosGateway.ts
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
const onRequest = (config: AxiosRequestConfig): AxiosRequestConfig => {
// You can add token here
// const token = '';
// config.headers.Authorization = `Bearer ${token}`;
return config;
};
const onRequestError = (error: AxiosError): Promise<AxiosError> => {
return Promise.reject(error);
};
const onResponse = (response: AxiosResponse) => {
return response.data;
};
const onResponseError = (error: AxiosError): Promise<AxiosError> => {
return Promise.reject(error.response.data);
};
const instance = axios.create({
baseURL: 'http://',
});
instance.interceptors.request.use(onRequest, onRequestError);
instance.interceptors.response.use(onResponse, onResponseError);
export default instance;
Payment Method
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { MethodSelectionAccordion } from 'serino-mobile-mapp-payment-method';
import { PaymentMethodGAppFlow } from 'serino-mobile-gapp-payment-method-flow';
import { Text } from 'react-native-paper';
import { MyNavigator } from '../App';
import axios from '../library/axiosGateway';
const PaymentMethodFlow = ({ navigation }: any) => {
const [selectedPaymentMethod, setSelectedPaymentMethod] = React.useState({
id: 0,
text: '',
value: '',
});
const public_key = 'pk-8c6axxxx-xxxx-xxxx-xxxx-xxxxxx120002';
const screens = [
// mini-app index 0
{
stackName: 'PaymentMethod',
stackOptions: {
title: 'Payment Method',
},
},
// mini-app index 1
{
stackName: 'CardDetails',
stackOptions: {
title: 'Debit/Credit Card Details',
},
},
];
const constructData = (item: any) => {
return item.map((i: any) => ({
id: i.id,
text: i.name,
value: i.name,
subText: i.description,
descriptionText: '', // i.description,
isExpanded: i.expanded || false,
child: i.merchant_processors?.map((d: any) => ({
id: d.id,
text: d.name,
value: d.name,
subText: d.description,
descriptionText: '', //d.description,
imageUri: d.icon_url || undefined,
})),
}));
};
const handleDataOut = (values: any) => {
const paymentMethodDetails = values.paymentMethod?.id
? values.paymentMethod
: selectedPaymentMethod;
// set selected payment method
setSelectedPaymentMethod(paymentMethodDetails);
// If selected payment method is debit or credit card
if (values.paymentMethod.id === 1) {
console.log('values.paymentMethod.id', values.paymentMethod.id);
navigation.navigate('PaymentMethodFlow', { screen: 'CardDetails' });
}
};
React.useLayoutEffect(() => {
navigation.setOptions({
headerShown: false,
});
}, [navigation]);
return (
<View style={styles.container}>
<PaymentMethodGAppFlow
dataLoad={{
axios,
endpoints: {
getAll: `/api/public/merchants/${public_key}/mode-of-payments`,
},
}}
dataIn={{
dataLoadType: 'network-service',
constructData,
StackNavigator: MyNavigator,
initialRouteName: 'PaymentMethod',
screens,
}}
dataOut={handleDataOut}
>
{/* mini-app index 0 */}
<MethodSelectionAccordion
key="payment-method-accordion-list"
dataLoad={[]}
dataIn={{
selectedPaymentMethod,
}}
dataOut={(value: any) => {}}
/>
{/* mini-app index 1 */}
<Text>Card Details</Text>
</PaymentMethodGAppFlow>
</View>
);
};
export default PaymentMethodFlow;
const styles = StyleSheet.create({
container: {
flex: 1,
},
box: {
width: 60,
height: 60,
marginVertical: 20,
},
});
Example (dataLoad='network-service-config')
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import MethodSelectionAccordion from '../payment-method-v3/MethodSelectionAccordion/MethodSelectionAccordion';
import { PaymentMethodGAppFlow } from 'serino-mobile-gapp-payment-method-flow';
import { Text } from 'react-native-paper';
import { MyNavigator } from '../App';
const PaymentMethodFlow = ({ navigation }: any) => {
const [selectedPaymentMethod, setSelectedPaymentMethod] = React.useState({
id: 1,
text: 'Credit/Debit Card',
value: 'Credit/Debit Card',
});
const public_key = 'pk-8c6axxxx-xxxx-xxxx-xxxx-xxxxxx120002';
const screens = [
// mini-app index 0
{
stackName: 'PaymentMethod',
stackOptions: {
title: 'Payment Method',
},
},
// mini-app index 1
{
stackName: 'CardDetails',
stackOptions: {
title: 'Debit/Credit Card Details',
},
},
];
const constructData = (item: any) => {
return item.map((i: any) => ({
id: i.id,
text: i.name,
value: i.name,
subText: i.description,
descriptionText: '', // i.description,
isExpanded: i.expanded || false,
child: i.merchant_processors?.map((d: any) => ({
id: d.id,
text: d.name,
value: d.name,
subText: d.description,
descriptionText: '', //d.description,
imageUri: d.icon_url || undefined,
})),
}));
};
const handleDataOut = (values: any) => {
const paymentMethodDetails = values.paymentMethod?.id
? values.paymentMethod
: selectedPaymentMethod;
// set selected payment method
setSelectedPaymentMethod(paymentMethodDetails);
// If selected payment method is debit or credit card
if (values.paymentMethod.id === 1) {
console.log('values.paymentMethod.id', values.paymentMethod.id);
// navigation.navigate('CardDetails');
navigation.navigate('PaymentMethodFlow', { screen: 'CardDetails' });
}
};
React.useLayoutEffect(() => {
navigation.setOptions({
headerShown: false,
});
}, [navigation]);
return (
<View style={styles.container}>
<PaymentMethodGAppFlow
dataLoad={{
baseUrl: 'http://',
endpoints: {
getAll: `/api/public/merchants/${public_key}/mode-of-payments`,
},
}}
dataIn={{
dataLoadType: 'network-service-config',
constructData,
StackNavigator: MyNavigator,
initialRouteName: 'PaymentMethod',
screens,
}}
dataOut={handleDataOut}
>
{/* mini-app index 0 */}
<MethodSelectionAccordion
key="payment-method-accordion-list"
dataLoad={[]}
dataIn={{
selectedPaymentMethod,
}}
dataOut={(value: any) => {}}
/>
{/* mini-app index 1 */}
<Text>Card Details</Text>
</PaymentMethodGAppFlow>
</View>
);
};
export default PaymentMethodFlow;
const styles = StyleSheet.create({
container: {
flex: 1,
},
box: {
width: 60,
height: 60,
marginVertical: 20,
},
});
License
MIT