Skip to content

Instantly share code, notes, and snippets.

@masterashu
Last active February 13, 2022 18:25
Show Gist options
  • Save masterashu/f90b8ba6d4324d0a7d65ab0f2d8306c0 to your computer and use it in GitHub Desktop.
Save masterashu/f90b8ba6d4324d0a7d65ab0f2d8306c0 to your computer and use it in GitHub Desktop.
Paytm Payment Gateway: Checksum Generator for Python3
import base64
import string
import random
import hashlib
from Crypto.Cipher import AES
IV = "@@@@&&&&####$$$$"
BLOCK_SIZE = 16
def generate_checksum(param_dict, merchant_key, salt=None):
params_string = __get_param_string__(param_dict)
salt = salt if salt else __id_generator__(4)
final_string = '%s|%s' % (params_string, salt)
hasher = hashlib.sha256(final_string.encode())
hash_string = hasher.hexdigest()
hash_string += salt
return __encode__(hash_string, IV, merchant_key)
def generate_refund_checksum(param_dict, merchant_key, salt=None):
for i in param_dict:
if("|" in param_dict[i]):
param_dict = {}
exit()
params_string = __get_param_string__(param_dict)
salt = salt if salt else __id_generator__(4)
final_string = '%s|%s' % (params_string, salt)
hasher = hashlib.sha256(final_string.encode())
hash_string = hasher.hexdigest()
hash_string += salt
return __encode__(hash_string, IV, merchant_key)
def generate_checksum_by_str(param_str, merchant_key, salt=None):
params_string = param_str
salt = salt if salt else __id_generator__(4)
final_string = '%s|%s' % (params_string, salt)
hasher = hashlib.sha256(final_string.encode())
hash_string = hasher.hexdigest()
hash_string += salt
return __encode__(hash_string, IV, merchant_key)
def verify_checksum(param_dict, merchant_key, checksum):
# Remove checksum
if 'CHECKSUMHASH' in param_dict:
param_dict.pop('CHECKSUMHASH')
# Get salt
paytm_hash = __decode__(checksum, IV, merchant_key)
salt = paytm_hash[-4:]
calculated_checksum = generate_checksum(param_dict, merchant_key, salt=salt)
return calculated_checksum == checksum
def verify_checksum_by_str(param_str, merchant_key, checksum):
# Remove checksum
#if 'CHECKSUMHASH' in param_dict:
#param_dict.pop('CHECKSUMHASH')
# Get salt
paytm_hash = __decode__(checksum, IV, merchant_key)
salt = paytm_hash[-4:]
calculated_checksum = generate_checksum_by_str(param_str, merchant_key, salt=salt)
return calculated_checksum == checksum
def __id_generator__(size=6, chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
return ''.join(random.choice(chars) for _ in range(size))
def __get_param_string__(params):
params_string = []
for key in sorted(params.keys()):
if "REFUND" in params[key] or "|" in params[key]:
respons_dict = {}
exit()
value = params[key]
params_string.append('' if value == 'null' else str(value))
return '|'.join(params_string)
__pad__ = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
__unpad__ = lambda s: s[0:-ord(s[-1])]
def __encode__(to_encode, iv, key):
# Pad
to_encode = __pad__(to_encode)
# Encrypt
c = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
to_encode = c.encrypt(to_encode.encode('utf-8'))
# Encode
to_encode = base64.b64encode(to_encode)
return to_encode.decode("UTF-8")
def __decode__(to_decode, iv, key):
# Decode
to_decode = base64.b64decode(to_decode)
# Decrypt
c = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
to_decode = c.decrypt(to_decode)
if type(to_decode) == bytes:
# convert bytes array to str.
to_decode = to_decode.decode()
# remove pad
return __unpad__(to_decode)
if __name__ == "__main__":
params = {
"MID": "mid",
"ORDER_ID": "order_id",
"CUST_ID": "cust_id",
"TXN_AMOUNT": "1",
"CHANNEL_ID": "WEB",
"INDUSTRY_TYPE_ID": "Retail",
"WEBSITE": "xxxxxxxxxxx"
}
print(verify_checksum(
params, 'xxxxxxxxxxxxxxxx',
"CD5ndX8VVjlzjWbbYoAtKQIlvtXPypQYOg0Fi2AUYKXZA5XSHiRF0FDj7vQu66S8MHx9NaDZ/uYm3WBOWHf+sDQAmTyxqUipA7i1nILlxrk="))
# print(generate_checksum(params, "xxxxxxxxxxxxxxxx"))
@deepti11
Copy link

deepti11 commented Jun 19, 2020 via email

@deepti11
Copy link

Thanks Ashu for your quick response. I really appreciate it. I figured out that the redirect view has extra quotes in the value i.e. value="{{MID}}". Removing these quotes work fine.

@maddy4555
Copy link

ModuleNotFoundError: No module named 'PayTm'
I got this error ,please help me out.

@masterashu
Copy link
Author

Use import <filename_without_extension> to import this.
For example if you are using paytm_checksum.py, use import paytm__checksum

@maddy4555
Copy link

@masterashu
Bro i was asking because i wrote
from PayTm import Checksum in views.py
And then i got that error please help me in this way

@masterashu
Copy link
Author

Make sure you have this file in the same folder. Replace PayTm with the file name(without extension) in the from PayTm import Checksum. Note: python import are case sensitive.

@mayankwadhwani
Copy link

Hey, I am a new user to PayTM Businesses, and it seems they have deprecated this API, and used a new one. Still I am trying to integrate it, Can you let me know if it will work. I am stuck on invalid checksum error when i send the data to staging

@masterashu
Copy link
Author

@mayankwadhwani Yes, Thanks for pointing that out. I will create a post/sample for the new one and mention it here.

@Raj1503
Copy link

Raj1503 commented Dec 11, 2020

I am getting error at Incorrect AES key length (23 bytes)....i am using windows7 32 bit 4 gb ram...
please help me i am absulute begginer.

@cord-1000
Copy link

ModuleNotFoundError: No module named 'PayTm'
I got the same error ,please help me out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment