def _redirect_response_to_basket_or_payment(self, request, skus): redirect_url = get_payment_microfrontend_or_basket_url(request) # If a user is eligible and bucketed, REV1074 experiment information will be added to their url if waffle.flag_is_active(self.request, 'REV1074.enable_experiment') and skus: # pragma: no cover redirect_url = add_REV1074_information_to_url_if_eligible(redirect_url, request, skus[0]) redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) basket = 'basket_id=' + str(request.basket.id) has_params = urlparse(redirect_url).query redirect_url += '&' + basket if has_params else '?' + basket else: # pragma: no cover redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) return HttpResponseRedirect(redirect_url, status=303)
def redirect_on_transaction_declined(self): redirect_url = get_payment_microfrontend_or_basket_url(self.request) redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) return JsonResponse({ 'redirectTo': redirect_url, }, status=400)
def _redirect_response_to_basket_or_payment(self, request): redirect_url = _get_payment_microfrontend_url_if_configured(request) if not redirect_url: redirect_url = reverse('basket:summary') redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) return HttpResponseRedirect(redirect_url, status=303)
def get(self, request): partner = get_partner_for_site(request) skus = request.GET.getlist('sku') code = request.GET.get('code', None) if not skus: return HttpResponseBadRequest(_('No SKUs provided.')) products = Product.objects.filter(stockrecords__partner=partner, stockrecords__partner_sku__in=skus) if not products: return HttpResponseBadRequest(_('Products with SKU(s) [{skus}] do not exist.').format(skus=', '.join(skus))) voucher = Voucher.objects.get(code=code) if code else None if voucher is None: # If there is an Enterprise entitlement available for this basket, # we redirect to the CouponRedeemView to apply the discount to the # basket and handle the data sharing consent requirement. code_redemption_redirect = get_enterprise_code_redemption_redirect( request, products, skus, 'basket:add-multi' ) if code_redemption_redirect: return code_redemption_redirect try: prepare_basket(request, products, voucher) except AlreadyPlacedOrderException: return render(request, 'edx/error.html', {'error': _('You have already purchased these products')}) url = add_utm_params_to_url(reverse('basket:summary'), self.request.GET.items()) return HttpResponseRedirect(url, status=303)
def redirect_on_transaction_declined(self): redirect_url = get_payment_microfrontend_or_basket_url(self.request) redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) # TODO: Remove as part of PCI-81 redirect_url = add_flex_microform_flag_to_url(redirect_url, self.request) return HttpResponseRedirect(redirect_url)
def get(self, request): partner = get_partner_for_site(request) skus = [escape(sku) for sku in request.GET.getlist('sku')] code = request.GET.get('code', None) if not skus: return HttpResponseBadRequest(_('No SKUs provided.')) products = Product.objects.filter(stockrecords__partner=partner, stockrecords__partner_sku__in=skus) if not products: return HttpResponseBadRequest(_('Products with SKU(s) [{skus}] do not exist.').format(skus=', '.join(skus))) logger.info('Starting payment flow for user[%s] for products[%s].', request.user.username, skus) voucher = Voucher.objects.get(code=code) if code else None if voucher is None: # If there is an Enterprise entitlement available for this basket, # we redirect to the CouponRedeemView to apply the discount to the # basket and handle the data sharing consent requirement. code_redemption_redirect = get_enterprise_code_redemption_redirect( request, products, skus, 'basket:basket-add' ) if code_redemption_redirect: return code_redemption_redirect # check availability of products unavailable_product_ids = [] for product in products: purchase_info = request.strategy.fetch_for_product(product) if not purchase_info.availability.is_available_to_buy: logger.warning('Product [%s] is not available to buy.', product.title) unavailable_product_ids.append(product.id) available_products = products.exclude(id__in=unavailable_product_ids) if not available_products: msg = _('No product is available to buy.') return HttpResponseBadRequest(msg) # Associate the user's email opt in preferences with the basket in # order to opt them in later as part of fulfillment BasketAttribute.objects.update_or_create( basket=request.basket, attribute_type=BasketAttributeType.objects.get(name=EMAIL_OPT_IN_ATTRIBUTE), defaults={'value_text': request.GET.get('email_opt_in') == 'true'}, ) try: prepare_basket(request, available_products, voucher) except AlreadyPlacedOrderException: return render(request, 'edx/error.html', {'error': _('You have already purchased these products')}) url = add_utm_params_to_url(reverse('basket:summary'), self.request.GET.items()) return HttpResponseRedirect(url, status=303)
def _redirect_response_to_basket_or_payment(self, request, invalid_code=None): redirect_url = get_payment_microfrontend_or_basket_url(request) redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) redirect_url = add_invalid_code_message_to_url(redirect_url, invalid_code) return HttpResponseRedirect(redirect_url, status=303)
def _redirect_to_payment_microfrontend_if_configured(request): if waffle.flag_is_active(request, ENABLE_MICROFRONTEND_FOR_BASKET_PAGE_FLAG_NAME): if (request.site.siteconfiguration.enable_microfrontend_for_basket_page and request.site.siteconfiguration.payment_microfrontend_url): url = add_utm_params_to_url( request.site.siteconfiguration.payment_microfrontend_url, request.GET.items(), ) return HttpResponseRedirect(url) return None
def _redirect_response_to_basket_or_payment(self, request, skus): redirect_url = get_payment_microfrontend_or_basket_url(request) redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) # If a user is eligible and bucketed, REV1074 experiment information will be added to their url if waffle.flag_is_active( self.request, 'REV1074.enable_experiment'): # pragma: no cover if skus: redirect_url = add_REV1074_information_to_url_if_eligible( redirect_url, request, skus[0]) return HttpResponseRedirect(redirect_url, status=303)
def redirect_on_transaction_declined(self): redirect_url = get_payment_microfrontend_or_basket_url(self.request) redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) # TODO: Remove as part of PCI-81 redirect_url = add_flex_microform_flag_to_url(redirect_url, self.request, force_flag=False) return JsonResponse({ 'redirectTo': redirect_url, }, status=400)
def _redirect_response_to_basket_or_payment(self, request, skus, invalid_code=None): redirect_url = get_payment_microfrontend_or_basket_url(request) # If a user is eligible and bucketed, REV1074 experiment information will be added to their url REV1074_is_active = waffle.flag_is_active(self.request, 'REV1074.enable_experiment') if REV1074_is_active and skus and not invalid_code: # pragma: no cover redirect_url = add_REV1074_information_to_url_if_eligible(redirect_url, request, skus[0]) redirect_url += '?basket_id=' + str(request.basket.id) else: # pragma: no cover redirect_url = add_utm_params_to_url(redirect_url, list(self.request.GET.items())) redirect_url = add_invalid_code_message_to_url(redirect_url, invalid_code) return HttpResponseRedirect(redirect_url, status=303)
def get(self, request): partner = get_partner_for_site(request) sku = request.GET.get('sku', None) code = request.GET.get('code', None) if not sku: return HttpResponseBadRequest(_('No SKU provided.')) voucher = Voucher.objects.get(code=code) if code else None try: product = StockRecord.objects.get(partner=partner, partner_sku=sku).product except StockRecord.DoesNotExist: return HttpResponseBadRequest( _('SKU [{sku}] does not exist.').format(sku=sku)) logger.info('Starting payment flow for user[%s] for product[%s].', request.user.username, sku) if voucher is None: # If there is an Enterprise entitlement available for this basket, # we redirect to the CouponRedeemView to apply the discount to the # basket and handle the data sharing consent requirement. code_redemption_redirect = get_enterprise_code_redemption_redirect( request, [product], [sku], 'basket:single-item') if code_redemption_redirect: return code_redemption_redirect # If the product isn't available then there's no reason to continue with the basket addition purchase_info = request.strategy.fetch_for_product(product) if not purchase_info.availability.is_available_to_buy: msg = _('Product [{product}] not available to buy.').format( product=product.title) return HttpResponseBadRequest(msg) # At this point we're either adding an Enrollment Code product to the basket, # or the user is adding a Seat product for which they are not already enrolled try: prepare_basket(request, [product], voucher) except AlreadyPlacedOrderException: msg = _('You have already purchased {course} seat.').format( course=product.title) return render(request, 'edx/error.html', {'error': msg}) url = add_utm_params_to_url(reverse('basket:summary'), self.request.GET.items()) return HttpResponseRedirect(url, status=303)
def test_add_utm_params_to_url(self): url = add_utm_params_to_url('/basket', [('utm_param', 'test'), ('other_param', 'test2')]) self.assertEqual(url, '/basket?utm_param=test')
class BasketAddItemsView(View): """ View that adds multiple products to a user's basket. An additional coupon code can be supplied so the offer is applied to the basket. """ def get(self, request): # lms/ecommerce has different user if 'username' in request.GET and request.user.username != request.GET.get( 'username'): logout(request) query_dict = request.GET.dict() query_dict.pop('username') redirect_url = '{path}?{query_string}'.format( path=request.path, query_string=urlencode(query_dict)) logger.info('logout user {username}'.format( username=request.GET.get('username'))) return redirect(redirect_url) partner = get_partner_for_site(request) skus = [escape(sku) for sku in request.GET.getlist('sku')] code = request.GET.get('code', None) if not skus: return HttpResponseBadRequest(_('No SKUs provided.')) products = Product.objects.filter(stockrecords__partner=partner, stockrecords__partner_sku__in=skus) if not products: return HttpResponseBadRequest( _('Products with SKU(s) [{skus}] do not exist.').format( skus=', '.join(skus))) try: lms_api = EdxRestApiClient( get_lms_url('/api/v1/vip/'), oauth_access_token=request.user.access_token, append_slash=False) # user is vip, redirect lms course about if lms_api.info().get().get('data', {}).get('status') is True: course_key = CourseKey.from_string(products[0].attr.course_key) return redirect( get_lms_course_about_url(course_key=course_key)) except Exception, e: logger.exception(e) logger.info('Starting payment flow for user[%s] for products[%s].', request.user.username, skus) voucher = Voucher.objects.get(code=code) if code else None if voucher is None: # If there is an Enterprise entitlement available for this basket, # we redirect to the CouponRedeemView to apply the discount to the # basket and handle the data sharing consent requirement. code_redemption_redirect = get_enterprise_code_redemption_redirect( request, products, skus, 'basket:basket-add') if code_redemption_redirect: return code_redemption_redirect # check availability of products unavailable_product_ids = [] for product in products: purchase_info = request.strategy.fetch_for_product(product) if not purchase_info.availability.is_available_to_buy: logger.warning('Product [%s] is not available to buy.', product.title) unavailable_product_ids.append(product.id) available_products = products.exclude(id__in=unavailable_product_ids) if not available_products: msg = _('No product is available to buy.') return HttpResponseBadRequest(msg) # Associate the user's email opt in preferences with the basket in # order to opt them in later as part of fulfillment BasketAttribute.objects.update_or_create( basket=request.basket, attribute_type=BasketAttributeType.objects.get( name=EMAIL_OPT_IN_ATTRIBUTE), defaults={'value_text': request.GET.get('email_opt_in') == 'true'}, ) try: prepare_basket(request, available_products, voucher) except AlreadyPlacedOrderException: return render( request, 'edx/error.html', { 'error': _('You have already purchased these products'), 'lms_contact_url': get_lms_url('/contact') }) url = add_utm_params_to_url(reverse('basket:summary'), self.request.GET.items()) return HttpResponseRedirect(url, status=303)