Exemplo n.º 1
0
    def test_retrieve_error(self):
        self.retrieve_product_mock.side_effect = InvalidRequestError(
            "message", param="prod_id"
        )

        with self.assertRaises(InvalidRequestError):
            vendor.retrieve_stripe_product("prod_test1")
Exemplo n.º 2
0
 def get_subscription_type(self, new_product: Dict[str, Any],
                           previous_product: Dict[str, Any]) -> str:
     """
     Determine if new product is an upgrade or downgrade
     :param new_product:
     :param previous_product:
     :return:
     """
     logger.debug("get sub meta",
                  new_product=new_product,
                  previous_product=previous_product)
     new_product_metadata = new_product.get("metadata", None)
     new_product_set_order = new_product_metadata.get("productSetOrder", 0)
     previous_product_metadata = previous_product.get("metadata", None)
     previous_product_set_order = previous_product_metadata.get(
         "productSetOrder", 0)
     logger.debug(
         "get subscription type",
         new_product_set_order=new_product_set_order,
         previous_product_set_order=previous_product_set_order,
     )
     if new_product_set_order > previous_product_set_order:
         return "customer.subscription.upgrade"
     elif previous_product_set_order > new_product_set_order:
         return "customer.subscription.downgrade"
     else:
         raise InvalidRequestError(message="Not valid subscription change",
                                   param="invalid_change")
Exemplo n.º 3
0
    def test_get_user_id_fetch_error(self):
        self.mock_customer.side_effect = InvalidRequestError(
            message="invalid data", param="bad data")

        with self.assertRaises(InvalidRequestError):
            StripeCustomerSubscriptionDeleted(
                self.subscription_deleted_event).get_user_id("cust_123")
Exemplo n.º 4
0
 def run(self):
     try:
         logger.info("customer source expiring")
         customer_id = self.payload.data.object.customer
         updated_customer = stripe.Customer.retrieve(id=customer_id)
         email = updated_customer.email
         nicknames = list()
         for subs in updated_customer.subscriptions["data"]:
             if subs["status"] in ["active", "trialing"]:
                 nicknames.append(subs["plan"]["nickname"])
         data = self.create_data(
             email=email,
             nickname=nicknames[0],
             customer_id=self.payload.data.object.customer,
             last4=self.payload.data.object.last4,
             brand=self.payload.data.object.brand,
             exp_month=self.payload.data.object.exp_month,
             exp_year=self.payload.data.object.exp_year,
         )
         routes = [StaticRoutes.SALESFORCE_ROUTE]
         self.send_to_routes(routes, json.dumps(data))
     except InvalidRequestError as e:
         logger.error("Unable to find customer", error=e)
         raise InvalidRequestError(message="Unable to find customer",
                                   param=str(e))
Exemplo n.º 5
0
 def run(self):
     logger.info("payment intent succeeded", payload=self.payload)
     try:
         invoice_id = self.payload.data.object.invoice
         invoice = stripe.Invoice.retrieve(id=invoice_id)
         subscription_id = invoice.subscription
         period_start = invoice.period_start
         period_end = invoice.period_end
         logger.info("subscription id", subscription_id=subscription_id)
         charges = self.payload.data.object.charges
         data = self.create_data(
             subscription_id=subscription_id,
             period_end=period_end,
             period_start=period_start,
             brand=charges.data[0].payment_method_details.card.brand,
             last4=charges.data[0].payment_method_details.card.last4,
             exp_month=charges.data[0].payment_method_details.card.
             exp_month,
             exp_year=charges.data[0].payment_method_details.card.exp_year,
             charge_id=charges.data[0].id,
             invoice_id=self.payload.data.object.invoice,
             customer_id=self.payload.data.object.customer,
             amount_paid=sum(
                 [p.amount - p.amount_refunded for p in charges.data]),
             created=self.payload.data.object.created,
             currency=self.payload.data.object.currency,
         )
         routes = [StaticRoutes.SALESFORCE_ROUTE]
         self.send_to_routes(routes, json.dumps(data))
     except InvalidRequestError as e:
         logger.error("Unable to find invoice", error=e)
         raise InvalidRequestError(message="Unable to find invoice",
                                   param=str(e))
Exemplo n.º 6
0
 def test_run_customer_not_found(self):
     self.mock_customer.side_effect = InvalidRequestError(
         message="message", param="param"
     )
     self.mock_run_pipeline = None
     with self.assertRaises(InvalidRequestError):
         StripeCustomerSourceExpiring(self.source_expiring_event).run()
Exemplo n.º 7
0
 def run(self):
     logger.info("customer subscription deleted", payload=self.payload)
     try:
         customer_id = self.payload.data.object.customer
         updated_customer = stripe.Customer.retrieve(id=customer_id)
         user_id = updated_customer.metadata.get("userid")
     except InvalidRequestError as e:
         logger.error("Unable to find customer", error=e)
         raise InvalidRequestError(message="Unable to find customer",
                                   param=str(e))
     if user_id:
         data = dict(
             active=self.is_active_or_trialing,
             subscriptionId=self.payload.data.object.id,
             productName=self.payload.data.object.plan.nickname,
             eventId=self.payload.id,  # required by FxA
             event_id=self.payload.id,  # required by SubHub
             eventCreatedAt=self.payload.created,
             messageCreatedAt=int(time.time()),
         )
         logger.info("customer subscription deleted", data=data)
         routes = [StaticRoutes.FIREFOX_ROUTE]
         self.send_to_routes(routes, json.dumps(data))
     else:
         logger.error(
             "customer subscription deleted no userid",
             error=self.payload.object.customer,
             user_id=user_id,
         )
         raise ClientError(
             f"userid is None for customer {self.payload.object.customer}")
Exemplo n.º 8
0
	def test_sync_fail(self, stripe_customer_create_mock, api_retrieve_mock, _sync_mock):
		_sync_mock.side_effect = InvalidRequestError("No such customer:", "blah")

		with capture_stdout() as stdout:
			sync_subscriber(self.user)

		self.assertEqual("ERROR: No such customer:", stdout.getvalue().strip())
Exemplo n.º 9
0
    def test_cancel_already_canceled(
        self,
        subscription_retrieve_mock,
        product_retrieve_mock,
        subscription_delete_mock,
    ):
        subscription_delete_mock.side_effect = InvalidRequestError(
            "No such subscription: sub_xxxx", "blah")

        subscription_fake = deepcopy(FAKE_SUBSCRIPTION)
        subscription = Subscription.sync_from_stripe_data(subscription_fake)

        self.assertEqual(
            Subscription.objects.filter(status="canceled").count(), 0)
        subscription.cancel(at_period_end=False)
        self.assertEqual(
            Subscription.objects.filter(status="canceled").count(), 1)

        self.assert_fks(
            subscription,
            expected_blank_fks={
                "djstripe.Customer.coupon",
                "djstripe.Subscription.pending_setup_intent",
            },
        )
Exemplo n.º 10
0
    def test_create_payload_charge_fetch_error(self):
        self.mock_invoice.return_value = self.invoice
        self.mock_charge.side_effect = InvalidRequestError(
            message="invalid data", param="bad data")

        with self.assertRaises(InvalidRequestError):
            StripeCustomerSubscriptionCreated(
                self.subscription_created_event).create_payload("cust_123")
Exemplo n.º 11
0
    def test_retry_unpaid_invoices_unexpected_exception(self, invoice_retry_mock, invoice_list_mock,
                                                        charge_retrieve_mock, customer_retrieve_mock,
                                                        subscription_retrive_mock, default_account_mock):
        default_account_mock.return_value = self.account
        invoice_retry_mock.side_effect = InvalidRequestError("This should fail!", "blah")

        with self.assertRaisesMessage(InvalidRequestError, "This should fail!"):
            self.customer.retry_unpaid_invoices()
Exemplo n.º 12
0
    def test_customer_delete_raises_unexpected_exception(self, customer_retrieve_mock):
        customer_retrieve_mock.side_effect = InvalidRequestError("Unexpected Exception", "blah")

        with self.assertRaisesMessage(InvalidRequestError, "Unexpected Exception"):
            self.customer.purge()

        customer_retrieve_mock.assert_called_once_with(id=self.customer.stripe_id, api_key=settings.STRIPE_SECRET_KEY,
                                                       expand=['default_source'])
Exemplo n.º 13
0
    def test_send_invoice_failure(self, invoice_create_mock):
        invoice_create_mock.side_effect = InvalidRequestError(
            "Invoice creation failed.", "blah")

        return_status = self.customer.send_invoice()
        self.assertFalse(return_status)

        invoice_create_mock.assert_called_once_with(api_key=STRIPE_SECRET_KEY,
                                                    customer=self.customer.id)
Exemplo n.º 14
0
def _validate_origin_system(origin_system: str):
    """
    This function validates a request's origin_system to validate that is permitted.  This
    allows us to ensure that callers are permitted by configuration to interact with this application.
    :param origin_system: The originating system in Mozilla
    """
    if origin_system not in CFG.ALLOWED_ORIGIN_SYSTEMS:
        msg = f"origin_system={origin_system} not one of allowed origin system values, please contact a system administrator in the #subscription-platform channel."
        raise InvalidRequestError(message=msg, param=str(origin_system))
Exemplo n.º 15
0
    def test_cancel_error_in_cancel(self, subscription_delete_mock):
        subscription_delete_mock.side_effect = InvalidRequestError(
            "Unexpected error", "blah")

        subscription_fake = deepcopy(FAKE_SUBSCRIPTION)
        subscription = Subscription.sync_from_stripe_data(subscription_fake)

        with self.assertRaises(InvalidRequestError):
            subscription.cancel()
Exemplo n.º 16
0
    def test_detach(self):
        original_detach = PaymentMethodDict.detach

        def mocked_detach(*args, **kwargs):
            return original_detach(*args, **kwargs)

        with patch(
                "stripe.PaymentMethod.retrieve",
                return_value=deepcopy(FAKE_PAYMENT_METHOD_I),
                autospec=True,
        ):
            PaymentMethod.sync_from_stripe_data(
                deepcopy(FAKE_PAYMENT_METHOD_I))

        self.assertEqual(1, self.customer.payment_methods.count())

        payment_method = self.customer.payment_methods.first()

        with patch("tests.PaymentMethodDict.detach",
                   side_effect=mocked_detach,
                   autospec=True) as mock_detach, patch(
                       "stripe.PaymentMethod.retrieve",
                       return_value=deepcopy(FAKE_PAYMENT_METHOD_I),
                       autospec=True,
                   ):
            self.assertTrue(payment_method.detach())

        self.assertEqual(0, self.customer.payment_methods.count())
        self.assertIsNone(self.customer.default_payment_method)

        self.assertIsNone(payment_method.customer)

        if sys.version_info >= (3, 6):
            # this mock isn't working on py34, py35, but it's not strictly necessary
            # for the test
            mock_detach.assert_called()

        self.assert_fks(payment_method,
                        expected_blank_fks={"djstripe.PaymentMethod.customer"})

        with patch(
                "tests.PaymentMethodDict.detach",
                side_effect=InvalidRequestError(
                    message="A source must be attached to a customer to be used "
                    "as a `payment_method`",
                    param="payment_method",
                ),
                autospec=True,
        ) as mock_detach, patch(
                "stripe.PaymentMethod.retrieve",
                return_value=deepcopy(FAKE_PAYMENT_METHOD_I),
                autospec=True,
        ) as payment_method_retrieve_mock:
            payment_method_retrieve_mock.return_value["customer"] = None

            self.assertFalse(payment_method.detach(),
                             "Second call to detach should return false")
Exemplo n.º 17
0
def _validate_origin_system(origin_system: str):
    """
    This function validates a request's origin_system to validate that is permitted.  This
    allows us to ensure that callers are permitted by configuration to interact with this application.
    :param origin_system: The originating system in Mozilla
    """
    if origin_system not in CFG.ALLOWED_ORIGIN_SYSTEMS:
        msg = f"origin_system={origin_system} not one of {CFG.ALLOWED_ORIGIN_SYSTEMS}"
        raise InvalidRequestError(message=msg, param=str(origin_system))
Exemplo n.º 18
0
    def test_create_payload_error(self):
        self.mock_product.side_effect = InvalidRequestError(
            message="invalid data", param="bad data")

        with self.assertRaises(InvalidRequestError):
            StripeCustomerSubscriptionUpdated(
                self.subscription_updated_event_no_match).create_payload(
                    event_type="event.type",
                    user_id="user_123",
                    previous_plan=None)
Exemplo n.º 19
0
    def test_retry_unpaid_invoices_expected_exception(self, invoice_retry_mock, invoice_list_mock,
                                                      charge_retrieve_mock, customer_retrieve_mock,
                                                      subscription_retrive_mock, default_account_mock):
        default_account_mock.return_value = self.account
        invoice_retry_mock.side_effect = InvalidRequestError("Invoice is already paid", "blah")

        try:
            self.customer.retry_unpaid_invoices()
        except:
            self.fail("Exception was unexpectedly raised.")
Exemplo n.º 20
0
    def test_find_product_not_found(self):
        self.mock_stripe_retrieve_product.side_effect = InvalidRequestError(
            "message", param="prod_id", http_status=404)

        with self.assertRaises(EntityNotFoundError) as e:
            find_stripe_product("prod_test1")

        error = e.exception
        assert error.status_code == 404
        assert error.to_dict() == dict(message="Product not found", errno=4002)
Exemplo n.º 21
0
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
Exemplo n.º 22
0
    def test_sync_customers_with_test_customer(self, SyncChargesMock, SyncInvoicesMock, SyncMock, RetrieveMock):
        user2 = get_user_model().objects.create_user(username="******")
        get_user_model().objects.create_user(username="******")
        Customer.objects.create(stripe_id="cus_XXXXX", user=self.user)
        Customer.objects.create(stripe_id="cus_YYYYY", user=user2)

        SyncMock.side_effect = InvalidRequestError('Unknown customer', None, http_status=404)

        management.call_command("sync_customers")
        self.assertEqual(SyncChargesMock.call_count, 0)
        self.assertEqual(SyncInvoicesMock.call_count, 0)
        self.assertEqual(SyncMock.call_count, 2)
Exemplo n.º 23
0
    def test_remove_unexpected_exception(self, customer_retrieve_mock, card_delete_mock):
        stripe_card = Card._api_create(customer=self.customer, source=FAKE_CARD["id"])
        Card.sync_from_stripe_data(stripe_card)

        card_delete_mock.side_effect = InvalidRequestError("Unexpected Exception", "blah")

        self.assertEqual(1, self.customer.sources.count())

        card = self.customer.sources.all()[0]

        with self.assertRaisesMessage(InvalidRequestError, "Unexpected Exception"):
            card.remove()
Exemplo n.º 24
0
	def test_cancel_error_in_cancel(self, subscription_delete_mock):
		subscription_delete_mock.side_effect = InvalidRequestError("Unexpected error", "blah")

		subscription_fake = deepcopy(FAKE_SUBSCRIPTION)
		subscription = Subscription.sync_from_stripe_data(subscription_fake)

		with self.assertRaises(InvalidRequestError):
			subscription.cancel(at_period_end=False)

		self.assert_fks(
			subscription,
			expected_blank_fks={"djstripe.Customer.coupon", "djstripe.Plan.product"},
		)
Exemplo n.º 25
0
    def test_cancel_already_canceled(self, subscription_retrieve_mock,
                                     subscription_delete_mock):
        subscription_delete_mock.side_effect = InvalidRequestError(
            "No such subscription: sub_xxxx", "blah")

        subscription_fake = deepcopy(FAKE_SUBSCRIPTION)
        subscription = Subscription.sync_from_stripe_data(subscription_fake)

        self.assertEqual(
            Subscription.objects.filter(status="canceled").count(), 0)
        subscription.cancel()
        self.assertEqual(
            Subscription.objects.filter(status="canceled").count(), 1)
Exemplo n.º 26
0
    def test_cancel_error_in_cancel(self, product_retrieve_mock,
                                    subscription_delete_mock):
        subscription_delete_mock.side_effect = InvalidRequestError(
            "Unexpected error", "blah")

        subscription_fake = deepcopy(FAKE_SUBSCRIPTION)
        subscription = Subscription.sync_from_stripe_data(subscription_fake)

        with self.assertRaises(InvalidRequestError):
            subscription.cancel(at_period_end=False)

        self.assert_fks(subscription,
                        expected_blank_fks=self.default_expected_blank_fks)
Exemplo n.º 27
0
    def test_remove_no_such_customer(self, customer_retrieve_mock, card_delete_mock):
        stripe_card = Card._api_create(customer=self.customer, source=FAKE_CARD["id"])
        Card.sync_from_stripe_data(stripe_card)

        card_delete_mock.side_effect = InvalidRequestError("No such customer:", "blah")

        self.assertEqual(1, self.customer.sources.count())

        card = self.customer.sources.all()[0]
        card.remove()

        self.assertEqual(0, self.customer.sources.count())
        self.assertTrue(card_delete_mock.called)
Exemplo n.º 28
0
    def test_customer_purge_raises_customer_exception(self, customer_retrieve_mock):
        customer_retrieve_mock.side_effect = InvalidRequestError("No such customer:", "blah")

        self.customer.purge()
        customer = Customer.objects.get(stripe_id=self.customer.stripe_id)
        self.assertTrue(customer.subscriber is None)
        self.assertTrue(customer.default_source is None)
        self.assertTrue(not customer.sources.all())
        self.assertTrue(get_user_model().objects.filter(pk=self.user.pk).exists())

        customer_retrieve_mock.assert_called_with(id=self.customer.stripe_id, api_key=settings.STRIPE_SECRET_KEY,
                                                  expand=['default_source'])
        self.assertEqual(3, customer_retrieve_mock.call_count)
Exemplo n.º 29
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)
Exemplo n.º 30
0
def test_plan_manager_error(plan_create_mock):
    plan_create_mock.side_effect = InvalidRequestError(param="id",
                                                       message="no!")
    plan = models.Plan(
        name="Gold Plan",
        amount=100,
        interval=models.Plan.MONTHLY,
        name_on_invoice="Gold Plan Subscription",
        statement_descriptor="GOLDPLANSUB",
    )

    with pytest.raises(ValidationError) as err:
        plan.save()
    assert err.value.message_dict == {"id": ["no!"]}