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
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
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
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
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
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"], }
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
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