我正在尝试创建一个College项目,在该项目中我试图实现到我的网站的付款网关。我使用的支付网关是Paytm(印度)。 他们已经为我提供了checksum.py文件。 但是,当我尝试传递商家ID和订单ID时,我最终会收到错误消息。
这是回溯:-
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/orders/create/
Django Version: 2.2
Python Version: 3.7.3
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'crispy_forms',
'social_django',
'cart.apps.CartConfig',
'payment.apps.PaymentConfig',
'orders.apps.OrdersConfig',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'products',
'drf_paytm',
'drfaddons',
'feedback.apps.FeedbackConfig',
'users.apps.UsersConfig',
'shop.apps.ShopConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'social_django.middleware.SocialAuthExceptionMiddleware']
Traceback:
File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)
File "/Users/shyambalakrishnan/Dev/trydjango/src/orders/views.py" in order_create
40. param_dict['CHECKSUMHASH'] = Checksum.generate_checksum_by_str(param_dict, MERCHANT_KEY)
File "/Users/shyambalakrishnan/Dev/trydjango/src/payTm/Checksum.py" in generate_checksum_by_str
52. return __encode__(hash_string, IV, merchant_key)
File "/Users/shyambalakrishnan/Dev/trydjango/src/payTm/Checksum.py" in __encode__
102. c = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/Crypto/Cipher/AES.py" in new
95. return AESCipher(key, *args, **kwargs)
File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/Crypto/Cipher/AES.py" in __init__
59. blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
File "/Users/shyambalakrishnan/Dev/trydjango/lib/python3.7/site-packages/Crypto/Cipher/blockalgo.py" in __init__
141. self._cipher = factory.new(key, *args, **kwargs)
Exception Type: ValueError at /orders/create/
Exception Value: AES key must be either 16, 24, or 32 bytes long.
这是我的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/uYm3WBOWHf+sDQAmTyxqUipA7i1nILlxrk="))
print(generate_checksum(params, "xxxxxxxxxxxxxxxx"))
这些是我当前可用的版本: pycrypto == 2.6.1 pycryptodome == 3.8.1
我的订单/views.py:
from django.shortcuts import render
from .models import OrderItem , Order
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from payTm import Checksum
from django.views.decorators.csrf import csrf_exempt
from .forms import OrderCreateForm
from cart.cart import Cart
MERCHANT_KEY = 'my_merchant_key'
@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': str(order.total_cost),
'CUST_ID': order.email,
'INDUSTRY_TYPE_ID': 'Retail',
'WEBSITE': 'WEBSTAGING',
'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})
@csrf_exempt
def handlerequest(request,*args,**kwargs):
return HttpRespone("Done")
我该如何解决此错误?还是他们的Checksum.py文件有问题?
答案 0 :(得分:0)
要解决此问题,您必须将密钥设置为16或24或32个字节长。在您的代码中,
{-# LANGUAGE OverloadedLists, GADTs, TypeFamilies, ConstraintKinds,
FlexibleInstances, MultiParamTypeClasses, StandaloneDeriving, TypeApplications #-}
import Prelude ()
import Control.Category.Constrained.Prelude
import qualified Control.Category.Hask as Hask
-- import Data.Constraint.Trivial
import Data.Foldable.Constrained
import Data.Map as M
import Data.Set as S
import qualified Data.Foldable as FL
main :: IO ()
main = print $ fmap (constrained @Ord (+1))
$ RMS ([(1,[11,21]),(2,[31,41])])
data RelationMS a b where
IdRMS :: RelationMS a a
RMS :: Map a (Set b) -> RelationMS a b
deriving instance (Show a, Show b) => Show (RelationMS a b)
instance Category RelationMS where
type Object RelationMS o = Ord o
id = IdRMS
RMS mp2 . RMS mp1
| M.null mp2 || M.null mp1 = RMS M.empty
| otherwise = RMS $ M.foldrWithKey
(\k s acc -> M.insert k (S.foldr (\x acc2 -> case M.lookup x mp2 of
Nothing -> acc2
Just s2 -> S.union s2 acc2
) S.empty s
) acc
) M.empty mp1
(°) :: (Object k a, Object k b, Object k c, Category k) => k a b -> k b c -> k a c
r1 ° r2 = r2 . r1
instance (Ord a, Ord b) => Semigroup (RelationMS a b) where
RMS r1 <> RMS r2 = RMS $ M.foldrWithKey (\k s acc -> M.insertWith S.union k s acc) r1 r2
instance (Ord a, Ord b) => Monoid (RelationMS a b) where
mempty = RMS M.empty
mappend = (<>)
instance Functor (RelationMS a) (ConstrainedCategory (->) Ord) Hask where
fmap (ConstrainedMorphism f) = ConstrainedMorphism $
\(RMS r) -> RMS $ M.map (S.map f) r
fldl :: (a -> Set b -> a) -> a -> RelationMS k b -> a
fldl f acc (RMS r) = M.foldl f acc r
fldMp :: Monoid b1 => (Set b2 -> b1) -> RelationMS k b2 -> b1
fldMp m (RMS r) = M.foldr (mappend . m) mempty r
-- instance Foldable (RelationMS a) (ConstrainedCategory (->) Ord) Hask where
-- foldMap f (RMS r)
-- | M.null r = mempty
-- | otherwise = FL.foldMap f r
-- ffoldl f = uncurry $ M.foldl (curry f)
这里的密钥长15个字节,请添加一个字符使其变为16个字节
MERCHANT_KEY = 'my_merchant_key'
AES标准所要求的密钥大小应为128、192或256位,分别为16、24和32字节。