I'm trying to build a webhook that receives JSON being POSTed from a third party service, Messagebird. In their documentation they have an example of an outgoing query:
GET http://your-own.url/script
?id=e8077d803532c0b5937c639b60216938
&recipient=31642500190
&originator=31612345678
&body=This+is+an+incoming+message
&createdDatetime=2016-05-03T14:26:57+00:00
My webhook is being built with Python in Django, and this is what I have in my views.py:
from django.shortcuts import render
from django.views.decorators.http import require_POST
from django.http import HttpResponse
from .models import UserText
#require_POST
def webhookmb(request):
usrtxt = json.loads(request.body.decode("utf-8"))
UserText.objects.create(
id = usrtxt['id']
recipient = usrtxt['recipient']
originator = usrtxt['originator']
body = usrtxt['body']
createdDatetime = usrtxt['createdDatetime']
)
return HttpResponse(200)
My goal is to read the JSON into a file usrtxt and then map those fields to a model. I'm getting this error (deployed on heroku):
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Is this because json.loads is trying to read the file and the first like starts with GET? Do I need to skip this line? Or is there another way to go about this?
This might seem overly simple but try adding #csrf_exempt decorator to your webhook.
Related
I am working on DRF in which I have created multiple pythons and importing that file into views.py but when I am trying to send the response to the user from another file it is not working I understand the behind the reason but is there any way to send the response to the user from other than view.py.
view.py Structure
#restframework view and all
from concurrent.futures import ThreadPoolExecutor
import other as o
call FileView(APIView):
#parseclass
def post(self,request):
o.func(d)
Other.py
from rest_framework.response import Response
from rest_framework.status import status
from django.conf import setting
def func(d):
return Response({"A":"OK"})
but Response is not coming to the user end.
is there any way to send a response from other.py to the user instead of getting value and then send the response from the view.py?
I am also implementing multithreading in my DRF.
Just add return and it should work:
class FileView(APIView):
#parseclass
def post(self,request):
return o.func(d)
If you want to skip this step and call view in others.py directly. Just make that an APIView and register it in urls.py. It should work
I am trying to integrate Coinbase Commerce Webhook API in my Django App; but it seems am doing things in the right way. I have searched the web for more than 2 days but no solution available for this. Coinbase commerce official documentation did not provide way to integrate this in Django. Please your help will be appreciated. This is what I have tried; but keep on throwing an error.
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from coinbase_commerce.error import WebhookInvalidPayload, SignatureVerificationError
from coinbase_commerce.webhook import Webhook
from django.http import HttpResponse
import json
WEBHOOK_SECRET = settings.COINBASE_SECRET
#csrf_exempt
def payment_webhook(request):
request_data = request.data.decode('utf-8')
request_sig = request.headers.get('X-CC-Webhook-Signature', None)
try:
event = Webhook.construct_event(request_data, request_sig, WEBHOOK_SECRET)
except (WebhookInvalidPayload, SignatureVerificationError) as e:
return HttpResponse(e, status=400)
print("Received event: id={id}, type={type}".format(id=event.id, type=event.type))
return HttpResponse('ok', status=200)
I face the same issue, but since I'm only creating an endpoint to receive the webhook from 'charge:confirmed' which confirms that someone payed. I decided to do the validation of a request differently.
Upon receiving a request from the webhook, I check in the event['data']['timeline'] object if the status COMPLETED is present which according to: https://commerce.coinbase.com/docs/api/ specifies that the payment has been completed.
In Django, you have to use request.body.decode('utf-8') instead of request.data.decode('utf-8')
request_data = request.body.decode('utf-8')
I'm trying to develop a very simple script in Django, I'd collect a Json data from the request and then store all data in the database.
I developed one python script that I'm using to send the Json data to the Django view, but I'm doing something wrong and I can't understand what, because every time that I run it,I've got "Malformed data!".
Can someone helps me? what am I doing wrong?
Sender.py
import json
import urllib2
data = {
'ids': ["milan", "rome","florence"]
}
req = urllib2.Request('http://127.0.0.1:8000/value/')
req.add_header('Content-Type', 'application/json')
response = urllib2.urlopen(req, json.dumps(data))
Django view.py
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
import json
from models import *
from django.http import StreamingHttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def value(request):
try:
data = json.loads(request.body)
label = data['label']
url = data ['url']
print label, url
except:
return HttpResponse("Malformed data!")
return HttpResponse("Got json data")
Your dictionary "data" in sender.py contains only one value with key "ids" but in view.py you are trying to access keys "label" and "url" in this parsed dictionary.
I am facing a strange problem while inserting data to database using Django models.save() method. I have been using save() method in some other apps of same project. In this app named payments, I am getting postrequest from a payment gateway and I am inserting data into database on success
Structure of my payment model is given below:
Payment Model
from django.db import models
# Create your models here.
class payments(models.Model):
transactionId = models.CharField(max_length=50,default=None)
uniqueOrderId = models.CharField(max_length=50,default=None)
userId = models.CharField(max_length=30,default=None)
productId = models.CharField(max_length=30,default=None)
amount = models.CharField(max_length=30,default=None)
date = models.CharField(max_length=30,default=None)
Views.py
from django.shortcuts import render, render_to_response
from django.http import HttpResponse,HttpResponseRedirect
from django.template.loader import get_template
from django.template import Context, Template,RequestContext
import datetime
import hashlib
from random import randint
from django.views.decorators.csrf import csrf_protect, csrf_exempt
from django.core.context_processors import csrf
from django.contrib.auth.models import User
from questions.models import questions as questionData
from payments.models import payments
def success(request):
c = {}
c.update(csrf(request))
status=request.POST["status"]
firstname=request.POST["firstname"]
amount=request.POST["amount"]
txnid=request.POST["txnid"]
posted_hash=request.POST["hash"]
key=request.POST["key"]
productinfo=request.POST["productinfo"]
email=request.POST["email"]
uniqueOrder = request.POST["paymentGatewayOrderID"]
useridReturn = request.POST["udf1"]
productIdReturn = request.POST["udf2"]
salt="mysecretsalt"
try:
additionalCharges=request.POST["additionalCharges"]
retHashSeq=additionalCharges+'|'+salt+'|'+status+'|||||||||||'+email+'|'+firstname+'|'+productinfo+'|'+amount+'|'+txnid+'|'+key
except Exception:
retHashSeq = salt+'|'+status+'|||||||||||'+email+'|'+firstname+'|'+productinfo+'|'+amount+'|'+txnid+'|'+key
hashh=hashlib.sha512(retHashSeq).hexdigest().lower()
if(hashh !=posted_hash):
print "Invalid Transaction. Please try again"
else:
paymentDataInsert = payments(transactionId=txnid,userId=useridReturn,productId=productIdReturn,amount=amount,uniqueOrderId=uniqueOrder,date="today")
paymentDataInsert.save()
print "Thank You. Your order status is ", status
print "Your Transaction ID for this transaction is ",txnid
print "We have received a payment of Rs. ", amount ,". Your order will soon be shipped."
return render_to_response('success.html',RequestContext(request,{"txnid":txnid,"status":status,"amount":amount,"useridReturn":useridReturn,"uniqueOrder":uniqueOrder,"productIdReturn":productIdReturn}))
Payment is processing correctly and all the data correctly rendered on the success.html template.
But data is not inserted into table even though I correctly called
paymentDataInsert = payments(transactionId=txnid,userId=useridReturn,productId=productIdReturn,amount=amount,uniqueOrderId=uniqueOrder,date="today")
paymentDataInsert.save()
Strange thing is, it is not showing any error message. I tried my best to solve the problem, but no success.
Edit 1
I tried paymentDataInsert.save() from another function in a different view with a default value for the entries. Then it worked. It seems like the problem is only for that specific function.
My views.py code:
from django.template import Context, loader, RequestContext
from django.http import HttpResponse
from skey import find_root_tags, count, sorting_list
from search.models import Keywords
def front_page(request):
if request.method == 'get' :
str1 = request.getvalue['word']
fo = open("xml.txt","r")
for i in range(count.__len__()):
file = fo.readline()
file = file.rstrip('\n')
find_root_tags(file,str1,i)
list.append((file,count[i]))
sorting_list(list)
for name, count in list:
s = Keywords(file_name=name,frequency_count=count)
s.save()
fo.close()
return HttpResponseRedirect('/results/')
else :
str1 = ''
list = []
template = loader.get_template('search/front_page.html')
c = RequestContext(request)
response = template.render(c)
return HttpResponse(response)
def results(request):
list1 = Keywords.objects.all()
t = loader.get_template('search/results.html')
c = Context({'list1':list1,
})
return HttpResponse(t.render(c))
#this for everyone.
the flow is this:
1) I run my app on the server .
2)It shows me the search page due to the else part of the view "def front_page(request)", now I want to execute the if part of the view "def front_page(request)" because I want to execute my python code written there and the redirected to the view "def results(request)", how can I do that ?
3) what should I mention in "action" of the front_page.html and in urls.py so that I can get back to the same view again. because I could'nt get back to the same view that I want it is repetitively showing me the same search page.Please help.
To enlarge upon the answer posted by #Barnaby....by using action='#' your form will be posted to the same url as the url used in the get request for the form.
Then in your view code, you have logic that says - if the request for this url is a GET request then do the work to configure the form, otherwise, you assume it is a POST and then you can handle the response.
Additionally I would advise that the your view explicitly checks that the request is a POST and if not make the assumption that it is a GET, rather than the other way around (as you have it), this is safer, as GET and POST are not the only request types, and you definitely need to know that you are dealing with a POST request if you want to deal with variables submitted in the POST request.
Hope that helps
Short answer: action="#". This is a HTML trick to post back to the current URL.
The general answer to how to reference a view in a template is to use the url tag. You may also want to consider using Django's forms functionality.