Example #1
0
def cancel_subscription(uid: str, sub_id: str) -> FlaskResponse:
    """
    Cancel an existing subscription for a user.
    :param uid:
    :param sub_id:
    :return: Success or failure message for the cancellation.
    """
    customer = fetch_customer(g.subhub_account, uid)
    if not customer:
        return dict(message="Customer does not exist."), 404

    for item in customer["subscriptions"]["data"]:
        if item["id"] == sub_id and item["status"] in [
            "active",
            "trialing",
            "incomplete",
        ]:
            Subscription.modify(sub_id, cancel_at_period_end=True)
            updated_customer = fetch_customer(g.subhub_account, uid)
            logger.info("updated customer", updated_customer=updated_customer)
            subs = retrieve_stripe_subscriptions(updated_customer)
            logger.info("subs", subs=subs, type=type(subs))
            for sub in subs:
                if sub["cancel_at_period_end"] and sub["id"] == sub_id:
                    return {"message": "Subscription cancellation successful"}, 201

    return dict(message="Subscription not available."), 400
Example #2
0
def subscribe_to_plan(uid, data) -> FlaskResponse:
    """
    Subscribe to a plan given a user id, payment token, email, orig_system
    :param uid:
    :param data:
    :return: current subscriptions for user.
    """
    customer = existing_or_new_customer(
        g.subhub_account,
        user_id=uid,
        email=data["email"],
        source_token=data["pmt_token"],
        origin_system=data["orig_system"],
        display_name=data["display_name"],
    )
    existing_plan = has_existing_plan(customer, plan_id=data["plan_id"])
    if existing_plan:
        return {"message": "User already subscribed."}, 409
    if not customer.get("deleted"):
        Subscription.create(customer=customer.id,
                            items=[{
                                "plan": data["plan_id"]
                            }])
        updated_customer = fetch_customer(g.subhub_account, user_id=uid)
        newest_subscription = find_newest_subscription(
            updated_customer["subscriptions"])
        return create_return_data(newest_subscription), 201
    else:
        return dict(message=None), 400
Example #3
0
    def test_update(self):
        """Test update from stripe."""
        stripe_subscription = StripeSubscription.construct_from(
            {
                'id': 'sub_foo',
                'status': 'active',
                'current_period_start': 120778389,
                'current_period_end': 123456789,
                'trial_end': 1475437877,
                'plan': {
                    'id': 'advanced',
                }
            },
            None,
        )
        subscription = fixture.get(
            Subscription,
            stripe_id='sub_foo',
            status='trialing',
        )
        Subscription.objects.update_from_stripe(
            rtd_subscription=subscription,
            stripe_subscription=stripe_subscription,
        )
        subscription.refresh_from_db()
        self.assertEqual(subscription.status, 'active')
        self.assertEqual(
            subscription.end_date,
            timezone.make_aware(datetime.fromtimestamp(123456789)),
        )
        self.assertEqual(
            subscription.trial_end_date,
            timezone.make_aware(datetime.fromtimestamp(1475437877)),
        )

        # Cancel event
        stripe_subscription = StripeSubscription.construct_from(
            {
                'id': 'sub_foo',
                'status': 'unpaid',
                'plan': {
                    'id': 'advanced',
                }
            },
            None,
        )
        Subscription.objects.update_from_stripe(
            rtd_subscription=subscription,
            stripe_subscription=stripe_subscription,
        )
        subscription.refresh_from_db()
        self.assertEqual(subscription.status, 'unpaid')
        self.assertEqual(
            subscription.trial_end_date,
            timezone.make_aware(datetime.fromtimestamp(1475437877)),
        )
Example #4
0
def reactivate_stripe_subscription(subscription_id: str,
                                   idempotency_key: str) -> Subscription:
    """
    Set Stripe subscription to cancel at period end
    :param subscription_id:
    :param idempotency_key:
    :return: Subscription
    """
    try:
        sub = Subscription.modify(
            sid=subscription_id,
            cancel_at_period_end=False,
            idempotency_key=idempotency_key,
        )
        return sub
    except (
            InvalidRequestError,
            APIConnectionError,
            APIError,
            RateLimitError,
            IdempotencyError,
            StripeErrorWithParamCode,
    ) as e:
        logger.error("reactivate sub error", error=str(e))
        raise e
Example #5
0
def build_stripe_subscription(customer_id: str, plan_id: str,
                              idempotency_key: str) -> Subscription:
    """
    Create a new Stripe subscription for a given customer
    :param customer_id:
    :param plan_id:
    :param idempotency_key:
    :return: Subscription object
    """
    try:
        sub = Subscription.create(
            customer=customer_id,
            items=[{
                "plan": plan_id
            }],
            idempotency_key=idempotency_key,
        )
        return sub
    except (
            InvalidRequestError,
            APIConnectionError,
            APIError,
            RateLimitError,
            IdempotencyError,
            StripeErrorWithParamCode,
            AuthenticationError,
    ) as e:
        logger.error("sub error", error=e)
        raise e
Example #6
0
def subscribe_customer(customer: Customer, plan_id: str) -> Subscription:
    """
    Subscribe Customer to Plan
    :param customer:
    :param plan:
    :return: Subscription Object
    """
    try:
        sub = Subscription.create(customer=customer, items=[{"plan": plan_id}])
        return sub
    except Exception as e:
        logger.error("sub error", error=e)
        raise InvalidRequestError("Unable to create plan", param=plan_id)
Example #7
0
def reactivate_subscription(uid: str, sub_id: str) -> FlaskResponse:
    """
    Given a user's subscription that is flagged for cancellation, but is still active
    remove the cancellation flag to ensure the subscription remains active
    :param uid: User ID
    :param sub_id: Subscription ID
    :return: Success or failure message for the activation
    """

    customer = fetch_customer(g.subhub_account, uid)
    if not customer:
        return dict(message="Customer does not exist."), 404

    active_subscriptions = customer["subscriptions"]["data"]
    for subscription in active_subscriptions:
        if subscription["id"] == sub_id:
            if subscription["cancel_at_period_end"]:
                Subscription.modify(sub_id, cancel_at_period_end=False)
                return dict(message="Subscription reactivation was successful."), 200
            return dict(message="Subscription is already active."), 200

    return dict(message="Current subscription not found."), 404
Example #8
0
def cancel_subscription(uid, sub_id) -> FlaskResponse:
    """
    Cancel an existing subscription for a user.
    :param uid:
    :param sub_id:
    :return: Success or failure message for the cancellation.
    """

    customer = fetch_customer(g.subhub_account, uid)
    if not customer:
        return {"message": "Customer does not exist."}, 404

    for item in customer["subscriptions"]["data"]:
        if item["id"] == sub_id and item["status"] in [
                "active",
                "trialing",
                "incomplete",
        ]:
            Subscription.modify(sub_id, cancel_at_period_end=True)
            updated_customer = fetch_customer(g.subhub_account, uid)
            check_stripe_subscriptions(updated_customer)
            return {"message": "Subscription cancellation successful"}, 201
    return {"message": "Subscription not available."}, 400
Example #9
0
def subscription_status(uid) -> FlaskResponse:
    """
    Given a user id return the current subscription status
    :param uid:
    :return: Current subscriptions
    """
    items = g.subhub_account.get_user(uid)
    if not items or not items.cust_id:
        return {"message": "Customer does not exist."}, 404
    subscriptions = Subscription.list(customer=items.cust_id,
                                      limit=100,
                                      status="all")
    if not subscriptions:
        return {"message": "No subscriptions for this customer."}, 403
    return_data = create_return_data(subscriptions)
    return return_data, 201
Example #10
0
def list_customer_subscriptions(cust_id: str) -> List[Subscription]:
    """
    List customer subscriptions
    :param cust_id:
    :return: List of Subscriptions
    """
    try:
        subscriptions = Subscription.list(customer=cust_id,
                                          limit=100,
                                          status="all")
        return subscriptions
    except (
            InvalidRequestError,
            APIConnectionError,
            APIError,
            RateLimitError,
            IdempotencyError,
            StripeErrorWithParamCode,
    ) as e:
        logger.error("list subscriptions error", error=e)
        raise e
Example #11
0
def cancel_stripe_subscription_immediately(
        subscription_id: str, idempotency_key: str) -> Subscription:
    """
    Set Stripe subscription to cancel at period end
    :param subscription_id:
    :param idempotency_key:
    :return: Subscription
    """
    try:
        sub = Subscription.delete(sid=subscription_id,
                                  idempotency_key=idempotency_key)
        return sub
    except (
            InvalidRequestError,
            APIConnectionError,
            APIError,
            RateLimitError,
            IdempotencyError,
            StripeErrorWithParamCode,
    ) as e:
        logger.error("cancel sub error", error=str(e))
        raise e
Example #12
0
def update_stripe_subscription(subscription: Dict[str, Any], plan_id: str,
                               idempotency_key: str) -> Subscription:
    """
    Update a stripe subscription to a new plan
    :param customer_id:
    :param plan_id:
    :param idempotency_key:
    :return: Subscription object
    """
    try:
        subscription = Subscription.modify(
            subscription["id"],
            cancel_at_period_end=False,
            items=[{
                "id": subscription["items"]["data"][0]["id"],
                "plan": plan_id
            }],
            metadata={
                "previous_plan_id": subscription["plan"]["id"],
                "plan_change_date": int(time.time()),
            },
            idempotency_key=idempotency_key,
        )

        logger.debug("update stripe subscription", sub=subscription)
        return subscription
    except (
            InvalidRequestError,
            APIConnectionError,
            APIError,
            RateLimitError,
            IdempotencyError,
            StripeErrorWithParamCode,
            AuthenticationError,
    ) as e:
        logger.error("sub error", error=e)
        raise e
Example #13
0
 def test_replace_subscription(self):
     """Test update from stripe."""
     stripe_subscription = StripeSubscription.construct_from(
         {
             'id': 'sub_bar',
             'status': 'active',
             'plan': {
                 'id': 'advanced',
             }
         },
         None,
     )
     subscription = fixture.get(
         Subscription,
         stripe_id='sub_foo',
         status='trialing',
     )
     Subscription.objects.update_from_stripe(
         rtd_subscription=subscription,
         stripe_subscription=stripe_subscription,
     )
     subscription.refresh_from_db()
     self.assertEqual(subscription.stripe_id, 'sub_bar')
     self.assertEqual(subscription.status, 'active')