trying to implement stripe "AttributeError: sources" - reactjs

i am getting an error when submiting Credit Card information Saying ("AttributeError at /API/CheckOut/" sources) i think it's comming from here but i don't know what the problem is
views.py
class PaymentView(APIView):
def post(self, request, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
userprofile = UserProfile.objects.get(user=self.request.user)
token = request.data.get('stripeToken')
if userprofile.stripe_customer_id != '' and userprofile.stripe_customer_id is not None:
customer = stripe.Customer.retrieve(
userprofile.stripe_customer_id)
customer.sources.create(source=token)
else:
customer = stripe.Customer.create(
email=self.request.user.email,
)
customer.sources.create(source=token)
userprofile.stripe_customer_id = customer['id']
userprofile.one_click_purchasing = True
userprofile.save()
i am using React on the frontend and Posting the Token like this
const {error, paymentMethod} = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
});
const stoken=paymentMethod.id
if (error) {
seterror(error)
setloading(false);
} else {
seterror(null)
axios
.post(checkoutURL, {
stoken,
selectedBillingAddress,
selectedShippingAddress
})

Related

Flask & React JS error 422 (UNPROCESSABLE ENTITY)

Trying to read some data from the /profile route of my flask api. I keep getting error 422 unprocessable entity. This is on my Home.tsx file where I am already authenticated and am trying to read some more data from flask.
picture of error
I have no issues getting a response from the api when getting tokens via /tokens. I followed this guide here exactly to connect flask to react and I have no idea why it is not working.
I am pretty comfortable with React but very new to flask to please forgive me. Any help with this would really be appreciated.
It looks like if I get rid of #jwt_required() it does work but my understanding is this should be used.
base.py
api = Flask(__name__)
CORS(api)
api.config["JWT_SECRET_KEY"] = "please-remember-to-change-me"
api.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(hours=1)
jwt = JWTManager(api)
#api.after_request
def refresh_expiring_jwts(response):
try:
exp_timestamp = get_jwt()["exp"]
now = datetime.now(timezone.utc)
target_timestamp = datetime.timestamp(now + timedelta(minutes=30))
if target_timestamp > exp_timestamp:
access_token = create_access_token(identity=get_jwt_identity())
data = response.get_json()
if type(data) is dict:
data["access_token"] = access_token
response.data = json.dumps(data)
return response
except (RuntimeError, KeyError):
# Case where there is not a valid JWT. Just return the original response
return response
#api.route('/token', methods=["POST"])
def create_token():
email = request.json.get("email", None)
password = request.json.get("password", None)
if email != "test" or password != "test":
return {"msg": "Wrong email or password"}, 401
access_token = create_access_token(identity=email)
response = {"access_token":access_token}
return response
#api.route("/logout", methods=["POST"])
def logout():
response = jsonify({"msg": "logout successful"})
unset_jwt_cookies(response)
return response
#api.route("/profile", methods=["GET"])
#jwt_required()
def my_profile():
response_body = {
"name": "Michael",
"about" :"Admin"
}
return response_body
Home.tsx
import { useEffect, useState } from "react";
import { BsPersonFill, BsCalendarFill } from "react-icons/bs";
import { RiTeamFill } from "react-icons/ri";
import { BiLogOut } from "react-icons/bi";
import axios from "axios";
import Navbar from "../components/Navbar";
import Footer from "../components/Footer";
const Home = (props: any) => {
const [profileData, setProfileData] = useState<any>(null);
function getData() {
axios({
method: "GET",
url: "http://127.0.0.1:5000/profile",
headers: {
Authorization: "Bearer " + props.token,
},
})
.then((response) => {
const res = response.data;
res.access_token && props.setToken(res.access_token);
setProfileData({
profile_name: res.name,
about_me: res.about,
});
})
.catch((error) => {
if (error.response) {
console.log(error.response);
console.log(error.response.status);
console.log(error.response.headers);
}
});
}
useEffect(() => {
getData();
}, []);
Tried searching for this on other threads and nothing I tried worked such as messing with authorization header, did not make a difference. It works fine when sending the request with postman.

React JS axios error Request failed with status code 500 using Django REST Framework

I need data from 4 table in same output json from Django Rest API.
Models.py
class T(model.Model)
book = models.ForeignKey(
'b.B',
on_delete=models.CASCADE,
)
user = models.ForeignKey('a.U', on_delete=models.CASCADE)
status = models.CharField(max_length=1, choices=[('0', 'DRAFT'),('1', 'PUBLISH')], default=0)
class B(model.Model)
title = models.CharField(max_length=256, default='TITLE')
user = models.ForeignKey('a.U', on_delete=models.CASCADE)
category = models.ForeignKey('c.C', on_delete=models.CASCADE, blank=True, null=True)
class C(models.Model):
name = models.CharField(max_length=256)
class U(models.Model):
name = models.CharField(max_length=256)
Views.py
#api_view(['GET'])
def collect(request):
data = T.objects.select_related('b').filter(status=1)
list = []
for row in data:
list.append(
{
'id':row.book.id,
'book_title': row.b.title,
'author': row.b.u.name,
'category': row.b.c.name,
}
)
return Response(
data = list,
status=status.HTTP_201_CREATED
)
Output in Postman
But when calling the API in React.js using Axios, the data doesn't show and get error.
the server responded with a status of 500 (Internal Server Error)
This is a code in React.js
import useAuth from '../../hooks/useAuth';
import axios from '../../api/axios';
const Library = () => {
const { auth, setAuth } = useAuth();
const [dataKoleksi, setProjek] = useState([])
const getProjek = async() => {
try {
let response = await axios.get('https://app.com/api/collect',
{
headers: {
'Content-Type': 'application/json',
'Authorization' : `Bearer ${auth.access}`
},
withCredentials: true
}
)
setProjek(response.data)
setFoundBook(response.data)
} catch (e) {
console.log(e.message)
}
}
useEffect(() => {
getProjek();
}, [])
My question is why in React.js data can't show and got error, but it's success when try to testing get data in Postman.

Django/React 415 (Unsupported Media Type)

I'm getting POST http://localhost:8000/api/reports/ 415 (Unsupported Media Type) when I try to submit the form from React and I don't understand what's the problem.
Here's the code.
models.py
class Report(models.Model):
category = models.ForeignKey(Category, on_delete=models.PROTECT)
description = models.TextField()
address = models.CharField(max_length=500)
reporter_first_name = models.CharField(max_length=250)
reporter_last_name = models.CharField(max_length=250)
reporter_email = models.CharField(max_length=250)
reporter_phone = models.CharField(max_length=250)
report_image_1 = models.ImageField(_("Image"), upload_to=upload_to, null=True, blank=True)
report_image_2 = models.ImageField(_("Image"), upload_to=upload_to, null=True, blank=True)
report_image_3 = models.ImageField(_("Image"), upload_to=upload_to, null=True, blank=True)
date = models.DateTimeField(default=timezone.now)
class Meta:
ordering = ('-date',)
def __str__(self):
return self.description
I also tried to put default values for images, but I still get the error.
serializers.py
class ReportSerializer(serializers.ModelSerializer):
categoryName = CategorySerializer(many=False, read_only=True, source='category')
class Meta:
model = Report
fields = '__all__'
views.py
class ManageReports(viewsets.ModelViewSet):
serializer_class = ReportSerializer
parser_classes = [MultiPartParser, FormParser]
def get_object(self, queryset=None, **kwargs):
id = self.kwargs.get('pk')
return get_object_or_404(Report, id=id)
def get_queryset(self):
return Report.objects.all()
This is the code responsible for the submit.
report.js
const initialPostData = Object.freeze({
category: '',
address: '',
description: '',
reporter_first_name: '',
reporter_last_name: '',
reporter_email: '',
reporter_phone: '',
});
const [postData, updatePostData] = useState(initialPostData);
const [postImage1, setPostImage1] = useState({image: null});
const [postImage2, setPostImage2] = useState({image: null});
const [postImage3, setPostImage3] = useState({image: null});
const handleChange = (e) => {
if([e.target.name] == 'reporter_image_1') {
setPostImage1({
image: e.target.files[0],
});
} else if([e.target.name] == 'reporter_image_2') {
setPostImage2({
image: e.target.files[0],
});
} else if([e.target.name] == 'reporter_image_3') {
setPostImage3({
image: e.target.files[0],
});
} else if([e.target.name] == 'category') {
updatePostData({
...postData,
[e.target.name]: e.target.value,
});
} else {
updatePostData({
...postData,
[e.target.name]: e.target.value.trim(),
});
}
};
const handleSubmit = async(e) => {
e.preventDefault();
let formData = new FormData();
formData.append('category', postData.category);
formData.append('address', postData.address);
formData.append('description', postData.description);
formData.append('reporter_first_name', postData.reporter_first_name);
formData.append('reporter_last_name', postData.reporter_last_name);
formData.append('reporter_email', postData.reporter_email);
formData.append('reporter_image_1', postImage1.image);
formData.append('reporter_image_2', postImage2.image);
formData.append('reporter_image_3', postImage3.image);
const submitForm = await submitReport(formData);
And here's the submitReport API
API.js
const axiosInstance = axios.create({
baseURL: 'http://localhost:8000/api/',
timeout: 5000,
headers: {
Authorization: accessToken
? 'JWT ' + accessToken
: null,
'Content-Type': 'application/json',
accept: 'application/json',
},
});
// Submit Report Form
const submitReport = async(formData) => {
const { data } = await axiosInstance.post('reports/', {...formData });
return data;
}
These should be all the files needed to understand what's going on.
Thanks in advance.
Your parser_classes attribute on viewset is wrong. If you want to accept JSON format in request body you need to include JSONParser in your parser_classes attribute.
See the related section from here in DRF docs.
I found the solution, I was using the spread operator in the submitReport function, but instead I don't need to use it, so:
API.js
// Submit Report Form
const submitReport = async(formData) => {
const { data } = await axiosInstance.post('reports/', {...formData });
return data;
}
becomes
// Submit Report Form
const submitReport = async(formData) => {
const { data } = await axiosInstance.post('reports/', formData);
return data;
}

why getting 'WSGIRequest' object has no attribute 'data' error?

I am trying to use card payment through stripe in react Js and Django. I am following https://betterprogramming.pub/how-to-integrate-django-react-app-with-stripe-payments-95709b3f23e5 this tutorial.
frontend
const handleSubmit = async (event) => {
event.preventDefault();
const card = elements.getElement(CardElement);
const {paymentMethod, error} = await stripe.createPaymentMethod({
type: 'card',
card: card
});
ApiService.saveStripeInfo({
email, payment_method_id: paymentMethod.id})
.then(response => {
console.log(response.data);
}).catch(error => {
console.log(error)
})
}
export const api = axios.create({
baseURL: API_URL,
headers: {
"Content-type": "application/json"
}
});
export default class ApiService{
static saveStripeInfo(data={}){
return api.post(`${API_URL}/payments/save-stripe-info/`, data)
}
}
server
#api_view(['POST'])
def test_payment(request):
test_payment_intent = stripe.PaymentIntent.create(
amount=1000, currency='pln',
payment_method_types=['card'],
receipt_email='test#example.com')
return Response(status=status.HTTP_200_OK, data=test_payment_intent)
def save_stripe_info(request):
print('this => ',request.data)
data = request.data
email = data['email']
payment_method_id = data['payment_method_id']
# creating customer
customer = stripe.Customer.create(
email=email, payment_method=payment_method_id)
return Response(status=status.HTTP_200_OK,
data={
'message': 'Success',
'data': {'customer_id': customer.id}
}
)
but whenever I click the submit button it given me following error
AttributeError: 'WSGIRequest' object has no attribute 'data'
[12/Dec/2021 21:55:57] "POST /payments/save-stripe-info/ HTTP/1.1" 500 71355
for full code please visit https://betterprogramming.pub/how-to-integrate-django-react-app-with-stripe-payments-95709b3f23e5
According to the docs there is no data member of WSGIRequest. You will need to refer to the body attribute instead.
data is part of the rest_framework. You need to decorate the view with an api_view.
Just add "#api_view(['POST'])" before the def save_stripe_info(request).
It should be:
#api_view(['POST'])
def save_stripe_info(request):
print('this => ',request.data)
data = request.data
email = data['email']
payment_method_id = data['payment_method_id']
# creating customer
customer = stripe.Customer.create(
email=email, payment_method=payment_method_id)
return Response(status=status.HTTP_200_OK,
data={
'message': 'Success',
'data': {'customer_id': customer.id}
}
)
or just load the body in json.
data = json.loads(request.body)

Django + ReactJS. The Httponly cookie is not saved in the browser at React side. I also gave {withcredentials : true} at both side

I use django rest_framework_simplejwt package to generate JWT tokens and set them in browsable cookie with Httponly flag. At the Django side it work perfectly but at react side it does not work perfectly.
I read many answers related to this question like this and this but they have not solved my problem yet.
Please help me understand where I'm wrong.
DJANGO SIDE
views.py
from rest_framework_simplejwt.views import TokenObtainPairView
from django.conf import settings
from rest_framework import status
from rest_framework_simplejwt.exceptions import TokenError,\
InvalidToken
from rest_framework.response import Response
class MyTokenObtainPairView(TokenObtainPairView):
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0])
# set access token in browser with Httponly cookie.
res = Response(serializer.validated_data, status=status.HTTP_200_OK)
access_token = serializer.validated_data['access']
res.set_cookie("access_token", access_token, max_age=settings.SIMPLE_JWT.get('ACCESS_TOKEN_LIFETIME').total_seconds(),samesite='Lax',secure=False, httponly=True)
return res
authentication.py
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings
class CookieHandlerJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
# If cookie contains access token, put it inside authorization header
access_token = request.COOKIES.get('access_token')
if(access_token):
request.META['HTTP_AUTHORIZATION'] = '{header_type} {access_token}'.format(
header_type=settings.SIMPLE_JWT['AUTH_HEADER_TYPES'][0], access_token=access_token)
return super().authenticate(request)
urls.py
from .views import MyTokenObtainPairView
urlpatterns = [
......
path('auth/', include('djoser.urls')),
# path('auth/', include('djoser.urls.jwt')),
path('auth/api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
]
settings.py
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
'http://127.0.0.1:8000'
)
Work perfectly(Token set in cookie with Httponly.):
REACTJS SIDE
Login.js
axios.defaults.withCredentials = true
const Login = () => {
const [ivalue, setValue] = useState({});
const { state, dispatch } = useContext(Authcontext);
.......
const loginClick = (e) => {
e.preventDefault();
setLoader(true);
axios.post('http://127.0.0.1:8000/auth/api/token/', {
username: ivalue.username,
password: ivalue.password,
})
.then((res) => {
setValue({ password: "" });
dispatch({
type: LOGIN_SUCCESS,
});
setLoader(false);
history.push("/my_profile");
})
.catch((err) => {
setLoader(false);
setOpen({ act: true, msg: "error" });
dispatch({
type: LOGIN_ERROR,
});
setError(err.response.data);
});
};
.........
};
Myprofile.js
axios.defaults.withCredentials = true
const MyProfile = () => {
const history = useHistory();
const { state, dispatch } = useContext(Authcontext);
useEffect(() => {
const auth_check = () => {
axios.get('http://127.0.0.1:8000/auth/users/me/')
.then((res) => {
dispatch({
type: AFTER_LOGIN,
payload: res.data
});
})
.catch((err) => {
history.push('/login')
});
};
auth_check();
}, []);
}
.......
JWT Response(cookie not set in browser).
Unauthorized Error
I set backend and frontend under same IP. ex. my backend is
localhost:8000
and frontend is
localhost:3000
different ports same Ip.
This is not the scenario when it goes to production you can have any domain.
You are getting a samesite=Lax value in your set-cookie header try using CSRF_COOKIE_SECURE = True, SESSION_COOKIE_SECURE = True, CSRF_COOKIE_SAMESITE = 'None', SESSION_COOKIE_SAMESITE = 'None'
this will let browser to set cookies even from a different domain.
and use withCredentials: true on your client side.

Resources