@@ -534,15 +534,43 @@ def create_checkout_session(self, owner: Owner, desired_plan):
534534 "metadata" : self ._get_checkout_session_and_subscription_metadata (owner ),
535535 },
536536 tax_id_collection = {"enabled" : True },
537- customer_update = {"name" : "auto" , "address" : "auto" }
538- if owner .stripe_customer_id
539- else None ,
537+ customer_update = (
538+ {"name" : "auto" , "address" : "auto" }
539+ if owner .stripe_customer_id
540+ else None
541+ ),
540542 )
541543 log .info (
542544 f"Stripe Checkout Session created successfully for owner { owner .ownerid } by user #{ self .requesting_user .ownerid } "
543545 )
544546 return session ["id" ]
545547
548+ def _is_unverified_payment_method (self , payment_method_id : str ) -> bool :
549+ payment_method = stripe .PaymentMethod .retrieve (payment_method_id )
550+
551+ is_us_bank_account = payment_method .type == "us_bank_account" and hasattr (
552+ payment_method , "us_bank_account"
553+ )
554+ if is_us_bank_account :
555+ setup_intents = stripe .SetupIntent .list (
556+ payment_method = payment_method_id , limit = 1
557+ )
558+ if (
559+ setup_intents
560+ and hasattr (setup_intents , "data" )
561+ and isinstance (setup_intents .data , list )
562+ and len (setup_intents .data ) > 0
563+ ):
564+ latest_intent = setup_intents .data [0 ]
565+ if (
566+ latest_intent .status == "requires_action"
567+ and latest_intent .next_action
568+ and latest_intent .next_action .type == "verify_with_microdeposits"
569+ ):
570+ return True
571+
572+ return False
573+
546574 @_log_stripe_error
547575 def update_payment_method (self , owner : Owner , payment_method ):
548576 log .info (
@@ -718,6 +746,54 @@ def create_setup_intent(self, owner: Owner) -> stripe.SetupIntent:
718746 customer = owner .stripe_customer_id ,
719747 )
720748
749+ def _get_unverified_payment_methods (self , owner ):
750+ log .info (
751+ "Getting unverified payment methods" ,
752+ extra = dict (
753+ owner_id = owner .ownerid , stripe_customer_id = owner .stripe_customer_id
754+ ),
755+ )
756+ if not owner .stripe_customer_id :
757+ return []
758+
759+ unverified_payment_methods = []
760+
761+ # Check payment intents
762+ payment_intents = stripe .PaymentIntent .list (
763+ customer = owner .stripe_customer_id , limit = 100
764+ )
765+ for intent in payment_intents .data or []:
766+ if (
767+ intent .get ("next_action" )
768+ and intent .next_action
769+ and intent .next_action .get ("type" ) == "verify_with_microdeposits"
770+ ):
771+ unverified_payment_methods .append (
772+ {
773+ "payment_method_id" : intent .payment_method ,
774+ "hosted_verification_link" : intent .next_action .verify_with_microdeposits .hosted_verification_url ,
775+ }
776+ )
777+
778+ # Check setup intents
779+ setup_intents = stripe .SetupIntent .list (
780+ customer = owner .stripe_customer_id , limit = 100
781+ )
782+ for intent in setup_intents .data :
783+ if (
784+ intent .get ("next_action" )
785+ and intent .next_action
786+ and intent .next_action .get ("type" ) == "verify_with_microdeposits"
787+ ):
788+ unverified_payment_methods .append (
789+ {
790+ "payment_method_id" : intent .payment_method ,
791+ "hosted_verification_link" : intent .next_action .verify_with_microdeposits .hosted_verification_url ,
792+ }
793+ )
794+
795+ return unverified_payment_methods
796+
721797
722798class EnterprisePaymentService (AbstractPaymentService ):
723799 # enterprise has no payments setup so these are all noops
@@ -758,6 +834,9 @@ def apply_cancellation_discount(self, owner: Owner):
758834 def create_setup_intent (self , owner ):
759835 pass
760836
837+ def get_unverified_payment_methods (self , owner ):
838+ pass
839+
761840
762841class BillingService :
763842 payment_service = None
@@ -788,6 +867,9 @@ def get_invoice(self, owner, invoice_id):
788867 def list_filtered_invoices (self , owner , limit = 10 ):
789868 return self .payment_service .list_filtered_invoices (owner , limit )
790869
870+ def get_unverified_payment_methods (self , owner ):
871+ return self .payment_service ._get_unverified_payment_methods (owner )
872+
791873 def update_plan (self , owner , desired_plan ):
792874 """
793875 Takes an owner and desired plan, and updates the owner's plan. Depending
0 commit comments