Im trying to integrate paytm with django rest framework. But don't know why I get checksum mismatch. That is while initiating payment app a checksum is generated but when verifying the checksum it is different.
#Views - initiating payment
context = {
"MID": settings.PAYTM_MERCHANT_ID,
"INDUSTRY_TYPE_ID": settings.PAYTM_INDUSTRY_TYPE_ID,
"WEBSITE": settings.PAYTM_WEBSITE,
"CHANNEL_ID": settings.PAYTM_CHANNEL_ID,
"CALLBACK_URL": settings.PAYTM_CALLBACK_URL,
"ORDER_ID": str(order.order_number),
"TXN_AMOUNT": str(amount),
"CUST_ID": str(user.id),
}
context["CHECKSUMHASH"] = Checksum.generate_checksum(
context, settings.PAYTM_MERCHANT_KEY
)
return Response({"context": context})
After initiating it Iam sending the CHECKSUMHASH in post request along with MID, ORDERID through postman and check for the checksum validation
def VerifyPaytmResponse(response):
response_dict = dict()
print('in VerifyPaytmResponse 0')
if response.method == "POST":
data_dict = dict()
form = response.POST
for key in form.keys():
data_dict[key] = form[key]
print('ENTERING HERER')
if key == 'CHECKSUMHASH':
check_sum = data_dict[key]
MID = data_dict['MID']
ORDERID = data_dict['ORDERID']
verify = Checksum.verify_checksum(
data_dict, settings.PAYTM_MERCHANT_KEY, check_sum)
if verify:
STATUS_URL = settings.PAYTM_TRANSACTION_STATUS_URL
headers = {
'Content-Type': 'application/json',
}
data = '{"MID":"%s","ORDERID":"%s"}' % (MID, ORDERID)
check_resp = requests.post(
STATUS_URL, data=data, headers=headers).json()
if check_resp['STATUS'] == 'TXN_SUCCESS':
response_dict['verified'] = True
response_dict['paytm'] = check_resp
return (response_dict)
else:
response_dict['verified'] = False
response_dict['paytm'] = check_resp
return (response_dict)
else:
response_dict['verified'] = False
return (response_dict)
response_dict['verified'] = False
return response_dict
This is getting failed because the function to verify checksum is not getting matched. Below is the verifying function
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 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:]
return calculated_checksum == checksum
In above function verify_checksum the calculated_checksum is not equal to the checksum. This is why verification getting failed.
Related
login reporting wrong username or password, after a new user is registered successfully. I am sure the there is no typo! below is my code and I guess the problem is to do with the hash code related to the password setup?
#csrf_exempt
def api_register(request):
data = json.loads(request.body)
username = data['username']
password_1 = data['password_1']
password_2 = data['password_2']
# 1,check if two pw is same
if password_1 != password_2:
return JsonResponse({"code": 0, "msg": "pw not consistant"})
else:
m = hashlib.md5()
m.update(password_1.encode())
password_m = m.hexdigest()
# 2 check if username exists
users = User.objects.filter(username=username)
if users:
return JsonResponse({"error": "username already exists"})
else:
try:
user = User.objects.create_user(username = username, password = password_m)
user.set_password(password_m)
user.save()
user.is_active = True
user.success = True
ret_data = {"username": user.username, 'uid': user.id, 'password': user.password}
token = TimestampSigner(sep='.').sign_object(ret_data)
ret_data['token'] = token
ret = {"code": 1, "msg": ret_data}
except Exception as e:
print('--create user error is %s' % e)
return JsonResponse({"error": "username already exists"})
return JsonResponse(ret)
below is login function
#csrf_exempt
def api_login(request):
data = json.loads(request.body)
user = authenticate(**data) #same as authenticate(username=data['username'],password=data['password']
if user:
ret_data = {"username":user.username,'uid':user.id}
token = TimestampSigner(sep='.').sign_object(ret_data)
ret_data['token'] = token
ret = {"code":1,"msg":ret_data}
print("ret ", ret)
else:
ret = {"code":0,"msg":"username or password wrong!" }
return JsonResponse(ret)
Django's .set_password hashes the password itself, so you should not to that manually. By doing this, the authentication will of course no longer work, since the entered password is not the same as the MD5-hashing. Furthermore MD5 is not considered a "safe" hasher.
#csrf_exempt
def api_register(request):
data = request.json()
username = data['username']
password_1 = data['password_1']
password_2 = data['password_2']
# 1 check if two pw is same
if password_1 != password_2:
return JsonResponse({'code': 0, 'msg': 'pw not consistant'})
# 2 check if username exists
if User.objects.filter(username=username).exists():
return JsonResponse({'error': 'username already exists'})
user = User.objects.create_user(
username=username, password=password1, is_active=True, success=True
)
ret_data = {'username': user.username, 'uid': user.id, 'password': password1}
token = TimestampSigner(sep='.').sign_object(ret_data)
ret_data['token'] = token
return JsonResponse({'code': 1, 'msg': ret_data})
I have a django app that contains samples. On my home page, it displays a table with many samples, containing hyperlinks to the 'Sample page' - which is a view get request.
When I click on several of these samples in tandem, to open new tabs, each to a specific tab - I am getting cross over of data - I.e the url sample_id kwargs is different, but the page is displaying the same results which is incorrect. When i refresh the page, the correct sample data appears.
Is there any way around this happening is a user is to open several different sample tabs at the same time? This would impact on results and could cause errors in the workflow offered by the django app.
*is this because my view is processing too much, so the different view request=s ends up over lapping ?
Edit: adding view:
class FilterVariantSampleView(ReportView, ReportPDFGenerator, FileGenerator, limsQuery):
template_name = os.path.join(
'results',
'filter_templates',
'sample_page.html'
)
type = 'sample'
choice = False
group_required = ['filter']
def get(self, request, *args, **kwargs):
self.user = request.user
self.obtain_sample_information(kwargs)
self.obtain_patient_information()
self.obtain_header()
# create sample notes form
sample_notes_form = SampleNotesForm(
instance=self.sample_obj)
self.context['sample_notes_form'] = sample_notes_form
self.create_variant_filter_formset()
panel_list = [o.run_id.machine_panel_id.panel_id
for o in self.all_sr_obj]
if len(panel_list):
self.panel_obj = panel_list[0]
# self.generate_hotspot_form()
self.assess_fails()
crs_qs = ClinicallyReportedSample.objects.filter(
sample_id=self.sample_obj)
crs_qs = crs_qs.exclude(
reported_on_panel__parent_panel__isnull=False,
primary_technical_report=False,
final_technical_report=False
)
remove_report_form_list = []
lims_molecular_results = self.query_lims_clone_molecular(
qs=crs_qs)
mol_df = lims_molecular_results[0]
summary = lims_molecular_results[1]
self.context['summary'] = summary
if crs_qs.count() == 1:
crs_obj = crs_qs[0]
self.context['crs_qs'] = crs_qs
remove_report_form = RemoveDiagnosticReportForm(
instance=crs_obj)
remove_report_form_list.append(remove_report_form)
else:
messages.add_message(self.request, messages.WARNING,
'This sample has been sequenced on multiple panels.')
self.context['crs_qs'] = crs_qs
lims_molecular_results = self.query_molecular_lims(
sample_obj=self.sample_obj)
for crs_obj in crs_qs:
remove_report_form = RemoveDiagnosticReportForm(
instance=crs_obj)
remove_report_form_list.append(remove_report_form)
if crs_obj.diagnostic_report_required == False:
messages.add_message(self.request, messages.WARNING,
f'This sample does NOT require a diagnostic reoprt '
f'for the {crs_obj.reported_on_panel} panel.')
self.context['remove_report_form_list'] = remove_report_form_list
return render(request, self.template_name, self.context)
def post(self, request, *args, **kwargs):
"""
"""
self.define_variant_filter_formset()
submit = request.POST.get('submit', None)
if submit:
if submit == 'Modify sample':
logger.info('')
logger.info('Sample: {}'.format(self.sample_obj))
logger.info("Submit: '{}'".format(submit))
# pass POST dict to formset
modify_formset = self.CRVFormSet(request.POST, prefix='crv')
# validate
if modify_formset.is_valid():
logger.info('Modify Variant Formset valid')
logger.info('')
self.modify_variants(modify_formset)
self.modify_sample()
return HttpResponseRedirect(
reverse('results:filter_variant_sample',
kwargs={'sample_id': self.sample_obj.id}))
else:
msg = ('Modify ClinicallyReportedVariant '
f'Formset NOT valid: {modify_formset.errors}')
logger.error(msg)
messages.add_message(request, messages.ERROR, msg)
return HttpResponseRedirect(
reverse('results:filter_variant_sample',
kwargs={'sample_id': self.sample_obj.id}))
elif submit == 'Update':
form = RemoveDiagnosticReportForm(request.POST,
instance=ClinicallyReportedSample.objects.get(
sample_id=kwargs['sample_id'],
reported_on_panel=request.POST['reported_on_panel'])
)
if form.is_valid():
logger.info('RemoveDiagnosticReportForm is valid')
try:
form.save()
except Exception as e:
logger.error(e)
else:
msg = f'RemoveDiagnosticReportForm is NOT valid: {form.errors}'
logger.error(msg)
messages.add_message(self.request, messages.ERROR, msg)
return HttpResponseRedirect(request.path_info)
elif 'Download' in submit:
panel_name = submit.split(' ')[1]
self.panel_obj = Panel.objects.get(panel_name=panel_name)
self.crs_obj = ClinicallyReportedSample.objects.get(
sample_id=self.sample_obj, reported_on_panel=self.panel_obj)
if 'panel data' in submit:
logger.info(f'Downloading data for {self.sample_obj}')
if self.crs_obj.sample_id.external_dept.site in ['Newcastle', 'Sheffield']:
downloaded_data = self.download_yne_data()
if downloaded_data:
self.crs_obj.downloaded_data = True
self.crs_obj.downloaded_data_user = request.user
self.crs_obj.downloaded_data_date = timezone.now()
self.crs_obj.save()
return downloaded_data
else:
return HttpResponseRedirect(self.request.path_info)
elif 'report' in submit:
logger.info(f'Downloading report for {self.sample_obj}')
# update crs_obj
self.crs_obj.download_technical_report = True
self.crs_obj.download_technical_report_user = self.user
self.crs_obj.download_technical_report_date = timezone.now()
self.crs_obj.save()
# return HttpResponseRedirect(self.request.path_info)
lims_molecular_results = self.query_molecular_lims(
sample_obj=self.sample_obj)
mol_df = lims_molecular_results[0]
summary = lims_molecular_results[1]
if mol_df.empty:
logger.info('No molecular tests done')
self.latex_context['gene_status'] = False
else:
gene = mol_df[
(mol_df['test_name'] == 'gene') &
(mol_df['status'] == 'complete')
]
if gene.empty:
self.context['gene'] = False
else:
msg = ("gene Sanger in-fill test has been completed.{}")
result = gene['result'].to_string(index=False)
if result == 'normal or wild-type':
msg = msg.format(' No detectable variants.')
msg_info = messages.INFO
gene_df = pd.DataFrame()
elif result == 'failed':
msg = msg.format(' Unfortunately the test failed.')
msg_info = messages.WARNING
gene_df = pd.DataFrame()
elif result == 'mutated' or result == 'suspicious':
gene_df = self.get_gene_result(gene, technical_report=True)
if result == 'suspicious':
msg = msg.format(' There is suspicion of a variant '
'(see below for more information).')
else:
msg = msg.format(' A variant was detected '
'(see below for more information).')
msg_info = messages.INFO
else:
msg = msg.format(' Error - contact administrator.')
msg_info = messages.ERROR
result = 'error'
gene_df = pd.DataFrame()
self.latex_context['gene_status'] = result
self.latex_context['gene_df'] = gene_df
logger.info(msg)
messages.add_message(self.request, msg_info, msg)
print(self.latex_context)
# call method from TechnicalReportPDFGenerator
self.generateReport(report_type='technical')
response = self.download_technical_report()
return response
return render(request, self.template_name, self.context)
This may be due to the cache of your browser, are you sure the calls are going through the first time ?
In my API using Django Rest Framework I have a function based view for part of a sign up process for using Stripe. The view succefully sends everything to stripe and updates my sites database with the proper information, but when trying to return the serializer data I get this error:
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
Assuming it has to do with the files needed for personal identification
Here is the view:
#api_view(['POST'])
def StripePersonalOnboard(request):
serializer = StripePersonalSerializer(data=request.data)
profile = get_object_or_404(Profile, user=request.user)
if serializer.is_valid():
phone_number = serializer.validated_data.get('phone_number')
ss_number = serializer.validated_data.get('ss_number')
id_front = serializer.validated_data.get('id_front')
id_back = serializer.validated_data.get('id_back')
try:
stripe.api_key = settings.STRIPE_TEST_SEC_KEY
id_front_file = stripe.File.create(
purpose='identity_document',
file=id_front
)
id_back_file = stripe.File.create(
purpose='identity_document',
file=id_back
)
stripe.Account.modify(
profile.stripe_acc_id,
individual= {
'phone': phone_number,
'id_number': ss_number,
'verification': {
'document': {
'back': id_back_file,
'front': id_front_file
}
}
}
)
profile.stripe_id_front_tkn = id_front_file.id
profile.stripe_id_back_tkn = id_back_file.id
profile.save(update_fields=['stripe_id_front_tkn', 'stripe_id_back_tkn'])
return Response(serializer.validated_data)
except stripe.error.InvalidRequestError as e:
#invalid parameters were provided
return Response(e.error.message)
else:
return Response(serializer.errors)
I have created a class for retrieving data about a specific food product from farsecret API.
In class I have created 3 functions for:
*obtaining authorization
*getting id of item, for which we are looking
*download data of item
class IngredientImport(APIView):
def get_authorization_token(self):
request_token_url = "https://oauth.fatsecret.com/connect/token"
consumer_key = os.environ.get('NTS_Client_ID')
consumer_secret = os.environ.get('NTS_Client_Secret')
data = {'grant_type':'client_credentials', "scope":"basic"}
access_token_response = requests.post(
request_token_url,
data=data,
verify=False,
allow_redirects=False,
auth=(consumer_key, consumer_secret)
)
return access_token_response.json()["access_token"]
def get_list_by_name(self, name, access_token):
api_url = "https://platform.fatsecret.com/rest/server.api"
params={
"method":"foods.search",
"search_expression":name,
"page_number":1,
"max_results":1,
"format":"json"
}
header = {"Authorization":access_token}
api_call_headers = {"Authorization": "Bearer " + access_token}
response = requests.get(
api_url,
params=params,
headers=api_call_headers
)
items = response.json()["foods"]
try:
return response.json()["foods"]["food"]["food_id"]
except KeyError:
return None
def import_item(self, item_id, api_token):
if item_id == None:
return None
api_url = "https://platform.fatsecret.com/rest/server.api"
params={"method":"food.get", "food_id":item_id, "format":"json"}
api_call_headers = {"Authorization": "Bearer " + access_token}
response = requests.get(
api_url,
params=params,
headers=api_call_headers
)
item = response.json()["food"]["servings"]["serving"]
item_name = response.json()["food"]["food_name"]
if type(item) == list:
item = item[0]
try:
portion_size = float(item["metric_serving_amount"])
carbs = round(float(item["carbohydrate"]) / portion_size * 100, 2)
fats = round(float(item["fat"]) / portion_size * 100, 2)
proteins = round(float(item["protein"]) / portion_size * 100, 2)
except KeyError:
return None
How can I implement this class in my aplication to avoid creating 3 different paths in urls.py for each function. Is it possible or should I break it into function-based views?
class IngredientImport(APIView):
def get_authorization_token(self):
...
def get_list_by_name(self, name, access_token):
...
def import_item(self, item_id, api_token):
...
def get(self, request):
# get name from query param
name = self.request.GET.get('name')
token = self.get_authorization_token()
food_list = self.get_list_by_name(name, token)
for food_id in food_list:
self.import_item(food_id, token)
return Response({'imported_foods': food_list})
Then, on your urls.py:
urlpatterns = [
path('import_foods', IngredientImport.as_view())
]
in view.py:
#require_POST
#csrf_exempt
def ipn(request):
transactions_logger = logging.getLogger("django")
processor = Ipn(request.POST, logger=transactions_logger)
verification_success = processor.verify_ipn()
encoding = request.POST.get('ok_charset', None)
data = QueryDict(request.body, encoding=encoding)
if verification_success:
form = OkpayIpnForm(data)
if form.is_valid():
print("ALL FINE!!")
form.save()
return HttpResponse("")
In forms.py:
class OkpayIpnForm(forms.ModelForm):
class Meta:
model = OkpayIpn
exclude = []
Code for IPN Checkprocessor = Ipn(request.POST, logger=transactions_logger:
class Ipn(object):
OKPAY_VERIFICATION_URL = 'https://checkout.okpay.com/ipn-verify'
OKPAY_IPN_INVALID = b'INVALID'
OKPAY_IPN_VERIFIED = b'VERIFIED'
OKPAY_IPN_TEST = b'TEST'
OKPAY_STATUS_COMPLETED = 'completed'
__verification_result = False
def __init__(self, request_data, logger):
if 'ok_verify' in request_data:
raise Exception("ok_verify must not be present in initial request data for {}".format(
self.__class__.__name__
))
self._request_data = request_data
self.logger = logger
return
def verify_ipn(self):
self.__verification_result = False
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
verify_request_payload = {
'ok_verify': 'true',
}
verify_request_payload.update(self._request_data)
resp = requests.post(self.OKPAY_VERIFICATION_URL, data=verify_request_payload, headers=headers)
if resp.content == self.OKPAY_IPN_VERIFIED or resp.content == self.OKPAY_IPN_TEST:
self.__verification_result = True
# if resp.content == self.OKPAY_IPN_VERIFIED: # anyway disable test on production.
# self.__verification_result = True
return self.__verification_result
All is ok, I revice IPN and validate it, then I try to validate form and save it to Database.
But form doesn't pass validation and doesn't save to database.
Thank You for help
Problem was that 1 CharField of Model for saving IPN has maxlength=20, but recieved 40 symbols.
Thx jape he advised to add in form validation else statement and print form.errors
the error of of form validation was :
<li>ok_item_1_type<ul class="errorlist"><li>Ensure this value has at most 20 characters (it has 40).</li></ul></li>