-
-
Save masterashu/f90b8ba6d4324d0a7d65ab0f2d8306c0 to your computer and use it in GitHub Desktop.
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 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.
If still not helps send me a copy of params which you are using, except MID of course.
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!
@quanta-kt I am glad it helped.
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': "[email protected]",
'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!
@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.
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.
ModuleNotFoundError: No module named 'PayTm'
I got this error ,please help me out.
Use import <filename_without_extension>
to import this.
For example if you are using paytm_checksum.py, use import paytm__checksum
@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
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.
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
@mayankwadhwani Yes, Thanks for pointing that out. I will create a post/sample for the new one and mention it here.
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.
ModuleNotFoundError: No module named 'PayTm'
I got the same error ,please help me out.
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