Stripe create customer for one time charge - python

I am working with stripe to build a donation form in python Django. Some donations are one-time and others are recurring. What I want to do is create a customer object with both types of charges, so we can gather mailing address, email address, etc for each donation.
The problem I am having, is I can process a one-time payment using the stripe token. But I can't figure out how to do it with a customer. This is what I have tried to so far. The error I receive is No such token: cus_asdfasdfasdf. Any idea what I'm doing wrong?
Javascript on donate.html page:
var stripe = Stripe('public_key');
var elements = stripe.elements();
var card = elements.create('card');
card.mount('#card-element');
// Create a token or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createPaymentMethod({
type: 'card',
card: card,
billing_details: {
email: 'my_email#gmail.com',
},
}).then(function(result) {
stripePaymentMethodHandler(result.PaymentMethod)
});
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
function stripePaymentMethodHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var paymentMethodInput = document.createElement('input');
paymentMethodInput.setAttribute('type', 'hidden');
paymentMethodInput.setAttribute('name', 'paymentMethodToken');
paymentMethodInput.setAttribute('value', token);
form.appendChild(paymentMethodInput);
}
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
View in django:
from django.shortcuts import render
import stripe
from transcal.settings import STRIPE_SECRET_KEY
from .forms import DonateForm
stripe.api_key = STRIPE_SECRET_KEY
def donate(request):
if request.method == 'POST':
stripe.api_key = STRIPE_SECRET_KEY
# Get the payment token ID submitted by the form:
token = request.POST.get('stripeToken')
amount = request.POST.get('amount')
payment_method = request.POST.get('paymentMethodToken')
single_or_recurring = request.POST.get('single_or_recurring')
customer = stripe.Customer.create(
description="Customer for jenny.rosen#example.com",
name='Joe',
email='joe#gmail.com',
payment_method=payment_method
)
if single_or_recurring == 'recurring':
# charge subscription
stripe.Subscription.create(
customer=customer,
items=[
{
"plan": "my_plan_id",
},
],
expand=["latest_invoice.payment_intent"]
)
else:
# charge one time
stripe.Charge.create(
amount=amount,
currency='usd',
description='Example charge',
source=customer
)
return render(request, 'donate.html')

It looks like you are using Payment Methods here, and with these you will need to explicitly specify the Payment Method in addition to the Customer when creating a one-off transaction or a subscription.
You can get Payment Methods attached to a Customer with stripe.PaymentMethod.list
Specifically, for one-off charges made with Payment Methods, you must use the Payment Intent API to create a Charge instead of the Charge API. You can associate a Payment Intent with a Customer.
For your subscription call: when creating a Subscription with stripe.Subscription.create you will want to specify the customer AND default_payment_method (pm_xxxyyyzz) attached to the customer that you wish the subscription to charge.

Related

Django + React axios POST cant access Json properties

I created two abjects that need to be treated separated in the backend, and sent it to backend with:
const order = {
order_id: 1,
customer: {
name: "Jonas Illver"
age: 18
}
}
const car = {
model: 'XHL'
brand: 'Toyota'
}
const postData = {
order: order,
car: car
}
const res = await axios.post("orders/shipping/create", JSON.stringify(postData));
console.log(res);
And here I return the response: views.py
#api_view(['POST'])
#permission_classes([IsAuthenticated])
def shipping_create_order(request):
if request.method == 'POST':
return JsonResponse(request.POST)
Here's what the console.log prints:
res.data // {"order:"{"order_id": 1, "customer": {"name": "Jonas Illver", "age": 18}}, "car": **car object content**}
The problem is that if I try to access those data in my django view, I always got a 500 error
I tried accessing it via:
order = request.POST['order']
# and also
data = json.loads(request.POST)
order = data['order']
# also
order = request.POST.get('order')
None os the above approaches worked, the only one that doesn't occurs an 500 error is the last one, using the POST.get, but as soon as I add the if not order: return HttpResponse("No order") line, it always return "No order"
How can I access specific info from the request.POST? Am I doing something wrong with the axios request?
Try using request.data to get the data passed in the body. Have a look at the rest-framework docs.
Or another way to get the data is using json.loads(request.body). But using request.data is a bit shorter as it does the json.loads job for you.

How to use Axios/Vue.js to call data from SQLite/Django backend?

Status Quo:
Whenever a user visits my web application, Axios makes a request to a third party API to fetch data and populate the frontend with that data using v-for.
Conclusion: I have one API call per website visitor.
Desired status:
Whenever a user visits my web application, Axios shall fetch the data from the SQLite database which itself is populated every XX seconds by a python request to reduce API calls.
Questions:
Now I implemented a SQLite database using Django models and views. So far so good, the API gets fetched regularly and updates the database table properly.
1.) How can I now call the data in the database using Axios? As by my research Axios somehow needs to call a view and the view will call the data from the database, is this correct?
2.) If Axios needs to call a view, do I need another view.py file that calls the database? If I would insert the needed view function into the existing view.py file it would initiate another API call, wouldn't it?
3.) And how can I implement the link to the view function to Axios? Instead of a third party API url would I just use the path to the view file?
Quotes_app/Views.py:
from django.shortcuts import render
from Quotes_app.models import ratesEUR
import json
import requests
response = requests.get("http://data.fixer.io/api/latest?access_key=XXXX&base=EUR")
rates_EUR = json.loads(response.content.decode('utf-8'))
timestamp = rates_EUR['timestamp']
base = rates_EUR['base']
date = rates_EUR['date']
rates = rates_EUR['rates']
id = 1
rates_new = ratesEUR(id=id, timestamp=timestamp, base=base, date=date, rates=rates)
rates_new.save()
def render_Quotes_app(request, template="Quotes_app/templates/Quotes_app/Quotes_app.html"):
return render(request, template)
Quotes_app/models.py:
from django.db import models
class ratesEUR(models.Model):
timestamp = models.CharField(max_length=10)
base = models.CharField(max_length=3)
date = models.DateField(auto_now=False, auto_now_add=False)
rates = models.CharField(max_length=8)
def __str__(self):
return self.base
Vue.js/axios: (as of now directly fetching the API)
Vue.config.devtools = true;
var app = new Vue({
delimiters: ['[[', ']]'],
el: '.eurQuotesWrapper',
data() {
return {
rates: [],
};
},
computed: {
rates1() {
const ratesArr1 = Object.entries(this.rates);
const ret = ratesArr1.reduce((a, c, i, d) => {
if (i < d.length / 2) a[c[0]] = c[1];
return a;
}, {});
console.log('rates1', ret);
return ret;
},
rates2() {
const ratesArr2 = Object.entries(this.rates);
const ret = ratesArr2.reduce((a, c, i, d) => {
if (i >= d.length / 2) a[c[0]] = c[1];
return a;
}, {});
console.log('rates2', ret);
return ret;
}
},
created() {
axios
.get("http://data.fixer.io/api/latest?access_key=XXXX&base=EUR")
.then(response => {
this.rates = response.data.rates;
console.log(this.rates);
for(key in this.rates) {
this.rates[key] = new Intl.NumberFormat('de-DE', {
minimumFractionDigits: 5,
maximumFractionDigits: 5
}).format(this.rates[key]);
}
console.log(this.rates);
});
}
});
In advance thank you very much for your help!
You can use DRF(Django Rest Framework) to make REST API's or You can use JsonResponse
to send JSON objects as response.
from django.http import JsonResponse
data = # Your data
JsonResponse(data, encoder=MyJSONEncoder)
For more details visit django's documentation
Better would be if you use DRF for making rest apis. It's much easier.

request.POST.get() doesn't work when I pass context to the view

I'm using Stripe for my django site to accept one-off payments. The following code works fine and the charge is successfull:
def pay(request):
# Set your secret key: remember to change this to your live secret key in production
# See your keys here: https://dashboard.stripe.com/account/apikeys
stripe.api_key = "sk_test_exhH8mdKfkXkaxzvtVphJOBZ"
# Token is created using Checkout or Elements!
# Get the payment token ID submitted by the form:
if request.POST.get('stripeToken'):
print(request.POST)
token = request.POST.get('stripeToken')
charge = stripe.Charge.create(
amount=999,
currency='usd',
description='Boosted Post',
source=token,
)
print('Charge:', charge)
return HttpResponseRedirect('/')
else:
print('NO')
context = {
'amount': 999,
}
return render(request, 'advertising/pay.html', context)
however if I add context to this view, it doesn't work (if request.POST.get('stripeToken') doesn't fire):
def post_ad(request):
boost_form = AdvertisePostForm(request.POST or None, request.FILES or None)
if boost_form.is_valid():
instance = boost_form.save(commit=False)
instance.total_price = ad_price(instance.position, instance.duration)
instance.ad = True
instance.save()
context = {
'hash': instance.hash,
}
return pay(request, context)
else:
pass
context = {
'boost_form': boost_form
}
return render(request, 'advertising/post_ad.html', context)
def pay(request, context):
ad = get_object_or_404(AdvertisePost, hash=context['hash'])
amount = ad.total_price * 100
# Set your secret key: remember to change this to your live secret key in production
# See your keys here: https://dashboard.stripe.com/account/apikeys
stripe.api_key = "sk_test_exhH8mdKfkXkaxzvtVphJOBZ"
# Token is created using Checkout or Elements!
# Get the payment token ID submitted by the form:
if request.POST.get('stripeToken'):
print(request.POST)
token = request.POST.get('stripeToken')
charge = stripe.Charge.create(
amount=amount,
currency='usd',
description='Boosted Post',
source=token,
)
print('Charge:', charge)
return HttpResponseRedirect('/')
else:
print(request.POST)
print('NO')
context = {
'amount': amount,
'ad': ad
}
return render(request, 'advertising/pay.html', context)
Any idea why this is and how I can fix it?
Here is the stripe form if you are curious:
<form action="" method="POST">{% csrf_token %}
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_8rSK77eA02iovefCmQCeV9su"
data-amount="{{ amount }}"
data-name="My name"
data-description="Example charge"
data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
data-locale="auto"
data-currency="aud">
</script>
</form>

Stripe does not accept my token

I am trying to create a django shopping site. But I can't get stripe to work. I don't belive it is anything workng in my code. It works fine withe the "tok_visa" sendt with javascript. But it does not accept my token. I have even tried manuelly writing it in.
views.py
if form.is_valid():
token = form.cleaned_data['token']
try:
stripe.Charge.create(
amount = 20000,
currency = "nok",
description = ""+form.cleaned_data['etternavn']+", "+form.cleaned_data['fornavn'],
source = token,
)
form.save()
return HttpResponse("<p>"+form.cleaned_data['fornavn']+"</p>")
except stripe.CardError as e:
form.add_error("Kortet ble ikke akseptert "+token)
Jquery
Stripe.setPublishableKey('pk_test_H1PZQA7ypCa8UIlEy6S9ovhE');
$( '#payment-form' ).submit(function(e){
$form = $(this);
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, function(status, response){
if(response.error){
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
}
else{
var token = response.id;
$form.find('input[id="id_token"]').val(token);
$('#id_token').val(token);
$form.get(0).submit();
}
});
return false;
});
Thank you for the help

Python/Django form where user selects from a list of Images

I'm new to django and want to make a form that allows a user to select one of three images using radio boxes, once the user selects the image it is saved to their profile and displayed on their profile page.
I am using:
django 1.8.3
userena 1.4.1
Any help or links to documentation that will help would be great.
Basic example. Models:
def get_upload(instance, filename):
return "uploaded_files/user_%s_%s_%s" % (instance.user, datetime.datetime.today().strftime("%d-%m-%Y %H-%M-%S"), filename)
class UserModel():
# your fields
image = models.FileField(upload_to=get_upload, default='')
FileField
Forms:
class UploadForm(forms.ModelForm):
"""Auxiliary class to make file uploading more convenient."""
def __init__(self, *args, **kwargs):
super(UploadForm, self).__init__(*args, **kwargs)
class Meta:
model = UserModel
fields = ('image')
View:
def upload(request):
if request.method == "POST":
profile = request.user.profile
image_type = request.POST.get("image_type", None)
if image_type == "blah":
profile.image = request.FILES[image_type]
else:
return HttpResponse("Error")
request.user.profile.save()
return HttpResponse('OK')
request.FILES
JS with soem Jquery:
var SIZE_RESTRICT = 10*1024*1024; //10 Mbytes
$(document).ready(function()
{
$(".upload_file").find(".upload_button").click(send_file);
$(".upload_file").find(".upload_file_form").find("input[type='file']").click(enable_upload);
});
function send_file()
{
if ($(this).attr("enabled") != "true") return;
// Prevent double-triple clicks with multiple upload.
$(this).attr("enabled", "false");
var form = $(this).parent().find(".upload_file_form").get(0);
var formData = new FormData(form);
var file = $(form).find("input[type='file']").get(0).files[0];
// Not sure about this
// Prevent attack with HUGE files, that will smash server memory
// TODO: Restrict file types (Ex. MIME-image, pdf, doc)
if (file.size > SIZE_RESTRICT)
{
alert("File is too big.");
return;
}
formData.append("proof_type", $(this).attr("upload-type"));
var xhr = new XMLHttpRequest();
var that = this;
// TODO: Define another events like error, abort
xhr.upload.onprogress = function(e) {
// TODO: Progressbar as e.loaded / e.total
if (e.lengthComputable)
console.log((e.loaded / e.total) * 100);
else
console.log("Cant count length");
};
xhr.onload = function(e){
// TODO: Show success confirmation to user.
if (this.response == "Success")
{
// pass
alert(this.response);
}
else if (this.response == "Error")
{
// pass
alert(this.response);
}
else
{
// pass
}
};
xhr.open('POST', '/upload_proof');
xhr.send(formData);
}
function enable_upload()
{
$(this).parent().parent().find(".upload_button").attr("enabled", "true");
}
Actually another simple example could be founded in docs
If the set of images is small and fixed, the best option is to use the choice attribute in the field that defines the image within your model.
The image field could be the path to the image file on the file system.
class UserProfile(models.Model):
GOOD = 'Good.jpg'
UGLY = 'Ugly.jpg'
BAD = 'Bad.jpg'
AVATAR_CHOICES = (
(GOOD, 'Good'),
(UGLY, 'Ugly'),
(BAD, 'Bad'),
)
avatar_img = models.CharField(max_length=255,
choices=AVATAR_CHOICES,
default=GOOD)
Another option is to use FilePathField as your model field
FilePathField(path="/path/to/avatar_images", match="*.jpg", recursive=False)
Another way is to fill the form field dynamically when the form is instantiated.
Please see this SO QA for more on that.
However, as Django docs say
But if you find yourself hacking choices to be dynamic, you’re
probably better off using a proper database table with a ForeignKey
To specify Radiobuttons to be used for the form field, please refer to the official docs on how to set the proper widget.

Categories

Resources