Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for python #323

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,39 @@ tmp/
# Temp files
.*~

# python
__pycache__/
*.py[cod]
*$py.class

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST


.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

.vscode

109 changes: 74 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ The latest `scraper` workflow on GitHub should publish a `release-artifact` as w

Various official sources are linked below, with the ones currently used marked with a †

- List of NEFT IFSCs from [RBI website][combined]†
- List of RTGS IFSCs from [RBI website][rtgs]†
- RBI maintains several lists:
- [List of banks in India](https://www.rbi.org.in/commonman/english/scripts/banksinindia.aspx)
- [Websites of banks in India](https://www.rbi.org.in/scripts/banklinks.aspx).
- [Bankwise Volumes in ECS/NEFT/RTGS/Mobile](https://www.rbi.org.in/Scripts/NEFTUserView.aspx?Id=166)
- [List of Banks permitted to provide Mobile Banking](https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2463)
- List of NEFT IFSCs from [RBI website][combined]†
- List of RTGS IFSCs from [RBI website][rtgs]†
- RBI maintains several lists:
- [List of banks in India](https://www.rbi.org.in/commonman/english/scripts/banksinindia.aspx)
- [Websites of banks in India](https://www.rbi.org.in/scripts/banklinks.aspx).
- [Bankwise Volumes in ECS/NEFT/RTGS/Mobile](https://www.rbi.org.in/Scripts/NEFTUserView.aspx?Id=166)
- [List of Banks permitted to provide Mobile Banking](https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2463)
- NPCI website has several lists:
- [NACH Live Members][ach]†
- [RuPay Live Members](https://www.npci.org.in/what-we-do/rupay/live-members)
Expand All @@ -39,15 +39,18 @@ Various official sources are linked below, with the ones currently used marked w
SWIFT/BIC codes are supported for a few banks.

##### SBI
- https://sbi.co.in/web/nri/quick-links/swift-codes †
- https://sbi.co.in/documents/16012/263663/sbinri_merged_bran_swfcodet.xlsx †
- Branch codes from above are checked against the [SBI Branch Locator](https://www.sbi.co.in/web/home/locator/branch) to get the IFSC.

- https://sbi.co.in/web/nri/quick-links/swift-codes †
- https://sbi.co.in/documents/16012/263663/sbinri_merged_bran_swfcodet.xlsx †
- Branch codes from above are checked against the [SBI Branch Locator](https://www.sbi.co.in/web/home/locator/branch) to get the IFSC.

##### PNB

- https://pnbindia.com/downloadprocess.aspx?fid=Zb7ImdUNlz9Ge73qn1nXQg== †
- https://www.pnbindia.in/document/PNB-helpdesk/bic_code.pdf †

##### HDFC

- https://www.hdfcbank.com/nri-banking/correspondent-banks †

## Installation
Expand Down Expand Up @@ -110,6 +113,10 @@ Finally, to use the top-of-trunk version of this repo, use the following command

`go get github.com/razorpay/ifsc/v2@master`

## Python

`pip install ifsc`

## Support Matrix

Only the latest version of each SDK is considered.
Expand All @@ -120,6 +127,7 @@ Only the latest version of each SDK is considered.
| Ruby | ✅ | ✅ | ✅ (✅) | ✅ |
| Node.js | ✅ | ✅ | ❎ (❎) | ✅ |
| Go | ✅ | ✅ | ✅ (✅) | ✅ |
| Python | ✅ | ✅ | ✅ (✅) | ✅ |

## API Documentation

Expand Down Expand Up @@ -194,31 +202,31 @@ echo $client->lookupIFSC('https://ifsc.razorpay.com/HDFC0CAGSBK')->swift; // 'HD
### Node.js

```js
var ifsc = require('ifsc');

ifsc.validate('KKBK0000261'); // returns true
ifsc.validate('BOTM0XEEMRA'); // returns false

ifsc.fetchDetails('KKBK0000261').then(function(res) {
console.log(res);
// {
// MICR: '560226263',
// BRANCH: 'THE AGS EMPLOYEES COOP BANK LTD',
// ADDRESS: 'SANGMESH BIRADAR BANGALORE',
// STATE: 'KARNATAKA',
// CONTACT: '+91802265658',
// UPI: true,
// RTGS: true,
// CITY: 'BANGALORE',
// CENTRE: 'BANGALORE URBAN',
// DISTRICT: 'BANGALORE URBAN',
// NEFT: true,
// IMPS: true,
// SWIFT: 'HDFCINBB',
// BANK: 'HDFC Bank',
// BANKCODE: 'HDFC',
// IFSC: 'HDFC0CAGSBK'
// }
var ifsc = require("ifsc");

ifsc.validate("KKBK0000261"); // returns true
ifsc.validate("BOTM0XEEMRA"); // returns false

ifsc.fetchDetails("KKBK0000261").then(function (res) {
console.log(res);
// {
// MICR: '560226263',
// BRANCH: 'THE AGS EMPLOYEES COOP BANK LTD',
// ADDRESS: 'SANGMESH BIRADAR BANGALORE',
// STATE: 'KARNATAKA',
// CONTACT: '+91802265658',
// UPI: true,
// RTGS: true,
// CITY: 'BANGALORE',
// CENTRE: 'BANGALORE URBAN',
// DISTRICT: 'BANGALORE URBAN',
// NEFT: true,
// IMPS: true,
// SWIFT: 'HDFCINBB',
// BANK: 'HDFC Bank',
// BANKCODE: 'HDFC',
// IFSC: 'HDFC0CAGSBK'
// }
});

console.log(ifsc.bank.PUNB); // prints PUNB
Expand Down Expand Up @@ -409,6 +417,37 @@ func main() {

```

### Python

```

from ifsc import IFSC, Bank

ifsc_obj = IFSC()

ifsc_obj.validate("ABHY0065001") # returns True
ifsc_obj.validate_bank_code("ABHY") # returns True
ifsc_obj.get_bank_name("ABHY") # returns Abhyudaya Co-operative Bank
ifsc_obj.get_details("ABHY0065001")

"""

returns
{'ADDRESS': 'ABHYUDAYA BANK BLDG., B.NO.71, NEHRU NAGAR, KURLA (E), MUMBAI-400024', 'MICR': '400065001', 'DISTRICT': 'GREATER MUMBAI', 'ISO3166': 'IN-MH', 'STATE': 'MAHARASHTRA', 'BRANCH': 'Abhyudaya Co-operative Bank IMPS', 'CITY': 'MUMBAI', 'UPI': True, 'IMPS': True, 'SWIFT': None, 'RTGS': True, 'NEFT': True, 'CONTACT': '+912225260173', 'CENTRE': 'GREATER MUMBAI', 'BANK': 'Abhyudaya Co-operative Bank', 'BANKCODE': 'ABHY', 'IFSC': 'ABHY0065001'}

"""

bank_obj = Bank()
bank_obj.get_bank_details("ABHY")

"""

returns
{'code': 'ABHY', 'ifsc': 'ABHY0065001', 'micr': '400065001', 'iin': '607261', 'ach_credit': True, 'ach_debit': True, 'apbs': True, 'nach_debit': False, 'type': 'S-UCB', 'upi': True, 'name': 'Abhyudaya Co-operative Bank', 'bank_code': '065'}
"""

```

### Code Notes

Both the packages ship with a 300kb JSON file, that
Expand Down
13 changes: 13 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[tool.isort]
profile = "black"
line_length = 79
honor_noqa = true
src_paths = ["boto3", "tests"]

[tool.black]
line-length = 79
skip_string_normalization = true
50 changes: 50 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
import shutil
import glob
import pathlib
from setuptools import setup


BASE_DIR = pathlib.Path(__file__).parent.resolve()

long_description = (BASE_DIR / "README.md").read_text(encoding="utf-8")


try:
json_files = glob.glob(str(BASE_DIR / "src" / "*.json"))
os.makedirs(BASE_DIR / "src" / "python" / "data", exist_ok=True)
for json_file in json_files:
os.symlink(
json_file,
BASE_DIR / "src" / "python" / "data" / os.path.basename(json_file),
)
setup(
name="ifsc",
version="0.0.1",
author="sreevardhanreddi",
author_email="[email protected]",
description="This is part of the IFSC toolset released by Razorpay. You can find more details about the entire release at [ifsc.razorpay.com](https://ifsc.razorpay.com).",
long_description=long_description,
include_package_data=True,
package_dir={"ifsc": "src/python"},
package_data={"ifsc": ["data/*.json"]},
python_requires=">=3.7",
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
project_urls={
"Homepage": "https://github.com/razorpay/ifsc",
"Source": "https://github.com/razorpay/ifsc",
},
install_requires=[
"requests",
],
test_suite="tests",
zip_safe=False,
)
except Exception as e:
print("error: ", e, "during setup")
finally:
shutil.rmtree(BASE_DIR / "src" / "python" / "data")
4 changes: 4 additions & 0 deletions src/python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .ifsc import IFSC
from .bank import Bank

__all__ = ["IFSC", "Bank"]
27 changes: 27 additions & 0 deletions src/python/bank.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import json
from importlib.resources import files
from .ifsc import IFSC

pkg_path = files("ifsc.data")


with open(pkg_path.joinpath("banks.json")) as f:
banks = json.load(f)


class Bank:
def __init__(self):
self.banks = banks

def get_bank_details(self, bank_code):
if not bank_code in banks:
return
else:
data = banks[bank_code]
bank_name = IFSC().get_bank_name(bank_code)
if bank_name:
data["name"] = bank_name
if data["micr"] != "":
data["bank_code"] = data["micr"][3:6]

return data
87 changes: 87 additions & 0 deletions src/python/ifsc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import json
import requests
from importlib.resources import files

pkg_path = files("ifsc.data")

with open(pkg_path.joinpath("IFSC.json")) as f:
ifscs = json.load(f)

with open(pkg_path.joinpath("banknames.json")) as f:
bank_names = json.load(f)

with open(pkg_path.joinpath("sublet.json")) as f:
sublets = json.load(f)

with open(pkg_path.joinpath("custom-sublets.json")) as f:
custom_sublets = json.load(f)


class IFSC:
def __init__(self):
self.base_url = "https://ifsc.razorpay.com/"
self.ifscs = ifscs
self.bank_names = bank_names
self.sublets = sublets
self.custom_sublets = custom_sublets

def validate(self, code):
if len(code) != 11:
return False

if code[4] != "0":
return False

_bank_code = code[:4].upper()
_branch_code = code[5:].upper()

if not _bank_code in self.ifscs:
return False

if _branch_code.isnumeric():
_branch_code = int(_branch_code)
return _branch_code in self.ifscs[_bank_code]

return _branch_code in self.ifscs[_bank_code]

def get_details(self, code):
url = self.base_url + code
if not self.validate(code):
raise ValueError("Invalid IFSC code")

data = {}
res = requests.get(url)
if res.status_code == 200:
data = res.json()
elif res.status_code == 404:
raise ValueError("Invalid IFSC code")
else:
raise ValueError("IFSC API returned an invalid response")

return data

def get_bank_name(self, code):
if code in self.bank_names:
return self.bank_names[code]

if self.validate(code):
if code in self.sublets:
bank_code = self.sublets[code]
return self.bank_names[bank_code]
else:
return self.get_custom_sublet(code)
else:
raise ValueError("Invalid IFSC code")

def get_custom_sublet(self, code):
for key, value in self.custom_sublets.items():
if len(code) >= len(key) and code[: len(key)] == key:
if value in self.bank_names:
return self.bank_names[value]
else:
return value

raise ValueError("Invalid IFSC code")

def validate_bank_code(self, code):
return code in self.bank_names
Empty file added src/python/tests/__init__.py
Empty file.
Loading