使用 Django 支付网关 (Paytm) 时如何修复 "TypeError at /orders/create/ argument of type 'DeferredAttribute' is not iterable"

How to fix "TypeError at /orders/create/ argument of type 'DeferredAttribute' is not iterable" when using Django Payment Gateway (Paytm)

我的问题是在我的电子商务项目中实施支付网关。我使用的支付网关来自印度国家 "Paytm"。

访问他们的网站后,https://developer.paytm.com/docs/v1/payment-gateway

我收集了我的测试 ID 和密钥。

我有一个结帐页面,一旦用户输入 his/her 详细信息。他被重定向到一个带有订单 ID 的成功订购页面。 一切正常。

但是,现在当我开始实施我的支付网关时,我 运行 在我的 views.py 订单应用文件中出现错误 "argument of type 'DeferredAttribute' is not iterable"。

首先我用pip3安装了pycryptodome

我在我的 src 文件夹下创建了一个名为 "payTm" 的目录。我制作了一个名为 "Checksum.py" 的新 python 文件。(我从 paytm 的网站复制粘贴)

所以我的问题出现在我的 views.py 文件下。

views.py(在订单应用中)

 from django.shortcuts import render
 from .models import OrderItem , Order
 from django.contrib.auth.decorators import login_required
 from django.views.decorators.csrf import csrf_exempt
 from .forms import OrderCreateForm
 from cart.cart import Cart
 from payTm import Checksum
 from django.http import HttpResponse
 MERCHANT_KEY = 'my_merchant_key';

 @csrf_exempt
 def handlerequest(request):
 return HttpResponse('done')
 pass

 @login_required
 def order_create(request):
 cart = Cart(request)
 if request.method == 'POST':
    form = OrderCreateForm(request.POST)
    if form.is_valid():
        order = form.save()
        for item in cart:
            OrderItem.objects.create(
                order=order,
                product=item['product'],
                price=item['price'],
                quantity=item['quantity'],
                total_price=item['total_price'],
            )
        cart.clear()
        param_dict = {
            'MID': 'my_merchant_id',
            'ORDER_ID': str(Order.id),
            'TXN_AMOUNT': Order.total_cost,
            'CUST_ID': Order.email,
            'INDUSTRY_TYPE_ID': 'Retail',
            'WEBSITE': 'WENSTAGING',
            'CHANNEL_ID': 'WEB',
            'CALLBACK_URL': 'http://127.0.0.1:8000/handlerequest',
        }
        param_dict['CHECKSUMHASH'] = 
        Checksum.generate_checksum(param_dict, MERCHANT_KEY)
        return render(request, 'paytm.html', {'order': order}, 
        {'param_dict': param_dict})

 else:
    form = OrderCreateForm()
   return render(request, 'create.html', {'form': form})

服务器 运行s 没有任何错误。

但是错误输出是:

Error

这是我的 html 页面。 post Url link 由 paytm 本身从其网站提供。 paytm.html

{% extends 'base.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 don't refresh this 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>

Checksum.py

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/u
         Ym3WBOWHf+sDQAmTyxqUipA7i1nILlxrk="))

# print(generate_checksum(params, "xxxxxxxxxxxxxxxx"))

可能是什么错误?或者我应该做哪些改变?如果我的商家密钥和 ID 凭证有任何错误,我已经多次交叉检查,但没有。

您在参数字典中传递了错误的内容。您引用了 Order,这是 class 本身,而不是 order,这是您刚刚创建的实例。所以应该是:

   param_dict = {
        'MID': 'my_merchant_id',
        'ORDER_ID': str(order.id),
        'TXN_AMOUNT': order.total_cost,
        'CUST_ID': order.email,
        'INDUSTRY_TYPE_ID': 'Retail',
        'WEBSITE': 'WENSTAGING',
        'CHANNEL_ID': 'WEB',
        'CALLBACK_URL': 'http://127.0.0.1:8000/handlerequest',
    }

(但还要注意,校验和模块中有很多非常奇怪的东西。为什么要用前导和尾随 double-underscores 命名函数?为什么要在调用的函数中调用 exit()从 Django 的角度来看?为什么要对参数键进行排序,为什么要遍历键然后查找值而不是遍历 key-value 与 items() 对?事实上你为什么当您可能仅在特定位置寻找退款时,是否进行迭代?)