Skip to content

Instantly share code, notes, and snippets.

@masterashu
Last active February 13, 2022 18:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • 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"))
@akd6203
Copy link

akd6203 commented May 12, 2020

Here is an error:
ValueError at /pay/
AES key must be either 16, 24, or 32 bytes long
Please give me some solution. Thanks in advance

@masterashu
Copy link
Author

@akd6203 This error occurs when the params has some missing field. Make sure you are providing all the parameters defined in params.

Also note that you use the library pycryptodome. If you have installed crypto uninstall it and reinstall pycrypotodome, do no install pycryptodome with without uninstalling pycrypto.

@masterashu
Copy link
Author

If still not helps send me a copy of params which you are using, except MID of course.

@quanta-kt
Copy link

I swear to god, this was totally helpful. PayTM doesn't even bothers updating their development kits (which are already very ill designed to be honest) and I was really frustrated realizing that even the version of pycrypto library used was not mentioned anywhere. This was like a life saver to me. Thanks a lot for making this available, really appreciated!

@masterashu
Copy link
Author

@quanta-kt I am glad it helped.

@deepti11
Copy link

@masterashu

Thanks for the article. I am following it, I got the checksum python file, however, I am getting "Invalid checksum" error. Here is my code snippet:

def post(self, request):
    merchant_key = settings.PAYTM_SECRET_KEY
    params = {
        'MID': settings.PAYTM_MERCHANT_ID,
        'ORDER_ID': "ORDER_001",
        'CUST_ID': "CUST_001",
        'TXN_AMOUNT': "10.00",
        'CHANNEL_ID': settings.PAYTM_CHANNEL_ID,
        'WEBSITE': settings.PAYTM_WEBSITE,
        'EMAIL': "abc@gmail.com",
        'MOBILE_NO': '9392757777',
        'INDUSTRY_TYPE_ID': settings.PAYTM_INDUSTRY_TYPE_ID,
        'CALLBACK_URL': 'http://localhost:8000/callback',
    }

    paytm_params = dict(params)
    checksum = Checksum.generate_checksum(paytm_params, merchant_key)

    paytm_params['CHECKSUMHASH'] = checksum
    print('SENT: ', checksum)
    return render(request, 'market/redirect.html', context=paytm_params)

PAYTM_MERCHANT_ID = 'QdsHSO0302248******'
PAYTM_SECRET_KEY = '*******************'
PAYTM_WEBSITE = 'WEBSTAGING'
PAYTM_CHANNEL_ID = 'WEB'
PAYTM_INDUSTRY_TYPE_ID = 'Retail'

Response what I receive is DATA is <QueryDict: {'ORDERID': ['ORDER_001'], 'MID': ['QdsHSO03022482394552'], 'TXNAMOUNT': ['10.00'], 'CURRENCY': ['INR'], 'STATUS': ['TXN_FAILURE'], 'RESPCODE': ['330'], 'RESPMSG': ['Invalid checksum'], 'BANKTX
NID': ['']}> <QueryDict: {'ORDERID': ['ORDER_001'], 'MID': ['QdsHSO03022482394552'], 'TXNAMOUNT': ['10.00'], 'CURRENCY': ['INR'], 'STATUS': ['TXN_FAILURE'], 'RESPCODE': ['330'], 'RESPMSG': ['Invalid checksum'], 'B
ANKTXNID': ['']}>

Thanks in advance!

@masterashu
Copy link
Author

masterashu commented Jun 19, 2020

@deepti11
Invalid checksum could only mean wrong Secret Key or merchant Id.
You can try editing the main in this gist. with sample details and verify the checksum is verified.
Also don't use the same order id twice, that could be the issue.

@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