Skip to content

Commit 14d2caf

Browse files
Input Validation info added in card componenet (#77)
2.1.21
1 parent 25a561d commit 14d2caf

File tree

8 files changed

+149
-74
lines changed

8 files changed

+149
-74
lines changed

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"@react-native-community/checkbox": "^0.5.16",
1414
"react": "18.2.0",
1515
"react-native": "0.72.4",
16-
"react-native-cashfree-pg-sdk": "^2.1.19-dev.3"
16+
"react-native-cashfree-pg-sdk": "^2.1.20-dev.1"
1717
},
1818
"devDependencies": {
1919
"@babel/core": "^7.20.0",

example/src/App.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import * as React from 'react';
33
import { Component } from 'react';
44
import CheckBox from '@react-native-community/checkbox';
55
import { Button, Image, Platform, ScrollView, StyleSheet, Text, TextInput, ToastAndroid, View, } from 'react-native';
6-
import { CFPaymentGatewayService, CFCard, } from 'react-native-cashfree-pg-sdk';
6+
import { CFPaymentGatewayService, } from 'react-native-cashfree-pg-sdk';
77
import { Card, CFCardPayment, CFDropCheckoutPayment, CFEnvironment, CFPaymentComponentBuilder, CFPaymentModes, CFSession, CFThemeBuilder, CFUPI, CFUPIIntentCheckoutPayment, CFUPIPayment, SavedCard, UPIMode, ElementCard, } from 'cashfree-pg-api-contract';
8+
import CustomCardInput from './CustomCardInput';
89
const BASE_RESPONSE_TEXT = 'Payment Status will be shown here.';
910
export default class App extends Component {
1011
constructor() {
@@ -28,7 +29,7 @@ export default class App extends Component {
2829
this.cfCardInstance = this.createCFCard();
2930
}
3031
createCFCard() {
31-
return (React.createElement(CFCard, { cfSession: this.getFixSession(), style: { flex: 1 }, cardListener: this.handleCFCardInput, placeholder: "Enter Card Number", placeholderTextColor: "#0000ff", underlineColorAndroid: "transparent", cursorColor: "gray", returnKeyType: "next", ref: this.creditCardRef, onSubmitEditing: () => console.log('onSubmitEditing'), onEndEditing: () => console.log('onEndEditing'), onBlur: () => console.log('onBlur'), onFocus: () => console.log('onFocus') }));
32+
return React.createElement(CustomCardInput, { ref: this.creditCardRef, session: this.getFixSession(), cardListener: this.handleCFCardInput });
3233
}
3334
updateStatus = (message) => {
3435
this.setState({ responseText: message });
@@ -266,7 +267,7 @@ export default class App extends Component {
266267
* To handle scenario where merchant can't create order beforehand or before rendering.
267268
*/
268269
getFixSession() {
269-
return new CFSession('session_4HgWsBw3mS_0abA1dkj_OPG5KLCSOAAlh3eTQnJ_3P-qSLDvoxzdbD_MTdQd64W5IW3_Y9CBu8W_cyNb0VJ1lYMPPxof-IWHK8T--H4X8oaQseY2lB9aVDApayment', 'devstudio_91538541', this.state.cfEnv === 'PROD'
270+
return new CFSession('session_4zxKsUyNPorU6aZbHcxf8LJmyET2xA_svlDF69vSa8k9mkjAV3Zeosc2l3__mxno38hTK3pXR6_jL8X5R5WVC9BEXoN6SPef5V5lAYJyIE234IODJE1TXtIpayment', 'devstudio_20339474', this.state.cfEnv === 'PROD'
270271
? CFEnvironment.PRODUCTION
271272
: CFEnvironment.SANDBOX);
272273
}

example/src/App.tsx

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
UPIMode,
3737
ElementCard,
3838
} from 'cashfree-pg-api-contract';
39+
import CustomCardInput from './CustomCardInput';
3940

4041
const BASE_RESPONSE_TEXT = 'Payment Status will be shown here.';
4142

@@ -63,23 +64,10 @@ export default class App extends Component {
6364
}
6465

6566
createCFCard() {
66-
return (
67-
<CFCard
68-
cfSession={this.getFixSession()}
69-
style={{flex: 1}}
70-
cardListener={this.handleCFCardInput}
71-
placeholder="Enter Card Number"
72-
placeholderTextColor="#0000ff"
73-
underlineColorAndroid="transparent"
74-
cursorColor="gray"
75-
returnKeyType="next"
76-
ref={this.creditCardRef}
77-
onSubmitEditing={() => console.log('onSubmitEditing')}
78-
onEndEditing={() => console.log('onEndEditing')}
79-
onBlur={() => console.log('onBlur')}
80-
onFocus={() => console.log('onFocus')}
81-
/>
82-
);
67+
return <CustomCardInput
68+
ref={this.creditCardRef}
69+
session={this.getFixSession()}
70+
cardListener={this.handleCFCardInput} />;
8371
}
8472

8573
updateStatus = (message: string) => {
@@ -349,8 +337,8 @@ export default class App extends Component {
349337
*/
350338
private getFixSession(): CFSession {
351339
return new CFSession(
352-
'session_4HgWsBw3mS_0abA1dkj_OPG5KLCSOAAlh3eTQnJ_3P-qSLDvoxzdbD_MTdQd64W5IW3_Y9CBu8W_cyNb0VJ1lYMPPxof-IWHK8T--H4X8oaQseY2lB9aVDApayment',
353-
'devstudio_91538541',
340+
'session_4zxKsUyNPorU6aZbHcxf8LJmyET2xA_svlDF69vSa8k9mkjAV3Zeosc2l3__mxno38hTK3pXR6_jL8X5R5WVC9BEXoN6SPef5V5lAYJyIE234IODJE1TXtIpayment',
341+
'devstudio_20339474',
354342
this.state.cfEnv === 'PROD'
355343
? CFEnvironment.PRODUCTION
356344
: CFEnvironment.SANDBOX,

example/src/CustomCardInput.js

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/src/CustomCardInput.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type {CFSession} from 'cashfree-pg-api-contract';
2+
import React, {forwardRef} from 'react';
3+
import {CFCard} from 'react-native-cashfree-pg-sdk';
4+
5+
interface CustomCardInputProps {
6+
cardListener?: (response: any) => void;
7+
session: CFSession;
8+
[key: string]: any; // Allow other props
9+
}
10+
const CustomCardInput = forwardRef<any, CustomCardInputProps>(
11+
({cardListener, session, ...props}, ref) => (
12+
<CFCard
13+
cfSession={session}
14+
style={{flex: 1}}
15+
cardListener={cardListener}
16+
placeholder="Enter Card Number"
17+
placeholderTextColor="#0000ff"
18+
underlineColorAndroid="transparent"
19+
cursorColor="gray"
20+
returnKeyType="next"
21+
ref={ref}
22+
onSubmitEditing={() => console.log('onSubmitEditing')}
23+
onEndEditing={() => console.log('onEndEditing')}
24+
onBlur={() => console.log('onBlur')}
25+
onFocus={() => console.log('onFocus')}
26+
{...props}
27+
/>
28+
),
29+
);
30+
31+
export default CustomCardInput;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-cashfree-pg-sdk",
3-
"version": "2.1.20",
3+
"version": "2.1.21",
44
"description": "Cashfree PG Plugin for React Native",
55
"main": "lib/commonjs/index.js",
66
"module": "lib/module/index.js",

src/Card/CFCardComponent.js

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,24 @@ function luhnCheck(cardNumber) {
2222
}
2323
return sum % 10 === 0;
2424
}
25+
function getInputValidationDetails(cardBinResponse) {
26+
if (!cardBinResponse || !cardBinResponse.scheme) {
27+
return null;
28+
}
29+
let schemeType = cardBinResponse.scheme.toLowerCase();
30+
let inputValidationDetails;
31+
switch (schemeType) {
32+
case 'amex':
33+
inputValidationDetails = { max_input_length: 15, cvv_length: 4 };
34+
break;
35+
case 'diners':
36+
inputValidationDetails = { max_input_length: 14, cvv_length: 3 };
37+
break;
38+
default: // Covers visa, mastercard, rupay, jcb, discover, and unknown schemes
39+
inputValidationDetails = { max_input_length: 16, cvv_length: 3 };
40+
}
41+
return inputValidationDetails;
42+
}
2543
/**
2644
* Fetching Tdr info with card bin data & cfSession object
2745
* @param session : for payment sessionId & env
@@ -73,9 +91,9 @@ const CardInput = forwardRef(({ cfSession, cardListener, style, ...props }, ref)
7391
doPayment,
7492
doPaymentWithPaymentSessionId,
7593
}));
76-
let tdrJson = null;
77-
let cardBinJson = null;
78-
let firstEightDigits = '';
94+
const tdrJsonRef = React.useRef(null);
95+
const cardBinJsonRef = React.useRef(null);
96+
const firstEightDigitsRef = React.useRef('');
7997
const handleChange = React.useCallback(async (cardNumber) => {
8098
let completeResponse = {};
8199
const textWithoutSpaces = cardNumber.replaceAll(' ', '');
@@ -95,7 +113,7 @@ const CardInput = forwardRef(({ cfSession, cardListener, style, ...props }, ref)
95113
formattedText += ' ';
96114
}
97115
inputNumberRef.current = formattedText;
98-
setInputNumber(formattedText);
116+
setInputNumber((prev) => prev === formattedText ? prev : formattedText);
99117
}
100118
let tdrResponse = null;
101119
let cardBinResponse = null;
@@ -106,63 +124,65 @@ const CardInput = forwardRef(({ cfSession, cardListener, style, ...props }, ref)
106124
await getTDR(cfSession, textWithoutSpaces)
107125
.then((response) => {
108126
tdrResponse = response;
127+
firstEightDigitsRef.current = textWithoutSpaces.substring(0, 8);
109128
})
110129
.catch(() => {
111130
tdrResponse = null;
112131
});
113132
await getCardBin(cfSession, textWithoutSpaces)
114133
.then((response) => {
115134
cardBinResponse = response;
135+
firstEightDigitsRef.current = textWithoutSpaces.substring(0, 8);
116136
})
117137
.catch(() => {
118138
cardBinResponse = null;
119139
});
120140
if (tdrResponse) {
121-
tdrJson = tdrResponse;
122-
completeResponse['tdr_info'] = tdrJson;
141+
tdrJsonRef.current = tdrResponse;
142+
completeResponse.tdr_info = tdrJsonRef.current;
123143
}
124144
if (cardBinResponse) {
125-
cardBinJson = cardBinResponse;
126-
completeResponse['card_bin_info'] = cardBinJson;
145+
cardBinJsonRef.current = cardBinResponse;
146+
completeResponse.card_bin_info = cardBinJsonRef.current;
147+
completeResponse.input_validation = getInputValidationDetails(cardBinJsonRef.current);
127148
}
128149
}
129150
if (textWithoutSpaces.length === 8) {
130-
firstEightDigits = textWithoutSpaces;
131151
await fetchDataAndSet();
132152
}
133153
else if (textWithoutSpaces.length > 8) {
134-
if (firstEightDigits === textWithoutSpaces.substring(0, 8)) {
135-
completeResponse['tdr_info'] = tdrJson;
136-
completeResponse['card_bin_info'] = cardBinJson;
154+
if (firstEightDigitsRef.current === textWithoutSpaces.substring(0, 8)) {
155+
completeResponse.tdr_info = tdrJsonRef.current;
156+
completeResponse.card_bin_info = cardBinJsonRef.current;
157+
completeResponse.input_validation = getInputValidationDetails(cardBinJsonRef.current);
137158
}
138159
else {
139-
firstEightDigits = textWithoutSpaces.substring(0, 8);
140-
tdrJson = null;
141-
cardBinJson = null;
160+
tdrJsonRef.current = null;
161+
cardBinJsonRef.current = null;
142162
await fetchDataAndSet();
143163
}
144164
}
145165
if (textWithoutSpaces.length < 8) {
146-
cardBinJson = null;
147-
tdrJson = null;
148-
firstEightDigits = '';
166+
tdrJsonRef.current = null;
167+
cardBinJsonRef.current = null;
168+
firstEightDigitsRef.current = '';
149169
}
150-
if (cardBinJson !== null) {
151-
completeResponse['card_network'] = cardBinJson['scheme'];
170+
if (cardBinJsonRef.current !== null) {
171+
completeResponse.card_network = cardBinJsonRef.current.scheme;
152172
}
153173
let luhnStatus = luhnCheck(textWithoutSpaces);
154174
if (luhnStatus) {
155-
completeResponse['luhn_check_info'] = 'SUCCESS';
175+
completeResponse.luhn_check_info = 'SUCCESS';
156176
if (textWithoutSpaces && textWithoutSpaces.length > 4) {
157-
completeResponse['last_four_digit'] = textWithoutSpaces.substring(textWithoutSpaces.length - 4);
177+
completeResponse.last_four_digit = textWithoutSpaces.substring(textWithoutSpaces.length - 4);
158178
}
159179
}
160180
else {
161-
completeResponse['luhn_check_info'] = 'FAIL';
181+
completeResponse.luhn_check_info = 'FAIL';
162182
}
163-
completeResponse['card_length'] = textWithoutSpaces.length;
183+
completeResponse.card_length = textWithoutSpaces.length;
164184
return cardListener(JSON.stringify(completeResponse));
165-
}, [cardListener]);
185+
}, [cfSession, cardListener]);
166186
const doPayment = (cardInfo) => {
167187
try {
168188
let cfCardNumber = inputNumberRef.current;

0 commit comments

Comments
 (0)