问题描述
我正致力于将 Paytm 集成到我的 Django 项目中。它在演示运行中运行良好,即登台。当我尝试为生产运行它时,它开始抛出错误。校验和在生产中不匹配。
Paytm/Checksum.py
# pip install pycryptodome
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,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,merchant_key)
def generate_checksum_by_str(param_str,salt=None):
params_string = param_str
salt = salt if salt else __id_generator__(4)
final_string = '%s|%s' % (params_string,merchant_key)
def verify_checksum(param_dict,checksum):
# Remove checksum
if 'CHECKSUMHASH' in param_dict:
param_dict.pop('CHECKSUMHASH')
# Get salt
paytm_hash = __decode__(checksum,merchant_key)
salt = paytm_hash[-4:]
calculated_checksum = generate_checksum(param_dict,salt=salt)
return calculated_checksum == checksum
def verify_checksum_by_str(param_str,checksum):
# Remove checksum
#if 'CHECKSUMHASH' in param_dict:
#param_dict.pop('CHECKSUMHASH')
# Get salt
paytm_hash = __decode__(checksum,merchant_key)
salt = paytm_hash[-4:]
calculated_checksum = generate_checksum_by_str(param_str,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,key):
# Decode
to_decode = base64.b64decode(to_decode)
# Decrypt
c = AES.new(key.encode('utf-8'),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"))
views.py
def orderproduct(request):
category = Category.objects.all()
current_user = request.user
shopcart = ShopCart.objects.filter(user_id=current_user.id)
total = 0
for rs in shopcart:
total += rs.product.price * rs.quantity
if request.method == 'POST': # if there is a post
form = OrderForm(request.POST)
# return HttpResponse(request.POST.items())
if form.is_valid():
data = Order()
data.first_name = form.cleaned_data['first_name']
data.last_name = form.cleaned_data['last_name']
data.address = form.cleaned_data['address']
data.city = form.cleaned_data['city']
data.country = form.cleaned_data['country']
data.phone = form.cleaned_data['phone']
data.user_id = current_user.id
data.total = total
data.ip = request.META.get('REMOTE_ADDR')
ordercode = get_random_string(5).upper() # random cod
data.code = ordercode
data.save()
for rs in shopcart:
detail = OrderProduct()
detail.order_id = data.id # Order Id
detail.product_id = rs.product_id
detail.user_id = current_user.id
detail.quantity = rs.quantity
detail.price = rs.product.price
# detail.variant_id = rs.variant_id
detail.amount = rs.amount
detail.save()
# ***Reduce quantity of sold product from Amount of Product
product = Product.objects.get(id=rs.product_id)
product.amount -= rs.quantity
product.save()
# ************ <> *****************
ShopCart.objects.filter(user_id=current_user.id).delete() # Clear & Delete shopcart
request.session['cart_items']=0
amount = int(total)
# Request paytm to transfer the amount to your account after payment by user
param_dict = {
'MID': 'MY_MERCHANT_ID','ORDER_ID': str(ordercode),'TXN_AMOUNT': str(amount),'CUST_ID': request.user.email,'INDUSTRY_TYPE_ID': 'Retail','WEBSITE': 'WEBSTAGING','CHANNEL_ID': 'WEB','CALLBACK_URL': 'http://127.0.0.1:8000/order/handlerequest/',}
param_dict['CHECKSUMHASH'] = Checksum.generate_checksum(
param_dict,MERCHANT_KEY)
return render(request,'order/paytm.html',{'param_dict': param_dict})
# Clear & Delete shopcart
return render(request,'order/order_completed.html',{'ordercode': ordercode,'category': category})
else:
messages.warning(request,form.errors)
return HttpResponseRedirect("/order/orderproduct")
form = OrderForm()
profile = UserProfile.objects.filter(user_id=current_user.id)
context = {'shopcart': shopcart,'category': category,'total': total,'form': form,'profile': profile,}
return render(request,'order/order_form.html',context)
@csrf_exempt
def handlerequest(request):
# paytm will send you post request here
form = request.POST
# print(form)
response_dict = {}
for i in form.keys():
response_dict[i] = form[i]
if i == 'CHECKSUMHASH':
checksum = form[i]
verify = Checksum.verify_checksum(response_dict,MERCHANT_KEY,checksum)
if verify:
if response_dict['RESPCODE'] == '01':
ShopCart.objects.filter(user_id=request.user.id).delete()
request.session['cart_items'] = 0
order = Order.objects.get(code = form['ORDERID'])
order.paid = True
order.save()
messages.success(
request,"Your Order has been completed. Thank you ")
print('order successful')
else:
print('order was not successful because' + response_dict['RESPMSG'])
return render(request,'order/paymentstatus.html',{'response': response_dict})
models.py
class Order(models.Model):
STATUS = (
('New','New'),('Accepted','Accepted'),('Preaparing','Preaparing'),('OnShipping','OnShipping'),('Completed','Completed'),('Canceled','Canceled'),)
user = models.ForeignKey(User,on_delete=models.SET_NULL,null=True)
code = models.CharField(max_length=5,editable=False )
first_name = models.CharField(max_length=10)
last_name = models.CharField(max_length=10)
phone = models.CharField(blank=True,max_length=20)
address = models.CharField(blank=True,max_length=150)
city = models.CharField(blank=True,max_length=20)
country = models.CharField(blank=True,max_length=20)
total = models.FloatField()
status=models.CharField(max_length=10,choices=STATUS,default='New')
ip = models.CharField(blank=True,max_length=20)
adminnote = models.CharField(blank=True,max_length=100)
create_at=models.DateTimeField(auto_now_add=True)
update_at=models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
def __str__(self):
return self.user.first_name
#Paytm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Paytm merchant payment page</title>
</head>
<body>
<h1>Redirecting you to the merchant....</h1>
<h1>Please do not refresh your page....</h1>
<form action="https://securegw-stage.paytm.in/theia/processTransaction" method="post" name="paytm">
{% for key,value in param_dict.items %}
<input type="hidden" name="{{key}}" value="{{value}}">
{% endfor %}
</form>
</body>
<script>
document.paytm.submit()
</script>
</html>
演示的表单操作如上所述。但对于生产,我尝试过:“https://securegw-stage.paytm.in/theia/processTransaction”。
当我运行演示时。一切正常。校验和匹配,交易成功。 但是当我尝试运行生产时,弹出的错误是:
UnboundLocalError at /order/handlerequest/
local variable 'checksum' referenced before assignment
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)