Ejemplo n.º 1
0
    def post(self, request, *args, **kwargs):
        user = request.user
        email = user.email
        customer_id = user.tracking_context['customer_id']
        customer = stripe.Customer.retrieve(customer_id)
        user_basket = Basket.objects.filter(owner=request.user,
                                            status="Commited").last()
        if user_basket:
            user_basket.strategy = Selector().strategy(user=self.request.user)
        else:
            return Response({
                "message": "No item found in cart.",
                "status": False,
                "result": {},
                "status_code": 400
            })

        if waffle.flag_is_active(
                request,
                DYNAMIC_DISCOUNT_FLAG) and user_basket.lines.count() > 0:
            discount_lms_url = get_lms_url('/api/discounts/')
            lms_discount_client = EdxRestApiClient(
                discount_lms_url,
                jwt=request.site.siteconfiguration.access_token)
            ck = user_basket.lines.first().product.course_id
            user_id = user_basket.owner.lms_user_id
            response = lms_discount_client.course(ck).get()
            jwt = jwt_decode_handler(response.get('jwt'))
            if jwt['discount_applicable']:
                offers = Applicator().get_offers(user_basket, request.user,
                                                 request)
                user_basket.strategy = request.strategy
                discount_benefit = DynamicPercentageDiscountBenefit()
                percentage = jwt['discount_percent']
                discount_benefit.apply(user_basket,
                                       'dynamic_discount_condition',
                                       offers[0],
                                       discount_percent=percentage)
        Applicator().apply(user_basket, self.request.user, self.request)

        if user_basket.status == "Commited":
            total_amount = int(user_basket.total_incl_tax)
            if total_amount > 0:
                try:
                    with transaction.atomic():
                        payment_response = self.make_stripe_payment_for_mobile(
                            None, user_basket)
                        response = {"total_amount": payment_response.total, "transaction_id": payment_response.transaction_id, \
                                    "currency": payment_response.currency, "client_secret": payment_response.client_secret}

                        # Freezing basket to prevent student from getting enrolled to possibily unpaid courses
                        user_basket.status = Basket.FROZEN
                        user_basket.save()

                        return Response({
                            "message": "Payment completed.",
                            "status": True,
                            "result": response,
                            "status_code": 200
                        })
                except Exception as e:
                    logger.exception(e)
                    msg = 'Attempts to handle payment for basket ' + str(
                        user_basket.id) + ' failed.'
                    return Response({
                        "message": msg,
                        "status": False,
                        "result": {},
                        "status_code": 400
                    })
            else:
                return Response({
                    "message": "Total amount must be greater than 0.",
                    "status": False,
                    "result": {},
                    "status_code": 400
                })
        else:
            return Response({
                "message": "No item found in cart.",
                "status": False,
                "result": {},
                "status_code": 400
            })
Ejemplo n.º 2
0
class EnrollmentApiClient(object):
    """
    Object builds an API client to make calls to the edxapp Enrollment API.
    Authenticates using settings.OPENEDX_EDX_API_KEY.
    """

    API_BASE_URL = settings.OPENEDX_ENROLLMENT_API_URI
    APPEND_SLASH = False
    CACHE_ACCOUNTS_PREFIX = "enrollmentapi_data__"

    def __init__(self):
        """
        Create an LMS API client, authenticated with the OAuth2 token for client in settings
        """
        # session = Session()
        # # session.headers = {"X-Edx-Api-Key": settings.OPENEDX_EDX_API_KEY}
        token = EdxRestApiClient.get_oauth_access_token(
            url="{}{}".format(settings.OPENEDX_PLATFORM_URI,
                              constants.OPENEDX_OAUTH2_TOKEN_URL),
            client_id=settings.OPENEDX_OAUTH2_CLIENT_ID,
            client_secret=settings.OPENEDX_OAUTH2_CLIENT_SECRET,
        )
        self.cache = False
        if settings.LMS_API_USE_MEMCACHED:
            self.cache = memcache.Client([settings.MEMCACHED_ADDRESS], debug=0)
        self.client = EdxRestApiClient(self.API_BASE_URL,
                                       append_slash=self.APPEND_SLASH,
                                       username="******",
                                       oauth_access_token=token[0])

    def get_course_info(self, course_id, unti=False):
        """
        Query the Enrollment API for the course details of the given course_id.
        unti is flag for University 2035 LRS data inegration
        """
        try:
            resp = self.client.course(
                u'{}?include_expired=1'.format(course_id)).get()

            if resp:
                data = {
                    'name': resp['course_name'],
                    'description': resp['description']
                }
                if unti and resp['integrate_2035_id'].strip():
                    data.update({'2035_id': resp['integrate_2035_id']})
                logger.error('get_course_info {}'.format(data))
                return data
            #if unti and resp:
            #    if resp['integrate_2035_id'].strip():
            #        return {'name': resp['course_name'], '2035_id': resp['integrate_2035_id'], 'description': resp['description']}
            #    else:
            #       message = 'Course {} not found in University 2035 database'.format(course_id)
            #       raise exceptions.XAPIBridgeCourseNotFoundError(message)
            #elif resp:
            #    return {'name': resp['course_name'], 'description': resp['description']}
            else:
                # TODO: look at other reasons for no resp.success
                message = 'Failed to retrieve course details for course id {}. Course not found in LMS'.format(
                    course_id)
                raise exceptions.XAPIBridgeCourseNotFoundError(message)
        except (SlumberBaseException, ConnectionError, Timeout,
                HttpClientError) as e:
            message = 'Failed to retrieve course details for course id {} due to: {}'.format(
                course_id, str(e))
            e = exceptions.XAPIBridgeConnectionError(message)
            e.err_continue_exc()
            raise exceptions.XAPIBridgeCourseNotFoundError(message)
Ejemplo n.º 3
0
    def form_valid(self, form):
        form_data = form.cleaned_data
        #basket = form_data['basket']
        committed_basket = Basket.objects.filter(owner=self.request.user,
                                                 status="Commited").last()
        committed_basket.strategy = self.request.strategy
        committed_basket.save()
        token = form_data['stripe_token']
        order_number = committed_basket.order_number
        if waffle.flag_is_active(
                self.request,
                DYNAMIC_DISCOUNT_FLAG) and committed_basket.lines.count() == 1:
            discount_lms_url = get_lms_url('/api/discounts/')
            lms_discount_client = EdxRestApiClient(
                discount_lms_url,
                jwt=self.request.site.siteconfiguration.access_token)
            ck = committed_basket.lines.first().product.course_id
            user_id = committed_basket.owner.lms_user_id
            response = lms_discount_client.course(ck).get()
            self.request.GET = self.request.GET.copy()
            self.request.GET['discount_jwt'] = response.get('jwt')
            self.request.POST = self.request.POST.copy()
            self.request.POST['discount_jwt'] = response.get('jwt')
        Applicator().apply(committed_basket, self.request.user, self.request)
        basket_add_organization_attribute(committed_basket, self.request.POST)
        committed_basket.freeze()
        try:
            billing_address = self.payment_processor.get_address_from_token(
                token)
        except Exception:  # pylint: disable=broad-except
            logger.exception(
                'An error occurred while parsing the billing address for basket [%d]. No billing address will be '
                'stored for the resulting order [%s].', committed_basket.id,
                order_number)
            billing_address = None

        try:
            self.handle_payment(token, committed_basket)
        except Exception:  # pylint: disable=broad-except
            logger.exception(
                'An error occurred while processing the Stripe payment for basket [%d].',
                committed_basket.id)
            return JsonResponse({}, status=400)

        # Remove paid items from last open baskets
        user_baskets = Basket.objects.filter(owner=self.request.user,
                                             status="Open")
        if user_baskets.exists():
            last_open_basket = user_baskets.last()
            del_lines = committed_basket.all_lines()
            open_lines = last_open_basket.all_lines()
        for line in del_lines:
            product = line.product
            filtered_lines = open_lines.filter(product_id=product.id)
            if filtered_lines.exists():
                filtered_lines.delete()
            last_open_basket.save()

        try:
            order = self.create_order(self.request,
                                      committed_basket,
                                      billing_address=billing_address)
            send_confirm_purchase_email(None,
                                        user=self.request.user,
                                        order=order)
        except Exception:  # pylint: disable=broad-except
            logger.exception(
                'An error occurred while processing the Stripe payment for basket [%d].',
                committed_basket.id)
            return JsonResponse({}, status=400)

        self.handle_post_order(order)

        receipt_url = get_receipt_page_url(
            site_configuration=self.request.site.siteconfiguration,
            order_number=order_number,
            disable_back_button=True,
        )
        return JsonResponse({'url': receipt_url}, status=201)