コード例 #1
0
ファイル: api.py プロジェクト: kimdhamilton/mitxpro
def fulfill_order(request_data):
    """
    Fulfill an order for end user purchase of a Product.

    Args:
        request_data (dict): Request data from CyberSource
    """
    # First, save this information in a receipt
    receipt = Receipt.objects.create(data=request_data)

    # Link the order with the receipt if we can parse it
    reference_number = request_data["req_reference_number"]
    req_bill_to_email = request_data.get("req_bill_to_email")
    order = Order.objects.get_by_reference_number(reference_number)
    receipt.order = order
    receipt.save()

    new_order_status = determine_order_status_change(order,
                                                     request_data["decision"])
    if new_order_status is None:
        # This is a duplicate message, ignore since it's already handled
        return

    order.status = new_order_status
    order.save()
    sync_hubspot_deal(order)

    if order.status == Order.FULFILLED:
        complete_order(order)
        if settings.ENABLE_ORDER_RECEIPTS:
            send_ecommerce_order_receipt(
                order=order, cyber_source_provided_email=req_bill_to_email)

    # Save to log everything to an audit table including enrollments created in complete_order
    order.save_and_log(None)
コード例 #2
0
    def post(
        self, request, *args, **kwargs
    ):  # pylint: disable=too-many-locals,unused-argument
        """
        Create a new unfulfilled Order from the user's basket
        and return information used to submit to CyberSource.
        """
        validated_basket = validate_basket_for_checkout(request.user)
        affiliate_id = get_affiliate_id_from_request(request)
        order = create_unfulfilled_order(validated_basket, affiliate_id=affiliate_id)
        base_url = request.build_absolute_uri("/")
        text_id = validated_basket.product_version.product.content_object.text_id
        receipt_url = make_receipt_url(base_url=base_url, readable_id=text_id)
        user_ip, _ = get_client_ip(request)

        if order.total_price_paid == 0:
            # If price is $0, don't bother going to CyberSource, just mark as fulfilled
            order.status = Order.FULFILLED
            order.save()
            sync_hubspot_deal(order)

            complete_order(order)
            order.save_and_log(request.user)

            product = validated_basket.product_version.product

            # $0 orders do not go to CyberSource so we need to build a payload
            # for GTM in order to track these purchases as well. Actual tracking
            # call is sent from the frontend.
            payload = {
                "transaction_id": "T-{}".format(order.id),
                "transaction_total": 0.00,
                "product_type": product.type_string,
                "courseware_id": text_id,
                "reference_number": "REF-{}".format(order.id),
            }

            # This redirects the user to our order success page
            url = receipt_url
            if settings.ENABLE_ORDER_RECEIPTS:
                send_ecommerce_order_receipt(order)
            method = "GET"
        else:
            # This generates a signed payload which is submitted as an HTML form to CyberSource
            cancel_url = urljoin(base_url, "checkout/")
            payload = generate_cybersource_sa_payload(
                order=order,
                receipt_url=receipt_url,
                cancel_url=cancel_url,
                ip_address=user_ip,
            )
            url = settings.CYBERSOURCE_SECURE_ACCEPTANCE_URL
            method = "POST"

        return Response({"payload": payload, "url": url, "method": method})
コード例 #3
0
ファイル: api.py プロジェクト: kimdhamilton/mitxpro
def create_unfulfilled_order(validated_basket, affiliate_id=None):
    """
    Create a new Order which is not fulfilled for a purchasable Product. Note that validation should
    be done in the basket REST API so the validation is not done here (different from MicroMasters).

    Args:
        validated_basket (ValidatedBasket): The validated Basket and related objects
        affiliate_id (Optional[int]): The id of the Affiliate record to associate with this order

    Returns:
        Order: A newly created Order for the Product in the basket
    """
    with transaction.atomic():
        total_price_paid = get_product_version_price_with_discount(
            coupon_version=validated_basket.coupon_version,
            product_version=validated_basket.product_version,
        )
        order = Order.objects.create(
            status=Order.CREATED,
            purchaser=validated_basket.basket.user,
            total_price_paid=total_price_paid,
        )
        line = Line.objects.create(
            order=order,
            product_version=validated_basket.product_version,
            quantity=validated_basket.basket_item.quantity,
        )
        if validated_basket.basket_item.program_run:
            ProgramRunLine.objects.create(
                line=line,
                program_run=validated_basket.basket_item.program_run)
        if validated_basket.run_selection_ids:
            LineRunSelection.objects.bulk_create(
                LineRunSelection(line=line, run_id=run_id)
                for run_id in validated_basket.run_selection_ids)
        if validated_basket.coupon_version:
            redeem_coupon(coupon_version=validated_basket.coupon_version,
                          order=order)
        if affiliate_id is not None:
            AffiliateReferralAction.objects.create(affiliate_id=affiliate_id,
                                                   created_order=order)
    sync_hubspot_deal(order)
    return order
コード例 #4
0
 def save_model(self, request, obj, form, change):
     """
     Saves object and logs change to object
     """
     super().save_model(request, obj, form, change)
     sync_hubspot_deal(obj)