To integrate itemshop into your app, you need to add the ItemBP blueprint to your application, and create some templates with a bit of javascript to handle the form:
The sections below will go into more detail about each of these steps. You can also re-use the demo code found in the source repo.
You can copy from the demos that most closely match what you are trying to do. First, clone the source repo:
hg clone https://bitbucket.org/lost_theory/flask-stripe-blueprint/
Then, to integrate one of the demos into your app:
itemshop was designed to be integrated into an existing app, so let’s grab the sample app from flask’s home page.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Welcome to my item shop."
if __name__ == "__main__":
app.run(use_debugger=True, use_reloader=True)
Now, at the top of app.py, we need to import the stripe library, the itemshop library, and set the stripe API key:
import itemshop
import stripe
stripe.api_key = 'UwK0UE4tdPGNJckqfiu5UbzUJxHClRjW'
Now let’s instantiate the ItemBP object by passing in three arguments:
item = itemshop.ItemBP('my_item', stripe.Charge, dict(
amount=1500,
currency='usd',
))
- stripe.Charge is used for one-time payments, all it needs is an amount to charge
- stripe.Customer is used for recurring payments, it needs a plan argument, which is created through the stripe web interface (e.g. plan='silver' might correspond to a monthly charge of $10.00)
After that, all you need to do is mount the blueprint on your app using register_blueprint:
app.register_blueprint(item.blueprint)
By default, this will mount the blueprint onto the root of your app (“/”). Let’s mount the blueprint somewhere else, so we don’t override the existing view at “/”. To do this, use url_prefix:
app.register_blueprint(item.blueprint, url_prefix="/shop")
Now, run your application:
$ python app.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader...
Go to “/shop” in your browser and you should see an error page, because the template is missing. That means it’s time for the next step!
Now we need to create the template that contains the credit card form.
In the <head>, include the following Javascript:
<script type="text/javascript" src="https://js.stripe.com/v1/"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="/static/demo.js"></script>
<script type="text/javascript">
Stripe.setPublishableKey('pk_uo5x4qcbsPsrDy6dBosrq1Ykub53C');
</script>
We are using the stripe.js API library, jQuery, a demo.js file we’ll define in a bit, and setting our Stripe account’s public key. The key in that example (pk_uo5...) is my test key, please try to use your own if you have one.
Next, we’ll include some item details in the body of the page:
<h1>{{item.name}}</h1>
<p>
Please fill out the form below to complete your purchase for {{item.name}}.
{% if item.price %}
The price is ${{item.price}}.
{% else %}
This is a subscription.
{% endif %}
</p>
Next, we’ll use a hidden div to contain the validation message when the stripe API rejects the payment:
<div id="fail" style="display: none; color: red;">
Sorry, we could not process your credit card: <span id="fail_reason"></span>.
<br/><br/>
Please correct the form and try again.
</div>
Now we create the purchase form:
<form id="stripe-form" action="{{url_for('itemshop.%s.process' % item.name)}}" method="POST">
<input type="hidden" name="stripe_token" value="" />
<div>
<label>Email</label>
<input type="text" size="20" maxlength="99" name="email" />
</div>
<div>
<label>Card number</label>
<input type="text" size="20" maxlength="20" autocomplete="off" id="card-number"/>
</div>
<div>
<label>CVC</label>
<input type="text" size="4" maxlength="4" autocomplete="off" id="card-cvc"/>
</div>
<div>
<label>Expiration (MM/YYYY)</label>
<input type="text" size="2" maxlength="2" id="card-expiry-month"/>
/
<input type="text" size="4" maxlength="4" id="card-expiry-year"/>
</div>
<div>
<button type="submit" class="submit-button">Submit Payment</button>
</div>
</form>
Two important things to note:
The last step for the HTML templates is to create the “thanks” template, default_process.html, which is what gets shown to users after they successfully make a purchase. It could be as simple as this:
<html>
<head>
<title>Thank you</title>
</head>
<body>
<h1>Thank you!</h1>
<div>
<p>Thank you for purchasing {{item.name}}!</p>
<p>
<a href="{{url_for('itemshop.%s.index' % item.name)}}">Back</a> to order form.</a><br />
</p>
</div>
</body>
</html>
Now we need to write the javascript to process the credit card form.
Create a new static JS file at static/demo.js (you could also just put this in a <script> tag in default_index.html).
First, we attach an on-submit handler to the “#stripe-form” form tag:
$(document).ready(function() {
$("#stripe-form").submit(function(event) {
// disable the submit button to prevent repeated clicks
$('.submit-button').attr("disabled", "disabled");
$("#fail").hide('fast');
var amount = 0;
Stripe.createToken({
number: $('#card-number').val(),
cvc: $('#card-cvc').val(),
exp_month: $('#card-expiry-month').val(),
exp_year: $('#card-expiry-year').val()
}, amount, stripeResponseHandler);
// prevent the form from submitting with the default action
return false;
});
});
When the user clicks the submit button (or presses Enter on their keyboard), we first disable the submit button (to prevent repeated form submissions going through), and re-hide the failure message div (in case it was already showing). We then make the stripe.js API call, Stripe.createToken. Note that the values are pulled out of the form fields using CSS element IDs (#card-number, #card-cvc, etc.), not with name attributes. We set the amount to 0 when we create the token, because we will pass the real value from the server-side code. The stripeResponseHandler function is a callback, which we will define next. Finally, we return false to prevent the default form action, which would have POSTed the form to the flask app.
function stripeResponseHandler(status, response) {
if(status == 200) {
$("input[name=stripe_token]").val(response.id);
$("#stripe-form button").removeAttr('disabled');
$('#stripe-form').off("submit");
$("#stripe-form").submit();
} else {
$("#fail").show('fast');
$("#fail_reason").html(response.error.message);
$("#stripe-form button").removeAttr('disabled');
}
}
The stripeResponseHandler callback does a check on the status of the stripe API call:
Now you’re ready to start making some (test) money!
Go back to http://127.0.0.1:5000/shop and use the following test values on the form:
You should get the “Thank you” page. Go to your stripe dashboard, switch to test mode, and you should see the charge recorded.
Also try with some bad values (blank fields, invalid credit card, past expiration date), to see what errors are shown on the form.
Congrats! You’ve earned your first (test) dollar!
Where to go from here? Clone the repository and check out the demos for more advanced usage (multiple items, receipt codes, retrieving payments from the stripe API, etc.).