Пример #1
0
    def test_coupon_redemption_direct_discount(self):
        # add a sample plan to the plans backend
        mocurly.backend.plans_backend.add_object(
            self.base_backed_plan_data['plan_code'],
            self.base_backed_plan_data)
        # add a sample coupon to the coupons backend
        base_coupon_data = {
            'coupon_code': 'special',
            'name': 'Special $1.00 off',
            'discount_type': 'dollars',
            'discount_in_cents': 100
        }
        mocurly.backend.coupons_backend.add_object(
            base_coupon_data['coupon_code'], base_coupon_data)
        # ... and redeem the coupon
        base_redemption_data = {
            'account_code': self.base_account_data['account_code'],
            'currency': 'USD',
            'coupon': base_coupon_data['coupon_code']
        }
        mocurly.backend.coupon_redemptions_backend.add_object(
            base_redemption_data['coupon'] + '__' +
            self.base_account_data['account_code'], base_redemption_data)

        # Now add an active subscription and verify the transactions are discounted properly
        new_subscription = recurly.Subscription(**self.base_subscription_data)
        new_subscription.save()
        invoice = new_subscription.invoice()
        self.assertEqual(invoice.total_in_cents, 900)
        line_items = invoice.line_items
        self.assertEqual(len(line_items), 1)
        line_item = line_items[0]
        self.assertEqual(line_item.unit_amount_in_cents, 1000)
        self.assertEqual(line_item.discount_in_cents, 100)
        self.assertEqual(line_item.total_in_cents, 900)
Пример #2
0
    def test_trial_subscription_creation(self):
        # add a sample plan to the plans backend
        self.base_backed_plan_data['trial_interval_length'] = 1
        mocurly.backend.plans_backend.add_object(
            self.base_backed_plan_data['plan_code'],
            self.base_backed_plan_data)

        self.assertEqual(len(mocurly.backend.subscriptions_backend.datastore),
                         0)

        new_subscription = recurly.Subscription(**self.base_subscription_data)
        new_subscription.save()

        self.assertEqual(len(mocurly.backend.subscriptions_backend.datastore),
                         1)

        # Make sure a new transaction and invoice was created with it
        invoice = new_subscription.invoice()
        self.assertEqual(invoice.line_items[0].start_date.date(),
                         datetime.datetime.utcnow().date())
        self.assertEqual(invoice.line_items[0].end_date.date(),
                         (datetime.datetime.utcnow() +
                          relativedelta(months=1)).date())
        transactions = invoice.transactions
        self.assertEqual(len(transactions), 1)
        self.assertEqual(transactions[0].subscription().uuid,
                         new_subscription.uuid)

        # Make sure we can reference the subscription from the account
        account = new_subscription.account()
        account_subscriptions = account.subscriptions()
        self.assertEqual(len(account_subscriptions), 1)
        self.assertEqual(account_subscriptions[0].uuid, new_subscription.uuid)
        self.assertEqual(account_subscriptions[0].state, 'active')
Пример #3
0
    def test_trial_override_subscription_creation(self):
        # add a sample plan to the plans backend
        self.base_backed_plan_data['trial_interval_length'] = 1
        mocurly.backend.plans_backend.add_object(
            self.base_backed_plan_data['plan_code'],
            self.base_backed_plan_data)

        self.assertEqual(len(mocurly.backend.subscriptions_backend.datastore),
                         0)

        # Make the trial immediately expire
        self.base_subscription_data[
            'trial_ends_at'] = datetime.datetime.utcnow()
        new_subscription = recurly.Subscription(**self.base_subscription_data)
        new_subscription.save()

        self.assertEqual(len(mocurly.backend.subscriptions_backend.datastore),
                         1)

        # Make sure a new transaction and invoice was created with it
        invoice = new_subscription.invoice()
        # The invoice should not contain 0 (trial cost) but the actual cost of the subscription since the trial has expired immediately
        self.assertNotEqual(invoice.total_in_cents, 0)

        transactions = invoice.transactions
        self.assertEqual(len(transactions), 1)
        self.assertEqual(transactions[0].subscription().uuid,
                         new_subscription.uuid)

        # Make sure we can reference the subscription from the account
        account = new_subscription.account()
        account_subscriptions = account.subscriptions()
        self.assertEqual(len(account_subscriptions), 1)
        self.assertEqual(account_subscriptions[0].uuid, new_subscription.uuid)
        self.assertEqual(account_subscriptions[0].state, 'active')
Пример #4
0
    def new_subscription(self):

        try:
            subscription = recurly.Subscription()
            subscription.plan_code = 'pro'
            subscription.currency = 'USD'

            account = recurly.Account(account_code=uuid.uuid1())
            account.email = '*****@*****.**'
            account.first_name = 'Michael1'
            account.last_name = 'McGovern'

            billing_info = recurly.BillingInfo()
            billing_info.number = '4111-1111-1111-1111'
            billing_info.month = 05
            billing_info.year = 2019

            account.billing_info = billing_info
            subscription.account = account
            log.warn("========================test========================")
            subscription.save()
        except recurly.NotFoundError:
            print 'Account not Found.\n'
        except recurly.errors:
            for e in errors:
                print "%s:%s" % (e.field, e.message)
Пример #5
0
def new_subscription():

    # We'll wrap this in a try to catch any API
    # errors that may occur
    try:

        # Create the scubscription using minimal
        # information: plan_code, account_code, currency and
        # the token we generated on the frontend
        subscription = recurly.Subscription(
            plan_code='basic',
            currency='USD',
            account=recurly.Account(
                account_code=uuid.uuid1(),
                billing_info=recurly.BillingInfo(
                    token_id=request.form['recurly-token'])))

        # The subscription has been created and we can redirect
        # to a confirmation page
        subscription.save()
        return redirect('SUCCESS_URL')
    except recurly.ValidationError, errors:

        # Here we may wish to log the API error and send the
        # customer to an appropriate URL, perhaps including
        # and error message. See the `error_redirect` and
        # `compose_errors` functions below.
        error_redirect(compose_errors(errors))
Пример #6
0
def new_subscription():

    # If user is not logged in, have them login or register
    if not current_user.is_authenticated:
        flash('Please login or register to create an account first!', 'danger')
        return redirect(url_for('users.login'))

    # We'll wrap this in a try to catch any API
    # errors that may occur
    try:

        # Get the user_account
        user_account_code = fa.create_account_code(current_user.id)
        user_account = recurly.Account.get(user_account_code)
        billing_info = recurly.BillingInfo(
            token_id=request.form['recurly-token'])
        user_account.billing_info = billing_info

        # Create the scubscription using minimal
        # information: plan_code, account_code, currency and
        # the token we generated on the frontend
        subscription = recurly.Subscription(currency='USD',
                                            account=user_account,
                                            plan_code='testplancode')

    except:
        flash(('Sorry, our servers experienced an issue creating your'
               'subscription. Please try again later!'), 'danger')
    # The subscription has been created and we can redirect to a confirmation page
    subscription.save()
    flash('You have been successfully subscribed to the Basic Plan!',
          'success')
    return redirect(url_for('main.home'))
Пример #7
0
def new_recurly_account():

    # If user is not logged in, have them login or register
    if not current_user.is_authenticated:
        flash('Please login or register to create an account first!', 'danger')
        return redirect(url_for('users.login'))

    # Create user's account_code from hidden hash library
    user_account_code = fa.create_account_code(current_user.id)

    try:

        # Create user account
        new_account = recurly.Account(
            account_code=user_account_code,
            billing_info=recurly.BillingInfo(
                token_id=request.form['recurly-token']))

        # Create subscription
        subscription = recurly.Subscription()
        subscription.plan_code = request.form['plan']
        subscription.currency = 'USD'
        subscription.account = new_account
        subscription.save()

        flash('Account subscribed successfully!', 'success')
        return redirect(url_for('users.account'))

    except recurly.ValidationError:
        flash('ValidationError! Please try again shortly.', 'danger')
        return redirect(url_for('users.account'))
Пример #8
0
def create_remote_subsciption(subscription_params,
                              account_params,
                              billing_info_params=None):
    assert "account" not in subscription_params, subscription_params
    recurly_account = _construct_recurly_account_resource(
        account_params, billing_info_params=billing_info_params)

    subscription_params = copy.deepcopy(
        subscription_params)  # do not touch input object
    subscription_params["account"] = recurly_account

    recurly_subscription = recurly.Subscription(**subscription_params)
    return recurly_subscription
Пример #9
0
def new_subscription():

    # We'll wrap this in a try to catch any API
    # errors that may occur
    try:

        recurly_token_id = request.form['recurly-token']
        if 'recurly-account-code' in request.form:
            recurly_account_code = request.form['recurly-account-code']
        else:
            recurly_account_code = uuid.uuid1()

        # Build our billing info object
        billing_info = recurly.BillingInfo(token_id=recurly_token_id)

        # Optionally add a 3D Secure token if one is present. You only need to do this
        # if you are integrating with Recurly's 3D Secure support
        if 'three-d-secure-token' in request.form:
            billing_info.three_d_secure_action_result_token_id = request.form[
                'three-d-secure-token']

        # Create the scubscription using minimal
        # information: plan_code, account_code, currency and
        # the token we generated on the frontend
        subscription = recurly.Subscription(
            plan_code='basic',
            currency='USD',
            account=recurly.Account(account_code=recurly_account_code,
                                    billing_info=billing_info))

        # The subscription has been created and we can redirect
        # to a confirmation page
        subscription.save()
        return redirect(SUCCESS_URL)
    except recurly.ValidationError as error:

        # Here we handle a 3D Secure required error by redirecting to an authentication page
        if error.transaction_error_code == 'three_d_secure_action_required':
            action_token_id = error.transaction_error.three_d_secure_action_token_id
            return redirect("/3d-secure/authenticate.html#token_id=" +
                            recurly_token_id + "&action_token_id=" +
                            action_token_id + "&account_code=" +
                            str(recurly_account_code))

        # Here we may wish to log the API error and send the
        # customer to an appropriate URL, perhaps including
        # and error message. See the `error_redirect` and
        # `compose_errors` functions below.
        error_redirect(compose_errors(error))
Пример #10
0
    def test_subscription_termination_full_refund(self):
        # add a sample plan to the plans backend
        mocurly.backend.plans_backend.add_object(
            self.base_backed_plan_data['plan_code'],
            self.base_backed_plan_data)
        # add an active subscription
        new_subscription = recurly.Subscription(**self.base_subscription_data)
        new_subscription.save()
        self.assertEqual(new_subscription.state, 'active')

        # Now terminate it with a full refund
        new_subscription.terminate(refund='full')

        self.assertEqual(new_subscription.state, 'expired')
        invoice = new_subscription.invoice()
        transactions = invoice.transactions
        self.assertEqual(len(transactions), 1)
        self.assertEqual(transactions[0].status, 'void')
Пример #11
0
    def test_subscription_cancel_reactivate(self):
        # add a sample plan to the plans backend
        mocurly.backend.plans_backend.add_object(
            self.base_backed_plan_data['plan_code'],
            self.base_backed_plan_data)
        # add an active subscription
        new_subscription = recurly.Subscription(**self.base_subscription_data)
        new_subscription.save()
        self.assertEqual(new_subscription.state, 'active')

        # trying to reactivate an active subscription should fail
        with self.assertRaises(BadRequestError):
            new_subscription.reactivate()

        # now cancel it and verify it was canceled
        new_subscription.cancel()
        self.assertEqual(new_subscription.state, 'canceled')

        # now reactivate it and verify it was reactivated
        new_subscription.reactivate()
        self.assertEqual(new_subscription.state, 'active')
        self.assertEqual(new_subscription.canceled_at, None)
        self.assertEqual(new_subscription.expires_at, None)
Пример #12
0
    def test_subscriptions_with_addons(self):
        # add a sample plan to the plans backend
        mocurly.backend.plans_backend.add_object(
            self.base_backed_plan_data['plan_code'],
            self.base_backed_plan_data)
        # add some add ons to the backend
        for add_on in self.base_add_on_backed_data:
            uuid = mocurly.endpoints.PlansEndpoint().generate_plan_add_on_uuid(
                self.base_backed_plan_data['plan_code'], add_on['add_on_code'])
            mocurly.backend.plan_add_ons_backend.add_object(uuid, add_on)

        self.assertEqual(len(mocurly.backend.subscriptions_backend.datastore),
                         0)

        self.base_subscription_data['subscription_add_ons'] = [
            recurly.SubscriptionAddOn(add_on_code=addon['add_on_code'],
                                      quantity=1)
            for addon in self.base_add_on_data
        ]
        new_subscription = recurly.Subscription(**self.base_subscription_data)
        new_subscription.save()

        self.assertEqual(len(mocurly.backend.subscriptions_backend.datastore),
                         1)
Пример #13
0
    def test_subscription_termination_partial_refund(self):
        # add a sample plan to the plans backend
        mocurly.backend.plans_backend.add_object(
            self.base_backed_plan_data['plan_code'],
            self.base_backed_plan_data)
        # add an active subscription
        new_subscription = recurly.Subscription(**self.base_subscription_data)
        new_subscription.save()
        self.assertEqual(new_subscription.state, 'active')

        # modify start time so a partial refund will refund half the cost
        start = new_subscription.current_period_started_at
        end = new_subscription.current_period_ends_at
        new_start = start - (end - start)
        mocurly.backend.subscriptions_backend.update_object(
            new_subscription.uuid,
            {'current_period_started_at': new_start.isoformat()})

        # get the original transaction and invoice objects for use later
        self.assertEqual(len(mocurly.backend.transactions_backend.datastore),
                         1)
        self.assertEqual(len(mocurly.backend.invoices_backend.datastore), 1)
        transaction_keys = iterkeys(
            mocurly.backend.transactions_backend.datastore)
        invoice_keys = iterkeys(mocurly.backend.invoices_backend.datastore)
        original_transaction_id = next(transaction_keys)
        original_invoice_id = next(invoice_keys)

        # Now terminate it with a partial refund
        new_subscription.terminate(refund='partial')

        self.assertEqual(new_subscription.state, 'expired')
        self.assertEqual(len(mocurly.backend.transactions_backend.datastore),
                         2)
        self.assertEqual(len(mocurly.backend.invoices_backend.datastore), 2)
        for invoice_id, invoice in mocurly.backend.invoices_backend.datastore.items(
        ):
            if invoice_id == original_invoice_id:
                original_invoice = invoice
            else:
                refund_invoice = invoice
        # The following two lines reference the objects to make sure they exist
        original_invoice
        refund_invoice

        original_transaction_ids = original_invoice['transactions']
        self.assertEqual(len(original_transaction_ids), 1)
        self.assertEqual(original_transaction_ids[0], original_transaction_id)
        original_transaction = mocurly.backend.transactions_backend.get_object(
            original_transaction_id)
        self.assertEqual(original_transaction['status'],
                         'success')  # not voided

        refund_transaction_ids = refund_invoice['transactions']
        self.assertEqual(len(refund_transaction_ids), 1)
        self.assertNotEqual(refund_transaction_ids[0], original_transaction_id)
        refund_transaction = mocurly.backend.transactions_backend.get_object(
            refund_transaction_ids[0])
        self.assertEqual(refund_transaction['status'], 'success')
        self.assertEqual(refund_transaction['action'], 'refund')
        # 29 / 60, because today doesn't count
        self.assertEqual(
            refund_transaction['amount_in_cents'],
            -int(original_transaction['amount_in_cents'] * (29.0 / 60)))
Пример #14
0
    def create(cls,
               plan,
               account,
               subscription_add_ons=None,
               coupon_code=None,
               unit_amount=None,
               currency='USD',
               quantity=1,
               trial_ends_at=None,
               starts_at=None,
               total_billing_cycles=None,
               first_renewal_date=None):
        recurly_account = account.recurly_account
        recurly_subscription = recurly.Subscription(plan_code=plan.plan_code,
                                                    account=recurly_account,
                                                    currency=currency)

        if coupon_code is not None:
            recurly_subscription.coupon_code = coupon_code

        if unit_amount is None:
            unit_amount = plan.unit_amount  # use plan's unit amount as default if none is provided.
            recurly_subscription.unit_amount_in_cents = int(plan.unit_amount *
                                                            100)
        else:
            recurly_subscription.unit_amount_in_cents = int(unit_amount * 100)

        if quantity is not None:
            recurly_subscription.quantity = quantity

        if trial_ends_at is not None:
            recurly_subscription.trial_ends_at = trial_ends_at

        if starts_at is not None:
            recurly_subscription.starts_at = starts_at

        if total_billing_cycles is not None:
            recurly_subscription.total_billing_cycles = total_billing_cycles

        if first_renewal_date is not None:
            recurly_subscription.first_renewal_date = first_renewal_date

        if subscription_add_ons is not None:
            #TODO Add-ons
            pass

        recurly_subscription.save()

        return cls._create_local(
            account=account,
            plan=plan,
            uuid=recurly_subscription.uuid,
            state=recurly_subscription.state,
            unit_amount=unit_amount,
            currency=currency,
            quantity=quantity,
            activated_at=recurly_subscription.activated_at,
            canceled_at=recurly_subscription.canceled_at,
            expires_at=recurly_subscription.expires_at,
            current_period_started_at=recurly_subscription.
            current_period_started_at,
            current_period_ends_at=recurly_subscription.current_period_ends_at,
            trial_started_at=recurly_subscription.trial_started_at,
            trial_ends_at=recurly_subscription.trial_ends_at)