gapp-checkout
v1.0.10
Published
Mobile Gapp flow for Checkout
Downloads
5
Maintainers
Readme
Checkout GApp Flow
GApp Flow for Checkout
Installation
npm install serino-mobile-gapp-checkout-flow --registry http://miniapp.serino.com:4873/
Changelogs
See the Change logs
Dependecies
- npm install axios
- npm install crypto-js
(CheckoutGAppFlow) DataLoad Props
| Prop | Required | Type | Description |
| :------------------ | :------- | :------------ | :--------------------------------------------------------------------------------------------------- |
| axiosOrder
| No | AxiosInstance | set axios instance for order api. Applicable for dataloadType=network-service
|
| axiosCheckout
| No | AxiosInstance | set axios instance for checkout api. Applicable for dataloadType=network-service
|
| endpoints
| No | object | endpoint for checkout api. Applicable for dataloadType=network-service
or network-service-config
|
| baseUrl
| No | object | baseurl for getAll endpoint. Applicable for dataloadType=network-service-config
|
| payload
| No | object | payload request. Applicable for dataloadType=network-service
or network-service-config
|
| requestParams
| 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
|
(CheckoutGAppFlow) DataIn Props
| Prop | Required | Type | Description |
| :----------------------------- | :------- | :----------------------------------------- | :------------------------------------------------------------------ |
| dataLoadType
| Yes | network-service
,network-service-config
| choices what dataLoad should be apply |
| constructOrderPayload
| Yes | function | function that reconstruct order payload. should return details. |
| constructCheckoutPayload
| No | function | function that reconstruct checkout payload. should return details. |
| initialRouteName
| No | string | initialRouteName for StackNavigator |
| screens
| No | array of objects | modify mini-app and gapp. able to use with the combination of Stack |
(dataLoad > baseUrl) Props
| Prop | Required | Type | Description |
| :------------- | :------- | :----- | :-------------------------------------------------------------------------- |
| order
| No | string | base url for order. Applicable for dataloadType=network-service-config
|
| checkout
| No | string | base url for checkout. Applicable for dataloadType=network-service-config
|
(dataLoad > endpoints) Props
| Prop | Required | Type | Description |
| :----------------- | :------- | :----- | :-------------------------------------------------------------------------- |
| postOrder
| No | string | endpoint for order. Applicable for dataloadType=network-service-config
|
| postCheckout
| No | string | endpoint for checkout. Applicable for dataloadType=network-service-config
|
(dataLoad > payload) Props
| Prop | Required | Type | Description |
| :----------------------------------- | :------- | :-------------- | :----------------------------- |
| payee
| Yes | string | customer full name |
| first_name
| Yes | string | customer first name |
| last_name
| Yes | string | customer last name |
| contact_number
| Yes | string | customer contact number |
| email
| Yes | string | customer email |
| region
| Yes | string | region |
| barangay
| Yes | string | barangay |
| street
| Yes | string | street |
| building_name
| Yes | string | building name |
| landmark
| Yes | string | nearest landmark |
| payment_method
| Yes | string | payment method |
| subtotal
| Yes | number | order subtotal |
| discount
| Yes | number | voucher discount |
| shopee_fee
| Yes | number | shopee fee |
| delivery_fee
| Yes | number | delivery fee |
| total_amount
| Yes | number | total amount |
| items
| Yes | array of object | order items |
| merchant_transaction_reference
| Yes | string | merchant transaction reference |
| merchant_processor_id
| Yes | number | merchant processor id |
| processor
| Yes | object | processor |
| any property name | No | any | the res payload values. |
(dataLoad > payload > items) Props
| Prop | Required | Type | Description |
| :---------------- | :------- | :----- | :---------------------- |
| name
| Yes | string | product name |
| description
| Yes | string | product description |
| quantity
| Yes | number | product quantity |
| price
| Yes | number | prod' |
| uct price |
| any property name | No | any | the res payload values. |
(dataLoad > payload > processor) Props
| Prop | Required | Type | Description |
| :----------------- | :------- | :----- | :--------------------- |
| token
| Yes | string | processor token |
| redirect_url
| Yes | string | processor redirect url |
(dataLoad > payload > processor > redirect_url) Props
| Prop | Required | Type | Description |
| :------------ | :------- | :----- | :----------------------------- |
| success
| Yes | string | processor success redirect url |
| failure
| Yes | string | processor failure redirect url |
| cancel
| Yes | string | processor cancel redirect url |
(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 |
useViewModel returned value
'customer-details':{
dataIn: {
fullName, // payload > payee
firstName, // payload > first_name
lastName, // payload > last_name
contactNumber, // payload > contact_number
email,
region,
city,
barangay,
street,
buildingName, // payload > building_name
landmark,
}
},
'order-items': {
dataIn: {
items, // order items
},
},
'payment-method': {
dataIn: {
label, // payload > payment_method; payment method label
},
},
'order-summary': {
dataIn: {
subTotal, // payload > subtotal
voucherDiscount, // payload > discount
shopperFee, // payload > shopee_fee
deliveryFee, // payload > delivery_fee
grandTotal, // payload > total_amount
},
},
'submit-order': {
dataIn: {
disabled, // true or false
loading, // true or false
},
dataOut, // function to apply order & checkout api
}
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 (dataLoadType="network-service")
axiosCheckout.tsx
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
const onRequest = (config: AxiosRequestConfig): AxiosRequestConfig => {
const token = '';
config.headers.Authorization = `Bearer ${token}`;
config.headers['x-public-key'] = '';
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);
};
const axiosCheckout = axios.create({
baseURL: 'https://....',
});
axiosCheckout.interceptors.request.use(onRequest, onRequestError);
axiosCheckout.interceptors.response.use(onResponse, onResponseError);
export default axiosCheckout;
Checkout Screen
import * as React from 'react';
import { Button, Text } from 'react-native-paper';
import { CheckoutGAppFlow } from 'serino-mobile-gapp-checkout-flow';
import { GlobalContext } from '../context/GlobalContext';
import axiosCart from '../library/axiosCart';
import axiosCheckout from '../library/axiosCheckout';
import axiosOrder from '../library/axiosOrder';
import OrderItems from '../components/Cart/OrderedItems';
import OrderSummary from '../components/Cart/OrderSummary';
import checkoutJsonStab from '../json-stab/place-order copy.json';
const Checkout = ({ navigation }: any) => {
const context: any = React.useContext(GlobalContext);
const reconstructOrderPayload = (values: any) => {
return {
orders: [
{
action_to_proceed:
values.action_to_proceed ||
'Cancel the whole order if any item is out of stock',
cart_id: values.cart_id || 'a89b5c67-4c19-40e0-a81b-062523a078fb',
change_for: values.total_amount || '0',
customer: {
contact_number: values.contact_number || '+639876546231',
email: values.email || '[email protected]',
first_name: values.first_name || 'Ej',
last_name: values.last_name || 'Dalman',
reference_1: values.reference_1 || '',
reference_2: values.reference_2 || '',
reference_3: values.reference_3 || '',
},
fulfillment_type: values.fulfillment_type || 'deliver later',
items: values.items,
merchant_reference_id: values.merchant_reference_id || 'market',
notes: [{ type: 'Order Notes', notes: '' }],
platform: 'Web',
platform_details:
values.platform_details ||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
promo_reference_id: '',
reference_1: '',
reference_2: '',
reference_3: '',
reservation_reference: 'branch_advance_6',
schedule: '2023-02-28 10:30:0',
shipping_address: {
barangay: '',
city: '',
details: '',
full_address:
'BLK 10 LOT 10 SAMPAGUITA STREET, Bel-Air, Makati, Metro Manila, Philippines',
landmark: '',
latitude: 14.554729,
longitude: 121.0244452,
pinned_address: 'Makati, Metro Manila, Philippines',
region: '',
street: '',
zip_code: '',
},
source: 'Central PH',
store_reference_id: '6',
},
],
payment: {
type: values.payment_method_type,
option: values.payment_method,
},
};
};
const payload = {
...checkoutJsonStab,
payment_method_type:
context.paymentMethod?.parent_type || context.paymentMethod?.type,
payment_method: context.paymentMethod?.text,
merchant_processor_id: context.paymentMethod?.id,
merchant_transaction_reference: 'CENTRAL03411',
processor: {
token: '',
redirect_url: {
success:
'https://ordering.com/CENTRAL03411/payment-result?status=sucess',
failure:
'https://ordering.com/CENTRAL03411/payment-result?status=failure',
cancel:
'https://ordering.com/CENTRAL03411/payment-result?status=cancel',
},
},
items: context?.cartDetails.items.map((d: any) => {
const customData = JSON.parse(d.custom_data);
const barcodeDetails = customData
? customData.find((c: any) => c.name === 'barcode')
: {};
return {
barcode: barcodeDetails.value || '28400017503',
description:
d.itemDescription ||
'<p>Frito Lay it all start with farm grown potatoes cooked and seasoned to perfection, Then we add just the right balanced of tangly Vinegar. So every Lays potato is perfectly crispy and delicious happiness in every bite.</p>\n<ul>\n<li>No Artificial Flavours</li>\n<li>No Preservatives</li>\n</ul>\n<p><strong>Ingredients:</strong><br />Potatoes, Vegetable Oil (Sunflower, corn and/or Canola Oil), Salt & Vinegar Seasoning (Maltodextrin made from corn, Natural Flavours, Salt, Malic Acid and Vinegar).</p>',
image:
d.itemImage ||
'https://qa-centralmain.s3.ap-southeast-1.amazonaws.com/thumbnails/28400017503-01_8_thumbnail.jpg',
instructions: d.instructions || '',
name: d.itemName || 'Lays Salt & Vinegar Potato Chips 184.2g',
options: '',
price: d.price ? parseFloat(d.price) : 167.95,
quantity: d.quantity || 1,
reference_1: '',
reference_2: '',
reference_3: '',
reference_id: d.itemReferenceId || '24698',
sku: d.itemSKU || '105146',
type: d.itemReferenceType || 'basic_product',
weight: 0,
weight_price_per_unit: 0,
weight_uom: '',
};
}),
};
const public_key = 'pk-8c6a927a-972f-11ed-a8fc-0242ac120002';
const handleDataOut = (values: any) => {
console.log('checkout DATAOUT', values);
};
const fetchCart = React.useCallback(async () => {
try {
const res: any = await axiosCart.get('/cart');
context.setContext({
...context,
cartDetails: {
...context?.cartDetails,
items: res?.data?.data,
},
});
} catch (err: any) {}
}, []);
// life-cycle method to get cart details
React.useEffect(() => {
fetchCart();
}, []);
return (
<React.Fragment>
<CheckoutGAppFlow
dataLoad={{
axiosCheckout: axiosCheckout,
axiosOrder: axiosOrder,
endpoints: {
postOrder: '/public/create',
postCheckout: `/api/public/merchants/${public_key}/checkout`,
},
payload: payload,
}}
dataIn={{
dataLoadType: 'network-service',
constructOrderPayload: reconstructOrderPayload,
}}
dataOut={handleDataOut}
>
<OrderItems key="order-items" dataIn={{ navigation }} />
<SelectPaymentMethod
key="payment-method"
dataIn={{
label: context.paymentMethod?.text
? context.paymentMethod.text
: 'Select Payment Method',
}}
dataOut={() => {
navigation.navigate('PaymentMethodFlow');
}}
/>
<OrderSummary
key="order-summary"
dataIn={{
subTotal: 0,
voucherDiscount: 0,
showPickupDiscount: false,
pickupDiscount: 0,
showShopperFee: false,
shopperFee: 0,
showDeliveryFee: false,
deliveryFee: 0,
}}
/>
<CheckoutButton
key="submit-order"
dataIn={{ label: 'Pay Now' }}
dataOut={() => {}}
/>
</CheckoutGAppFlow>
</React.Fragment>
);
};
const CheckoutButton = (props: any) => {
return (
<Button
mode={props?.dataIn?.mode || 'contained'}
disabled={props?.dataIn?.disabled || props?.dataIn?.loading}
onPress={props?.dataOut}
>
{props?.dataIn?.loading ? 'Loading...' : props?.dataIn?.label}
</Button>
);
};
const SelectPaymentMethod = ({ dataIn, dataOut }: any) => {
return (
<React.Fragment>
<Text>Select Payment method</Text>
<CheckoutButton
dataIn={{
label: dataIn.label,
mode: 'outlined',
}}
dataOut={dataOut}
/>
</React.Fragment>
);
};
export default Checkout;
License
MIT