File Coverage

blib/lib/BankDetails/India.pm
Criterion Covered Total %
statement 99 119 83.1
branch 18 32 56.2
condition 7 18 38.8
subroutine 24 29 82.7
pod 14 15 93.3
total 162 213 76.0


line stmt bran cond sub pod time code
1             package BankDetails::India;
2 11     11   262658 use strict;
  11         78  
  11         299  
3 11     11   58 use warnings;
  11         21  
  11         303  
4 11     11   6605 use CHI;
  11         1069182  
  11         442  
5 11     11   106 use Carp qw (croak);
  11         27  
  11         556  
6 11     11   8082 use LWP::UserAgent;
  11         532911  
  11         456  
7 11     11   6176 use Moose;
  11         4825336  
  11         77  
8 11     11   86474 use Sereal qw(encode_sereal decode_sereal);
  11         10516  
  11         728  
9 11     11   88 use Digest::MD5 qw(md5_hex);
  11         33  
  11         497  
10 11     11   7112 use JSON;
  11         96886  
  11         66  
11 11     11   15282 use XML::Simple;
  11         94202  
  11         67  
12 11     11   812 use Cwd;
  11         26  
  11         14943  
13              
14             our $VERSION = '1.0';
15              
16             has user_agent => (
17             is => 'ro',
18             lazy => 1,
19             builder => '_build_user_agent',
20             );
21            
22             sub _build_user_agent {
23 8     8   23 my $self = shift;
24 8         86 return LWP::UserAgent->new;
25             }
26              
27             has api_url => (
28             isa => 'Str',
29             is => 'ro',
30             default => 'https://ifsc.razorpay.com/',
31             );
32              
33             sub ping_api {
34 12     12 1 41 my ($self) = @_;
35 12         415 my $response = $self->user_agent->get($self->api_url);
36 12 50       9276538 return ($response->code == 200) ? 1 : 0;
37             }
38              
39             has 'cache_data' => (
40             is => 'rw',
41             isa => 'CHI::Driver',
42             builder => '_build_cache_data',
43             );
44              
45             my $cwd = getcwd();
46             sub _build_cache_data {
47 9     9   14322 my $cache = CHI->new(driver => 'File',
48             namespace => 'BankDetailsIndiaIFSC',
49             root_dir => $cwd . '/cache/');
50 9         1219095 return $cache;
51             }
52              
53             sub get_all_data_by_ifsc {
54 1     1 1 20 my ($self, $ifsc_code) = @_;
55              
56 1         37 return $self->get_response($self->api_url, $ifsc_code);
57             }
58              
59             sub get_bank_name_by_ifsc {
60 3     3 1 64 my ($self, $ifsc_code) = @_;
61              
62 3         108 my $data = $self->get_response($self->api_url, $ifsc_code);
63 2         28 return $data->{'BANK'};
64             }
65              
66             sub get_address_by_ifsc {
67 2     2 1 737 my ($self, $ifsc_code) = @_;
68              
69 2         78 my $data = $self->get_response($self->api_url, $ifsc_code);
70 2         30 return $data->{'ADDRESS'};
71             }
72              
73             sub get_contact_by_ifsc {
74 1     1 1 144357 my ($self, $ifsc_code) = @_;
75              
76 1         30 my $data = $self->get_response($self->api_url, $ifsc_code);
77 1         10 return $data->{'CONTACT'};
78             }
79              
80             sub get_state_by_ifsc {
81 0     0 1 0 my ($self, $ifsc_code) = @_;
82              
83 0         0 my $data = $self->get_response($self->api_url, $ifsc_code);
84 0         0 return $data->{'STATE'};
85             }
86              
87             sub get_district_by_ifsc {
88 0     0 1 0 my ($self, $ifsc_code) = @_;
89              
90 0         0 my $data = $self->get_response($self->api_url, $ifsc_code);
91 0         0 return $data->{'DISTRICT'};
92             }
93              
94             sub get_city_by_ifsc {
95 2     2 1 146165 my ($self, $ifsc_code) = @_;
96              
97 2         67 my $data = $self->get_response($self->api_url, $ifsc_code);
98 2         28 return $data->{'CITY'};
99             }
100              
101             sub get_micr_code_by_ifsc {
102 1     1 1 14 my ($self, $ifsc_code) = @_;
103            
104 1         36 my $data = $self->get_response($self->api_url, $ifsc_code);
105 1         9 return $data->{'MICR'};
106             }
107              
108             sub get_imps_value {
109 0     0 1 0 my ($self, $ifsc_code) = @_;
110              
111 0         0 my $data = $self->get_response($self->api_url, $ifsc_code);
112 0         0 return $data->{'IMPS'};
113             }
114              
115             sub get_neft_value {
116 0     0 1 0 my ($self, $ifsc_code) = @_;
117            
118 0         0 my $data = $self->get_response($self->api_url, $ifsc_code);
119 0         0 return $data->{'NEFT'};
120             }
121              
122             sub get_rtgs_value {
123 0     0 1 0 my ($self, $ifsc_code) = @_;
124            
125 0         0 my $data = $self->get_response($self->api_url, $ifsc_code);
126 0         0 return $data->{'RTGS'};
127             }
128              
129             sub download_json {
130 2     2 1 5727 my ($self, $ifsc_code, $file_name) = @_;
131 2 100       9 return if ( !$self->ping_api );
132 1         46 my $request_url = $self->api_url.$ifsc_code;
133 1         32 my $response = $self->user_agent->get($request_url);
134 1   33     354 $file_name ||= "bankdetails_$ifsc_code.json";
135 1 50       161 open(my $fh, '>', $file_name) or die $!;
136 1         17 print $fh $response->decoded_content;
137 1         489 close($fh);
138             }
139              
140             sub download_xml {
141 2     2 1 83729 my ($self, $ifsc_code, $file_name) = @_;
142 2 100       9 return if ( !$self->ping_api );
143 1         40 my $request_url = $self->api_url.$ifsc_code;
144 1         36 my $response = $self->user_agent->get($request_url);
145 1         350 my $response_data = decode_json($response->decoded_content);
146 1         376 $self->_convert_json_boolean($response_data);
147 1         11 my $xml = XMLout($response_data, RootName => 'data', NoAttr => 1);
148 1   33     624 $file_name ||= "bankdetails_$ifsc_code.xml";
149 1 50       168 open(my $fh, '>', $file_name) or die $!;
150 1         26 print $fh $xml;
151 1         90 close($fh);
152             }
153              
154             sub get_response {
155 11     11 0 41 my ($self, $endpoint, $ifsc) = @_;
156 11 100 66     67 return if ( !$self->ping_api || !defined $endpoint || length $endpoint <= 0);
      66        
157              
158 10         733 $ifsc = uc($ifsc);
159 10         48 my $request_url = $endpoint.$ifsc;
160 10         241 my $cache_key = md5_hex(encode_sereal($ifsc));
161 10         34 my $response_data;
162 10         664 my $cache_response_data = $self->cache_data->get($cache_key);
163 10 100       5234 if (defined $cache_response_data) {
164 5         253 $response_data = decode_sereal($cache_response_data);
165             } else {
166 5         298 my $response = $self->user_agent->get($request_url);
167 5         2780382 my $response_content;
168              
169 5 100       65 if ($response->is_success) {
170 4         294 $response_content = $response->decoded_content;
171             } else {
172 1         17 croak "Failed to fetch data: " . $response->status_line;
173             }
174 4         1933 $response_data = decode_json($response_content);
175 4         43 $self->_convert_json_boolean($response_data);
176 4         402 $self->cache_data->set($cache_key, encode_sereal($response_data));
177             }
178 9         13902 return $response_data;
179             }
180              
181             sub _convert_json_boolean {
182 5     5   30 my ( $self, $data ) = @_;
183              
184 5 50       36 if (ref($data) eq 'HASH') {
    0          
185 5         56 foreach my $key (keys %$data) {
186 71 100 33     740 if (ref($data->{$key}) eq 'JSON::PP::Boolean') {
    50          
187 16 50       441 $data->{$key} = $data->{$key} ? 1 : 0;
188             } elsif (ref($data->{$key}) eq 'HASH' || ref($data->{$key}) eq 'ARRAY') {
189 0           $self->_convert_json_boolean($data->{$key});
190             }
191             }
192             } elsif (ref($data) eq 'ARRAY') {
193 0           for (my $i = 0; $i < scalar(@$data); $i++) {
194 0 0 0       if (ref($data->[$i]) eq 'JSON::PP::Boolean') {
    0          
195 0 0         $data->[$i] = $data->[$i] ? 1 : 0;
196             } elsif (ref($data->[$i]) eq 'HASH' || ref($data->[$i]) eq 'ARRAY') {
197 0           $self->_convert_json_boolean($data->[$i]);
198             }
199             }
200             }
201             }
202              
203             1;
204              
205             __END__
206              
207             =head1 NAME
208              
209             BankDetails::India - Perl interface to access the ifsc.razorpay.com webservice.
210              
211             =head1 VERSION
212              
213             Version 1.0
214              
215             =head1 SYNOPSIS
216              
217             use BankDetails::India;
218              
219             my $api = BankDetails::India->new();
220             $api->get_all_data_by_ifsc('KKBK0005652');
221              
222             =head1 DESCRIPTION
223              
224             BankDetails::India is a module that provides methods to fetch details of Indian banks
225             using their IFSC codes. It uses the Razorpay API to retrieve the bank details.
226              
227             =head1 METHODS
228              
229             =head2 new([%$args])
230              
231             Construct a new BankDetails::India instance. Optionally takes a hash or hash reference.
232              
233             # Instantiate the class.
234             my $api = BankDetails::India->new();
235              
236             =head3 api_url
237              
238             The URL of the API resource is read only attribute.
239              
240             # get the API endpoint.
241             $api->api_url;
242              
243             =head3 cache_data
244              
245             The cache engine used to cache the web service API calls. By default, it uses
246             file-based caching.
247              
248             # Instantiate the class by setting the cache engine.
249             my $api = BankDetails::India->new(
250             CHI->new(
251             driver => 'File',
252             namespace => 'bankdetails',
253             root_dir => '/tmp/cache/'
254             )
255             );
256              
257             # Set through method.
258             $api->cache_data(CHI->new(
259             driver => 'File',
260             namespace => 'bankdetails',
261             root_dir => '/tmp/cache/'
262             ));
263              
264             # get cache engine.
265             $api->cache_data
266              
267             =head2 ping_api()
268              
269             Checks whether the API endpoint is currently up.
270              
271             # Returns 1 if up or 0 if not.
272             $api->ping_api();
273              
274             =head2 get_all_data_by_ifsc
275              
276             Fetches all the available bank details for the given IFSC code.
277              
278             my $data = $bank_details->get_all_data_by_ifsc($ifsc_code);
279              
280             =head3 Arguments
281              
282             =over 4
283              
284             =item * C<$ifsc_code> (String, required) - The Indian Financial System Code (IFSC) of the bank branch.
285              
286             =back
287              
288             =head3 Returns
289              
290             Returns a hashref containing various details related to the bank branch.
291              
292             =head3 Data Structure
293              
294             The returned hashref has the following structure:
295              
296             {
297             IFSC => "SBIN0000123",
298             BANK => "State Bank of India",
299             ADDRESS => "Main Branch, Mumbai",
300             CONTACT => "022-12345678",
301             STATE => "Maharashtra",
302             DISTRICT => "Mumbai",
303             CITY => "Mumbai",
304             MICR => "400002007",
305             IMPS => 1,
306             NEFT => 1,
307             RTGS => 1,
308             }
309              
310             =head2 get_bank_name_by_ifsc($ifsc_code)
311              
312             Get the name of the bank based on the provided IFSC code.
313              
314             $api->get_bank_name_by_ifsc('KKBK0005652');
315              
316             =head2 get_address_by_ifsc($ifsc_code)
317              
318             Get the address of the bank based on the provided IFSC code.
319              
320             $api->get_address_by_ifsc('KKBK0005652');
321              
322             =head2 get_contact_by_ifsc($ifsc_code)
323              
324             Get the contact number of the bank based on the provided IFSC code.
325              
326             $api->get_contact_by_ifsc('KKBK0005652');
327              
328             =head2 get_state_by_ifsc($ifsc_code)
329              
330             Get the state of the bank based on the provided IFSC code.
331              
332             $api->get_state_by_ifsc('KKBK0005652');
333              
334             =head2 get_district_by_ifsc($ifsc_code)
335              
336             Get the district of the bank based on the provided IFSC code.
337              
338             $api->get_district_by_ifsc('KKBK0005652');
339              
340             =head2 get_city_by_ifsc($ifsc_code)
341              
342             Get the city of the bank based on the provided IFSC code.
343              
344             $api->get_city_by_ifsc('KKBK0005652');
345              
346             =head2 get_rtgs_value($ifsc_code)
347              
348             Checks whether the RTGS service is enabled or not for the input IFSC.
349              
350             # Returns 1 if RTGS service is enabled or 0 if not.
351             $api->get_rtgs_value('KKBK0005652');
352              
353             =head2 get_imps_value($ifsc_code)
354              
355             Checks whether the IMPS service is enabled or not for the input IFSC.
356              
357             # Returns 1 if IMPS service is enabled or 0 if not.
358             $api->get_imps_value('KKBK0005652');
359              
360             =head2 get_neft_value($ifsc_code)
361              
362             Checks whether the NEFT service is enabled or not for the input IFSC.
363              
364             # Returns 1 if NEFT service is enabled or 0 if not.
365             $api->get_neft_value('KKBK0005652');
366              
367             =head2 get_micr_code_by_ifsc($ifsc_code)
368              
369             Gets the MICR code (9-digit code) of the bank based on the provided IFSC code.
370              
371             # Returns micr code.
372             $api->get_micr_code_by_ifsc('KKBK0005652');
373              
374             =head2 download_json($ifsc_code, $filename)
375              
376             Download the complete BankDetails data for IFSC code as JSON file. Optional path and file name.
377              
378             $ifsc_code = 'KKBK0005652';
379              
380             # Using default path and file name.
381             $api->download_json($ifsc_code);
382              
383             # Using specific path and file name.
384             $filename = "/tmp/bankdetails_$ifsc_code.json";
385             $api->download_json($ifsc_code, $filename);
386              
387             =head2 download_xml($ifsc_code, $filename)
388              
389             Download the complete BankDetails data for IFSC code as XML file. Optional path and file name.
390              
391             $ifsc_code = 'KKBK0005652';
392              
393             # Using default path and file name.
394             $api->download_xml($ifsc_code);
395              
396             # Using specific path and file name.
397             $filename = "/tmp/bankdetails_$ifsc_code.xml";
398             $api->download_xml($ifsc_code, $filename);
399              
400             =head1 AUTHOR
401              
402             Rohit R Manjrekar, C<< <manjrekarrohit76@gmail.com> >>
403              
404             =head1 REPOSITORY
405              
406             L<https://github.com/rmanjrekar/Webservice>
407              
408             =head1 LICENSE AND COPYRIGHT
409              
410             MIT License
411              
412             Copyright (c) 2023 Rohit R Manjrekar
413              
414             Permission is hereby granted, free of charge, to any person obtaining a copy
415             of this software and associated documentation files (the "Software"), to deal
416             in the Software without restriction, including without limitation the rights
417             to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
418             copies of the Software, and to permit persons to whom the Software is
419             furnished to do so, subject to the following conditions:
420              
421             The above copyright notice and this permission notice shall be included in all
422             copies or substantial portions of the Software.
423              
424             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
425             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
426             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
427             AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
428             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
429             OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
430             SOFTWARE.
431              
432             =cut