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)
def prepare_pay(request, addon): if addon.is_premium() and addon.has_purchased(request.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.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.user, uuid=str(uuid.uuid4()), ) log.debug('Storing contrib for uuid: {0}'.format(contribution.uuid)) return get_product_jwt(WebAppProduct(addon), contribution)
def post(self, request, *args, **kwargs): form = PrepareInAppForm(request.DATA) if not form.is_valid(): app_pay_cef.log( request._request, 'Preparing InApp JWT Failed', 'preparing_inapp_jwt_failed', 'Preparing InApp JWT Failed error: {0}'.format(form.errors), severity=3 ) return Response(form.errors, status=status.HTTP_400_BAD_REQUEST) inapp = form.cleaned_data['inapp'] app_pay_cef.log( request._request, 'Preparing InApp JWT', 'preparing_inapp_jwt', 'Preparing InApp JWT for: {0}'.format(inapp.pk), severity=3 ) token = get_product_jwt( InAppProduct(inapp), client_data=ClientData.get_or_create(request._request), lang=request._request.LANG, source=request._request.REQUEST.get('src', ''), ) return Response(token, status=status.HTTP_201_CREATED)
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)
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}
def postback(request): """Verify signature and set contribution to paid.""" signed_jwt = request.POST.get('notice', '') try: data = parse_from_webpay(signed_jwt, request.META.get('REMOTE_ADDR')) except InvalidSender, exc: app_pay_cef.log(request, 'Unknown app', 'invalid_postback', 'Ignoring invalid JWT %r: %s' % (signed_jwt, exc), severity=4) return http.HttpResponseBadRequest()
def free_postback(request, contrib, trans_id, user_profile): log.info(u'Got free product postback: fulfilling purchase for ' u'contrib={c}; trans={t}; user={u}'.format( c=contrib, t=trans_id, u=user_profile)) app_pay_cef.log(request, 'Purchase complete', 'purchase_complete', 'Purchase complete for: %s' % (contrib.addon.pk), severity=3) contrib.update(transaction_id=trans_id, type=mkt.CONTRIB_PURCHASE, user=user_profile) tasks.send_purchase_receipt.delay(contrib.pk) return http.HttpResponse(trans_id)
def free_postback(request, contrib, trans_id, user_profile): log.info(u'Got free product postback: fulfilling purchase for ' u'contrib={c}; trans={t}; user={u}'.format( c=contrib, t=trans_id, u=user_profile)) app_pay_cef.log(request, 'Purchase complete', 'purchase_complete', 'Purchase complete for: %s' % (contrib.webapp.pk), severity=3) contrib.update(transaction_id=trans_id, type=mkt.CONTRIB_PURCHASE, user=user_profile) tasks.send_purchase_receipt.delay(contrib.pk) return http.HttpResponse(trans_id)
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)
def post(self, request, *args, **kwargs): form = PrepareInAppForm(request.DATA) if not form.is_valid(): app_pay_cef.log( request._request, 'Preparing InApp JWT Failed', 'preparing_inapp_jwt_failed', 'Preparing InApp JWT Failed error: {0}'.format(form.errors), severity=3 ) return Response(form.errors, status=status.HTTP_400_BAD_REQUEST) inapp = form.cleaned_data['inapp'] app_pay_cef.log( request._request, 'Preparing InApp JWT', 'preparing_inapp_jwt', 'Preparing InApp JWT for: {0}'.format(inapp.pk), severity=3 ) log.debug('Starting purchase of in app: {0}'.format(inapp.pk)) contribution = Contribution.objects.create( addon_id=inapp.webapp and inapp.webapp.pk, inapp_product=inapp, # In-App payments are unauthenticated so we have no user # and therefore can't determine a meaningful region. amount=None, paykey=None, price_tier=inapp.price, source=request._request.REQUEST.get('src', ''), source_locale=request._request.LANG, type=amo.CONTRIB_PENDING, user=None, uuid=str(uuid.uuid4()), ) log.info('Storing contrib for uuid: {0}'.format(contribution.uuid)) if inapp.simulate: log.info('Preparing in-app JWT simulation for {i}' .format(i=inapp)) product = SimulatedInAppProduct(inapp) else: log.info('Preparing in-app JWT for {i}'.format(i=inapp)) product = InAppProduct(inapp) token = get_product_jwt(product, contribution) return Response(token, status=status.HTTP_201_CREATED)
def post(self, request, *args, **kwargs): form = PrepareInAppForm(request.DATA) if not form.is_valid(): app_pay_cef.log( request._request, 'Preparing InApp JWT Failed', 'preparing_inapp_jwt_failed', 'Preparing InApp JWT Failed error: {0}'.format(form.errors), severity=3 ) return Response(form.errors, status=status.HTTP_400_BAD_REQUEST) inapp = form.cleaned_data['inapp'] app_pay_cef.log( request._request, 'Preparing InApp JWT', 'preparing_inapp_jwt', 'Preparing InApp JWT for: {0}'.format(inapp.pk), severity=3 ) log.debug('Starting purchase of in app: {0}'.format(inapp.pk)) contribution = Contribution.objects.create( addon_id=inapp.webapp and inapp.webapp.pk, inapp_product=inapp, # In-App payments are unauthenticated so we have no user # and therefore can't determine a meaningful region. amount=None, paykey=None, price_tier=inapp.price, source=request._request.GET.get('src', ''), source_locale=request._request.LANG, type=mkt.CONTRIB_PENDING, user=None, uuid=str(uuid.uuid4()), ) log.info('Storing contrib for uuid: {0}'.format(contribution.uuid)) if inapp.simulate: log.info('Preparing in-app JWT simulation for {i}' .format(i=inapp)) product = SimulatedInAppProduct(inapp) else: log.info('Preparing in-app JWT for {i}'.format(i=inapp)) product = InAppProduct(inapp) token = get_product_jwt(product, contribution) return Response(token, status=status.HTTP_201_CREATED)
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.REQUEST.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)
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), )
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), ) # Until atob() supports encoded HTML we are stripping all tags. # See bug 831524 app_summary = bleach.clean(unicode(addon.summary), strip=True, tags=[]) acct = addon.app_payment_account.payment_account seller_uuid = acct.solitude_seller.uuid issued_at = calendar.timegm(time.gmtime()) 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_summary, "pricePoint": addon.premium.price.pk, "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}), }, } 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) return {"webpayJWT": jwt_, "contribStatusURL": reverse("webpay.pay_status", args=[addon.app_slug, uuid_])}
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)) # Until atob() supports encoded HTML we are stripping all tags. # See bug 831524 app_summary = bleach.clean(unicode(addon.summary), strip=True, tags=[]) acct = addon.app_payment_account.payment_account seller_uuid = acct.solitude_seller.uuid issued_at = calendar.timegm(time.gmtime()) 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_summary, 'pricePoint': addon.premium.price.pk, '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}), } } 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) return {'webpayJWT': jwt_, 'contribStatusURL': reverse('webpay.pay_status', args=[addon.app_slug, uuid_])}
def _prepare_pay(request, webapp): app_pay_cef.log(request, 'Preparing JWT', 'preparing_jwt', 'Preparing JWT for: %s' % (webapp.pk), severity=3) log.debug('Starting purchase of app: {0} by user: {1}'.format( webapp.pk, request.user)) contribution = Contribution.objects.create( webapp_id=webapp.pk, amount=webapp.get_price(region=request.REGION.id), paykey=None, price_tier=webapp.premium.price, source=request.GET.get('src', ''), source_locale=request.LANG, type=mkt.CONTRIB_PENDING, user=request.user, uuid=str(uuid.uuid4()), ) log.debug('Storing contrib for uuid: {0}'.format(contribution.uuid)) return get_product_jwt(WebAppProduct(webapp), contribution)
pd = urlparse.parse_qs(data["request"]["productData"]) contrib_uuid = pd["contrib_uuid"][0] try: contrib = Contribution.objects.get(uuid=contrib_uuid) except Contribution.DoesNotExist: etype, val, tb = sys.exc_info() raise LookupError( "JWT (iss:%s, aud:%s) for trans_id %s " "links to contrib %s which doesn't exist" % (data["iss"], data["aud"], data["response"]["transactionID"], contrib_uuid) ), None, tb trans_id = data["response"]["transactionID"] log.info("webpay postback: fulfilling purchase for contrib %s with " "transaction %s" % (contrib, trans_id)) app_pay_cef.log( request, "Purchase complete", "purchase_complete", "Purchase complete for: %s" % (contrib.addon.pk), severity=3 ) contrib.update(transaction_id=trans_id, type=amo.CONTRIB_PURCHASE) tasks.send_purchase_receipt.delay(contrib.pk) return http.HttpResponse(trans_id) @csrf_exempt @write @post_required def chargeback(request): """ Verify signature from and create a refund contribution tied to the original transaction. """
etype, val, tb = sys.exc_info() raise LookupError('JWT (iss:%s, aud:%s) for trans_id %s ' 'links to contrib %s which doesn\'t exist' % (data['iss'], data['aud'], data['response']['transactionID'], contrib_uuid)), None, tb trans_id = data['response']['transactionID'] if contrib.is_inapp_simulation(): return simulated_postback(contrib, trans_id) if contrib.transaction_id is not None: if contrib.transaction_id == trans_id: app_pay_cef.log( request, 'Repeat postback', 'repeat_postback', 'Postback sent again for: %s' % (contrib.webapp.pk), severity=4) return http.HttpResponse(trans_id) else: app_pay_cef.log(request, 'Repeat postback with new trans_id', 'repeat_postback_new_trans_id', 'Postback sent again for: %s, but with new ' 'trans_id: %s' % (contrib.webapp.pk, trans_id), severity=7) raise LookupError( 'JWT (iss:{iss}, aud:{aud}) for trans_id {jwt_trans} is ' 'for contrib {contrib_uuid} that is already paid and has ' 'a different trans_id: {contrib_trans}' .format(iss=data['iss'], aud=data['aud'], jwt_trans=data['response']['transactionID'], contrib_uuid=contrib_uuid,
"JWT (iss:%s, aud:%s) for trans_id %s " "links to contrib %s which doesn't exist" % (data["iss"], data["aud"], data["response"]["transactionID"], contrib_uuid) ), None, tb trans_id = data["response"]["transactionID"] if contrib.is_inapp_simulation(): return simulated_postback(contrib, trans_id) if contrib.transaction_id is not None: if contrib.transaction_id == trans_id: app_pay_cef.log( request, "Repeat postback", "repeat_postback", "Postback sent again for: %s" % (contrib.addon.pk), severity=4, ) return http.HttpResponse(trans_id) else: app_pay_cef.log( request, "Repeat postback with new trans_id", "repeat_postback_new_trans_id", "Postback sent again for: %s, but with new " "trans_id: %s" % (contrib.addon.pk, trans_id), severity=7, ) raise LookupError( "JWT (iss:%s, aud:%s) for trans_id %s is for " "contrib %s that is already paid and has "
try: contrib = Contribution.objects.get(uuid=contrib_uuid) except Contribution.DoesNotExist: etype, val, tb = sys.exc_info() raise LookupError('JWT (iss:%s, aud:%s) for trans_id %s ' 'links to contrib %s which doesn\'t exist' % (data['iss'], data['aud'], data['response']['transactionID'], contrib_uuid)), None, tb trans_id = data['response']['transactionID'] if contrib.transaction_id is not None: if contrib.transaction_id == trans_id: app_pay_cef.log(request, 'Repeat postback', 'repeat_postback', 'Postback sent again for: %s' % (contrib.addon.pk), severity=4) return http.HttpResponse(trans_id) else: app_pay_cef.log(request, 'Repeat postback with new trans_id', 'repeat_postback_new_trans_id', 'Postback sent again for: %s, but with new ' 'trans_id: %s' % (contrib.addon.pk, trans_id), severity=7) raise LookupError('JWT (iss:%s, aud:%s) for trans_id %s is for ' 'contrib %s that is already paid and has ' 'existing differnet trans_id: %s' % (data['iss'], data['aud'], data['response']['transactionID'], contrib_uuid, contrib.transaction_id))
contrib_uuid = pd['contrib_uuid'][0] try: contrib = Contribution.objects.get(uuid=contrib_uuid) except Contribution.DoesNotExist: etype, val, tb = sys.exc_info() raise LookupError('JWT (iss:%s, aud:%s) for trans_id %s ' 'links to contrib %s which doesn\'t exist' % (data['iss'], data['aud'], data['response']['transactionID'], contrib_uuid)), None, tb trans_id = data['response']['transactionID'] log.info('webpay postback: fulfilling purchase for contrib %s with ' 'transaction %s' % (contrib, trans_id)) app_pay_cef.log(request, 'Purchase complete', 'purchase_complete', 'Purchase complete for: %s' % (contrib.addon.pk), severity=3) contrib.update(transaction_id=trans_id, type=amo.CONTRIB_PURCHASE) tasks.send_purchase_receipt.delay(contrib.pk) return http.HttpResponse(trans_id) @csrf_exempt @write @post_required def chargeback(request): """ Verify signature from and create a refund contribution tied to the original transaction. """
try: contrib = Contribution.objects.get(uuid=contrib_uuid) except Contribution.DoesNotExist: etype, val, tb = sys.exc_info() raise LookupError( 'JWT (iss:%s, aud:%s) for trans_id %s ' 'links to contrib %s which doesn\'t exist' % (data['iss'], data['aud'], data['response']['transactionID'], contrib_uuid)), None, tb trans_id = data['response']['transactionID'] log.info('webpay postback: fulfilling purchase for contrib %s with ' 'transaction %s' % (contrib, trans_id)) app_pay_cef.log(request, 'Purchase complete', 'purchase_complete', 'Purchase complete for: %s' % (contrib.addon.pk), severity=3) contrib.update(transaction_id=trans_id, type=amo.CONTRIB_PURCHASE) tasks.send_purchase_receipt.delay(contrib.pk) return http.HttpResponse(trans_id) @csrf_exempt @write @post_required def chargeback(request): """ Verify signature from and create a refund contribution tied to the original transaction.
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('api_dispatch_detail', kwargs={ 'resource_name': 'status', 'api_name': 'webpay', 'uuid': uuid_ }) else: url = reverse('webpay.pay_status', args=[addon.app_slug, uuid_]) return {'webpayJWT': jwt_, 'contribStatusURL': url}