remove pricing2

This commit is contained in:
Son NK 2019-11-14 14:54:17 +01:00
parent 263f68ecec
commit 6f7c99963b
4 changed files with 23 additions and 249 deletions

View File

@ -1,167 +0,0 @@
{% extends 'default.html' %}
{% set active_page = "dashboard" %}
{% block title %}
Pricing
{% endblock %}
{% block head %}
<style type="text/css">
/**
* The CSS shown here will not be introduced in the Quickstart guide, but shows
* how you can use CSS to style your Element's container.
*/
.StripeElement {
box-sizing: border-box;
height: 40px;
padding: 10px 12px;
border: 1px solid transparent;
border-radius: 4px;
background-color: white;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
</style>
{% endblock %}
{% block default_content %}
<script src="https://js.stripe.com/v3/"></script>
<div class="row">
<div class="col-sm-6 col-lg-6">
<div class="card">
<div class="card-body text-center">
<div class="card-category">Premium</div>
<div class="display-4 my-6">$20/year</div>
<ul class="list-unstyled leading-loose">
<li><i class="fe fe-check text-success mr-2" aria-hidden="true"></i> Infinite Emails</li>
<li><i class="fe fe-check text-success mr-2" aria-hidden="true"></i> Custom Alias</li>
<li><i class="fe fe-check text-success mr-2" aria-hidden="true"></i> Privacy protected</li>
<li><i class="fe fe-check text-success mr-2" aria-hidden="true"></i> Infinite Login</li>
<li><i class="fe fe-check text-success mr-2" aria-hidden="true"></i>
Support us and our application partners
</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-6 col-lg-6">
<div class="display-6">
The payment is processed by <a href="https://stripe.com" target="_blank">Stripe</a>. <br>
Your card number is never stored on our server.
</div>
<hr>
<form method="post" id="payment-form">
<div class="form-group">
<label for="card-element" class="form-label">
Credit or debit card
</label>
<div id="card-element">
<!-- A Stripe Element will be inserted here. -->
</div>
<!-- Used to display form errors. -->
<div id="card-errors" role="alert" class="text-danger"></div>
</div>
<button type="submit" class="btn btn-success">Upgrade</button>
</form>
</div>
</div>
<script>
// Create a Stripe client.
var stripe = Stripe('{{ stripe_api }}');
// Create an instance of Elements.
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
// the postal code is asked on Safari but not on other browsers ...
// Disable it explicitly
var card = elements.create('card', {hidePostalCode: true, style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function (event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function (event) {
event.preventDefault();
stripe.createToken(card).then(function (result) {
if (result.error) {
// Inform the user if 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);
}
});
});
// Submit the form with the token ID.
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();
}
</script>
{% endblock %}

View File

@ -1,81 +0,0 @@
import stripe
from flask import render_template, request, flash, redirect, url_for
from flask_login import login_required, current_user
from stripe.error import CardError
from app.config import STRIPE_API, STRIPE_YEARLY_PLAN
from app.dashboard.base import dashboard_bp
from app.email_utils import notify_admin
from app.extensions import db
from app.log import LOG
from app.models import PlanEnum
@dashboard_bp.route("/pricing", methods=["GET", "POST"])
@login_required
def pricing():
# sanity check: make sure this page is only for free user that has never subscribed before
# case user unsubscribe and re-subscribe will be handled later
if current_user.is_premium():
flash("You are already a premium user", "warning")
return redirect(url_for("dashboard.index"))
if (
current_user.stripe_customer_id
or current_user.stripe_card_token
or current_user.stripe_subscription_id
):
raise Exception("only user not exist on stripe can view this page")
if stripe.Customer.list(email=current_user.email):
raise Exception("user email is already used on stripe!")
if request.method == "POST":
plan = PlanEnum.yearly
stripe_token = request.form.get("stripeToken")
LOG.d("stripe card token %s for plan %s", stripe_token, plan)
current_user.stripe_card_token = stripe_token
try:
customer = stripe.Customer.create(
source=stripe_token,
email=current_user.email,
metadata={"id": current_user.id},
name=current_user.name,
)
except CardError as e:
LOG.exception("payment problem, code:%s", e.code)
flash(
"Payment refused with error {e.message}. Could you re-try with another card please?",
"danger",
)
else:
LOG.d("stripe customer %s", customer)
current_user.stripe_customer_id = customer.id
stripe_plan = STRIPE_YEARLY_PLAN
subscription = stripe.Subscription.create(
customer=current_user.stripe_customer_id,
items=[{"plan": stripe_plan}],
expand=["latest_invoice.payment_intent"],
)
LOG.d("stripe subscription %s", subscription)
current_user.stripe_subscription_id = subscription.id
db.session.commit()
if subscription.latest_invoice.payment_intent.status == "succeeded":
LOG.d("payment successful for user %s", current_user)
current_user.plan = plan
current_user.plan_expiration = None
db.session.commit()
flash("Thanks for your subscription!", "success")
notify_admin(
f"user {current_user.email} has finished subscription {plan}"
)
return redirect(url_for("dashboard.index"))
return render_template("dashboard/pricing.html", stripe_api=STRIPE_API)

View File

@ -522,3 +522,22 @@ class ForwardEmail(db.Model, ModelMixin):
reply_email = db.Column(db.String(128), nullable=False)
gen_email = db.relationship(GenEmail)
class Subscription(db.Model, ModelMixin):
# Come from Paddle
cancel_url = db.Column(db.String(1024), nullable=False)
update_url = db.Column(db.String(1024), nullable=False)
subscription_id = db.Column(db.String(1024), nullable=False, unique=True)
event_time = db.Column(ArrowType, nullable=False)
next_bill_date = db.Column(db.Date, nullable=False)
cancelled = db.Column(db.Boolean, nullable=False, default=False)
plan = db.Column(db.Enum(PlanEnum), nullable=False)
user_id = db.Column(
db.ForeignKey(User.id, ondelete="cascade"), nullable=False, unique=True
)
user = db.relationship(User)

View File

@ -1,6 +1,8 @@
import arrow
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
from app.extensions import db
from app.models import generate_email, User, GenEmail, PlanEnum
from app.models import generate_email, User, GenEmail
def test_generate_email(flask_client):
@ -38,6 +40,7 @@ def test_suggested_emails_for_user_who_cannot_create_new_email(flask_client):
user = User.create(
email="a@b.c", password="password", name="Test User", activated=True
)
user.trial_expiration = arrow.now().shift(days=-1)
db.session.commit()
# make sure user runs out of quota to create new email