def create_customer( subhub_account: SubHubAccount, user_id: str, email: str, source_token: str, origin_system: str, display_name: str, ) -> Customer: _validate_origin_system(origin_system) # First search Stripe to ensure we don't have an unlinked Stripe record # already in Stripe customer = None customers = Customer.list(email=email) for possible_customer in customers.data: if possible_customer.email == email: # If the userid doesn't match, the system is damaged. if possible_customer.metadata.get("userid") != user_id: raise ServerError("customer email exists but userid mismatch") customer = possible_customer # If we have a mis-match on the source_token, overwrite with the # new one. if customer.default_source != source_token: Customer.modify(customer.id, source=source_token) break # No existing Stripe customer, create one. if not customer: try: customer = Customer.create( source=source_token, email=email, description=user_id, name=display_name, metadata={"userid": user_id}, ) except InvalidRequestError as e: logger.error("create customer error", error=e) raise InvalidRequestError( message="Unable to create customer.", param=str(e) ) # Link the Stripe customer to the origin system id db_account = subhub_account.new_user( uid=user_id, origin_system=origin_system, cust_id=customer.id ) if not subhub_account.save_user(db_account): # Clean-up the Stripe customer record since we can't link it Customer.delete(customer.id) e = IntermittentError("error saving db record") logger.error("unable to save user or link it", error=e) raise e return customer
def modify_customer(customer_id: str, source_token: str, idempotency_key: str) -> Customer: """ Update customer source :param customer_id: :param source_token: :param idempotency_key: :return: updated Customer """ try: customer = Customer.modify(customer_id, source=source_token, idempotency_key=idempotency_key) return customer except ( InvalidRequestError, APIConnectionError, APIError, RateLimitError, IdempotencyError, CardError, StripeErrorWithParamCode, ) as e: logger.error("modify customer token", error=e) raise e
def existing_payment_source(existing_customer: Customer, source_token: str) -> Customer: if not existing_customer.get("sources"): if not existing_customer.get("deleted"): existing_customer = Customer.modify( existing_customer["id"], source=source_token ) logger.info("add source", existing_customer=existing_customer) else: logger.info("existing source deleted") return existing_customer
def update_payment_method(uid, data) -> FlaskResponse: """ Given a user id and a payment token, update user's payment method :param uid: :param data: :return: Success or failure message. """ customer = fetch_customer(g.subhub_account, uid) logger.info("customer", customer=customer) if not customer: return dict(message="Customer does not exist."), 404 metadata = customer.get("metadata") logger.info("metadata", metadata=metadata, customer=type(customer)) if metadata: if metadata["userid"] == uid: Customer.modify(customer.id, source=data["pmt_token"]) return {"message": "Payment method updated successfully."}, 201 return dict(message="Customer mismatch."), 400