DBA Data[Home] [Help]

PACKAGE BODY: APPS.IBY_CC_VALIDATE

Source


1 PACKAGE BODY IBY_CC_VALIDATE AS
2 /* $Header: ibyccvlb.pls 120.5.12010000.3 2008/11/24 14:20:24 cjain ship $ */
3 
4 
5 -- *** Declaring global datatypes and variables ***
6 
7 
8   FUNCTION CheckCCDigits( p_cc_id  IN VARCHAR2 ) RETURN NUMBER
9   AS
10 
11 	v_DigitSum	INTEGER		:=0;
12 	v_CCDigit	INTEGER		:=0;
13 	v_CCLen		INTEGER		:=0;
14   BEGIN
15 	v_CCLen:=LENGTH(p_cc_id);
16 
17 	FOR v_Counter IN 1..v_CCLen LOOP
18 
19 	  v_CCDigit := TO_NUMBER(SUBSTR(p_cc_id,v_CCLen-v_Counter+1,1));
20 
21 	  -- every alternate digit beginning with the second one from the
22 	  -- right must be doubled and the resultant digits added together
23 	  --
24 	  IF MOD(v_Counter,2)=0 THEN
25 		--
26 		-- according to the algorithm, resulting digits must be
27 		-- added together; only an issue for #'s >=5
28 		IF v_CCDigit<5 THEN
29 		  v_CCDigit := v_CCDigit*2;
30 		ELSE
31 		  -- this function just happens to fit the algorithm
32 		  -- "double x and then add its digits together" for
33 		  -- all x >=5 and <=9
34 		  --
35 		  v_CCDigit := 1+2*(v_CCDigit-5);
36 		END IF;
37 	  END IF;
38 	  --DBMS_OUTPUT.PUT_LINE('digit value is : ' || v_CCDigit);
39 	  v_DigitSum := v_DigitSum + v_CCDigit;
40 
41 	END LOOP;
42 
43 	--DBMS_OUTPUT.PUT_LINE('digit sum is : ' || v_DigitSum);
44 
45 	RETURN MOD(v_DigitSum,10);
46 
47   EXCEPTION
48 --	WHEN VALUE_ERROR THEN
49 	WHEN OTHERS THEN
50 		RETURN NULL;
51   END CheckCCDigits;
52 
53 /*
54 ** This function returns the CC Type in String for the CC Type in
55 ** number passed. It maps the constant defined for CC Type in this
56 ** Package to ones in the LOOKUP Types for the type 'IBY_CARD_TYPES'.
57 */
58 
59     FUNCTION getLookupCCType( p_cc_type IN NUMBER )
60     RETURN VARCHAR2
61     AS
62 
63     BEGIN
64 
65        IF( p_cc_type = 0 ) THEN
66           RETURN 'UNKNOWN';
67        ELSIF( p_cc_type = 1 ) THEN
68           RETURN 'MASTERCARD';
69        ELSIF( p_cc_type = 2 ) THEN
70           RETURN 'VISA';
71        ELSIF( p_cc_type = 3 ) THEN
72           RETURN 'AMEX';
73        ELSIF( p_cc_type = 4 ) THEN
74           RETURN 'DINERS';
75        ELSIF( p_cc_type = 5 ) THEN
76           RETURN 'DISCOVER';
77        ELSIF( p_cc_type = 6 ) THEN
78           RETURN 'ENROUTE';
79        ELSIF( p_cc_type = 7 ) THEN
80           RETURN 'JCB';
81        ELSE
82           RETURN NULL;
83        END IF;
84 
85     EXCEPTION
86         WHEN OTHERS THEN
87                 RETURN NULL;
88     END getLookupCCType;
89 
90 
91   PROCEDURE StripCC (	p_api_version		IN	NUMBER,
92 			p_init_msg_list		IN	VARCHAR2,
93 			p_cc_id 		IN 	VARCHAR2,
94 			p_fill_chars		IN	VARCHAR2,
95 
96 			x_return_status		OUT NOCOPY VARCHAR2,
97 			x_msg_count		OUT NOCOPY NUMBER,
98 			x_msg_data		OUT NOCOPY VARCHAR2,
99 			x_cc_id 		OUT NOCOPY VARCHAR2,
100                         p_char_allowed          IN      VARCHAR2 DEFAULT 'N'
101 			)	AS
102 
103 	c_Digits	CONSTANT VARCHAR2(10) 	:='0123456789';
104         c_chars         CONSTANT VARCHAR2(52)   :='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
105 	v_StrippedCC	VARCHAR2(100)		:='';
106 	v_CCChar	CHAR;
107 	v_FoundBadChar	BOOLEAN			:=FALSE;
108   BEGIN
109 	FOR v_Counter IN 1..LENGTH(p_cc_id) LOOP
110 	  --
111 	  -- tests if a character is a digit
112 	  --
113 	  v_CCChar := SUBSTR(p_cc_id,v_Counter,1);
114 
115 	  IF INSTR(c_Digits,v_CCChar)>0 THEN
116 		v_StrippedCC := v_StrippedCC || v_CCChar;
117 	  ELSIF INSTR(p_fill_chars,v_CCChar)>0 THEN
118 		NULL;
119           ELSIF INSTR(c_chars,v_CCChar)>0	THEN
120 	  	v_StrippedCC := v_StrippedCC || v_CCChar;
121 	  ELSE
122 		-- an illegal character found in the string
123 		--
124 		v_FoundBadChar:=TRUE;
125 		--DBMS_OUTPUT.PUT_LINE('bad char: ' || v_CCChar);
126 		EXIT;
127 	  END IF;
128 	END LOOP;
129 
130 	IF v_FoundBadChar THEN
131 	  -- !!
132 	  -- do something useful here!!
133 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
134 	  x_cc_id := NULL;
135 	ELSE
136 	  x_return_status := FND_API.G_RET_STS_SUCCESS;
137 	  x_cc_id := v_StrippedCC;
138 	END IF;
139 
140 	--DBMS_OUTPUT.PUT_LINE('stripped value is: ' || v_StrippedCC);
141 
142   EXCEPTION
143 	WHEN OTHERS THEN
144 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
145 	  x_cc_id := NULL;
146   END StripCC;
147 
148   PROCEDURE StripCC (	p_api_version		IN	NUMBER,
149 			p_init_msg_list		IN	VARCHAR2,
150 			p_cc_id 		IN 	VARCHAR2,
151 
152 			x_return_status		OUT NOCOPY VARCHAR2,
153 			x_msg_count		OUT NOCOPY NUMBER,
154 			x_msg_data		OUT NOCOPY VARCHAR2,
155 			x_cc_id 		OUT NOCOPY VARCHAR2,
156                         p_char_allowed          IN      VARCHAR2 DEFAULT 'N'
157 			)	AS
158 
159   BEGIN
160 
161 	StripCC(p_api_version, p_init_msg_list, p_cc_id,
162 		c_FillerChars, x_return_status, x_msg_count,
163 		x_msg_data, x_cc_id, p_char_allowed );
164 
165   END StripCC;
166 
167   PROCEDURE GetCCType (	p_api_version		IN	NUMBER,
168 			p_init_msg_list		IN	VARCHAR2,
169 			p_cc_id 		IN 	VARCHAR2,
170 
171 			x_return_status		OUT NOCOPY VARCHAR2,
172 			x_msg_count		OUT NOCOPY NUMBER,
173 			x_msg_data		OUT NOCOPY VARCHAR2,
174 			x_cc_type 		OUT NOCOPY CCType
175 			)	AS
176 
177 	-- constants the lengths of various credit cards
178 
179 	c_MC_LEN	CONSTANT INTEGER	:= 16;
180 	c_VISA_LEN1	CONSTANT INTEGER	:= 13;
181 	c_VISA_LEN2	CONSTANT INTEGER	:= 16;
182 	c_AMEX_LEN	CONSTANT INTEGER	:= 15;
183 	c_DINERS_LEN	CONSTANT INTEGER	:= 14;
184 	c_DISCOVER_LEN	CONSTANT INTEGER	:= 16;
185 	c_ENROUTE_LEN	CONSTANT INTEGER	:= 15;
186 	c_JCB_LEN1	CONSTANT INTEGER	:= 16;
187 	c_JCB_LEN2	CONSTANT INTEGER	:= 15;
188 
189 	-- constants for credit card prefixes
190 
191 	c_VISA_PREFIX 	CONSTANT VARCHAR(4)	:= '4';
192 
193 	c_MC_PREFIX1 	CONSTANT VARCHAR(4)	:= '51';
194 	c_MC_PREFIX2 	CONSTANT VARCHAR(4)	:= '52';
195 	c_MC_PREFIX3 	CONSTANT VARCHAR(4)	:= '53';
196 	c_MC_PREFIX4 	CONSTANT VARCHAR(4)	:= '54';
197 	c_MC_PREFIX5 	CONSTANT VARCHAR(4)	:= '55';
198 
199 	c_DINERS_PREFIX1 CONSTANT VARCHAR(4)	:= '300';
200 	c_DINERS_PREFIX2 CONSTANT VARCHAR(4)	:= '301';
201 	c_DINERS_PREFIX3 CONSTANT VARCHAR(4)	:= '302';
202 	c_DINERS_PREFIX4 CONSTANT VARCHAR(4)	:= '303';
203 	c_DINERS_PREFIX5 CONSTANT VARCHAR(4)	:= '304';
204 	c_DINERS_PREFIX6 CONSTANT VARCHAR(4)	:= '305';
205 	c_DINERS_PREFIX7 CONSTANT VARCHAR(4)	:= '36';
206 	c_DINERS_PREFIX8 CONSTANT VARCHAR(4)	:= '38';
207 
208 	c_AMEX_PREFIX1 	CONSTANT VARCHAR(4)	:= '34';
209 	c_AMEX_PREFIX2 	CONSTANT VARCHAR(4)	:= '37';
210 
211 	c_DISCOVER_PREFIX CONSTANT VARCHAR(4)	:= '6011';
212 
213 	c_ENROUTE_PREFIX1 CONSTANT VARCHAR(4)	:= '2014';
214 	c_ENROUTE_PREFIX2 CONSTANT VARCHAR(4)	:= '2149';
215 
216 	c_JCB_PREFIX1	CONSTANT VARCHAR(4)	:= '3';
217 	c_JCB_PREFIX2	CONSTANT VARCHAR(4)	:= '2131';
218 	c_JCB_PREFIX3	CONSTANT VARCHAR(4)	:= '1800';
219 
220 	v_Length	INTEGER;
221 	v_DigitsOk	BOOLEAN;
222   BEGIN
223 	x_return_status := FND_API.G_RET_STS_SUCCESS;
224 
225 	IF (p_cc_id IS NULL) THEN
226 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
227 	  x_cc_type:=c_InvalidCC;
228 	  RETURN;
229 	END IF;
230 
231 	--DBMS_OUTPUT.PUT_LINE('cc length is: ' || v_Length);
232 
233 	v_Length:=LENGTH(p_cc_id);
234 
235 	IF (v_Length <=0) THEN
236 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
237 	  x_cc_type:=c_InvalidCC;
238 	  RETURN;
239 	END IF;
240 
241 	IF (v_Length=c_VISA_LEN1 OR v_Length=c_VISA_LEN2) AND
242 		INSTR(p_cc_id,c_VISA_PREFIX)=1		THEN
243 	  x_cc_type:=c_VisaCC;
244 	ELSIF v_Length=c_MC_LEN AND ( INSTR(p_cc_id,c_MC_PREFIX1)=1 OR
245 		INSTR(p_cc_id,c_MC_PREFIX2)=1 OR
246 		INSTR(p_cc_id,c_MC_PREFIX3)=1 OR
247 		INSTR(p_cc_id,c_MC_PREFIX4)=1 OR
248 		INSTR(p_cc_id,c_MC_PREFIX5)=1 )		THEN
249 	  x_cc_type:=c_McCC;
250 	ELSIF v_Length=c_AMEX_LEN AND ( INSTR(p_cc_id,c_AMEX_PREFIX1)=1
251 		OR INSTR(p_cc_id,c_AMEX_PREFIX2)=1 )	THEN
252 	  x_cc_type:=c_AmexCC;
253 	ELSIF v_Length=c_DISCOVER_LEN AND
254 		INSTR(p_cc_id,c_DISCOVER_PREFIX)=1	THEN
255 	  x_cc_type:=c_DiscoverCC;
256 	ELSIF v_Length=c_DINERS_LEN AND
257 		(INSTR(p_cc_id,c_DINERS_PREFIX1)=1 OR
258 		INSTR(p_cc_id,c_DINERS_PREFIX2)=1 OR
259 		INSTR(p_cc_id,c_DINERS_PREFIX3)=1 OR
260 		INSTR(p_cc_id,c_DINERS_PREFIX4)=1 OR
261 		INSTR(p_cc_id,c_DINERS_PREFIX5)=1 OR
262 		INSTR(p_cc_id,c_DINERS_PREFIX6)=1 OR
263 		INSTR(p_cc_id,c_DINERS_PREFIX7)=1 OR
264 		INSTR(p_cc_id,c_DINERS_PREFIX8)=1 )	THEN
265 	  x_cc_type:=c_DClubCC;
266 	ELSIF v_Length=c_ENROUTE_LEN AND
267 		(INSTR(p_cc_id,c_ENROUTE_PREFIX1)=1 OR
268 		INSTR(p_cc_id,c_ENROUTE_PREFIX2)=1)	THEN
269 	 x_cc_type:=c_EnrouteCC;
270 	ELSIF (v_Length=c_JCB_LEN1) AND
271 		INSTR(p_cc_id,c_JCB_PREFIX1)=1		THEN
272 	 x_cc_type:=c_JCBCC;
273 	ELSIF (v_Length=c_JCB_LEN2) AND
274 		(INSTR(p_cc_id,c_JCB_PREFIX2)=1 OR
275 		INSTR(p_cc_id,c_JCB_PREFIX3)=1)		THEN
276 	 x_cc_type:=c_JCBCC;
277 	ELSE
278 	 x_cc_type:=c_UnknownCC;
279 	END IF;
280 
281 	--DBMS_OUTPUT.PUT_LINE('seems like : ' || x_cc_type);
282 
283 	v_DigitsOk:= CheckCCDigits(p_cc_id) = 0;
284 
285 	-- this means there were some non-digit characters
286 	-- in the credit card number
287 	--
288 	IF v_DigitsOk IS NULL THEN
289 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
290 	  x_cc_type:=c_InvalidCC;
291 	  RETURN;
292 	END IF;
293 
294 	IF x_cc_type<>c_UnknownCC AND x_cc_type<>c_EnrouteCC THEN
295 	  IF NOT v_DigitsOk THEN
296 		x_cc_type:=c_InvalidCC;
297 	  END IF;
298 	END IF;
299 
300 	--DBMS_OUTPUT.PUT_LINE('cctype is : ' || x_cc_type);
301 
302   EXCEPTION
303 	WHEN OTHERS THEN
304 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
305 	  x_cc_type:=c_InvalidCC;
306   END GetCCType;
307 
308 
309 /*
310 ** This is an overloaded function which returns, a boolean value -
311 ** indicating whether the card is valid or not, AND CC type (in VARCHAR2)
312 ** from the lookup types defined for type 'IBY_CARD_TYPES'
313 */
314 
315   PROCEDURE ValidateCC (p_api_version		IN	NUMBER,
316 			p_init_msg_list		IN	VARCHAR2,
317 			p_cc_id 		IN 	VARCHAR2,
318 			p_expr_date		IN	DATE,
319 
320 			x_return_status		OUT NOCOPY VARCHAR2,
321 			x_msg_count		OUT NOCOPY NUMBER,
322 			x_msg_data		OUT NOCOPY VARCHAR2,
323 			x_cc_valid 		OUT NOCOPY BOOLEAN,
324 			x_cc_type               OUT NOCOPY VARCHAR2
325 			)	AS
326 
327 	v_CurrDate	DATE	:= SYSDATE();
328 	v_CardType	CCType;
329 	v_spread	REAL;
330   BEGIN
331 
332 	-- expr date is moved to the last day of the month it's on as
333 	-- most credit cards
334 	--
335 	v_spread:=MONTHS_BETWEEN(LAST_DAY(TRUNC(p_expr_date)),
336 		TRUNC(v_CurrDate));
337 	x_return_status := FND_API.G_RET_STS_SUCCESS;
338 
339 	--DBMS_OUTPUT.PUT_LINE('Difference in time: ' || v_spread);
340 	IF v_spread >= 0 THEN
341 
342 		GetCCType(p_api_version, p_init_msg_list, p_cc_id,
343 			x_return_status, x_msg_count, x_msg_data,
344 			v_CardType );
345 		x_cc_valid:=(v_CardType<>c_InvalidCC);
346                 x_cc_type := getLookupCCType( v_CardType );
347 
348 		/* set the other out variables here */
349 	ELSE
350 
351 		x_cc_valid:=FALSE;
352 
353 		/* set the other out variables here */
354 	END IF;
355 
356   EXCEPTION
357 	WHEN OTHERS THEN
358 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
359 	  x_cc_valid:=FALSE;
360   END ValidateCC;
361 
362 
363 /*
364 ** This is an overloaded function which returns, a boolean value -
365 ** indicating whether the card is valid or not.
366 */
367 
368   PROCEDURE ValidateCC (p_api_version		IN	NUMBER,
369 			p_init_msg_list		IN	VARCHAR2,
370 			p_cc_id 		IN 	VARCHAR2,
371 			p_expr_date		IN	DATE,
372 
373 			x_return_status		OUT NOCOPY VARCHAR2,
374 			x_msg_count		OUT NOCOPY NUMBER,
375 			x_msg_data		OUT NOCOPY VARCHAR2,
376 			x_cc_valid 		OUT NOCOPY BOOLEAN
377 			)	AS
378 
379         v_CC_Type       VARCHAR2(80);
380 
381   BEGIN
382 
383             ValidateCC (p_api_version       =>          p_api_version,
384                         p_init_msg_list     =>          p_init_msg_list,
385                         p_cc_id             =>          p_cc_id,
386                         p_expr_date         =>          p_expr_date,
387                         x_return_status     =>          x_return_status,
388                         x_msg_count         =>          x_msg_count,
389                         x_msg_data          =>          x_msg_data,
390                         x_cc_valid          =>          x_cc_valid,
391                         x_cc_type           =>          v_CC_Type
392                         );
393 
394   EXCEPTION
395 	WHEN OTHERS THEN
396 	  x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
397 	  x_cc_valid:=FALSE;
398 
399   END ValidateCC;
400 
401   PROCEDURE Get_CC_Issuer_Range
402   (p_card_number     IN     iby_creditcard.ccnumber%TYPE,
403    x_card_issuer     OUT NOCOPY iby_creditcard_issuers_b.card_issuer_code%TYPE,
404    x_issuer_range    OUT NOCOPY iby_cc_issuer_ranges.cc_issuer_range_id%TYPE,
405    x_card_prefix     OUT NOCOPY iby_cc_issuer_ranges.card_number_prefix%TYPE,
406    x_digit_check     OUT NOCOPY iby_creditcard_issuers_b.digit_check_flag%TYPE
407   )
408   IS
409     CURSOR c_range
410     (ci_card_number IN iby_creditcard.ccnumber%TYPE,
411      ci_card_len IN NUMBER)
412     IS
413       SELECT cc_issuer_range_id, r.card_issuer_code,
414         card_number_prefix, NVL(digit_check_flag,'N')
415       FROM iby_cc_issuer_ranges r, iby_creditcard_issuers_b i
416       WHERE (card_number_length = ci_card_len)
417         AND (INSTR(ci_card_number,card_number_prefix) = 1)
418         AND (r.card_issuer_code = i.card_issuer_code);
419   BEGIN
420     IF (c_range%ISOPEN) THEN CLOSE c_range; END IF;
421 
422     OPEN c_range(p_card_number,LENGTH(p_card_number));
423     FETCH c_range INTO x_issuer_range, x_card_issuer,
424       x_card_prefix, x_digit_check;
425     CLOSE c_range;
426 
427     IF (x_card_issuer IS NULL) THEN
428       x_card_issuer := G_CARD_TYPE_UNKNOWN;
429       x_digit_check := 'N';
430     END IF;
431 
432   END Get_CC_Issuer_Range;
433 
434   FUNCTION Get_CC_Issuer_Range
435   (p_card_number     IN     iby_creditcard.ccnumber%TYPE)
436   RETURN NUMBER
437   IS
438     lx_card_issuer     iby_creditcard_issuers_b.card_issuer_code%TYPE;
439     lx_issuer_range    iby_cc_issuer_ranges.cc_issuer_range_id%TYPE;
440     lx_card_prefix     iby_cc_issuer_ranges.card_number_prefix%TYPE;
441     lx_digit_check     iby_creditcard_issuers_b.digit_check_flag%TYPE;
442   BEGIN
443     Get_CC_Issuer_Range(p_card_number,lx_card_issuer,lx_issuer_range,
444       lx_card_prefix,lx_digit_check);
445     RETURN lx_issuer_range;
446   END Get_CC_Issuer_Range;
447 
448 END IBY_CC_VALIDATE;
449