I am new to Django and trying to integrate razorpay with my website but getting error
AttributeError: 'str' object has no attribute 'post'
views.py
def order(request, id):
product = Product.objects.get(prod_ID=id)
if request.method == 'POST':
customer_id = request.user
product = Product.objects.get(prod_ID=id)
product_id = product
try:
quantity = request.POST['quantity']
quantity = int(quantity)
order_price = quantity * product.prod_Price
print(order_price)
except MultiValueDictKeyError:
pass
try:
size = request.POST['size']
value.update(size=size)
except MultiValueDictKeyError:
pass
try:
Colour = request.POST['Color']
value.update(Colour=Colour)
except MultiValueDictKeyError:
pass
attribute_value = json.dumps(value)
order_store = Order(user_id=customer_id, prod_id=product_id, quantity=quantity,
attribute_value=attribute_value,
order_price=order_price)
if order_store:
order_store.save()
o_id = Order.objects.get(order_id=order_store.order_id)
payment_store = Payment(order_id=o_id)
payment_store.save()
client = razorpay.Client('rzp_test_Cut6mUJgrjfQU', 'LSNlrKrH0NoUq8Y9rEUbg27')
print(client)
data = {
'amount': order_price * 100,
'currency': "INR",
'receipt': 'Order for ' + str(o_id.order_id),
'notes': {
'name': o_id.user_id.first_name + o_id.user_id.last_name,
'Payment_for': o_id.prod_id.prod_Name
}
}
print(data)
order_detail = client.order.create(data=data)
print(order_detail)
return render(request, 'user/payment.html', {'order_store': order_store})
context = {'products': products
}
return render(request, 'user/order.html', context)
Here I am trying to integrate payment with my website but after creating order and payment status I am trying to do payment but I don't know what I am doing wrong.
To intialize the client you have to use the auth parameter - see razorpay Initialization.
And give a tuple as value:
import razorpay
client = razorpay.Client(auth=("<YOUR_KEY>", "<YOUR_SECRET>"))
Related
I'm practicing Django and was doing the Commerce assignment of CS50, got an error in the watchlist view and don't understand how to fix it. Hopefully you can help me.
Here is the view:
def watchlist(request):
if request.method == "POST":
listing_id = request.POST.get("listing_id")
try:
listing = Listing.objects.get(pk=listing_id)
user = User.objects.get(id=request.user.id)
except Listing.DoesNotExist:
return render(request, "auctions/error_handling.html", {
"code": 404,
"message": "Listing id doesn't exist"
})
if request.POST.get("on_watchlist") == "True":
watchlist_item_to_delete = Watchlist.objects.filter(
user = user,
listing = listing
)
watchlist_item_to_delete.delete()
else:
try:
watchlist_item = Watchlist(
user = user,
listing = listing
)
watchlist_item.save()
except IntegrityError:
return render(request, "auctions/error_handling.html", {
"code": 400,
"message": "Listing is already on your watchlist"
})
return HttpResponseRedirect("/" + listing_id)
watchlist_listings_ids = User.objects.get(id=request.user.id).watchlist.values_list("listing")
watchlist_items = Listing.objects.filter(id__in=watchlist_listings_ids, active_status=True)
return render(request, "auctions/watchlist.html", {
"watchlist_items": watchlist_items
})
Django reports the error in this line listing = Listing.objects.get(pk=listing_id), so not even the exception is handling the error.
I checked all the models and other views, and also using the app itself in the local host and the only thing alerting an error is that part.
i was trying to make my first e-commerce website using django and i received this error.
I already search in google but I can't find how to fix it. please help me to find the error.
this is attached. If any data is missing please comment.
cart.js :
var updateBtns = document.getElementsByClassName('update-cart')
for (var i = 0; i < updateBtns.length; i++) {
updateBtns[i].addEventListener('click', function () {
var productId = this.dataset.product`enter code here`
var action = this.dataset.action
console.log('productId:', productId, 'Action:', action)
console.log('USER:', user)
if (user == 'AnonymousUser') {
console.log('Not logged in')
} else {
updateUserOrder(productId)
}
})
}
function updateUserOrder(productId, action) {
console.log('User is logged in, sending data...')
var url = '/update_item/'
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({ 'productId': productId, 'action': action })
})
.then(response => response.json())
.then((data) => {
console.log('data:', data);
}
);
}
views.py :
from django.shortcuts import render
from django.http import JsonResponse
from django.http import HttpRequest
import json
from .models import *
def store(request):
products = Product.objects.all()
context = {'products': products}
return render(request, 'store/store.html', context)
def cart(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(
customer=customer, complete=False)
items = order.orderitem_set.all()
else:
# Create empty cart for now for non-logged in user
items = []
order = {'get_cart_total': 0, 'get_cart_items': 0}
context = {'items': items, 'order': order}
return render(request, 'store/cart.html', context)
def checkout(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(
customer=customer, complete=False)
items = order.orderitem_set.all()
else:
# Create empty cart for now for non-logged in user
items = []
order = {'get_cart_total': 0, 'get_cart_items': 0}
context = {'items': items, 'order': order}
return render(request, 'store/checkout.html', context)
def updateItem(request):
data = json.loads(request.data)
productId = data['productId']
action = data['action']
print('Action:', action)
print('productId:', productId)
return JsonResponse('Item was added', safe=False)'''
def updateItem(request):
data = json.loads(request.data)
request.data is available in Django rest framework, but it doesn't exist in regular Django views.
Change the view to use request.body instead.
def updateItem(request):
data = json.loads(request.body)
Can anyone please help me to fix this problem local variable 'intent' referenced before assignment i could not find out why client_secret in the context is triggered. to my knowledge if the code in if statement fails then else block will be executed but i have set a print statement and it does not appear in the teminal either. if someone can please help me in solving this issue.
from django.shortcuts import render, redirect, reverse
from django.contrib import messages
from django.conf import settings
from .forms import OrderForm
from .models import Order, OrderLineItem, ProductLineItem, ExerciseLineItem, NutritionLineItem
from merchandise.models import Product
from exercise.models import ExercisePlans
from nutrition.models import NutritionPlans
from cart.contexts import cart_contents
import stripe
def checkout(request):
stripe_public_key = settings.STRIPE_PUBLIC_KEY
stripe_secret_key = settings.STRIPE_SECRET_KEY
if request.method == 'POST':
cart = request.session.get('cart', {
'merchandise_dic': {},
'excercise_plans_dic': {},
'nutrition_plans_dic': {},
})
form_data = {
'full_name': request.POST['full_name'],
'email': request.POST['email'],
'phone_number': request.POST['phone_number'],
'country': request.POST['country'],
'postcode': request.POST['postcode'],
'town_or_city': request.POST['town_or_city'],
'street_address1': request.POST['street_address1'],
'street_address2': request.POST['street_address2'],
'county': request.POST['county'],
}
order_form = OrderForm(form_data)
if order_form.is_valid():
print("Order form is valid")
order = order_form.save()
for product_type, dic in cart.items():
if product_type == 'merchandise_dic':
for item_id, quantity in dic.items():
print(f"This is item id of merchandise: {item_id}")
print(f"This is quantity of merchandise: {quantity}")
product = Product.objects.get(id=item_id)
print(product)
order_line_item = ProductLineItem(
order=order,
product=product,
quantity=quantity,
)
order_line_item.save()
elif product_type == 'excercise_plans_dic':
for item_id, quantity in dic.items():
print(f"This is item id of exercise plan: {item_id}")
print(f"This is quantity of exercise plan: {quantity}")
product = ExercisePlans.objects.get(id=item_id)
print(product)
order_line_item = ExerciseLineItem(
order=order,
product=product,
quantity=quantity,
)
order_line_item.save()
elif product_type == 'nutrition_plans_dic':
for item_id, quantity in dic.items():
print(f"This is item id of nutrition plan: {item_id}")
print(f"This is quantity of nutrition plan: {quantity}")
product = NutritionPlans.objects.get(id=item_id)
print(product)
order_line_item = NutritionLineItem(
order=order,
product=product,
quantity=quantity,
)
order_line_item.save()
else:
print("Order form is invalid")
messages.error(request, ('There was an error with your form. '
'Please double check your information.'))
return redirect(reverse('checkout'))
else:
print("Order form is invalid")
cart = request.session.get('cart', {
'merchandise_dic': {},
'excercise_plans_dic': {},
'nutrition_plans_dic': {},
})
if not cart:
messages.error(request,
"There is nothing in your \
shopping cart at the moment")
return redirect(reverse('products'))
""" Got total from cart_contents """
current_cart = cart_contents(request)
current_total = current_cart['total']
stripe_total = round(current_total * 100)
""" Set secret key on stripe """
stripe.api_key = stripe_secret_key
""" Created payment intent """
intent = stripe.PaymentIntent.create(
amount=stripe_total,
currency=settings.STRIPE_CURRENCY,
)
print(intent)
order_form = OrderForm()
if not stripe_public_key:
messages.warning(request, 'Stripe public key is missing. \
Did you forget to set it in your environment?')
template = 'checkout/checkout.html'
context = {
'order_form': order_form,
'stripe_public_key': stripe_public_key,
'client_secret': intent.client_secret,
}
return render(request, template, context)
If your method == "POST": is true then the intent variable is not assigned any parameter.
context = {
'order_form': order_form,
'stripe_public_key': stripe_public_key,
'client_secret': intent.client_secret,
}
Hence, the intent in last section is not assigned anything.
else:
print("Order form is invalid")
cart = request.session.get('cart', {
'merchandise_dic': {},
'excercise_plans_dic': {},
'nutrition_plans_dic': {},
})
if not cart:
messages.error(request,
"There is nothing in your \
shopping cart at the moment")
return redirect(reverse('products'))
""" Got total from cart_contents """
current_cart = cart_contents(request)
current_total = current_cart['total']
stripe_total = round(current_total * 100)
""" Set secret key on stripe """
stripe.api_key = stripe_secret_key
""" Created payment intent """
---> intent = stripe.PaymentIntent.create(
amount=stripe_total,
currency=settings.STRIPE_CURRENCY,
)
print(intent)
order_form = OrderForm()
intent is assigned inside the else block, but it is referenced outside the else block
context = {
'order_form': order_form,
'stripe_public_key': stripe_public_key,
---> 'client_secret': intent.client_secret,
So if the else block is not executed there is no intent variable.
Thanks every one for your valuable input I found the problem and fixed it. Actually I was not returning anything if the form is valid! Thus I was missing the redirect to checkout_success page at the first for loop level before 1st else.
That is why even if the form is valid it's still trying to return the render() statement at the bottom which was causing this error. Thus I created a checkout_success view and and also checkout_success.html and redirected to it. like this and fixed this error.
return redirect(reverse('checkout_success',
args=[order.order_number]))
I am trying to save some information in database if transaction is successful, in the stripe_webhook view. But not successful. is it that data cannot be saved directly in webhook ? so frustrating for me. I checked online for sample codes but could not find the ones that insert or update database for successful transaction.
from site.models import Post, Chapter, Order
import stripe
from sqlalchemy import desc
#posts.route("/paynow")
#login_required
def paynow():
return render_template('paynow.html',)
#posts.route('/stripe_pay')
#login_required
def stripe_pay():
amt = 10000
stripe.api_key = current_app.config['STRIPE_SECRET_KEY']
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=[{
'price_data': {
'currency': 'usd',
'product_data': {
'name': 'T-shirt',
},
'unit_amount': amt,
},
'quantity': 1,
}],
mode='payment',
success_url=url_for('posts.payment_success', _external=True) + '?session_id={CHECKOUT_SESSION_ID}',
cancel_url=url_for('posts.paynow', _external=True),
)
return {
'checkout_session_id': session['id'],
'checkout_public_key': current_app.config['STRIPE_PUBLIC_KEY']
}
#posts.route('/stripe_webhook', methods=['POST'])
#login_required
def stripe_webhook():
print('WEBHOOK CALLED')
if request.content_length > 1024 * 1024:
print('REQUEST TOO BIG')
abort(400)
payload = request.get_data()
sig_header = request.environ.get('HTTP_STRIPE_SIGNATURE')
endpoint_secret = 'whsec_*************************************'
event = None
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
# Invalid payload
print('INVALID PAYLOAD')
return {}, 400
except stripe.error.SignatureVerificationError as e:
# Invalid signature
print('INVALID SIGNATURE')
return {}, 400
# Handle the checkout.session.completed event
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
print(session)
line_items = stripe.checkout.Session.list_line_items(session['id'], limit=1)
print(line_items['data'][0]['description'])
# save to database if successful
save_order = Order(trans_id = "pppppppppp")
db.session.add(save_order)
db.session.commit()
return {}
#posts.route('/payment_success')
#login_required
def payment_success():
cart=Cart.query.filter_by(username = current_user.username).all()
cart.status = "paid"
db.session.commit()
return render_template('payment_success.html')
According to the Stripe customer care, I must used a live domain instead of local host
I am sending a get request in my view and then using the response to fill my database and I need some confirmation on the following:
should i make an api call inside of a view?
what should that view response be?
if i have done it wrong then what would be the right way to send get requests in Django?
my_app/views.py
class api(APIView):
template_name = 'payment/api.html'
def get(self, request):
#I SEND THE GET REQUEST HERE
config = configparser.ConfigParser()
config.read('config.ini')
r = requests.get(config['DEFAULT']['api'])
response = r.json()
#HERE I FILTER THE RESPONSE AND PUT IN A DB
for item in response:
if 'Covered Recipient Physician' in item.values():
person, _ = models.Person.objects.get_or_create(
profile_id = int(item['physician_profile_id']),
first_name = item['physician_first_name'].lower(),
last_name = item['physician_last_name'].lower()
)
address, _ = models.Address.objects.get_or_create(
business_street =
item['recipient_primary_business_street_address_line1'].lower(),
city = item['recipient_city'].lower(),
state = item['recipient_state'].lower(),
country = item['recipient_country'].lower()
)
business, _ = models.Business.objects.get_or_create(
business = item['submitting_applicable_manufacturer_or_applicable_gpo_name'].lower(),
)
business_address_link = models.Business_address_link.objects.create(
business = business,
address = address
)
business_address_link.save()
payment = models.Payment.objects.create(
record_id = int(item['record_id']),
amount = float(item['total_amount_of_payment_usdollars']),
date = item['date_of_payment'],
number_of_payments = int(item['number_of_payments_included_in_total_amount']),
payment_form = item['form_of_payment_or_transfer_of_value'],
nature_of_payment = item['nature_of_payment_or_transfer_of_value']
)
payment.save()
person_payment_information = models.Person_payment_information.objects.create(
person = person,
business_address_link = business_address_link,
payment = payment
)
person_payment_information.save()
Try to use this function for GET request -
#require_http_methods(['GET'])
def get_persons(request):
try:
data = list(Message.objects.all.values())
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})
Once you get the response and send it to template.html, you can display it in any way you want.
If you want to add information to the DB you better use POST request, for example -
#require_http_methods(['POST'])
def add_person(request):
try:
data = json.loads(request.body)
new_person = Person(**data)
new_person.save()
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})