def create(): if current_user.subscription: flash('You already have an active subscription.', 'info') return redirect(url_for('user.settings')) plan = request.args.get('plan') subscription_plan = Subscription.get_plan_by_id(plan) # Guard against an invalid or missing plan. if subscription_plan is None and request.method == 'GET': flash('Sorry, that plan did not exist.', 'error') return redirect(url_for('billing.pricing')) stripe_key = current_app.config.get('STRIPE_PUBLISHABLE_KEY') form = CreditCardForm(stripe_key=stripe_key, plan=plan) if form.validate_on_submit(): subscription = Subscription() created = subscription.create(user=current_user, name=request.form.get('name'), plan=request.form.get('plan'), coupon=request.form.get('coupon_code'), token=request.form.get('stripe_token')) if created: flash('Awesome, thanks for subscribing!', 'success') else: flash('You must enable JavaScript for this request.', 'warning') return redirect(url_for('user.settings')) return render_template('billing/payment_method.html', form=form, plan=subscription_plan)
def bulk_delete(cls, ids): """ Override the general bulk_delete method because we need to delete them one at a time while also deleting them on Stripe. :param ids: List of ids to be deleted :type ids: list :return: int """ delete_count = 0 for id in ids: user = User.query.get(id) if user is None: continue if user.payment_id is None: user.delete() else: subscription = Subscription() cancelled = subscription.cancel(user=user) # If successful, delete it locally. if cancelled: user.delete() delete_count += 1 return delete_count
def update_payment_method(): if not current_user.credit_card: flash('You do not have a payment method on file.', 'error') return redirect(url_for('user.settings')) active_plan = Subscription.get_plan_by_id(current_user.subscription.plan) card = current_user.credit_card stripe_key = current_app.config.get('STRIPE_PUBLISHABLE_KEY') form = CreditCardForm(stripe_key=stripe_key, plan=active_plan, name=current_user.name) if form.validate_on_submit(): subscription = Subscription() updated = subscription.update_payment_method( user=current_user, credit_card=card, name=request.form.get('name'), token=request.form.get('stripe_token')) if updated: flash('Your payment method has been updated.', 'success') else: flash('You must enable JavaScript for this request.', 'warning') return redirect(url_for('user.settings')) return render_template('billing/payment_method.html', form=form, plan=active_plan, card_last4=str(card.last4))
def test_no_coin_change_for_subscription_downgrade(self): """ Same coins for a subscription downgrade. """ coins = 100 current_plan = Subscription.get_plan_by_id('gold') new_plan = Subscription.get_plan_by_id('bronze') coins = add_subscription_coins(coins, current_plan, new_plan, None) assert coins == 100
def test_add_coins_to_subscription_upgrade(self): """ Add coins to a subscription upgrade. """ coins = 100 current_plan = Subscription.get_plan_by_id('bronze') new_plan = Subscription.get_plan_by_id('gold') coins = add_subscription_coins(coins, current_plan, new_plan, None) assert coins == 590
def test_no_coin_change_for_same_subscription(self): """ Same coins for the same subscription. """ coins = 100 current_plan = Subscription.get_plan_by_id('gold') new_plan = Subscription.get_plan_by_id('gold') may_29_2015 = datetime.datetime(2015, 5, 29, 0, 0, 0) may_29_2015 = pytz.utc.localize(may_29_2015) coins = add_subscription_coins(coins, current_plan, new_plan, may_29_2015) assert coins == 100
def users_cancel_subscription(): form = UserCancelSubscriptionForm() if form.validate_on_submit(): user = User.query.get(request.form.get('id')) if user: subscription = Subscription() if subscription.cancel(user): flash(f'Subscripton has been cancelled for {user.name}', 'success') else: flash('No subscription was cancelle, something went wrong.', 'error') return redirect(url_for('admin.users'))
def event(): if not request.json: return render_json(406, {'error': 'Mime-type is not application/json'}) if request.json.get('id') is None: return render_json(406, {'error': 'Invalid Stripe event'}) try: safe_event = PaymentEvent.retrieve(request.json.get('id')) parsed_event = Invoice.parse_from_event(safe_event) user = Invoice.prepare_and_save(parsed_event) if parsed_event.get('total') > 0: plan = Subscription.get_plan_by_id(user.subscription.plan) user.add_coins(plan) except InvalidRequestError as e: # We could not parse the event. return render_json(422, {'error': str(e)}) except Exception as e: # Return a 200 because something is really wrong and we want Stripe to # stop trying to fulfill this webhook request. return render_json(200, {'error': str(e)}) return render_json(200, {'success': True})
def cancel(): if not current_user.subscription: flash("You don't have an active subscription.", 'error') return redirect(url_for('user.settings')) form = CancelSubscriptionForm() if form.validate_on_submit(): subscription = Subscription() cancelled = subscription.cancel(user=current_user) if cancelled: flash("Your subscription has been cancelled.", 'success') return redirect(url_for('user.settings')) return render_template('billing/cancel.html', form=form)
def update(): current_plan = current_user.subscription.plan active_plan = Subscription.get_plan_by_id(current_plan) new_plan = Subscription.get_new_plan(request.form.keys()) plan = Subscription.get_plan_by_id(new_plan) # Guard against an invalid, missing or identical plan. is_same_plan = new_plan == active_plan['id'] if ((new_plan is not None and plan is None) or is_same_plan) and \ request.method == 'POST': return redirect(url_for('billing.update')) form = UpdateSubscriptionForm(coupon_code=current_user.subscription.coupon) if form.validate_on_submit(): subscription = Subscription() updated = subscription.update(user=current_user, coupon=request.form.get('coupon_code'), plan=plan.get('id')) if updated: flash('Your subscription has been updated.', 'success') return redirect(url_for('user.settings')) return render_template('billing/pricing.html', form=form, plans=settings.STRIPE_PLANS, active_plan=active_plan)
def subscriptions(db): """ Create subscription fixtures. :param db: Pytest fixture :return: SQLAlchemy database session """ subscriber = User.find_by_identity('*****@*****.**') if subscriber: subscriber.delete() db.session.query(Subscription).delete() params = { 'role': 'admin', 'email': '*****@*****.**', 'name': 'Subby', 'password': '******', 'payment_id': 'cus_000' } subscriber = User(**params) # The account needs to be commit before we can assign a subscription to it. db.session.add(subscriber) db.session.commit() # Create a subscription. params = { 'user_id': subscriber.id, 'plan': 'gold' } subscription = Subscription(**params) db.session.add(subscription) # Create a credit card. params = { 'user_id': subscriber.id, 'brand': 'Visa', 'last4': '4242', 'exp_date': datetime.date(2015, 6, 1) } credit_card = CreditCard(**params) db.session.add(credit_card) db.session.commit() return db
def event(): if not request.json: return render_json(406, {'error': 'Mime-type is not application/json'}) if request.json.get('id') is None: return render_json(406, {'error': 'Invalid Stripe event'}) try: safe_event = PaymentEvent.retrieve(request.json.get('id')) parsed_event = Invoice.parse_from_event(safe_event) user = Invoice.prepare_and_save(parsed_event) if parsed_event.get('total') > 0: plan = Subscription.get_plan_by_id(user.subscription.plan) user.add_coins(plan) except InvalidRequestError as e: return render_json(422, {'error': str(e)}) except Exception as e: return render_json(200, {'error': str(e)}) return render_json(200, {'success': True})
def test_subscribed_user_receives_more_coins(self, users): """ Subscribed user receives more coins. """ user = User.find_by_identity('*****@*****.**') user.add_coins(Subscription.get_plan_by_id('bronze')) assert user.coins == 210