I am trying to setup the paymentIntent API from Stripe but I can't seem to figure out the error I am getting. I followed along from this video: https://www.youtube.com/watch?v=w1oLdAPyuok&t=1414s
I have a react frontend which makes a request to my Django view:
try {
const { data: clientSecret } = await axios.post("http://127.0.0.1:8000/paymentIntent/", {
amount: price * 100
});
My view:
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import View
from django.views.decorators.csrf import csrf_exempt
import logging
from rest_framework.views import APIView
from rest_framework import status, generics
from rest_framework.response import Response
from rest_framework.decorators import api_view
from django.conf import settings
import stripe
stripe.api_key = "pk_test_51HWMwZB5hTmoPZOBJd00GjCvDYUg"
#api_view(['POST'])
def payment(request):
try:
amount = request.body
paymentIntent = stripe.PaymentIntent.create(
amount = amount,
currency = "usd",
# payment_method_types=['card'],
# capture_method='manual',
metadata={'integration_check': 'accept_a_payment'},
)
data = paymentIntent.client_secret
return Response(data,status=status.HTTP_200_OK)
except :
return Response(status=status.HTTP_400_BAD_REQUEST)
When I make the request it just says 400 Bad Request with no response data
I don't see the actual error message you're getting, your server should log out the error in your try-catch block, as shown here: https://stripe.com/docs/api/errors/handling?lang=python allowing you to better debug and troubleshoot as you build your integration.
Most likely, it is that you have set your publishable key as your stripe-python API key. Instead you need to initialize stripe with your secret key: https://stripe.com/docs/api/authentication?lang=python
Related
I am having some trouble with the development of my React app. On the client side, I'm using Axios to make the requests to the API (Flask).
The problem is that I frequently get a CORS error only when I send the request to the localhost API. I have the same API running in Heroku without any error.
API route = http://127.0.0.1:5000
Client route = http://localhost:3000/#/
Client code:
const endpoint = process.env.REACT_APP_ENDPOINT;
// Fetch API data
const [data, setData] = useState([{}]);
useEffect(() => {
axios.get(endpoint + "/api/rooms")
.then((data) => {
console.log("API endpoint data retrieved.");
if (data[200] !== "No Rooms") {
setData(data);
}
}).catch((err) => {
console.error(err.message);
console.log("No rooms retrieved from API endpoint.");
});
}, [endpoint]);
Server (Python) code:
import os
from flask import Flask
from flask_socketio import SocketIO
from flask_cors import CORS, cross_origin
from dotenv import load_dotenv
from app_modules.util.rooms import Rooms
load_dotenv()
app = Flask(__name__, static_folder="/client/build")
app.config['SECRET_KEY'] = os.getenv("app_key")
app.config['CORS_HEADERS'] = "Content-Type"
ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS")
cors = CORS(app, resources={"/*": {"origins": ALLOWED_ORIGINS}}, support_credentials=True)
socketio = SocketIO(app,
cors_allowed_origins=ALLOWED_ORIGINS,
logger=False,
engineio_logger=False,
cors_credentials=True)
rooms = Rooms()
#app.route('/api/rooms')
#cross_origin(supports_credentials=True)
def home():
return {"rooms": rooms.secure_api} if rooms.secure_api else {"200": "No Rooms"}
Note:
ALLOWED_ORIGINS=*
But I keep getting this error:
In your server code change
ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS")
to
ALLOWED_ORIGINS = ['localhost', '127.0.0.1']
I'm trying to add authentication to my django-react app. At this point I am able to login/register users and it works fine but I want to get only data which is related with user logged in so posted or updated by them. Now I get all data regardless of user which is authenticated.
I assume I have to change it in my views but how to do this?
This is one of my classes
class ListView(viewsets.ModelViewSet):
serializer_class = ListSerializer
queryset = List.objects.all()
And on frontend side I get data this way:
const getList = async () => {
try {
const response = await axiosInstance.get('/list/')
if(response){
setList(response.data)
}
}catch(error){
throw error;
}
}
You can use Django Rest Framework to set the authentication scheme on a per-view or per-viewset basis. Using the APIView class-based views:
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request, format=None):
content = {
'user': str(request.user), # `django.contrib.auth.User` instance.
'auth': str(request.auth), # None
}
return Response(content)
Remember to set it up:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
Read more here
I am using axios to fetch data from aws.
import React, {useState, useEffect} from 'react';
import axios from 'axios';
function Employee() {
const[data, setData] = useState([]);
useEffect(() => {
axios.get('123.56.234.123:8080/employees?num=1')
.then(response => {
setData(response.data);
})
},[]);
return data;
}
From this code, I got the error message saying
Get http://localhost:8080/123.56.234.123:8080/employees?num=1 431(Request Header Fields Too Large).
I believe the cause is from the wrong url I am getting.
In this case, how can I fetch data from the endpoint?
PS) My node version: 14.XX
Thank you.
I think you need to set a PROXY. You have currently set the axios baseURL to be localhost:8080. That is why the get url is getting prepended to baseUrl.
The error 431(Request Header Fields Too Large) occurs because the Referrer url is too long.
If you are using create-react-app, then please refer this official documentation.
I have a project using React (frontend) and Django Rest Framework (backend), and it is currently deployed on PythonAnywhere. I'm using axios to connect to my API and load data from my database onto the React frontend.
During development, I hardcoded the username and password for accessing the database into my index.js file (credentials are obscured below):
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.js';
import axios from 'axios';
import 'semantic-ui-css/semantic.min.css';
import 'lightgallery.js/dist/css/lightgallery.css';
import './styles.css';
import * as serviceWorker from './serviceWorker';
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.withCredentials = true;
axios.post('/login/', { username: [HARD_CODED_USERNAME], password: [HARD_CODED_PASSWORD] }).then(rv => {
console.log('Login', rv)
}).catch(err => {
console.log('Login error', err.response)
});
const updatePhoto = () => {
axios.patch('https://[WEBSITEADDRESS.COM]/api/photos/').then(resp => {
console.log('Update response', resp)
}).catch(error => {
console.log("Update error", error)
})
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
serviceWorker.unregister();
This works, however the username and password are viewable upon inspection in the browser. Not only that, but the Django admin as well as the API is accessible to anyone, because it automatically logs them in using my username and password!
I then tried using an .env file located at the root of my create-react-app project (same level with my package.json file):
REACT_APP_USERNAME=myusername
REACT_APP_PASSWORD=mypassword
And I updated my index.js file to as follows:
const my_user_name = process.env.REACT_APP_USERNAME;
const my_password = process.env.REACT_APP_PASSWORD;
axios.post('/login/', { username: my_user_name, password: my_password }).then(rv => {
console.log('Login', rv)
}).catch(err => {
console.log('Login error', err.response)
});
However, this still does not obscure the credentials from inspection in the browser, and, while it does solve the issue of automatically logging anyone into my Django admin and API, the data from the database is not shown on the website.
My questions are as follows:
How do I properly set up axios to access my API and display data on my website WITHOUT logging someone into my Django admin?
How do I properly set up environment variables in React to hide sensitive data when using the browser's inspection tools?
Any help is much appreciated!
UPDATE: SOLUTION
Based on #Lior_Pollak's comment on his answer below, I managed to solve both of my issues by creating a public, read-only API endpoint on the backend. Anyone can view the API but cannot post, update, or delete data, nor can they access the Django admin. And no sensitive data is displayed in the browser's inspection tool, yet all my photos are displayed on the website. :)
In case anyone else stumbles across this question, I've provided the code I've used successfully below (both backend and frontend):
Frontend: index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.js';
import 'semantic-ui-css/semantic.min.css';
import 'lightgallery.js/dist/css/lightgallery.css';
import './styles.css';
import * as serviceWorker from './serviceWorker';
/*Removed all code related to axios; was not needed here*/
ReactDOM.render(
<App />,
document.getElementById('root')
);
serviceWorker.unregister();
Backend: views.py
from django.views.generic import View
from django.http import HttpResponse
from django.conf import settings
from rest_framework import generics
from rest_framework import permissions
from .models import Photo
from .serializers import PhotoSerializer
import logging
import os
class PhotoList(generics.ListCreateAPIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
queryset = Photo.objects.filter(show=True).order_by('order')
serializer_class = PhotoSerializer
class FrontendAppView(View):
def get(self, request):
print (os.path.join(settings.REACT_APP_DIR, 'build', 'index.html'))
try:
with open(os.path.join(settings.REACT_APP_DIR, 'build', 'index.html')) as f:
return HttpResponse(f.read())
except FileNotFoundError:
logging.exception('Production build of app not found')
return HttpResponse(status=501)
Backend: urls.py
from django.conf.urls import include, url
from rest_framework import routers
from backend import views
router = routers.DefaultRouter()
urlpatterns = [
url(r'^api/', include(router.urls)),
url(r'^api/photos/$', views.PhotoList.as_view()),
]
You are trying to obscure client data, which (for obvious reasons) resides in the client.
So you can't really obscure it.
You can force the user to login with their credentials, which is how authentication using username and password is done.
i want to receive a particular input from the frontend react textarea to perform a certain function in django backend. Anybody to help. i want to send a input's value from the textarea input field to my backend
Here is my React Frontend Code
import React, { Component } from 'react';
import axios from 'axios';
class QueryBuilder extends Component{
render() {
return (
<div>
<form>
<textarea cols="100" rows="20" name="text" />
<br /><br />
<button>Execute Query</button>
</form>
</div>
)
}
}
export default QueryBuilder;
Here is the views.py code
from django import db
from django.shortcuts import render, HttpResponse
from rest_framework import generics
from .models import Test
from .serializers import TestSerializer
from pymongo import MongoClient
from ast import literal_eval
from rest_framework import viewsets, permissions
# from .models import Test
# from .serializers import TestSerializer
#Test Viewset
class TestViewset(viewsets.ModelViewSet):
client = MongoClient()
db = client.test
# collect = db['state_entry'].find({})
queryset = db['queryTest_test'].find({})
permission_classes = [
permissions.AllowAny
]
serializer_class = TestSerializer
Serializer.py
from rest_framework import serializers
from queryTest.models import Test
# Test Serializers
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = Test
fields = '__all__'
Update your react component code to this, i see you have imported axios but havent't used it to make api call, You should definitely checkout axios official documentation, very useful package
import React, { Component } from "react";
import axios from "axios";
class App extends Component {
constructor() {
this.state({
textAreaValue: "",
});
}
api_call = (data) =>
axios
.post(`http://127.0.0.1:8000/your-api-path`, {
value_to_send: data,
})
.then(function (response) {
console.log(response);
this.setState({textAreaValue:''});
})
.catch(function (error) {
console.log(error);
});
render() {
return (
<div>
<textarea
onChange={(e) => this.setState({textAreaValue: e.target.value})}
value={this.state.textAreaValue}
/>
<button onClick={() => this.api_call(this.state.textAreaValue)}>Click it</button>
</div>
);
}
}
export default App;
Update your viewset to this i.e. use self.request.data received in api request
from django import db
from django.shortcuts import render, HttpResponse
from rest_framework import generics
from .models import Test
from .serializers import TestSerializer
from pymongo import MongoClient
from ast import literal_eval
from rest_framework import viewsets, permissions
# from .models import Test
# from .serializers import TestSerializer
#Test Viewset
class TestViewset(viewsets.ModelViewSet):
request_data = request.data
print(request_data)
client = MongoClient()
db = client.test
# collect = db['state_entry'].find({})
queryset = db['queryTest_test'].find({})
permission_classes = [
permissions.AllowAny
]
serializer_class = TestSerializer
Have a look at django request/response docs here
Checkout this answer here for a similar requirement in backend.