Как исправить «TypeError в / orders / create / аргумент типа« DeferredAttribute »не повторяется» при использовании Django Payment Gateway (Paytm) - PullRequest
0 голосов
/ 17 мая 2019

Моя проблема связана с внедрением Payment Gateway в моем проекте электронной коммерции. Платежный шлюз, которым я пользуюсь - это Paytm из страны Индия.

После посещения их сайта https://developer.paytm.com/docs/v1/payment-gateway.

Я собрал свой ID теста и Секретный ключ.

У меня есть страница оформления заказа, где пользователь вводит свои данные. Он перенаправлен на успешно размещенную заказанную страницу с идентификатором заказа. Все работает нормально.

Однако теперь, когда я начинаю реализовывать свой платежный шлюз, я сталкиваюсь с ошибкой «аргумент типа« DeferredAttribute »не повторяется» в моем файле views.py моего приложения заказов.

Сначала я установил pycryptodome с pip3

Я создал каталог с именем "payTm" в моей папке src. Я создал новый файл Python с именем "Checksum.py" (который я скопировал, вставил с сайта 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})

Сервер работает без ошибок.

Однако вывод ошибки:

Error

Это моя HTML-страница. Ссылка на URL-адрес предоставлена ​​самим сайтом 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, но это не так.

1 Ответ

0 голосов
/ 17 мая 2019

Вы передаете неправильную вещь в вашем параметре.Вы указали Order, который является самим классом, а не 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',
    }

(Но также обратите внимание, что в этом модуле контрольной суммы есть много действительно странных вещей. Почему вы называете функции с начальными и конечными двойными подчеркиваниями? Почему вы звоните * 1006?* в функции, вызываемой из представления Django? Почему вы сортируете ключи params и почему вы перебираете ключи, а затем просматриваете значение, а не перебираете пары ключ-значение с items()? Почему на самом делевы вообще итерируете, когда, по-видимому, вы ищете возврат только в определенном месте?)

...