react-nomba-checkout-sdk 2.0.5 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "react-nomba-checkout-sdk",
3
- "version": "2.0.5",
3
+ "version": "2.0.8",
4
4
  "main": "dist/index.js",
5
+ "files": [
6
+ "dist"
7
+ ],
5
8
  "module": "dist/index.esm.js",
6
9
  "types": "dist/index.d.ts",
7
10
  "scripts": {
@@ -11,7 +14,9 @@
11
14
  "lint": "eslint .",
12
15
  "lint:fix": "npm run lint -- --fix",
13
16
  "test": "jest --env=jsdom",
14
- "test:watch": "jest --watch --verbose --env=jsdom"
17
+ "test:watch": "jest --watch --verbose --env=jsdom",
18
+ "example": "npm run build && cd example && npm install && npm run dev",
19
+ "example:dev": "cd example && npm run dev"
15
20
  },
16
21
  "keywords": [],
17
22
  "author": "Israel Itua",
package/babel.config.js DELETED
@@ -1,13 +0,0 @@
1
- module.exports = {
2
- presets: [
3
- [
4
- "@babel/preset-env",
5
- {
6
- targets: {
7
- node: "current",
8
- },
9
- },
10
- ],
11
- "@babel/preset-typescript",
12
- ],
13
- };
package/rollup.config.js DELETED
@@ -1,43 +0,0 @@
1
- import typescript from "rollup-plugin-typescript2";
2
- import commonjs from "@rollup/plugin-commonjs";
3
- import external from "rollup-plugin-peer-deps-external";
4
- import resolve from "@rollup/plugin-node-resolve";
5
- import postcss from "rollup-plugin-postcss";
6
- import json from "@rollup/plugin-json";
7
- import pkg from "./package.json";
8
-
9
- export default {
10
- input: "src/index.tsx",
11
- output: [
12
- {
13
- file: pkg.main,
14
- format: "cjs",
15
- exports: "named",
16
- sourcemap: true,
17
- },
18
- {
19
- file: pkg.module,
20
- format: "es",
21
- exports: "named",
22
- sourcemap: true,
23
- },
24
- ],
25
- plugins: [
26
- external(),
27
- resolve({
28
- browser: true,
29
- preferBuiltins: false,
30
- }),
31
- json(),
32
- typescript({
33
- clean: true,
34
- }),
35
- commonjs(),
36
- postcss({
37
- extract: true,
38
- modules: true,
39
- minimize: true,
40
- sourceMap: true,
41
- }),
42
- ],
43
- };
@@ -1,26 +0,0 @@
1
- import axios from 'axios';
2
-
3
- export const handleNombaApiCall = async (
4
- url: string,
5
- method: string,
6
- body?: {} | null,
7
- customHeaders?: { [key: string]: string },
8
- environment?: string
9
- ) => {
10
- const baseUrl =
11
- environment === 'sandbox'
12
- ? 'https://sandbox.nomba.com/v1'
13
- : 'https://api.nomba.com/v1';
14
-
15
- const options = {
16
- method: method,
17
- headers: {
18
- 'content-type': 'application/json',
19
- ...customHeaders,
20
- },
21
- data: body && body,
22
- url: `${baseUrl}${url}`,
23
- };
24
- const response = await axios(options);
25
- return response;
26
- };
@@ -1,26 +0,0 @@
1
- import axios from 'axios';
2
-
3
- export const handleVendorApiCall = async (
4
- url: string,
5
- method: string,
6
- body?: {} | null,
7
- customHeaders?: { [key: string]: string },
8
- environment?: string
9
- ) => {
10
- const baseUrl =
11
- environment === 'sandbox'
12
- ? 'https://sandbox.nomba.com/v1'
13
- : 'https://api.nomba.com/v1';
14
-
15
- const options = {
16
- method: method,
17
- headers: {
18
- 'content-type': 'application/json',
19
- ...customHeaders,
20
- },
21
- data: body && body,
22
- url: `${baseUrl}${url}`,
23
- };
24
- const response = await axios(options);
25
- return response;
26
- };
@@ -1,35 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- interface CardCheckoutPayload {
4
- orderReference: string;
5
- cardDetails: string;
6
- saveCard?: boolean;
7
- accountId?: string;
8
- }
9
-
10
- export const useCardCheckout = async (payload: CardCheckoutPayload) => {
11
- try {
12
- const response = await handleVendorApiCall(
13
- "/checkout/checkout-card-detail",
14
- "POST",
15
- {
16
- ...payload,
17
- key: "",
18
- deviceInformation: {
19
- httpBrowserLanguage: navigator.language,
20
- httpBrowserJavaEnabled: "true",
21
- httpBrowserJavaScriptEnabled: "true",
22
- httpBrowserColorDepth: window.screen.colorDepth.toString(),
23
- httpBrowserScreenHeight: window.screen.height.toString(),
24
- httpBrowserScreenWidth: window.screen.width.toString(),
25
- httpBrowserTimeDifference: new Date().getTimezoneOffset().toString(),
26
- userAgentBrowserValue: navigator.userAgent,
27
- deviceChannel: "Browser",
28
- },
29
- }
30
- );
31
- return response.data;
32
- } catch (error: any) {
33
- return error;
34
- }
35
- };
@@ -1,21 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- interface OtpRequest {
4
- otp: string;
5
- orderReference: string | undefined;
6
- transactionId?: string | undefined;
7
- accountId?: string;
8
- }
9
-
10
- export const useCardCheckoutOtp = async (payload: OtpRequest) => {
11
- try {
12
- const response = await handleVendorApiCall(
13
- "/checkout/checkout-card-otp",
14
- "POST",
15
- payload
16
- );
17
- return response.data;
18
- } catch (error: any) {
19
- return error;
20
- }
21
- };
@@ -1,10 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- export const useFetchUssdBanks = async () => {
4
- try {
5
- const response = await handleVendorApiCall(`/checkout/ussd/banks`, "GET");
6
- return response.data;
7
- } catch (error: any) {
8
- return error;
9
- }
10
- };
@@ -1,13 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- export const useGenerateQrCode = async (orderReference: string) => {
4
- try {
5
- const response = await handleVendorApiCall(
6
- `/checkout/qr/${orderReference}`,
7
- "GET"
8
- );
9
- return response.data;
10
- } catch (error: any) {
11
- return error;
12
- }
13
- };
@@ -1,30 +0,0 @@
1
- import { handleNombaApiCall } from './handleNombaApiCall';
2
-
3
- interface GenerateTokenPayload {
4
- clientId: string;
5
- clientSecret: string;
6
- accountId: string;
7
- environment?: string;
8
- }
9
-
10
- export const useGenerateToken = async (payload: GenerateTokenPayload) => {
11
- try {
12
- const response = await handleNombaApiCall(
13
- '/auth/token/issue',
14
- 'POST',
15
- {
16
- grant_type: 'client_credentials',
17
- client_id: payload.clientId,
18
- client_secret: payload.clientSecret,
19
- },
20
- {
21
- accountId: payload.accountId,
22
- },
23
- payload.environment
24
- );
25
-
26
- return response;
27
- } catch (error: any) {
28
- return error;
29
- }
30
- };
@@ -1,13 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- export const useGetOrder = async (orderReference: string) => {
4
- try {
5
- const response = await handleVendorApiCall(
6
- `/checkout/order/${orderReference}`,
7
- "GET"
8
- );
9
- return response.data;
10
- } catch (error: any) {
11
- return error;
12
- }
13
- };
@@ -1,28 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- interface UssdCodeRequest {
4
- ussdBankId: string;
5
- bankName: string;
6
- bankCode: string;
7
- processor: string;
8
- processorCodeName: string;
9
- ussdCodeFormat: string;
10
- enabled: boolean;
11
- promptMessage: string;
12
- }
13
-
14
- export const useGetUssdCode = async (payload: {
15
- ussdCode: UssdCodeRequest;
16
- orderId: string;
17
- }) => {
18
- try {
19
- const response = await handleVendorApiCall(
20
- `/checkout/ussd/code`,
21
- "POST",
22
- payload
23
- );
24
- return response.data;
25
- } catch (error: any) {
26
- return error;
27
- }
28
- };
@@ -1,68 +0,0 @@
1
- import eventBus from '../eventBus';
2
- import { handleNombaApiCall } from './handleNombaApiCall';
3
-
4
- interface CheckoutPayload {
5
- order: {
6
- orderReference: string;
7
- customerId: string;
8
- callbackUrl: string;
9
- customerEmail: string;
10
- amount: string;
11
- currency: string;
12
- accountId: string;
13
- splitRequest?: {
14
- splitType: string;
15
- splitList: [
16
- {
17
- accountId: string;
18
- value: number;
19
- },
20
- ];
21
- };
22
- orderMetaData?: {
23
- [key: string]: any;
24
- };
25
- };
26
- tokenizeCard: boolean;
27
- clientId: string;
28
- accountId: string;
29
- environment?: string;
30
- onCreateOrder: (orderReference: string) => void;
31
- onFailure: (e: any) => void;
32
- onClose: () => {};
33
- onPaymentSuccess: (order: any) => {};
34
- }
35
-
36
- export const useNombaCheckout = async (payload: CheckoutPayload) => {
37
- try {
38
- console.log('🔗 Using LOCAL SDK version!', payload.order.orderMetaData);
39
- const response = await handleNombaApiCall(
40
- '/checkout/order',
41
- 'POST',
42
- {
43
- order: {
44
- ...payload.order,
45
- accountId: payload.accountId,
46
- },
47
- tokenizeCard: payload.tokenizeCard,
48
- },
49
- {
50
- accountId: payload.accountId,
51
- public_key: payload.clientId,
52
- 'X-Nomba-Integration': 'react-sdk',
53
- },
54
- payload.environment
55
- );
56
-
57
- eventBus.emit('openModal', {
58
- orderId: response?.data?.data?.orderReference,
59
- onClose: payload.onClose,
60
- onPaymentSuccess: payload.onPaymentSuccess,
61
- environment: payload.environment,
62
- });
63
- return payload.onCreateOrder(response.data);
64
- } catch (error: any) {
65
- payload.onFailure?.(error);
66
- return error;
67
- }
68
- };
@@ -1,12 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- export const useResendOtp = async (orderReference: string) => {
4
- try {
5
- const response = await handleVendorApiCall("/checkout/resend-otp", "POST", {
6
- orderReference,
7
- });
8
- return response.data;
9
- } catch (error: any) {
10
- return error;
11
- }
12
- };
@@ -1,14 +0,0 @@
1
- import { handleVendorApiCall } from "./handleVendorApiCall";
2
-
3
- export const useVerifyOrderStatus = async (orderReference: string) => {
4
- try {
5
- const response = await handleVendorApiCall(
6
- "/checkout/confirm-transaction-receipt",
7
- "POST",
8
- { orderReference }
9
- );
10
- return response.data;
11
- } catch (error: any) {
12
- return error;
13
- }
14
- };
@@ -1,19 +0,0 @@
1
- import React from 'react';
2
-
3
- export const CloseIcon = () => (
4
- <svg
5
- width='32'
6
- height='32'
7
- viewBox='0 0 32 32'
8
- fill='none'
9
- xmlns='http://www.w3.org/2000/svg'
10
- >
11
- <rect width='32' height='32' rx='16' fill='#F2F2F2' fillOpacity='0.64' />
12
- <path
13
- fillRule='evenodd'
14
- clipRule='evenodd'
15
- d='M11.7646 11.7646C11.8948 11.6344 12.1059 11.6344 12.236 11.7646L16.0003 15.5289L19.7646 11.7646C19.8948 11.6344 20.1059 11.6344 20.236 11.7646C20.3662 11.8948 20.3662 12.1059 20.236 12.236L16.4717 16.0003L20.236 19.7646C20.3662 19.8948 20.3662 20.1059 20.236 20.236C20.1059 20.3662 19.8948 20.3662 19.7646 20.236L16.0003 16.4717L12.236 20.236C12.1059 20.3662 11.8948 20.3662 11.7646 20.236C11.6344 20.1059 11.6344 19.8948 11.7646 19.7646L15.5289 16.0003L11.7646 12.236C11.6344 12.1059 11.6344 11.8948 11.7646 11.7646Z'
16
- fill='#0D0D0D'
17
- />
18
- </svg>
19
- );
@@ -1,18 +0,0 @@
1
- import React from "react";
2
-
3
- const Loader = () => (
4
- <svg
5
- width="18"
6
- height="21"
7
- viewBox="0 0 18 21"
8
- fill="none"
9
- xmlns="http://www.w3.org/2000/svg"
10
- >
11
- <path
12
- d="M10.3203 8.49095L12.002 7.47669L13.6836 6.46243L15.3652 5.44817L17.0468 4.43393V0.545959L15.3652 1.56021L13.6836 2.57447L12.002 3.58872L10.3203 4.60297L8.63871 5.6172V7.56118L6.95709 6.54697L5.27546 5.53271L3.50974 4.51845L1.82811 3.5042L0.146484 2.48994V6.37789L1.82811 7.39215L3.50974 8.40641L5.19136 9.42067L6.87298 10.4349L8.5546 11.4492L6.87298 12.4634L5.19136 13.4777L3.50974 14.4919L1.82811 15.5062L0.146484 16.3514V20.2394L1.82811 19.2251L3.50974 18.2108L5.19136 17.1966L6.87298 16.1824L8.5546 15.1681V13.2241L10.2362 14.2383L11.9179 15.2526L13.5995 16.2669L15.2811 17.2811L16.9628 18.2954V14.4074L15.2811 13.3932L13.5995 12.3789L11.9179 11.3646L10.2362 10.3504L8.5546 9.33613L10.3203 8.49095Z"
13
- fill="#121212"
14
- />
15
- </svg>
16
- );
17
-
18
- export default Loader;
@@ -1,183 +0,0 @@
1
- import React, { Component } from 'react';
2
- import '../styles.css';
3
- import Loader from '../assets/Loader';
4
- import { CloseIcon } from '../assets/CloseIcon';
5
- import eventBus from '../eventBus';
6
-
7
- interface NombaCheckoutModalState {
8
- orderId: string;
9
- isLoading: boolean;
10
- isOpen: boolean;
11
- onClose: () => void;
12
- onPaymentSuccess: (e: any) => void;
13
- environment: string;
14
- }
15
-
16
- class NombaCheckoutModal extends Component<{}, NombaCheckoutModalState> {
17
- constructor(props: {}) {
18
- super(props);
19
- this.state = {
20
- orderId: '',
21
- isLoading: true,
22
- isOpen: false,
23
- onClose: () => {},
24
- onPaymentSuccess: () => {},
25
- environment: 'live',
26
- };
27
- }
28
-
29
- handleOpen = (orderId: string) => {
30
- this.setState({ isOpen: true, orderId });
31
- };
32
-
33
- handleClose = () => {
34
- this.state.onClose?.();
35
- this.setState({ isOpen: false });
36
- };
37
-
38
- handleIframeLoad = () => {
39
- this.setState({ isLoading: false });
40
- };
41
-
42
- handleMessage = (event: MessageEvent) => {
43
- if (event.data?.type === 'onSuccess') {
44
- this.state?.onPaymentSuccess(event.data?.orderDetails);
45
- }
46
- };
47
-
48
- componentDidMount() {
49
- window.addEventListener('message', this.handleMessage);
50
-
51
- eventBus.on(
52
- 'openModal',
53
- ({
54
- orderId,
55
- onClose,
56
- environment,
57
- onPaymentSuccess,
58
- }: NombaCheckoutModalState) => {
59
- this.setState({
60
- isOpen: true,
61
- orderId,
62
- onClose,
63
- environment,
64
- onPaymentSuccess,
65
- });
66
- }
67
- );
68
-
69
- eventBus.on('closeModal', () => {
70
- this.setState({ isOpen: false });
71
- });
72
- }
73
-
74
- componentWillUnmount() {
75
- window.removeEventListener('message', this.handleMessage);
76
- eventBus.off('openModal', this.handleOpen);
77
- eventBus.off('closeModal', this.handleClose);
78
- }
79
-
80
- render() {
81
- const { isLoading, isOpen, orderId } = this.state;
82
-
83
- if (!isOpen) return null;
84
-
85
- return (
86
- <div style={modalStyles.overlay} onClick={this.handleClose}>
87
- <div style={modalStyles.modal} onClick={(e) => e.stopPropagation()}>
88
- <div style={modalStyles.content}>
89
- {isLoading && (
90
- <div style={modalStyles.loader}>
91
- <div className='spinner'></div>
92
- <Loader />
93
- </div>
94
- )}
95
- <button style={modalStyles.closeButton} onClick={this.handleClose}>
96
- <CloseIcon />
97
- </button>
98
-
99
- <iframe
100
- src={`https://checkout.nomba.com/${this.state.environment === 'sandbox' ? 'sandbox' : 'pay'}/${orderId}`}
101
- allow='clipboard-write clipboard-read'
102
- width='100%'
103
- height='80vh'
104
- style={modalStyles.iframe}
105
- title='Nomba checkout'
106
- onLoad={this.handleIframeLoad}
107
- id='checkout-sdk-iframe'
108
- name='react-sdk'
109
- />
110
- </div>
111
- </div>
112
- </div>
113
- );
114
- }
115
- }
116
-
117
- const modalStyles: { [key: string]: React.CSSProperties } = {
118
- overlay: {
119
- position: 'fixed',
120
- top: 0,
121
- left: 0,
122
- right: 0,
123
- bottom: 0,
124
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
125
- display: 'flex',
126
- justifyContent: 'center',
127
- alignItems: 'center',
128
- zIndex: 9999,
129
- },
130
- modal: {
131
- backgroundColor: 'white',
132
- width: '100%',
133
- maxWidth: '60vw',
134
- borderRadius: '8px',
135
- boxShadow: '0 4px 8px rgba(0, 0, 0, 0.1)',
136
- position: 'relative',
137
- height: '600px',
138
- maxHeight: '95vh',
139
-
140
- ...(window.innerWidth <= 768 ? { width: '98vw', maxWidth: '98vw' } : {}),
141
- },
142
-
143
- header: {
144
- position: 'relative',
145
- display: 'flex',
146
- justifyContent: 'space-between',
147
- alignItems: 'center',
148
- },
149
- closeButton: {
150
- position: 'absolute',
151
- top: '16px',
152
- right: '16px',
153
- border: 'none',
154
- background: 'transparent',
155
- },
156
- content: {
157
- position: 'relative',
158
- },
159
- iframe: {
160
- border: 'none',
161
- borderRadius: '8px',
162
- width: '100%',
163
- maxHeight: '95vh',
164
- height: '600px',
165
- display: 'block',
166
- },
167
- loader: {
168
- position: 'absolute',
169
- top: 0,
170
- left: 0,
171
- width: '100%',
172
- height: '100%',
173
- backgroundColor: 'rgba(255, 255, 255, 0.8)',
174
- display: 'flex',
175
- flexDirection: 'column',
176
- alignItems: 'center',
177
- justifyContent: 'center',
178
- fontSize: '18px',
179
- fontWeight: 'bold',
180
- },
181
- };
182
-
183
- export { NombaCheckoutModal };
package/src/eventBus.ts DELETED
@@ -1,25 +0,0 @@
1
- class EventBus {
2
- private events: { [key: string]: Array<(data: any) => void> } = {};
3
-
4
- on(event: string, listener: (data: any) => void): void {
5
- if (!this.events[event]) {
6
- this.events[event] = [];
7
- }
8
- this.events[event].push(listener);
9
- }
10
-
11
- emit(event: string, data: any): void {
12
- if (this.events[event]) {
13
- this.events[event].forEach(listener => listener(data));
14
- }
15
- }
16
-
17
- off(event: string, listener: (data: any) => void): void {
18
- if (this.events[event]) {
19
- this.events[event] = this.events[event].filter(l => l !== listener);
20
- }
21
- }
22
- }
23
-
24
- const eventBus = new EventBus();
25
- export default eventBus;
@@ -1,26 +0,0 @@
1
- import React from "react";
2
- import ReactDOM from "react-dom/client";
3
- import { NombaCheckoutModal } from "../components/NombaCheckoutModal";
4
-
5
- let root: ReactDOM.Root | null = null;
6
-
7
- export const InitializeNombaCheckout = () => {
8
- const modalDivId = "nomba-checkout-modal";
9
-
10
- let modalContainer = document.getElementById(modalDivId);
11
- if (!modalContainer) {
12
- modalContainer = document.createElement("div");
13
- modalContainer.id = modalDivId;
14
- document.body.appendChild(modalContainer);
15
- }
16
-
17
- if (!root) {
18
- root = ReactDOM.createRoot(modalContainer);
19
- }
20
-
21
- root!.render(
22
- <div>
23
- <NombaCheckoutModal />
24
- </div>
25
- );
26
- };