Example #1
0
def get_product_jwt(product, contribution):
    """Prepare a JWT for paid products to pass into navigator.pay()"""

    issued_at = calendar.timegm(time.gmtime())

    token_data = {
        'iss': settings.APP_PURCHASE_KEY,
        'typ': settings.APP_PURCHASE_TYP,
        'aud': settings.APP_PURCHASE_AUD,
        'iat': issued_at,
        'exp': issued_at + 3600,  # expires in 1 hour
        'request': {
            'id': product.external_id(),
            'name': unicode(product.name()),
            'icons': product.icons(),
            'description': strip_tags(product.description()),
            'pricePoint': product.price().name,
            'productData': urlencode(product.product_data(contribution)),
            'chargebackURL': absolutify(reverse('webpay.chargeback')),
            'postbackURL': absolutify(reverse('webpay.postback')),
        }
    }

    token = sign_webpay_jwt(token_data)

    log.debug('Preparing webpay JWT for self.product {0}: {1}'.format(
        product.id(), token))

    return {
        'webpayJWT': token,
        'contribStatusURL': reverse(
            'webpay-status',
            kwargs={'uuid': contribution.uuid}
        )
    }
Example #2
0
def create_test_receipt(root, status):
    time_ = calendar.timegm(time.gmtime())
    detail = absolutify(reverse('receipt.test.details'))
    receipt = {
        'detail': absolutify(detail),
        'exp': time_ + (60 * 60 * 24),
        'iat': time_,
        'iss': settings.SITE_URL,
        'nbf': time_,
        'product': {
            'storedata': urlencode({'id': 0}),
            'url': root,
        },
        'reissue': detail,
        'typ': 'test-receipt',
        'user': {
            'type': 'directed-identifier',
            'value': 'none'
        },
        'verify': absolutify(reverse('receipt.test.verify',
                                     kwargs={'status': status}))

    }
    if settings.SIGNING_SERVER_ACTIVE:
        return sign(receipt)
    else:
        return jwt.encode(receipt, get_key(), u'RS512')
Example #3
0
def create_test_receipt(root, status, storedata=None):
    if not storedata:
        storedata = {'id': 0}
    time_ = calendar.timegm(time.gmtime())
    detail = absolutify(reverse('receipt.test.details'))
    receipt = {
        'detail': absolutify(detail),
        'exp': time_ + (60 * 60 * 24),
        'iat': time_,
        'iss': settings.SITE_URL,
        'nbf': time_,
        'product': {
            'storedata': urlencode(storedata),
            'url': root,
        },
        'reissue': detail,
        'typ': 'test-receipt',
        'user': {
            'type': 'directed-identifier',
            'value': 'none'
        },
        'verify': absolutify(reverse('receipt.test.verify',
                                     kwargs={'status': status}))

    }
    return sign(receipt)
Example #4
0
def prepare_pay(request, addon):
    """Prepare a BlueVia JWT to pass into navigator.pay()"""
    amount, currency, uuid_, contrib_for = start_purchase(request, addon)
    log.debug('Storing contrib for uuid: %s' % uuid_)
    Contribution.objects.create(addon_id=addon.id, amount=amount,
                                source=request.REQUEST.get('src', ''),
                                source_locale=request.LANG,
                                uuid=str(uuid_), type=amo.CONTRIB_PENDING,
                                paykey=None, user=request.amo_user,
                                price_tier=addon.premium.price,
                                client_data=ClientData.get_or_create(request))

    prices = [{'currency': cur, 'amount': str(tier.price)}
              for cur, tier in addon.premium.price.currencies()]

    data = {'amount': str(amount),
            'prices': prices, 'currency': currency,
            'app_name': unicode(addon.name),
            'app_description': unicode(addon.description),
            'postback_url': absolutify(reverse('bluevia.postback')),
            'chargeback_url': absolutify(reverse('bluevia.chargeback')),
            'seller': addon.pk,
            'product_data': urlencode({'contrib_uuid': uuid_,
                                       'addon_id': addon.pk}),
            'typ': 'tu.com/payments/inapp/v1',
            'aud': 'tu.com',
            'memo': contrib_for}

    return {'blueviaJWT': prepare_bluevia_pay(data),
            'contribStatusURL': reverse('bluevia.pay_status',
                                        args=[addon.app_slug, uuid_])}
Example #5
0
def prepare_pay(request, addon):
    """Prepare a BlueVia JWT to pass into navigator.pay()"""
    amount, currency, uuid_, contrib_for = start_purchase(request, addon)
    log.debug('Storing contrib for uuid: %s' % uuid_)
    Contribution.objects.create(addon_id=addon.id, amount=amount,
                                source=request.REQUEST.get('src', ''),
                                source_locale=request.LANG,
                                uuid=str(uuid_), type=amo.CONTRIB_PENDING,
                                paykey=None, user=request.amo_user,
                                price_tier=addon.premium.price,
                                client_data=ClientData.get_or_create(request))

    acct = addon.app_payment_account.payment_account
    seller_uuid = acct.solitude_seller.uuid
    data = {'amount': str(amount),
            'price_point': addon.premium.price.pk,
            'id': addon.pk,
            'app_name': unicode(addon.name),
            'app_description': unicode(addon.summary),
            'postback_url': absolutify(reverse('webpay.postback')),
            'chargeback_url': absolutify(reverse('webpay.chargeback')),
            'seller': addon.pk,
            'product_data': urlencode({'contrib_uuid': uuid_,
                                       'seller_uuid': seller_uuid,
                                       'addon_id': addon.pk}),
            'typ': 'tu.com/payments/inapp/v1',
            'aud': 'tu.com',
            'memo': contrib_for}

    jwt_ = prepare_webpay_pay(data)
    log.debug('Preparing webpay JWT for addon %s: %s' % (addon, jwt_))
    return {'webpayJWT': jwt_,
            'contribStatusURL': reverse('webpay.pay_status',
                                        args=[addon.app_slug, uuid_])}
Example #6
0
def create_test_receipt(root, status):
    time_ = calendar.timegm(time.gmtime())
    detail = absolutify(reverse('receipt.test.details'))
    receipt = {
        'detail':
        absolutify(detail),
        'exp':
        time_ + (60 * 60 * 24),
        'iat':
        time_,
        'iss':
        settings.SITE_URL,
        'nbf':
        time_,
        'product': {
            'storedata': urlencode({'id': 0}),
            'url': root,
            'type': 'test'
        },
        'reissue':
        detail,
        'typ':
        'purchase-receipt',
        'user': {
            'type': 'directed-identifier',
            'value': 'none'
        },
        'verify':
        absolutify(reverse('receipt.test.verify', kwargs={'status': status}))
    }
    if settings.SIGNING_SERVER_ACTIVE:
        return sign(receipt)
    else:
        return jwt.encode(receipt, get_key(), u'RS512')
Example #7
0
    def test_addon_license(self):
        """Test for license information in response."""
        addon = Addon.objects.get(id=3615)
        license = addon.current_version.license
        license.name = 'My License'
        license.url = 'someurl'
        license.save()
        api_url = '/en-US/firefox/api/%.1f/addon/3615' % api.CURRENT_VERSION
        response = self.client.get(api_url)
        doc = pq(response.content)
        eq_(doc('license').length, 1)
        eq_(doc('license name').length, 1)
        eq_(doc('license url').length, 1)
        eq_(doc('license name').text(), unicode(license.name))
        eq_(doc('license url').text(), helpers.absolutify(license.url))

        license.url = ''
        license.save()
        addon.save()
        response = self.client.get(api_url)
        doc = pq(response.content)
        license_url = addon.current_version.license_url()
        eq_(doc('license url').text(), helpers.absolutify(license_url))

        license.delete()
        response = self.client.get(api_url)
        doc = pq(response.content)
        eq_(doc('license').length, 0)
Example #8
0
 def setUp(self):
     self.data = {'return_url': absolutify(reverse('home')),
                  'cancel_url': absolutify(reverse('home')),
                  'amount': 10,
                  'email': '*****@*****.**',
                  'uuid': time.time(),
                  'ip': '127.0.0.1'}
Example #9
0
def create_receipt(webapp, user, uuid, flavour=None, contrib=None):
    """
    Creates a receipt for use in payments.

    :params app: the app record.
    :params user: the UserProfile record.
    :params uuid: a uuid placed in the user field for this purchase.
    :params flavour: None, developer, inapp, or reviewer - the flavour
            of receipt.
    :param: contrib: the Contribution object for the purchase.
    """
    # Unflavo(u)red receipts are for plain ol' vanilla app purchases.
    assert flavour in (None, 'developer', 'inapp', 'reviewer'), (
        'Invalid flavour: %s' % flavour)

    time_ = calendar.timegm(time.gmtime())
    typ = 'purchase-receipt'
    storedata = {'id': int(webapp.pk)}

    # Generate different receipts for reviewers or developers.
    expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS
    verify = static_url('WEBAPPS_RECEIPT_URL')

    if flavour == 'inapp':
        if not contrib:
            raise ValueError(
                'a contribution object is required for in-app receipts')
        if not contrib.inapp_product:
            raise ValueError(
                'contribution {c} does not link to an in-app product'
                .format(c=contrib))
        storedata['contrib'] = int(contrib.pk)

    elif flavour in ('developer', 'reviewer'):
        if not (acl.action_allowed_user(user, 'Apps', 'Review') or
                webapp.has_author(user)):
            raise ValueError('User %s is not a reviewer or developer' %
                             user.pk)

        # Developer and reviewer receipts should expire after 24 hours.
        expiry = time_ + (60 * 60 * 24)
        typ = flavour + '-receipt'
        verify = absolutify(reverse('receipt.verify', args=[webapp.guid]))

    product = {'storedata': urlencode(storedata),
               # Packaged and hosted apps should have an origin. If there
               # isn't one, fallback to the SITE_URL.
               'url': webapp.origin or settings.SITE_URL}
    reissue = absolutify(reverse('receipt.reissue'))
    receipt = dict(exp=expiry, iat=time_,
                   iss=settings.SITE_URL, nbf=time_, product=product,
                   # TODO: This is temporary until detail pages get added.
                   # TODO: bug 1020997, bug 1020999
                   detail=absolutify(reissue),  # Currently this is a 404.
                   reissue=absolutify(reissue),
                   typ=typ,
                   user={'type': 'directed-identifier',
                         'value': uuid},
                   verify=verify)
    return sign(receipt)
Example #10
0
def prepare_pay(request, addon):
    """Prepare a BlueVia JWT to pass into navigator.pay()"""
    amount, currency, uuid_, contrib_for = start_purchase(request, addon)
    log.debug('Storing contrib for uuid: %s' % uuid_)
    Contribution.objects.create(addon_id=addon.id, amount=amount,
                                source=request.REQUEST.get('src', ''),
                                source_locale=request.LANG,
                                uuid=str(uuid_), type=amo.CONTRIB_PENDING,
                                paykey=None, user=request.amo_user,
                                price_tier=addon.premium.price,
                                client_data=ClientData.get_or_create(request))
    data = {'amount': str(amount), 'currency': currency,
            'app_name': unicode(addon.name),
            'app_description': unicode(addon.description),
            'postback_url': absolutify(reverse('bluevia.postback')),
            'chargeback_url': absolutify(reverse('bluevia.chargeback')),
            'seller': addon.pk,
            'product_data': urlencode({'contrib_uuid': uuid_,
                                       'addon_id': addon.pk}),
            'typ': 'tu.com/payments/inapp/v1',
            'aud': 'tu.com',
            'memo': contrib_for}

    if waffle.flag_is_active(request, 'solitude-payments'):
        bluevia_jwt = client.prepare_bluevia_pay(data)
    else:
        bluevia_jwt = prepare_bluevia_pay(data)
    return {'blueviaJWT': bluevia_jwt,
            'contribStatusURL': reverse('bluevia.pay_status',
                                        args=[addon.app_slug, uuid_])}
Example #11
0
    def test_suggestions(self):
        app1 = Webapp.objects.get(pk=337141)
        app1.save()
        app2 = app_factory(name=u"Second âpp",
                           description=u"Second dèsc" * 25,
                           created=self.days_ago(3))
        self.refresh('webapp')

        response = self.client.get(self.url)
        parsed = json.loads(response.content)
        eq_(parsed[0], '')
        self.assertSetEqual(
            parsed[1],
            [unicode(app1.name), unicode(app2.name)])
        self.assertSetEqual(
            parsed[2],
            [unicode(app1.description),
             unicode(truncate(app2.description))])
        self.assertSetEqual(parsed[3], [
            absolutify(app1.get_detail_url()),
            absolutify(app2.get_detail_url())
        ])
        self.assertSetEqual(parsed[4],
                            [app1.get_icon_url(64),
                             app2.get_icon_url(64)])

        # Cleanup to remove these from the index.
        unindex_webapps([app1.id, app2.id])
        app1.delete()
        app2.delete()
Example #12
0
def create_test_receipt(root, status):
    time_ = calendar.timegm(time.gmtime())
    detail = absolutify(reverse('receipt.test.details'))
    receipt = {
        'detail':
        absolutify(detail),
        'exp':
        time_ + (60 * 60 * 24),
        'iat':
        time_,
        'iss':
        settings.SITE_URL,
        'nbf':
        time_,
        'product': {
            'storedata': urlencode({'id': 0}),
            'url': root,
        },
        'reissue':
        detail,
        'typ':
        'test-receipt',
        'user': {
            'type': 'directed-identifier',
            'value': 'none'
        },
        'verify':
        absolutify(reverse('receipt.test.verify', kwargs={'status': status}))
    }
    return sign(receipt)
Example #13
0
 def get_context_data(self):
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             app = Webapp.objects.get(id=self.addon.id)
     else:
         app = self.addon
     return {
         'name':
         app.name,
         'reviewer':
         self.request.user.get_profile().name,
         'detail_url':
         absolutify(app.get_url_path(add_prefix=False)),
         'review_url':
         absolutify(
             reverse('reviewers.apps.review',
                     args=[app.app_slug],
                     add_prefix=False)),
         'status_url':
         absolutify(app.get_dev_url('versions')),
         'comments':
         self.data['comments'],
         'MKT_SUPPORT_EMAIL':
         settings.MKT_SUPPORT_EMAIL,
         'SITE_URL':
         settings.SITE_URL
     }
Example #14
0
def send_purchase_receipt(contrib_id, **kw):
    """
    Sends an email to the purchaser of the app.
    """
    contrib = Contribution.objects.get(pk=contrib_id)

    with contrib.user.activate_lang():
        addon = contrib.addon
        version = addon.current_version or addon.latest_version
        # L10n: {0} is the app name.
        subject = _('Receipt for {0}').format(contrib.addon.name)
        data = {
            'app_name': addon.name,
            'developer_name': version.developer_name if version else '',
            'price': contrib.get_amount_locale(get_locale_from_lang(
                contrib.source_locale)),
            'date': datetime(contrib.created.date()),
            'purchaser_email': contrib.user.email,
            #'purchaser_phone': '',  # TODO: See bug 894614.
            #'purchaser_last_four': '',
            'transaction_id': contrib.uuid,
            'purchases_url': absolutify('/purchases'),
            'support_url': addon.support_url,
            'terms_of_service_url': absolutify('/terms-of-use'),
        }

        log.info('Sending email about purchase: %s' % contrib_id)
        text_template = 'purchase/receipt.ltxt'
        html_template = 'purchase/receipt.html'
        send_html_mail_jinja(subject, html_template, text_template, data,
                             recipient_list=[contrib.user.email])
Example #15
0
def get_paykey(data):
    """
    Gets a paykey from Paypal. Need to pass in the following in data:
    pattern: the reverse pattern to resolve
    email: who the money is going to (required)
    amount: the amount of money (required)
    ip: ip address of end user (required)
    uuid: contribution_uuid (required)
    memo: any nice message (optional)
    qs: anything you want to append to the complete or cancel (optional)
    currency: valid paypal currency, defaults to USD (optional)
    """
    if data["pattern"]:
        complete = reverse(data["pattern"], args=[data["slug"], "complete"])
        cancel = reverse(data["pattern"], args=[data["slug"], "cancel"])
    else:
        # If there's no pattern given, just fake some urls.
        complete = cancel = settings.SITE_URL + "/paypal/dummy/"

    qs = {"uuid": data["uuid"]}
    if "qs" in data:
        qs.update(data["qs"])
    uuid_qs = urllib.urlencode(qs)

    paypal_data = {
        "actionType": "PAY",
        "currencyCode": data.get("currency", "USD"),
        "cancelUrl": absolutify("%s?%s" % (cancel, uuid_qs)),
        "returnUrl": absolutify("%s?%s" % (complete, uuid_qs)),
        "trackingId": data["uuid"],
        "ipnNotificationUrl": absolutify(reverse("amo.paypal")),
    }

    receivers = (data.get("chains", ()), data["email"], data["amount"], data["uuid"])

    if data.get("preapproval"):
        # The paypal_key might be empty if they have removed it.
        key = data["preapproval"].paypal_key
        if key:
            paypal_log.info("Using preapproval: %s" % data["preapproval"].pk)
            paypal_data["preapprovalKey"] = key

    paypal_data.update(add_receivers(*receivers, preapproval="preapprovalKey" in paypal_data))

    if data.get("memo"):
        paypal_data["memo"] = data["memo"]

    try:
        with statsd.timer("paypal.paykey.retrieval"):
            response = _call(settings.PAYPAL_PAY_URL + "Pay", paypal_data, ip=data["ip"])
    except PreApprovalError, e:
        # Let's retry just once without preapproval.
        paypal_log.error("Failed using preapproval, reason: %s" % e)
        # Now it's not a pre-approval, make sure we get the
        # DIGITALGOODS setting back in there.
        del paypal_data["preapprovalKey"]
        paypal_data.update(add_receivers(*receivers))
        # If this fails, we won't try again, just fail.
        with statsd.timer("paypal.paykey.retrieval"):
            response = _call(settings.PAYPAL_PAY_URL + "Pay", paypal_data, ip=data["ip"])
Example #16
0
 def send_notification(self, version):
     user_log.info('Sending addon update notice to %s for %s' %
                   (self.user.email, self.addon.pk))
     context = Context({
         'name':
         self.addon.name,
         'url':
         absolutify(
             reverse('addons.detail',
                     args=[self.addon.pk],
                     add_prefix=False)),
         'number':
         version.version,
         'review':
         absolutify(
             reverse('editors.review',
                     args=[self.addon.pk],
                     add_prefix=False)),
         'SITE_URL':
         settings.SITE_URL,
     })
     # Not being localised because we don't know the editors locale.
     subject = 'Mozilla Add-ons: %s Updated' % self.addon.name
     template = loader.get_template('editors/emails/notify_update.ltxt')
     send_mail(subject,
               template.render(Context(context)),
               recipient_list=[self.user.email],
               from_email=settings.EDITORS_EMAIL,
               use_blacklist=False)
Example #17
0
def get_preapproval_key(data):
    """
    Get a preapproval key from PayPal. If this passes, you get a key that
    you can use in a redirect to PayPal.
    """
    paypal_data = {
        'currencyCode': 'USD',
        'startingDate': data['startDate'].strftime('%Y-%m-%d'),
        'endingDate': data['endDate'].strftime('%Y-%m-%d'),
        'maxTotalAmountOfAllPayments': str(data.get('maxAmount', '2000')),
        'returnUrl': absolutify(reverse(data['pattern'], args=['complete'])),
        'cancelUrl': absolutify(reverse(data['pattern'], args=['cancel'])),
    }
    if settings.PAYPAL_LIMIT_PREAPPROVAL:
        paypal_data.update({
            'maxAmountPerPayment': 15,
            'maxNumberOfPaymentsPerPeriod': 15,
            'paymentPeriod': 'DAILY',
        })

    with statsd.timer('paypal.preapproval.token'):
        response = _call(settings.PAYPAL_PAY_URL + 'Preapproval', paypal_data,
                         ip=data.get('ip'))

    return response
Example #18
0
def get_preapproval_key(data):
    """
    Get a preapproval key from PayPal. If this passes, you get a key that
    you can use in a redirect to PayPal.
    """
    paypal_data = {
        'currencyCode': 'USD',
        'startingDate': data['startDate'].strftime('%Y-%m-%d'),
        'endingDate': data['endDate'].strftime('%Y-%m-%d'),
        'maxTotalAmountOfAllPayments': str(data.get('maxAmount', '2000')),
        'returnUrl': absolutify(reverse(data['pattern'], args=['complete'])),
        'cancelUrl': absolutify(reverse(data['pattern'], args=['cancel'])),
    }
    if settings.PAYPAL_LIMIT_PREAPPROVAL:
        paypal_data.update({
            'maxAmountPerPayment': 15,
            'maxNumberOfPaymentsPerPeriod': 15,
            'paymentPeriod': 'DAILY',
        })

    with statsd.timer('paypal.preapproval.token'):
        response = _call(settings.PAYPAL_PAY_URL + 'Preapproval',
                         paypal_data,
                         ip=data.get('ip'))

    return response
Example #19
0
def create_receipt(installed_pk):
    installed = Installed.objects.get(pk=installed_pk)
    addon_pk = installed.addon.pk
    verify = '%s%s' % (settings.WEBAPPS_RECEIPT_URL, addon_pk)
    detail = reverse('account.purchases.receipt', args=[addon_pk])
    reissue = installed.addon.get_purchase_url('reissue')
    time_ = calendar.timegm(time.gmtime())
    receipt = dict(typ='purchase-receipt',
                   product={'url': installed.addon.origin,
                            'storedata': urlencode({'id': int(addon_pk)})},
                   user={'type': 'directed-identifier',
                         'value': installed.uuid},
                   iss=settings.SITE_URL,
                   nbf=time_,
                   iat=time_,
                   exp=(time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS),
                   detail=absolutify(detail),
                   verify=absolutify(verify),
                   reissue=absolutify(reissue))
    if settings.SIGNING_SERVER_ACTIVE:
        # The shiny new code.
        return sign(receipt)
    else:
        # Our old bad code.
        return jwt.encode(receipt, get_key(), u'RS512')
Example #20
0
    def test_addon_license(self):
        """Test for license information in response."""
        addon = Addon.objects.get(id=3615)
        license = addon.current_version.license
        license.name = 'My License'
        license.url = 'someurl'
        license.save()
        api_url = '/en-US/firefox/api/%.1f/addon/3615' % api.CURRENT_VERSION
        response = self.client.get(api_url)
        doc = pq(response.content)
        eq_(doc('license').length, 1)
        eq_(doc('license name').length, 1)
        eq_(doc('license url').length, 1)
        eq_(doc('license name').text(), unicode(license.name))
        eq_(doc('license url').text(), helpers.absolutify(license.url))

        license.url = ''
        license.save()
        addon.save()
        response = self.client.get(api_url)
        doc = pq(response.content)
        license_url = addon.current_version.license_url()
        eq_(doc('license url').text(), helpers.absolutify(license_url))

        license.delete()
        response = self.client.get(api_url)
        doc = pq(response.content)
        eq_(doc('license').length, 0)
Example #21
0
def prepare_pay(request, addon):
    """Prepare a BlueVia JWT to pass into navigator.pay()"""
    amount, currency, uuid_, contrib_for = start_purchase(request, addon)
    log.debug('Storing contrib for uuid: %s' % uuid_)
    Contribution.objects.create(addon_id=addon.id, amount=amount,
                                source=request.REQUEST.get('src', ''),
                                source_locale=request.LANG,
                                uuid=str(uuid_), type=amo.CONTRIB_PENDING,
                                paykey=None, user=request.amo_user,
                                price_tier=addon.premium.price,
                                client_data=ClientData.get_or_create(request))

    prices = [{'currency': cur,
               'country': 'XX',  # This is unused but required!
               'amount': str(tier.price)}
              for cur, tier in addon.premium.price.currencies()]

    data = {'amount': str(amount),
            'prices': prices, 'currency': currency,
            'app_name': unicode(addon.name),
            'app_description': unicode(addon.description),
            'postback_url': absolutify(reverse('webpay.postback')),
            'chargeback_url': absolutify(reverse('webpay.chargeback')),
            'seller': addon.pk,
            'product_data': urlencode({'contrib_uuid': uuid_,
                                       'addon_id': addon.pk}),
            'typ': 'tu.com/payments/inapp/v1',
            'aud': 'tu.com',
            'memo': contrib_for}

    return {'webpayJWT': prepare_webpay_pay(data),
            'contribStatusURL': reverse('webpay.pay_status',
                                        args=[addon.app_slug, uuid_])}
Example #22
0
    def test_prepare_pay(self):
        from mkt.purchase.webpay import make_ext_id

        data = self.post(self.prepare_pay)
        cn = Contribution.objects.get()
        eq_(cn.type, amo.CONTRIB_PENDING)
        eq_(cn.user, self.user)
        eq_(cn.price_tier, self.price)

        data = jwt.decode(data["webpayJWT"].encode("ascii"), verify=False)
        eq_(data["typ"], settings.APP_PURCHASE_TYP)
        eq_(data["aud"], settings.APP_PURCHASE_AUD)
        req = data["request"]
        eq_(req["pricePoint"], self.price.name)
        eq_(req["id"], make_ext_id(self.addon.pk))
        eq_(req["name"], unicode(self.addon.name))
        eq_(req["description"], unicode(self.addon.description))
        eq_(req["postbackURL"], absolutify(reverse("webpay.postback")))
        eq_(req["chargebackURL"], absolutify(reverse("webpay.chargeback")))
        eq_(req["icons"]["512"], absolutify(self.addon.get_icon_url(512)))
        pd = urlparse.parse_qs(req["productData"])
        eq_(pd["contrib_uuid"][0], cn.uuid)
        eq_(pd["seller_uuid"][0], self.seller.uuid)
        eq_(pd["addon_id"][0], str(self.addon.pk))
        eq_(pd["application_size"][0], "388096")
Example #23
0
def send_purchase_receipt(contrib_id, **kw):
    """
    Sends an email to the purchaser of the app.
    """
    contrib = Contribution.objects.get(pk=contrib_id)
    with contrib.user.activate_lang():
        # L10n: {0} is the app name.
        subject = _('Receipt for {0}') % contrib.addon.name
        data = {
            'app_name':
            contrib.addon.name,
            'authors':
            ', '.join([
                author.display_name for author in contrib.addon.authors.all()
            ]),
            'date':
            datetime(contrib.created.date()),
            'purchases':
            absolutify(reverse('account.purchases')),
            'support_url':
            contrib.addon.support_url,
            'terms_of_service_url':
            absolutify(reverse('site.terms')),
            'transaction_id':
            contrib.uuid
        }

        log.info('Sending email about purchase: %s' % contrib_id)
        send_mail_jinja(subject,
                        'purchase/receipt.txt',
                        data,
                        recipient_list=[contrib.user.email])
Example #24
0
def send_purchase_receipt(contrib_id, **kw):
    """
    Sends an email to the purchaser of the app.
    """
    contrib = Contribution.objects.get(pk=contrib_id)

    with contrib.user.activate_lang():
        addon = contrib.addon
        version = addon.current_version or addon.latest_version
        # L10n: {0} is the app name.
        subject = _('Receipt for {0}').format(contrib.addon.name)
        data = {
            'app_name': addon.name,
            'developer_name': version.developer_name if version else '',
            'price': contrib.get_amount_locale(get_locale_from_lang(
                contrib.source_locale)),
            'date': jingo.helpers.datetime(contrib.created.date()),
            'purchaser_email': contrib.user.email,
            #'purchaser_phone': '',  # TODO: See bug 894614.
            #'purchaser_last_four': '',
            'transaction_id': contrib.uuid,
            'purchases_url': absolutify('/purchases'),
            'support_url': addon.support_url,
            'terms_of_service_url': absolutify('/terms-of-use'),
        }

        log.info('Sending email about purchase: %s' % contrib_id)
        text_template = 'purchase/receipt.ltxt'
        html_template = 'purchase/receipt.html'
        send_html_mail_jinja(subject, html_template, text_template, data,
                             recipient_list=[contrib.user.email])
Example #25
0
def _prepare_pay(request, addon):
    """Prepare a JWT to pass into navigator.pay()"""
    if addon.is_premium() and addon.has_purchased(request.amo_user):
        log.info('Already purchased: %d' % addon.pk)
        raise AlreadyPurchased

    amount, currency, uuid_, contrib_for = start_purchase(request, addon)
    log.debug('Storing contrib for uuid: %s' % uuid_)
    Contribution.objects.create(addon_id=addon.id, amount=amount,
                                source=request.REQUEST.get('src', ''),
                                source_locale=request.LANG,
                                uuid=str(uuid_), type=amo.CONTRIB_PENDING,
                                paykey=None, user=request.amo_user,
                                price_tier=addon.premium.price,
                                client_data=ClientData.get_or_create(request))

    # Until atob() supports encoded HTML we are stripping all tags.
    # See bug 831524
    app_description = bleach.clean(unicode(addon.description), strip=True,
                                   tags=[])

    acct = addon.app_payment_account.payment_account
    seller_uuid = acct.solitude_seller.uuid
    application_size = addon.current_version.all_files[0].size
    issued_at = calendar.timegm(time.gmtime())
    icons = {}
    for size in amo.ADDON_ICON_SIZES:
        icons[str(size)] = absolutify(addon.get_icon_url(size))
    req = {
        'iss': settings.APP_PURCHASE_KEY,
        'typ': settings.APP_PURCHASE_TYP,
        'aud': settings.APP_PURCHASE_AUD,
        'iat': issued_at,
        'exp': issued_at + 3600,  # expires in 1 hour
        'request': {
            'name': unicode(addon.name),
            'description': app_description,
            'pricePoint': addon.premium.price.name,
            'id': make_ext_id(addon.pk),
            'postbackURL': absolutify(reverse('webpay.postback')),
            'chargebackURL': absolutify(reverse('webpay.chargeback')),
            'productData': urlencode({'contrib_uuid': uuid_,
                                      'seller_uuid': seller_uuid,
                                      'addon_id': addon.pk,
                                      'application_size': application_size}),
            'icons': icons,
        }
    }

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

    if request.API:
        url = reverse('webpay-status', kwargs={'uuid': uuid_})
    else:
        url = reverse('webpay.pay_status', args=[addon.app_slug, uuid_])
    return {'webpayJWT': jwt_, 'contribStatusURL': url}
Example #26
0
def get_product_jwt(product,
                    user=None,
                    region=None,
                    source=None,
                    lang=None,
                    client_data=None):
    """Prepare a JWT for paid products to pass into navigator.pay()"""

    # TODO: Contribution should be created outside of the JWT producer
    contribution = Contribution.objects.create(
        addon_id=product.addon().pk,
        amount=product.amount(region),
        client_data=client_data,
        paykey=None,
        price_tier=product.price(),
        source=source,
        source_locale=lang,
        type=amo.CONTRIB_PENDING,
        user=user,
        uuid=str(uuid.uuid4()),
    )

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

    user_id = user.pk if user else None
    log.debug('Starting purchase of app: {0} by user: {1}'.format(
        product.id(), user_id))

    issued_at = calendar.timegm(time.gmtime())

    token_data = {
        'iss': settings.APP_PURCHASE_KEY,
        'typ': settings.APP_PURCHASE_TYP,
        'aud': settings.APP_PURCHASE_AUD,
        'iat': issued_at,
        'exp': issued_at + 3600,  # expires in 1 hour
        'request': {
            'id': product.external_id(),
            'name': unicode(product.name()),
            'icons': product.icons(),
            'description': strip_tags(product.description()),
            'pricePoint': product.price().name,
            'productData': urlencode(product.product_data(contribution)),
            'chargebackURL': absolutify(reverse('webpay.chargeback')),
            'postbackURL': absolutify(reverse('webpay.postback')),
        }
    }

    token = sign_webpay_jwt(token_data)

    log.debug('Preparing webpay JWT for self.product {0}: {1}'.format(
        product.id(), token))

    return {
        'webpayJWT':
        token,
        'contribStatusURL':
        reverse('webpay-status', kwargs={'uuid': contribution.uuid})
    }
Example #27
0
def get_paykey(data):
    """
    Gets a paykey from Paypal. Need to pass in the following in data:
    pattern: the reverse pattern to resolve
    email: who the money is going to (required)
    amount: the amount of money (required)
    ip: ip address of end user (required)
    uuid: contribution_uuid (required)
    memo: any nice message (optional)
    qs: anything you want to append to the complete or cancel (optional)
    currency: valid paypal currency, defaults to USD (optional)
    """
    complete = reverse(data['pattern'], args=[data['slug'], 'complete'])
    cancel = reverse(data['pattern'], args=[data['slug'], 'cancel'])

    qs = {'uuid': data['uuid']}
    if 'qs' in data:
        qs.update(data['qs'])
    uuid_qs = urllib.urlencode(qs)

    paypal_data = {
        'actionType': 'PAY',
        'currencyCode': data.get('currency', 'USD'),
        'cancelUrl': absolutify('%s?%s' % (cancel, uuid_qs)),
        'returnUrl': absolutify('%s?%s' % (complete, uuid_qs)),
        'trackingId': data['uuid'],
        'ipnNotificationUrl': absolutify(reverse('amo.paypal'))}

    receivers = (data.get('chains', ()), data['email'], data['amount'],
                 data['uuid'])

    if data.get('preapproval'):
        # The paypal_key might be empty if they have removed it.
        key = data['preapproval'].paypal_key
        if key:
            paypal_log.info('Using preapproval: %s' % data['preapproval'].pk)
            paypal_data['preapprovalKey'] = key

    paypal_data.update(add_receivers(*receivers,
                                preapproval='preapprovalKey' in paypal_data))

    if data.get('memo'):
        paypal_data['memo'] = data['memo']

    try:
        with statsd.timer('paypal.paykey.retrieval'):
            response = _call(settings.PAYPAL_PAY_URL + 'Pay', paypal_data,
                             ip=data['ip'])
    except PreApprovalError, e:
        # Let's retry just once without preapproval.
        paypal_log.error('Failed using preapproval, reason: %s' % e)
        # Now it's not a pre-approval, make sure we get the
        # DIGITALGOODS setting back in there.
        del paypal_data['preapprovalKey']
        paypal_data.update(add_receivers(*receivers))
        # If this fails, we won't try again, just fail.
        with statsd.timer('paypal.paykey.retrieval'):
            response = _call(settings.PAYPAL_PAY_URL + 'Pay', paypal_data,
                             ip=data['ip'])
Example #28
0
 def test_preapproval_patterns(self, _call):
     _call.return_value = good_preapproval_string
     data = self.get_data()
     paypal.get_preapproval_key(data)
     eq_(_call.call_args[0][1]['cancelUrl'],
         absolutify(reverse(data['pattern'], args=['cancel'])))
     eq_(_call.call_args[0][1]['returnUrl'],
         absolutify(reverse(data['pattern'], args=['complete'])))
Example #29
0
 def test_preapproval_patterns(self, _call):
     _call.return_value = good_preapproval_string
     data = self.get_data()
     paypal.get_preapproval_key(data)
     eq_(_call.call_args[0][1]['cancelUrl'],
         absolutify(reverse(data['pattern'], args=['cancel'])))
     eq_(_call.call_args[0][1]['returnUrl'],
         absolutify(reverse(data['pattern'], args=['complete'])))
Example #30
0
 def test_suggestions(self):
     response = self.client.get(self.url, data={"lang": "en-US"})
     parsed = json.loads(response.content)
     eq_(parsed[0], "")
     self.assertSetEqual(parsed[1], [unicode(self.app1.name), unicode(self.app2.name)])
     self.assertSetEqual(parsed[2], [unicode(self.app1.description), unicode(truncate(self.app2.description))])
     self.assertSetEqual(parsed[3], [absolutify(self.app1.get_detail_url()), absolutify(self.app2.get_detail_url())])
     self.assertSetEqual(parsed[4], [self.app1.get_icon_url(64), self.app2.get_icon_url(64)])
Example #31
0
def notify_compatibility(users, job, data, **kw):
    log.info('[%s@%s] Sending notification mail for job %s.'
             % (len(users), notify_compatibility.rate_limit, job.pk))
    set_user(get_task_user())
    dry_run = data['preview_only']
    app_id = job.target_version.application.pk
    stats = collections.defaultdict(int)
    stats['processed'] = 0
    stats['is_dry_run'] = int(dry_run)

    for user in users:
        stats['processed'] += 1

        for a in chain(user.passing_addons, user.failing_addons):
            results = job.result_set.filter(file__version__addon=a)

            a.links = ' '.join(absolutify(reverse('devhub.bulk_compat_result',
                                                  args=[a.slug, r.pk]))
                               for r in results)

            a.compat_link = absolutify(reverse('devhub.versions.edit',
                                               args=[a.pk,
                                                     a.current_version.pk]))


        context = Context({
            'APPLICATION': str(job.application),
            'VERSION': job.target_version.version,
            'PASSING_ADDONS': user.passing_addons,
            'FAILING_ADDONS': user.failing_addons,
        })

        log.info(u'Emailing %s%s for %d addons about '
                 'bulk validation job %s'
                 % (user.email,
                    ' [PREVIEW]' if dry_run else '',
                    len(user.passing_addons) + len(user.failing_addons),
                    job.pk))
        args = (Template(data['subject']).render(context),
                Template(data['text']).render(context))
        kwargs = dict(from_email=settings.DEFAULT_FROM_EMAIL,
                      recipient_list=[user.email])
        if dry_run:
            job.preview_notify_mail(*args, **kwargs)
        else:
            stats['author_emailed'] += 1
            send_mail(*args, **kwargs)
            amo.log(amo.LOG.BULK_VALIDATION_USER_EMAILED,
                    user,
                    details={'passing': [a.id for a in user.passing_addons],
                             'failing': [a.id for a in user.failing_addons],
                             'target': job.target_version.version,
                             'application': app_id})

    log.info('[%s@%s] bulk email stats for job %s: {%s}'
             % (len(users), notify_compatibility.rate_limit, job.pk,
                ', '.join('%s: %s' % (k, stats[k])
                          for k in sorted(stats.keys()))))
Example #32
0
def get_product_jwt(product, user=None, region=None,
                    source=None, lang=None, client_data=None):
    """Prepare a JWT for paid products to pass into navigator.pay()"""

    # TODO: Contribution should be created outside of the JWT producer
    contribution = Contribution.objects.create(
        addon_id=product.addon().pk,
        amount=product.amount(region),
        client_data=client_data,
        paykey=None,
        price_tier=product.price(),
        source=source,
        source_locale=lang,
        type=amo.CONTRIB_PENDING,
        user=user,
        uuid=str(uuid.uuid4()),
    )

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

    user_id = user.pk if user else None
    log.debug('Starting purchase of app: {0} by user: {1}'.format(
        product.id(), user_id))

    issued_at = calendar.timegm(time.gmtime())

    token_data = {
        'iss': settings.APP_PURCHASE_KEY,
        'typ': settings.APP_PURCHASE_TYP,
        'aud': settings.APP_PURCHASE_AUD,
        'iat': issued_at,
        'exp': issued_at + 3600,  # expires in 1 hour
        'request': {
            'id': product.external_id(),
            'name': unicode(product.name()),
            'icons': product.icons(),
            'description': strip_tags(product.description()),
            'pricePoint': product.price().name,
            'productData': urlencode(product.product_data(contribution)),
            'chargebackURL': absolutify(reverse('webpay.chargeback')),
            'postbackURL': absolutify(reverse('webpay.postback')),
        }
    }

    token = sign_webpay_jwt(token_data)

    log.debug('Preparing webpay JWT for self.product {0}: {1}'.format(
        product.id(), token))

    return {
        'webpayJWT': token,
        'contribStatusURL': reverse(
            'webpay-status',
            kwargs={
                'uuid': contribution.uuid
            }
        )
    }
Example #33
0
 def setUp(self):
     self.data = {
         'return_url': absolutify(reverse('home')),
         'cancel_url': absolutify(reverse('home')),
         'amount': 10,
         'email': '*****@*****.**',
         'uuid': time.time(),
         'ip': '127.0.0.1'
     }
Example #34
0
 def get_context_data(self):
     return {
         "name": self.addon.name,
         "number": self.version.version,
         "reviewer": (self.request.user.display_name),
         "addon_url": absolutify(self.addon.get_url_path(add_prefix=False)),
         "review_url": absolutify(reverse("editors.review", args=[self.addon.pk], add_prefix=False)),
         "comments": self.data["comments"],
         "SITE_URL": settings.SITE_URL,
     }
Example #35
0
 def get_context_data(self):
     return {
         "name": self.addon.name,
         "reviewer": self.request.user.get_profile().name,
         "detail_url": absolutify(self.addon.get_url_path(add_prefix=False)),
         "review_url": absolutify(reverse("reviewers.apps.review", args=[self.addon.app_slug], add_prefix=False)),
         "status_url": absolutify(self.addon.get_dev_url("versions")),
         "comments": self.data["comments"],
         "MKT_SUPPORT_EMAIL": settings.MKT_SUPPORT_EMAIL,
         "SITE_URL": settings.SITE_URL,
     }
Example #36
0
 def get_context_data(self):
     return {'name': self.addon.name,
             'number': self.version.version,
             'reviewer': (self.request.user.display_name),
             'addon_url': absolutify(
                 self.addon.get_url_path(add_prefix=False)),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data['comments'],
             'SITE_URL': settings.SITE_URL}
Example #37
0
 def get_context_data(self):
     return {'name': self.addon.name,
             'number': self.version.version,
             'reviewer': (self.request.user.display_name),
             'addon_url': absolutify(
                 self.addon.get_url_path(add_prefix=False)),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data['comments'],
             'SITE_URL': settings.SITE_URL}
Example #38
0
def create_receipt(webapp, user, uuid, flavour=None):
    """
    Creates a receipt for use in payments.

    :params app: the app record.
    :params user: the UserProfile record.
    :params uuid: a uuid placed in the user field for this purchase.
    :params flavour: None, developer or reviewer, the flavour of receipt.
    """
    assert flavour in [None, 'developer',
                       'reviewer'], ('Invalid flavour: %s' % flavour)

    time_ = calendar.timegm(time.gmtime())
    typ = 'purchase-receipt'

    product = {
        'storedata': urlencode({'id': int(webapp.pk)}),
        # Packaged and hosted apps should have an origin. If there
        # isn't one, fallback to the SITE_URL.
        'url': webapp.origin or settings.SITE_URL
    }

    # Generate different receipts for reviewers or developers.
    expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS
    if flavour:
        if not (acl.action_allowed_user(user, 'Apps', 'Review')
                or webapp.has_author(user)):
            raise ValueError('User %s is not a reviewer or developer' %
                             user.pk)

        # Developer and reviewer receipts should expire after 24 hours.
        expiry = time_ + (60 * 60 * 24)
        typ = flavour + '-receipt'
        verify = absolutify(reverse('receipt.verify', args=[webapp.guid]))
    else:
        verify = settings.WEBAPPS_RECEIPT_URL

    reissue = absolutify(reverse('receipt.reissue'))
    receipt = dict(
        exp=expiry,
        iat=time_,
        iss=settings.SITE_URL,
        nbf=time_,
        product=product,
        # TODO: This is temporary until detail pages get added.
        detail=absolutify(reissue),  # Currently this is a 404.
        reissue=absolutify(reissue),
        typ=typ,
        user={
            'type': 'directed-identifier',
            'value': uuid
        },
        verify=verify)
    return sign(receipt)
Example #39
0
 def get_context_data(self):
     return {'name': self.addon.name,
             'reviewer': self.request.user.get_profile().name,
             'detail_url': absolutify(
                 self.addon.get_url_path(add_prefix=False)),
             'review_url': absolutify(reverse('reviewers.apps.review',
                                              args=[self.addon.app_slug],
                                              add_prefix=False)),
             'status_url': absolutify(self.addon.get_dev_url('versions')),
             'comments': self.data['comments'],
             'MKT_SUPPORT_EMAIL': settings.MKT_SUPPORT_EMAIL,
             'SITE_URL': settings.SITE_URL}
Example #40
0
 def get_context_data(self):
     return {'name': self.addon.name,
             'reviewer': self.request.user.get_profile().name,
             'detail_url': absolutify(
                 self.addon.get_url_path(add_prefix=False)),
             'review_url': absolutify(reverse('reviewers.apps.review',
                                              args=[self.addon.app_slug],
                                              add_prefix=False)),
             'status_url': absolutify(self.addon.get_dev_url('versions')),
             'comments': self.data['comments'],
             'MKT_SUPPORT_EMAIL': settings.MKT_SUPPORT_EMAIL,
             'SITE_URL': settings.SITE_URL}
Example #41
0
def create_receipt(installed, flavour=None):
    assert flavour in [None, 'developer',
                       'reviewer'], ('Invalid flavour: %s' % flavour)

    webapp = installed.addon
    time_ = calendar.timegm(time.gmtime())
    typ = 'purchase-receipt'

    product = {
        'storedata': urlencode({'id': int(webapp.pk)}),
        # Packaged and hosted apps should have an origin. If there
        # isn't one, fallback to the SITE_URL.
        'url': webapp.origin or settings.SITE_URL
    }

    # Generate different receipts for reviewers or developers.
    expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS
    if flavour:
        if not (acl.action_allowed_user(installed.user, 'Apps', 'Review')
                or webapp.has_author(installed.user)):
            raise ValueError('User %s is not a reviewer or developer' %
                             installed.user.pk)

        # Developer and reviewer receipts should expire after 24 hours.
        expiry = time_ + (60 * 60 * 24)
        typ = flavour + '-receipt'
        verify = absolutify(reverse('receipt.verify', args=[webapp.guid]))
    else:
        verify = settings.WEBAPPS_RECEIPT_URL

    reissue = absolutify(reverse('receipt.reissue'))
    receipt = dict(
        exp=expiry,
        iat=time_,
        iss=settings.SITE_URL,
        nbf=time_,
        product=product,
        # TODO: This is temporary until detail pages get added.
        detail=absolutify(reissue),  # Currently this is a 404.
        reissue=absolutify(reissue),  # Currently this is a 404.
        typ=typ,
        user={
            'type': 'directed-identifier',
            'value': installed.uuid
        },
        verify=verify)

    if settings.SIGNING_SERVER_ACTIVE:
        # The shiny new code.
        return sign(receipt)
    else:
        # Our old bad code.
        return jwt.encode(receipt, get_key(), u'RS512')
Example #42
0
def preapproval(request, complete=None, cancel=None):
    if waffle.switch_is_active('currencies'):
        failure = currency(request, do_redirect=False)
        if failure:
            return failure

    today = datetime.today()
    data = {
        'startDate': today,
        'endDate': today + timedelta(days=365),
    }
    store = {
        'expiry': data['endDate'],
        'solitude-key': None,
        'complete': complete,
        'cancel': cancel,
    }

    if waffle.flag_is_active(request, 'solitude-payments'):
        client.create_buyer_if_missing(request.amo_user)
        try:
            result = client.post_preapproval(
                data={
                    'start':
                    data['startDate'].date(),
                    'end':
                    data['endDate'].date(),
                    'uuid':
                    request.amo_user,
                    'return_url':
                    absolutify(reverse('account.payment', args=['complete'])),
                    'cancel_url':
                    absolutify(reverse('account.payment', args=['cancel'])),
                })
        except client.Error:
            paypal_log.error(u'preapproval', exc_info=True)
            raise

        store.update({'key': result['key'], 'solitude-key': result['pk']})
        url = result['paypal_url']

    else:
        # TODO(solitude): remove this.
        data.update({'pattern': 'account.payment'})
        try:
            result = paypal.get_preapproval_key(data)
        except paypal.PaypalError, e:
            paypal_log.error(u'Preapproval key: %s' % e, exc_info=True)
            raise

        store.update({'key': result['preapprovalKey']})
        url = paypal.get_preapproval_url(result['preapprovalKey'])
Example #43
0
def get_context(addon, version, job, results):
    result_links = (absolutify(reverse('devhub.validation_result',
                                       args=[addon.slug, r.pk]))
                    for r in results)
    return Context({
            'ADDON_NAME': addon.name,
            'ADDON_VERSION': version.version,
            'APPLICATION': str(job.application),
            'COMPAT_LINK': absolutify(reverse('devhub.versions.edit',
                                              args=[addon.pk, version.pk])),
            'RESULT_LINKS': ' '.join(result_links),
            'VERSION': job.target_version.version,
        })
Example #44
0
 def good_data(da):
     da = json.loads(da)
     # TODO(Kumar) fix this when we have default currencies (bug 777747)
     eq_(da['currency'], 'USD')
     eq_(da['amount'], str(self.price.price))
     eq_(da['app_name'], unicode(self.addon.name))
     eq_(da['app_description'], unicode(self.addon.description))
     eq_(da['postback_url'],
         absolutify(reverse('bluevia.postback')))
     eq_(da['chargeback_url'],
         absolutify(reverse('bluevia.chargeback')))
     assert 'contrib_uuid' in da
     return True
Example #45
0
 def get_context_data(self):
     if self.addon.is_listed:
         url = self.addon.get_url_path(add_prefix=False)
     else:
         url = self.addon.get_dev_url('versions')
     return {'name': self.addon.name,
             'number': self.version.version,
             'reviewer': self.user.display_name,
             'addon_url': absolutify(url),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
Example #46
0
 def get_context_data(self):
     if self.addon.is_listed:
         url = self.addon.get_url_path(add_prefix=False)
     else:
         url = self.addon.get_dev_url('versions')
     return {'name': self.addon.name,
             'number': self.version.version,
             'reviewer': self.user.display_name,
             'addon_url': absolutify(url),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
Example #47
0
 def get_context_data(self):
     if self.addon.is_listed:
         url = self.addon.get_url_path(add_prefix=False)
     else:
         url = self.addon.get_dev_url("versions")
     return {
         "name": self.addon.name,
         "number": self.version.version,
         "reviewer": self.user.display_name,
         "addon_url": absolutify(url),
         "review_url": absolutify(reverse("editors.review", args=[self.addon.pk], add_prefix=False)),
         "comments": self.data.get("comments"),
         "SITE_URL": settings.SITE_URL,
     }
Example #48
0
def get_context(addon, version, job, results, fileob=None):
    result_links = (absolutify(reverse('devhub.bulk_compat_result',
                                       args=[addon.slug, r.pk]))
                    for r in results)
    addon_name = addon.name
    if fileob and fileob.platform != amo.PLATFORM_ALL.id:
        addon_name = u'%s (%s)' % (addon_name, fileob.get_platform_display())
    return Context({
        'ADDON_NAME': addon_name,
        'ADDON_VERSION': version.version,
        'APPLICATION': str(job.application),
        'COMPAT_LINK': absolutify(reverse('devhub.versions.edit',
                                          args=[addon.pk, version.pk])),
        'RESULT_LINKS': ' '.join(result_links),
        'VERSION': job.target_version.version})
Example #49
0
def get_context(addon, version, job, results, fileob=None):
    result_links = (absolutify(reverse("devhub.bulk_compat_result", args=[addon.slug, r.pk])) for r in results)
    addon_name = addon.name
    if fileob and fileob.platform.id != amo.PLATFORM_ALL.id:
        addon_name = u"%s (%s)" % (addon_name, fileob.platform)
    return Context(
        {
            "ADDON_NAME": addon_name,
            "ADDON_VERSION": version.version,
            "APPLICATION": str(job.application),
            "COMPAT_LINK": absolutify(reverse("devhub.versions.edit", args=[addon.pk, version.pk])),
            "RESULT_LINKS": " ".join(result_links),
            "VERSION": job.target_version.version,
        }
    )
Example #50
0
def create_receipt(installed_pk):
    installed = Installed.objects.get(pk=installed_pk)
    verify = "%s%s" % (settings.WEBAPPS_RECEIPT_URL, installed.addon.pk)
    detail = reverse("users.purchases.receipt", args=[installed.addon.pk])
    receipt = dict(
        typ="purchase-receipt",
        product=installed.addon.origin,
        user={"type": "email", "value": installed.email},
        iss=settings.SITE_URL,
        nbf=time.mktime(installed.created.timetuple()),
        iat=time.time(),
        detail=absolutify(detail),
        verify=absolutify(verify),
    )
    return jwt.encode(receipt, get_key(), u"RS512")
Example #51
0
def get_paykey(data):
    """
    Gets a paykey from Paypal. Need to pass in the following in data:
    pattern: the reverse pattern to resolve
    email: who the money is going to (required)
    amount: the amount of money (required)
    ip: ip address of end user (required)
    uuid: contribution_uuid (required)
    memo: any nice message (optional)
    qs: anything you want to append to the complete or cancel (optional)
    currency: valid paypal currency, defaults to USD (optional)
    """
    if data['pattern']:
        complete = reverse(data['pattern'], args=[data['slug'], 'complete'])
        cancel = reverse(data['pattern'], args=[data['slug'], 'cancel'])
    else:
        # If there's no pattern given, just fake some urls.
        complete = cancel = settings.SITE_URL + '/paypal/dummy/'

    qs = {'uuid': data['uuid']}
    if 'qs' in data:
        qs.update(data['qs'])
    uuid_qs = urllib.urlencode(qs)

    paypal_data = {
        'actionType': 'PAY',
        'currencyCode': data.get('currency', 'USD'),
        'cancelUrl': absolutify('%s?%s' % (cancel, uuid_qs)),
        'returnUrl': absolutify('%s?%s' % (complete, uuid_qs)),
        'trackingId': data['uuid'],
        'ipnNotificationUrl': absolutify(reverse('amo.paypal')),
        'receiverList.receiver(0).email': data['email'],
        'receiverList.receiver(0).amount': data['amount'],
        'receiverList.receiver(0).invoiceID': 'mozilla-%s' % data['uuid'],
        'receiverList.receiver(0).primary': 'TRUE',
        'receiverList.receiver(0).paymentType': 'DIGITALGOODS',
        'requestEnvelope.errorLanguage': 'US'
    }

    if data.get('memo'):
        paypal_data['memo'] = data['memo']

    with statsd.timer('paypal.paykey.retrieval'):
        response = _call(settings.PAYPAL_PAY_URL + 'Pay',
                         paypal_data,
                         ip=data['ip'])

    return response['payKey'], response['paymentExecStatus']
Example #52
0
def create_receipt(installed_pk, flavour=None):
    assert flavour in [None, 'developer',
                       'reviewer'], ('Invalid flavour: %s' % flavour)

    installed = Installed.objects.get(pk=installed_pk)
    webapp = installed.addon
    origin = (settings.SITE_URL if webapp.is_packaged else webapp.origin)
    time_ = calendar.timegm(time.gmtime())

    product = {'url': origin, 'storedata': urlencode({'id': int(webapp.pk)})}

    # Generate different receipts for reviewers or developers.
    expiry = time_ + settings.WEBAPPS_RECEIPT_EXPIRY_SECONDS
    if flavour:
        if not (acl.action_allowed_user(installed.user, 'Apps', 'Review')
                or webapp.has_author(installed.user)):
            raise ValueError('User %s is not a reviewer or developer' %
                             installed.user.pk)

        if flavour == 'reviewer':
            expiry = time_ + (60 * 60 * 24)
        product['type'] = flavour
        verify = absolutify(reverse('receipt.verify', args=[webapp.app_slug]))
    else:
        verify = settings.WEBAPPS_RECEIPT_URL

    detail = reverse('account.purchases.receipt', args=[webapp.pk])
    reissue = webapp.get_purchase_url('reissue')
    receipt = dict(detail=absolutify(detail),
                   exp=expiry,
                   iat=time_,
                   iss=settings.SITE_URL,
                   nbf=time_,
                   product=product,
                   reissue=absolutify(reissue),
                   typ='purchase-receipt',
                   user={
                       'type': 'directed-identifier',
                       'value': installed.uuid
                   },
                   verify=verify)

    if settings.SIGNING_SERVER_ACTIVE:
        # The shiny new code.
        return sign(receipt)
    else:
        # Our old bad code.
        return jwt.encode(receipt, get_key(), u'RS512')
Example #53
0
 def good_data(da):
     da = json.loads(da)
     # TODO(Kumar) fix this when we have default currencies (bug 777747)
     eq_(da['currency'], 'USD')
     eq_(da['typ'], 'tu.com/payments/inapp/v1')
     eq_(da['aud'], 'tu.com')
     eq_(da['amount'], str(self.price.price))
     eq_(da['app_name'], unicode(self.addon.name))
     eq_(da['app_description'], unicode(self.addon.description))
     eq_(da['postback_url'], absolutify(reverse('bluevia.postback')))
     eq_(da['chargeback_url'],
         absolutify(reverse('bluevia.chargeback')))
     pd = urlparse.parse_qs(da['product_data'])
     assert 'contrib_uuid' in pd, 'Unexpected: %s' % pd
     eq_(pd['addon_id'][0], str(self.addon.pk))
     return True
Example #54
0
def refund_permission_url(addon, dest='payments'):
    """
    Send permissions request to PayPal for refund privileges on
    this addon's paypal account. Returns URL on PayPal site to visit.
    """
    # This is set in settings_test so we don't start calling PayPal
    # by accident. Explicitly set this in your tests.
    if not settings.PAYPAL_PERMISSIONS_URL:
        return ''
    paypal_log.debug('Getting refund permission URL for addon: %s' % addon.pk)

    with statsd.timer('paypal.permissions.url'):
        url = urlparams(reverse('devhub.addons.acquire_refund_permission',
                                args=[addon.slug]),
                        dest=dest)
        try:
            r = _call(settings.PAYPAL_PERMISSIONS_URL + 'RequestPermissions', {
                'scope': 'REFUND',
                'callback': absolutify(url)
            })
        except PaypalError, e:
            paypal_log.debug('Error on refund permission URL addon: %s, %s' %
                             (addon.pk, e))
            if 'malformed' in str(e):
                # PayPal is very picky about where they redirect users to.
                # If you try and create a PayPal permissions URL on a
                # zamboni that has a non-standard port number or a
                # non-standard TLD, it will blow up with an error. We need
                # to be able to at least visit these pages and alter them
                # in dev, so this will give you a broken token that doesn't
                # work, but at least the page will function.
                r = {'token': 'wont-work-paypal-doesnt-like-your-domain'}
            else:
                raise
Example #55
0
 def link(self, category):
     """Link for the feed as a whole"""
     if self.category:
         base = url('browse.search-tools.rss', self.category.slug)
     else:
         base = url('browse.search-tools.rss')
     return absolutify(base + '?sort=' + self.sort)
Example #56
0
def _mini_manifest(addon, version_id, token=None):
    if not addon.is_packaged:
        raise http.Http404

    version = get_object_or_404(addon.versions, pk=version_id)
    file_ = version.all_files[0]
    manifest = addon.get_manifest_json(file_)

    package_path = absolutify(
        reverse('reviewers.signed', args=[addon.app_slug, version.id]))

    if token:
        # Generate a fresh token.
        token = Token(data={'app_id': addon.id})
        token.save()
        package_path = urlparams(package_path, token=token.token)

    data = {
        'name': manifest['name'],
        'version': version.version,
        'size': file_.size,
        'release_notes': version.releasenotes,
        'package_path': package_path,
    }
    for key in ['developer', 'icons', 'locales']:
        if key in manifest:
            data[key] = manifest[key]

    return json.dumps(data, cls=JSONEncoder)
Example #57
0
def _mini_manifest(addon, version_id):
    if not addon.is_packaged:
        raise http.Http404

    version = get_object_or_404(addon.versions, pk=version_id)
    file_ = version.all_files[0]
    manifest = addon.get_manifest_json(file_)

    data = {
        'name':
        addon.name,
        'version':
        version.version,
        'size':
        file_.size,
        'release_notes':
        version.releasenotes,
        'package_path':
        absolutify(
            reverse('reviewers.signed', args=[addon.app_slug, version.id]))
    }
    if 'icons' in manifest:
        data['icons'] = manifest['icons']
    if 'locales' in manifest:
        data['locales'] = manifest['locales']

    return json.dumps(data, cls=JSONEncoder)
Example #58
0
 def test_verify(self):
     url = absolutify(
         reverse('receipt.test.verify', kwargs={'status': 'expired'}))
     receipt = create_test_receipt('http://foo', 'expired')
     req = RawRequestFactory().post(url, receipt)
     res = devhub_verify(req, 'expired')
     eq_(json.loads(res.content)['status'], 'expired')