Пример #1
0
 def setUp(self):
     super(TestPurchaseJWT, self).setUp()
     self.product = WebAppProduct(self.addon)
     self.contribution = Contribution.objects.create(
         user=self.user,
         addon=self.addon,
     )
Пример #2
0
    def setUp(self):
        super(TestWebAppProduct, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.token = get_product_jwt(
            self.product,
            region=regions.US,
            user=self.user,
        )

        self.contribution = Contribution.objects.get()
Пример #3
0
    def setUp(self):
        super(TestPurchaseJWT, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.token = get_product_jwt(
            self.product,
            region=regions.US,
            user=self.user,
        )

        self.token_data = jwt.decode(str(self.token['webpayJWT']),
                                     verify=False)

        self.contribution = Contribution.objects.get()
Пример #4
0
    def post(self, request, *args, **kwargs):
        form = PrepareWebAppForm(request.DATA)
        if not form.is_valid():
            return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
        app = form.cleaned_data['app']

        region = getattr(request, 'REGION', None)
        if region and region.id not in app.get_price_region_ids():
            log.info('Region {0} is not in {1}'
                     .format(region.id, app.get_price_region_ids()))
            return Response('Payments are limited and flag not enabled',
                            status=status.HTTP_403_FORBIDDEN)

        if app.is_premium() and app.has_purchased(request._request.amo_user):
            log.info('Already purchased: {0}'.format(app.pk))
            return Response({'reason': u'Already purchased app.'},
                            status=status.HTTP_409_CONFLICT)

        app_pay_cef.log(request._request, 'Preparing JWT', 'preparing_jwt',
                        'Preparing JWT for: {0}'.format(app.pk), severity=3)

        token = get_product_jwt(
            WebAppProduct(app),
            client_data=ClientData.get_or_create(request._request),
            lang=request._request.LANG,
            region=request._request.REGION,
            source=request._request.REQUEST.get('src', ''),
            user=request._request.amo_user,
        )

        return Response(token, status=status.HTTP_201_CREATED)
Пример #5
0
def prepare_pay(request, addon):
    if addon.is_premium() and addon.has_purchased(request.amo_user):
        log.info('Already purchased: %d' % addon.pk)
        raise AlreadyPurchased

    app_pay_cef.log(request, 'Preparing JWT', 'preparing_jwt',
                    'Preparing JWT for: %s' % (addon.pk), severity=3)

    log.debug('Starting purchase of app: {0} by user: {1}'.format(
        addon.pk, request.amo_user))

    contribution = Contribution.objects.create(
        addon_id=addon.pk,
        amount=addon.get_price(region=request.REGION.id),
        paykey=None,
        price_tier=addon.premium.price,
        source=request.REQUEST.get('src', ''),
        source_locale=request.LANG,
        type=amo.CONTRIB_PENDING,
        user=request.amo_user,
        uuid=str(uuid.uuid4()),
    )

    log.debug('Storing contrib for uuid: {0}'.format(contribution.uuid))

    return get_product_jwt(WebAppProduct(addon), contribution)
Пример #6
0
def debug(request, addon):
    if not settings.DEBUG:
        raise http.Http404

    context = {
        'app': addon,
        'inapps': [],
        'urls': {
            'es': '%s/apps/webapp/%s' % (settings.ES_URLS[0], addon.pk)
        },
    }

    if addon.is_premium():
        contribution = Contribution.objects.create(addon=addon)
        context['app_jwt'] = get_product_jwt(
            WebAppProduct(addon),
            contribution,
        )['webpayJWT']

        for inapp in addon.inappproduct_set.all():
            contribution = Contribution.objects.create(
                addon=addon,
                inapp_product=inapp,
            )
            context['inapps'].append({
                'inapp':
                inapp,
                'jwt':
                get_product_jwt(
                    InAppProduct(inapp),
                    contribution,
                )['webpayJWT'],
            })

    return render(request, 'developers/debug.html', context)
Пример #7
0
 def setUp(self):
     super(BaseTestWebAppProduct, self).setUp()
     self.product = WebAppProduct(self.addon)
     self.contribution = Contribution.objects.create(
         user=self.user,
         addon=self.addon,
     )
     self.contribution = Contribution.objects.get()
Пример #8
0
 def setUp(self):
     super(TestPurchaseJWT, self).setUp()
     self.product = WebAppProduct(self.addon)
     self.contribution = Contribution.objects.create(
         user=self.user,
         addon=self.addon,
     )
     self.token = get_product_jwt(self.product, self.contribution)
     self.token_data = jwt.decode(
         str(self.token['webpayJWT']), verify=False)
Пример #9
0
    def setUp(self):
        super(TestWebAppProduct, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.token = get_product_jwt(
            self.product,
            region=regions.US,
            user=self.user,
        )

        self.contribution = Contribution.objects.get()
Пример #10
0
    def post(self, request, *args, **kwargs):
        form = PrepareWebAppForm(request.DATA)
        if not form.is_valid():
            return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)

        app = form.cleaned_data['app']

        region = getattr(request, 'REGION', None)
        if region:
            enabled_regions = app.get_price_region_ids()
            region_can_purchase = region.id in enabled_regions
            restofworld_can_purchase = RESTOFWORLD.id in enabled_regions

            if not region_can_purchase and not restofworld_can_purchase:
                log.info('Region {0} is not in {1}; '
                         'restofworld purchases are inactive'.format(
                             region.id, enabled_regions))
                return Response(
                    {'reason': 'Payments are restricted for this region'},
                    status=status.HTTP_403_FORBIDDEN)

        if app.is_premium() and app.has_purchased(request._request.user):
            log.info('Already purchased: {0}'.format(app.pk))
            return Response({'reason': u'Already purchased app.'},
                            status=status.HTTP_409_CONFLICT)

        app_pay_cef.log(request._request,
                        'Preparing JWT',
                        'preparing_jwt',
                        'Preparing JWT for: {0}'.format(app.pk),
                        severity=3)

        log.debug('Starting purchase of app: {0} by user: {1}'.format(
            app.pk, request._request.user))

        contribution = Contribution.objects.create(
            addon_id=app.pk,
            amount=app.get_price(region=request._request.REGION.id),
            paykey=None,
            price_tier=app.premium.price,
            source=request._request.GET.get('src', ''),
            source_locale=request._request.LANG,
            type=mkt.CONTRIB_PENDING,
            user=request._request.user,
            uuid=str(uuid.uuid4()),
        )

        log.debug('Storing contrib for uuid: {0}'.format(contribution.uuid))

        token = get_product_jwt(WebAppProduct(app), contribution)

        return Response(token, status=status.HTTP_201_CREATED)
Пример #11
0
class TestPurchaseJWT(PurchaseTest):

    def setUp(self):
        super(TestPurchaseJWT, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.token = get_product_jwt(
            self.product,
            region=regions.US,
            user=self.user,
        )

        self.token_data = jwt.decode(
            str(self.token['webpayJWT']), verify=False)

        self.contribution = Contribution.objects.get()

    def test_claims(self):
        verify_claims(self.token_data)

    def test_keys(self):
        verify_keys(self.token_data,
                    ('iss',
                     'typ',
                     'aud',
                     'iat',
                     'exp',
                     'request.name',
                     'request.description',
                     'request.pricePoint',
                     'request.postbackURL',
                     'request.chargebackURL',
                     'request.productData'))

    def test_valid_jwt(self):
        eq_(self.token_data['iss'], settings.APP_PURCHASE_KEY)
        eq_(self.token_data['typ'], settings.APP_PURCHASE_TYP)
        eq_(self.token_data['aud'], settings.APP_PURCHASE_AUD)

        contribution = Contribution.objects.get()
        eq_(contribution.type, amo.CONTRIB_PENDING)
        eq_(contribution.price_tier, self.addon.premium.price)
        eq_(contribution.user, self.user)

        request = self.token_data['request']
        eq_(request['id'], self.product.external_id())
        eq_(request['name'], self.product.name())
        eq_(request['icons'], self.product.icons())
        eq_(request['description'], self.product.description())
        eq_(request['pricePoint'], self.product.price().name)
        eq_(request['postbackURL'], absolutify(reverse('webpay.postback')))
        eq_(request['chargebackURL'], absolutify(reverse('webpay.chargeback')))

        token_product_data = urlparse.parse_qs(request['productData'])
        expected_product_data = urlparse.parse_qs(
            urlencode(self.product.product_data(self.contribution)))
        eq_(token_product_data, expected_product_data)
Пример #12
0
class TestPurchaseJWT(PurchaseTest):

    def setUp(self):
        super(TestPurchaseJWT, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.contribution = Contribution.objects.create(
            user=self.user,
            addon=self.addon,
        )

    def decode_token(self):
        token = get_product_jwt(self.product, self.contribution)
        return jwt.decode(str(token['webpayJWT']), verify=False)

    def test_claims(self):
        verify_claims(self.decode_token())

    def test_keys(self):
        verify_keys(self.decode_token(),
                    ('iss',
                     'typ',
                     'aud',
                     'iat',
                     'exp',
                     'request.name',
                     'request.description',
                     'request.pricePoint',
                     'request.postbackURL',
                     'request.chargebackURL',
                     'request.productData'))

    def test_valid_jwt(self):
        token_data = self.decode_token()
        eq_(token_data['iss'], settings.APP_PURCHASE_KEY)
        eq_(token_data['typ'], settings.APP_PURCHASE_TYP)
        eq_(token_data['aud'], settings.APP_PURCHASE_AUD)

        request = token_data['request']
        eq_(request['id'], self.product.external_id())
        eq_(request['name'], self.product.name())
        eq_(request['icons'], self.product.icons())
        eq_(request['description'], self.product.description())
        eq_(request['pricePoint'], self.product.price().name)
        eq_(request['postbackURL'], absolutify(reverse('webpay.postback')))
        eq_(request['chargebackURL'], absolutify(reverse('webpay.chargeback')))

        token_product_data = urlparse.parse_qs(request['productData'])
        expected_product_data = urlparse.parse_qs(
            urlencode(self.product.product_data(self.contribution)))
        eq_(token_product_data, expected_product_data)

    @raises(ValueError)
    def test_empty_public_id(self):
        self.addon.update(solitude_public_id=None)
        self.decode_token()
Пример #13
0
class TestPurchaseJWT(PurchaseTest):

    def setUp(self):
        super(TestPurchaseJWT, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.contribution = Contribution.objects.create(
            user=self.user,
            addon=self.addon,
        )

    def decode_token(self):
        token = get_product_jwt(self.product, self.contribution)
        return jwt.decode(str(token['webpayJWT']), verify=False)

    def test_claims(self):
        verify_claims(self.decode_token())

    def test_keys(self):
        verify_keys(self.decode_token(),
                    ('iss',
                     'typ',
                     'aud',
                     'iat',
                     'exp',
                     'request.name',
                     'request.description',
                     'request.pricePoint',
                     'request.postbackURL',
                     'request.chargebackURL',
                     'request.productData'))

    def test_valid_jwt(self):
        token_data = self.decode_token()
        eq_(token_data['iss'], settings.APP_PURCHASE_KEY)
        eq_(token_data['typ'], settings.APP_PURCHASE_TYP)
        eq_(token_data['aud'], settings.APP_PURCHASE_AUD)

        request = token_data['request']
        eq_(request['id'], self.product.external_id())
        eq_(request['name'], self.product.name())
        eq_(request['icons'], self.product.icons())
        eq_(request['description'], self.product.description())
        eq_(request['pricePoint'], self.product.price().name)
        eq_(request['postbackURL'], absolutify(reverse('webpay.postback')))
        eq_(request['chargebackURL'], absolutify(reverse('webpay.chargeback')))

        token_product_data = urlparse.parse_qs(request['productData'])
        expected_product_data = urlparse.parse_qs(
            urlencode(self.product.product_data(self.contribution)))
        eq_(token_product_data, expected_product_data)

    @raises(ValueError)
    def test_empty_public_id(self):
        self.addon.update(solitude_public_id=None)
        self.decode_token()
Пример #14
0
    def generic_create(self, account, app, secret):
        # This sets the product up in solitude.
        external_id = WebAppProduct(app).external_id()
        data = {'seller': uri_to_pk(account.seller_uri),
                'external_id': external_id}

        # Create the generic product.
        try:
            generic = self.generic.product.get_object_or_404(**data)
        except ObjectDoesNotExist:
            generic = self.generic.product.post(data={
                'seller': account.seller_uri, 'secret': secret,
                'external_id': external_id, 'public_id': str(uuid.uuid4()),
                'access': ACCESS_PURCHASE,
            })

        return generic
Пример #15
0
def prepare_pay(request, addon):
    if addon.is_premium() and addon.has_purchased(request.amo_user):
        log.info('Already purchased: %d' % addon.pk)
        raise AlreadyPurchased

    app_pay_cef.log(request,
                    'Preparing JWT',
                    'preparing_jwt',
                    'Preparing JWT for: %s' % (addon.pk),
                    severity=3)

    return get_product_jwt(
        WebAppProduct(addon),
        user=request.amo_user,
        region=request.REGION,
        source=request.REQUEST.get('src', ''),
        lang=request.LANG,
        client_data=ClientData.get_or_create(request),
    )
Пример #16
0
class TestPurchaseJWT(PurchaseTest):
    def setUp(self):
        super(TestPurchaseJWT, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.token = get_product_jwt(
            self.product,
            region=regions.US,
            user=self.user,
        )

        self.token_data = jwt.decode(str(self.token['webpayJWT']),
                                     verify=False)

        self.contribution = Contribution.objects.get()

    def test_claims(self):
        verify_claims(self.token_data)

    def test_keys(self):
        verify_keys(self.token_data,
                    ('iss', 'typ', 'aud', 'iat', 'exp', 'request.name',
                     'request.description', 'request.pricePoint',
                     'request.postbackURL', 'request.chargebackURL',
                     'request.productData'))

    def test_valid_jwt(self):
        eq_(self.token_data['iss'], settings.APP_PURCHASE_KEY)
        eq_(self.token_data['typ'], settings.APP_PURCHASE_TYP)
        eq_(self.token_data['aud'], settings.APP_PURCHASE_AUD)

        contribution = Contribution.objects.get()
        eq_(contribution.type, amo.CONTRIB_PENDING)
        eq_(contribution.price_tier, self.addon.premium.price)
        eq_(contribution.user, self.user)

        request = self.token_data['request']
        eq_(request['id'], self.product.external_id())
        eq_(request['name'], self.product.name())
        eq_(request['icons'], self.product.icons())
        eq_(request['description'], self.product.description())
        eq_(request['pricePoint'], self.product.price().name)
        eq_(request['postbackURL'], absolutify(reverse('webpay.postback')))
        eq_(request['chargebackURL'], absolutify(reverse('webpay.chargeback')))

        token_product_data = urlparse.parse_qs(request['productData'])
        expected_product_data = urlparse.parse_qs(
            urlencode(self.product.product_data(self.contribution)))
        eq_(token_product_data, expected_product_data)
Пример #17
0
def debug(request, addon):
    if not settings.DEBUG:
        raise http.Http404

    data = {
        'urls': {
            'es': '%s/apps/webapp/%s' % (settings.ES_URLS[0], addon.pk)
        },
        'pay_request': ''
    }
    if addon.is_premium():
        data['pay_request'] = get_product_jwt(
            WebAppProduct(addon),
            user=request.amo_user,
            region=request.REGION,
            source=request.REQUEST.get('src', ''),
            lang=request.LANG,
            client_data=ClientData.get_or_create(request),
        )['webpayJWT']

    return render(request, 'developers/debug.html', {
        'app': addon,
        'data': data
    })
Пример #18
0
class TestPurchaseJWT(PurchaseTest):
    def setUp(self):
        super(TestPurchaseJWT, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.contribution = Contribution.objects.create(user=self.user, addon=self.addon)

    def decode_token(self):
        token = get_product_jwt(self.product, self.contribution)
        return jwt.decode(str(token["webpayJWT"]), verify=False)

    def test_claims(self):
        verify_claims(self.decode_token())

    def test_keys(self):
        verify_keys(
            self.decode_token(),
            (
                "iss",
                "typ",
                "aud",
                "iat",
                "exp",
                "request.name",
                "request.description",
                "request.pricePoint",
                "request.postbackURL",
                "request.chargebackURL",
                "request.productData",
            ),
        )

    def test_valid_jwt(self):
        token_data = self.decode_token()
        eq_(token_data["iss"], settings.APP_PURCHASE_KEY)
        eq_(token_data["typ"], settings.APP_PURCHASE_TYP)
        eq_(token_data["aud"], settings.APP_PURCHASE_AUD)

        request = token_data["request"]
        eq_(request["id"], self.product.external_id())
        eq_(request["name"], self.product.name())
        eq_(request["defaultLocale"], self.product.default_locale())
        eq_(request["icons"], self.product.icons())
        eq_(request["description"], self.product.description())
        eq_(request["pricePoint"], self.product.price().name)
        eq_(request["postbackURL"], absolutify(reverse("webpay.postback")))
        eq_(request["chargebackURL"], absolutify(reverse("webpay.chargeback")))

        product = urlparse.parse_qs(request["productData"])
        expected = urlparse.parse_qs(urlencode(self.product.product_data(self.contribution)))
        eq_(product["buyer_email"], [self.user.email])
        eq_(product, expected)

    @raises(ValueError)
    def test_empty_public_id(self):
        self.addon.update(solitude_public_id=None)
        self.decode_token()

    def test_no_user(self):
        self.contribution.update(user=None)
        token_data = self.decode_token()
        request = token_data["request"]
        product = urlparse.parse_qs(request["productData"])
        ok_("buyer_email" not in product)

    def test_locales(self):
        with mock.patch.object(self.product, "localized_properties") as props:
            loc_data = {"es": {"name": "El Mocoso", "description": u"descripción de la aplicación"}}
            props.return_value = loc_data
            token_data = self.decode_token()
            # Make sure the JWT passes through localized_properties() data.
            eq_(token_data["request"]["locales"], loc_data)
Пример #19
0
class TestWebAppProduct(PurchaseTest):

    def setUp(self):
        super(TestWebAppProduct, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.token = get_product_jwt(
            self.product,
            region=regions.US,
            user=self.user,
        )

        self.contribution = Contribution.objects.get()

    def test_external_id_with_no_domain(self):
        with self.settings(DOMAIN=None):
            eq_(self.product.external_id(),
                'marketplace-dev:{0}'.format(self.addon.pk))

    def test_external_id_with_domain(self):
        with self.settings(DOMAIN='marketplace.allizom.org'):
            eq_(self.product.external_id(),
                'marketplace:{0}'.format(self.addon.pk))

    def test_webapp_product(self):
        eq_(self.product.id(), self.addon.pk)
        eq_(self.product.name(), unicode(self.addon.name))
        eq_(self.product.addon(), self.addon)
        eq_(self.product.amount(regions.US),
            self.addon.get_price(region=regions.US.id))
        eq_(self.product.price(), self.addon.premium.price)
        eq_(self.product.icons()['512'],
            absolutify(self.addon.get_icon_url(512)))
        eq_(self.product.description(), self.addon.description)
        eq_(self.product.application_size(),
            self.addon.current_version.all_files[0].size)
        eq_(self.product.seller_uuid(), (self.addon
                                             .single_pay_account()
                                             .payment_account
                                             .solitude_seller
                                             .uuid))

        product_data = self.product.product_data(self.contribution)
        eq_(product_data['contrib_uuid'], self.contribution.uuid)
        eq_(product_data['seller_uuid'], self.product.seller_uuid())
        eq_(product_data['addon_id'], self.product.addon().pk)
        eq_(product_data['application_size'], self.product.application_size())
Пример #20
0
class TestPurchaseJWT(PurchaseTest):

    def setUp(self):
        super(TestPurchaseJWT, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.contribution = Contribution.objects.create(
            user=self.user,
            addon=self.addon,
        )

    def decode_token(self):
        token = get_product_jwt(self.product, self.contribution)
        return jwt.decode(str(token['webpayJWT']), verify=False)

    def test_claims(self):
        verify_claims(self.decode_token())

    def test_keys(self):
        verify_keys(self.decode_token(),
                    ('iss',
                     'typ',
                     'aud',
                     'iat',
                     'exp',
                     'request.name',
                     'request.description',
                     'request.pricePoint',
                     'request.postbackURL',
                     'request.chargebackURL',
                     'request.productData'))

    def test_valid_jwt(self):
        token_data = self.decode_token()
        eq_(token_data['iss'], settings.APP_PURCHASE_KEY)
        eq_(token_data['typ'], settings.APP_PURCHASE_TYP)
        eq_(token_data['aud'], settings.APP_PURCHASE_AUD)

        request = token_data['request']
        eq_(request['id'], self.product.external_id())
        eq_(request['name'], self.product.name())
        eq_(request['defaultLocale'], self.product.default_locale())
        eq_(request['icons'], self.product.icons())
        eq_(request['description'], self.product.description())
        eq_(request['pricePoint'], self.product.price().name)
        eq_(request['postbackURL'], absolutify(reverse('webpay.postback')))
        eq_(request['chargebackURL'], absolutify(reverse('webpay.chargeback')))

        product = urlparse.parse_qs(request['productData'])
        expected = urlparse.parse_qs(
            urlencode(self.product.product_data(self.contribution)))
        eq_(product['buyer_email'], [self.user.email])
        eq_(product, expected)

    @raises(ValueError)
    def test_empty_public_id(self):
        self.addon.update(solitude_public_id=None)
        self.decode_token()

    def test_no_user(self):
        self.contribution.update(user=None)
        token_data = self.decode_token()
        request = token_data['request']
        product = urlparse.parse_qs(request['productData'])
        ok_('buyer_email' not in product)

    def test_locales(self):
        with mock.patch.object(self.product, 'localized_properties') as props:
            loc_data = {
                'es': {
                    'name': 'El Mocoso',
                    'description': u'descripción de la aplicación',
                }
            }
            props.return_value = loc_data
            token_data = self.decode_token()
            # Make sure the JWT passes through localized_properties() data.
            eq_(token_data['request']['locales'], loc_data)
Пример #21
0
class TestWebAppProduct(PurchaseTest):
    def setUp(self):
        super(TestWebAppProduct, self).setUp()
        self.product = WebAppProduct(self.addon)
        self.token = get_product_jwt(
            self.product,
            region=regions.US,
            user=self.user,
        )

        self.contribution = Contribution.objects.get()

    def test_external_id_with_no_domain(self):
        with self.settings(DOMAIN=None):
            eq_(self.product.external_id(),
                'marketplace-dev:{0}'.format(self.addon.pk))

    def test_external_id_with_domain(self):
        with self.settings(DOMAIN='marketplace.allizom.org'):
            eq_(self.product.external_id(),
                'marketplace:{0}'.format(self.addon.pk))

    def test_webapp_product(self):
        eq_(self.product.id(), self.addon.pk)
        eq_(self.product.name(), unicode(self.addon.name))
        eq_(self.product.addon(), self.addon)
        eq_(self.product.amount(regions.US),
            self.addon.get_price(region=regions.US.id))
        eq_(self.product.price(), self.addon.premium.price)
        eq_(self.product.icons()['512'],
            absolutify(self.addon.get_icon_url(512)))
        eq_(self.product.description(), self.addon.description)
        eq_(self.product.application_size(),
            self.addon.current_version.all_files[0].size)
        eq_(self.product.seller_uuid(), (self.addon.single_pay_account().
                                         payment_account.solitude_seller.uuid))

        product_data = self.product.product_data(self.contribution)
        eq_(product_data['contrib_uuid'], self.contribution.uuid)
        eq_(product_data['seller_uuid'], self.product.seller_uuid())
        eq_(product_data['public_id'], self.product.public_id())
        eq_(product_data['addon_id'], self.product.addon().pk)
        eq_(product_data['application_size'], self.product.application_size())