Beispiel #1
0
def _get_all_plans() -> List[Dict[str, str]]:
    plans = vendor.retrieve_plan_list(100)
    logger.info("number of plans", count=len(plans))
    stripe_plans = []
    products = {}  # type: Dict
    for plan in plans:
        try:
            product = products[plan["product"]]
        except KeyError:
            product = vendor.retrieve_stripe_product(plan["product"])
            products[plan["product"]] = product

        plan_name = format_plan_nickname(product_name=product["name"],
                                         plan_interval=plan["interval"])

        stripe_plans.append({
            "plan_id": plan["id"],
            "product_id": plan["product"],
            "interval": plan["interval"],
            "amount": plan["amount"],
            "currency": plan["currency"],
            "plan_name": plan_name,
            "product_name": product["name"],
        })
    return stripe_plans
Beispiel #2
0
def format_subscription(
    subscription: Dict[str, Any],
    product: Dict[str, Any],
    failed_charge: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
    """
    Format a single Subscription
    :param subscription:
    :param product:
    :param failed_charge:
    :return:
    """
    plan_name = format_plan_nickname(
        product_name=product["name"],
        plan_interval=subscription["plan"]["interval"])

    subscription = {
        "current_period_end": subscription["current_period_end"],
        "current_period_start": subscription["current_period_start"],
        "ended_at": subscription["ended_at"],
        "plan_name": plan_name,
        "plan_id": subscription["plan"]["id"],
        "product_metadata": product["metadata"],
        "plan_metadata": subscription["plan"]["metadata"],
        "status": subscription["status"],
        "subscription_id": subscription["id"],
        "cancel_at_period_end": subscription["cancel_at_period_end"],
    }

    if failed_charge is not None:
        subscription["failure_code"] = failed_charge["failure_code"]
        subscription["failure_message"] = failed_charge["failure_message"]

    return subscription
Beispiel #3
0
def create_return_data(subscriptions) -> JsonDict:
    """
    Create json object subscriptions object
    :param subscriptions:
    :return: JSON data to be consumed by client.
    """
    return_data: Dict[str, Any] = {}
    return_data["subscriptions"] = []

    products = {}  # type: Dict
    for subscription in subscriptions["data"]:
        try:
            product = products[subscription["plan"]["product"]]
        except KeyError:
            product = vendor.retrieve_stripe_product(
                subscription["plan"]["product"])
            products[subscription["plan"]["product"]] = product

        plan_name = format_plan_nickname(
            product_name=product["name"],
            plan_interval=subscription["plan"]["interval"])

        if subscription["status"] == "incomplete":
            invoice = vendor.retrieve_stripe_invoice(
                subscription["latest_invoice"])
            if invoice["charge"]:
                intents = vendor.retrieve_stripe_customer(invoice["charge"])
                logger.debug("intents", intents=intents)

                return_data["subscriptions"].append({
                    "current_period_end":
                    subscription["current_period_end"],
                    "current_period_start":
                    subscription["current_period_start"],
                    "ended_at":
                    subscription["ended_at"],
                    "plan_name":
                    plan_name,
                    "plan_id":
                    subscription["plan"]["id"],
                    "status":
                    subscription["status"],
                    "subscription_id":
                    subscription["id"],
                    "cancel_at_period_end":
                    subscription["cancel_at_period_end"],
                    "failure_code":
                    intents["failure_code"],
                    "failure_message":
                    intents["failure_message"],
                })
                continue

        return_data["subscriptions"].append(
            create_subscription_object_without_failure(subscription,
                                                       plan_name))
    return return_data
Beispiel #4
0
def test_format_plan_key_error():
    """
    Given a product name and an invalid interval
    Validate that the plan interval is not changed in the returned value
    :return:
    """
    product_name = "Test Product"
    plan_interval = "bi-weekly"
    formatted_plan = utils.format_plan_nickname(product_name=product_name,
                                                plan_interval=plan_interval)
    valid_plan_name = "Test Product (Bi-Weekly)"
    assert valid_plan_name == formatted_plan
Beispiel #5
0
def test_format_plan_nickname():
    """
    Given a product name and plan interval
    Validate that interval is  formatted correctly
    and the returned value is  concatenated correctly
    :return:
    """
    product_name = "Test Product"
    plan_interval = "month"
    formatted_plan = utils.format_plan_nickname(product_name=product_name,
                                                plan_interval=plan_interval)
    valid_plan_name = "Test Product (Monthly)"
    assert valid_plan_name == formatted_plan
Beispiel #6
0
def format_plan(plan: Dict[str, Any], product: Dict[str,
                                                    Any]) -> Dict[str, Any]:
    """
    Format a Stripe Plan for response
    :param plan:
    :param product:
    :return:
    """
    plan_name = format_plan_nickname(product_name=product["name"],
                                     plan_interval=plan["interval"])

    return {
        "plan_id": plan["id"],
        "product_id": product["id"],
        "interval": plan["interval"],
        "amount": plan["amount"],
        "currency": plan["currency"],
        "plan_name": plan_name,
        "product_name": product["name"],
        "plan_metadata": plan["metadata"],
        "product_metadata": product["metadata"],
    }
Beispiel #7
0
def create_update_data(customer) -> Dict[str, Any]:
    """
    Provide readable data for customer update to display
    :param customer:
    :return: return_data dict
    """
    payment_sources = customer["sources"]["data"]
    return_data: Dict[str, Any] = dict()
    return_data["subscriptions"] = []

    return_data["payment_type"] = ""
    return_data["last4"] = ""
    return_data["exp_month"] = ""
    return_data["exp_year"] = ""

    if len(payment_sources) > 0:
        first_payment_source = payment_sources[0]
        return_data["payment_type"] = first_payment_source.get("funding")
        return_data["last4"] = first_payment_source.get("last4")
        return_data["exp_month"] = first_payment_source.get("exp_month")
        return_data["exp_year"] = first_payment_source.get("exp_year")

    products = {}  # type: Dict
    for subscription in customer["subscriptions"]["data"]:
        try:
            product = products[subscription["plan"]["product"]]
        except KeyError:
            product = vendor.retrieve_stripe_product(
                subscription["plan"]["product"])
            products[subscription["plan"]["product"]] = product

        plan_name = format_plan_nickname(
            product_name=product["name"],
            plan_interval=subscription["plan"]["interval"])

        if subscription["status"] == "incomplete":
            invoice = vendor.retrieve_stripe_invoice(
                subscription["latest_invoice"])
            if invoice["charge"]:
                intents = vendor.retrieve_stripe_customer(invoice["charge"])
                intents = intents.to_dict()
                return_data["subscriptions"].append({
                    "current_period_end":
                    subscription["current_period_end"],
                    "current_period_start":
                    subscription["current_period_start"],
                    "ended_at":
                    subscription["ended_at"],
                    "plan_name":
                    plan_name,
                    "plan_id":
                    subscription["plan"]["id"],
                    "status":
                    subscription["status"],
                    "cancel_at_period_end":
                    subscription["cancel_at_period_end"],
                    "subscription_id":
                    subscription["id"],
                    "failure_code":
                    intents["failure_code"],
                    "failure_message":
                    intents["failure_message"],
                })
                continue

        return_data["cancel_at_period_end"] = subscription[
            "cancel_at_period_end"]
        return_data["subscriptions"].append(
            create_subscription_object_without_failure(subscription,
                                                       plan_name))

    return return_data
Beispiel #8
0
def delete_customer(uid: str) -> FlaskResponse:
    """
    Delete an existing customer, cancel active subscriptions
    and delete from payment provider
    :param uid:
    :return: Success of failure message for the deletion
    """
    logger.info("delete customer", uid=uid)
    subscription_user = g.subhub_account.get_user(uid)
    logger.info("delete customer", subscription_user=subscription_user)
    if subscription_user is not None:
        origin = subscription_user.origin_system
        logger.info("delete origin", origin=origin)
        if not subscription_user:
            return dict(message="Customer does not exist."), 404
        subscribed_customer = vendor.retrieve_stripe_customer(
            subscription_user.cust_id)
        subscribed_customer = subscribed_customer.to_dict()
        subscription_info: List = []
        logger.info(
            "subscribed customer",
            subscribed_customer=subscribed_customer,
            data_type=type(subscribed_customer),
        )

        products = {}  # type: Dict
        for subs in subscribed_customer["subscriptions"]["data"]:
            try:
                product = products[subs.plan.product]
            except KeyError:
                product = Product.retrieve(subs.plan.product)
                products[subs.plan.product] = product
            plan_id = subs.plan.product

            sub = dict(
                plan_amount=subs.plan.amount,
                nickname=format_plan_nickname(subs.plan.nickname,
                                              subs.plan.interval),
                productId=plan_id,
                current_period_end=subs.current_period_end,
                current_period_start=subs.current_period_start,
                subscription_id=subs.id,
            )
            subscription_info.append(sub)
            vendor.cancel_stripe_subscription_immediately(
                subs.id, utils.get_indempotency_key())
            data = dict(
                uid=subscribed_customer["metadata"]["userid"],
                active=False,
                subscriptionId=subs.id,
                productId=plan_id,
                eventId=utils.get_indempotency_key(),
                eventCreatedAt=int(time.time()),
                messageCreatedAt=int(time.time()),
            )
            sns_message = Message(json.dumps(data)).route()
            logger.info("delete message", sns_message=sns_message)
        else:
            deleted_payment_customer = vendor.delete_stripe_customer(
                subscription_user.cust_id)
            if deleted_payment_customer:
                deleted_customer = delete_user(
                    user_id=subscribed_customer["metadata"]["userid"],
                    cust_id=subscribed_customer["id"],
                    origin_system=origin,
                    subscription_info=subscription_info,
                )
                user = g.subhub_account.get_user(uid)
                if deleted_customer and user is None:
                    return dict(message="Customer deleted successfully"), 200
    return dict(message="Customer not available"), 400