示例#1
0
        public virtual Task <Overture.ServiceModel.Orders.Order> CompleteCheckoutAsync(CompleteCheckoutParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException("param", "param");
            }
            if (string.IsNullOrWhiteSpace(param.CartName))
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("param.CartName"), "param");
            }
            if (param.CultureInfo == null)
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("CultureInfo"), "param");
            }
            if (param.CustomerId == Guid.Empty)
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("CustomerId"), "param");
            }
            if (string.IsNullOrWhiteSpace(param.Scope))
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("Scope"), "param");
            }

            var request = new CompleteCheckoutRequest
            {
                CartName    = param.CartName,
                CultureName = param.CultureInfo.Name,
                CustomerId  = param.CustomerId,
                ScopeId     = param.Scope
            };

            return(OvertureClient.SendAsync(request));
        }
示例#2
0
        public virtual Task <Overture.ServiceModel.Orders.Order> CompleteCheckoutAsync(CompleteCheckoutParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException(nameof(param));
            }
            if (string.IsNullOrWhiteSpace(param.CartName))
            {
                throw new ArgumentException(GetMessageOfNullWhiteSpace(nameof(param.CartName)), nameof(param));
            }
            if (param.CultureInfo == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(param.CultureInfo)), nameof(param));
            }
            if (param.CustomerId == Guid.Empty)
            {
                throw new ArgumentException(GetMessageOfEmpty(nameof(param.CustomerId)), nameof(param));
            }
            if (string.IsNullOrWhiteSpace(param.Scope))
            {
                throw new ArgumentException(GetMessageOfNullWhiteSpace(nameof(param.Scope)), nameof(param));
            }

            var request = new CompleteCheckoutRequest
            {
                CartName    = param.CartName,
                CultureName = param.CultureInfo.Name,
                CustomerId  = param.CustomerId,
                ScopeId     = param.Scope
            };

            return(OvertureClient.SendAsync(request));
        }
示例#3
0
        public virtual async Task <IHttpActionResult> CompleteCheckout(CompleteCheckoutRequest request)
        {
            if (request == null)
            {
                return(BadRequest("No request body found."));
            }

            var nextStepUrl = CartUrlProvider.GetCheckoutStepUrl(new GetCheckoutStepUrlParam
            {
                CultureInfo = ComposerContext.CultureInfo,
                StepNumber  = request.CurrentStep + 1
            });

            var checkoutViewModel = await CheckoutService.CompleteCheckoutAsync(new CompleteCheckoutParam
            {
                CartName    = CartConfiguration.ShoppingCartName,
                CustomerId  = ComposerContext.CustomerId,
                CultureInfo = ComposerContext.CultureInfo,
                Scope       = ComposerContext.Scope,
                BaseUrl     = RequestUtils.GetBaseUrl(Request).ToString(),
            });

            checkoutViewModel.NextStepUrl = nextStepUrl;

            return(Ok(checkoutViewModel));
        }
示例#4
0
        /// <summary>
        /// If you pass 'true’ to 'merchant_completes’ in our Create CreateCheckoutRequest flow, then you must call our Complete CreateCheckoutRequest endpoint.
        /// For some checkouts, a merchant may need to have the user return to their site for additional steps before completing the purchase.
        /// If this is the case, the order completion endpoint is used to complete the CreateCheckoutRequest with Sezzle.
        /// From the time the user is redirected back to the Merchant’s site, you must make the request to complete the createCheckoutRequest within 30 minutes, or the createCheckoutRequest will be
        /// cancelled by Sezzle. If the createCheckoutRequest has expired, we will return the rejection response on the right, with a Status 409
        /// There are two non-error responses expected. Either an HTTP 200 (currently no response body) or a rejection message.
        /// </summary>
        /// <param name="completeCheckoutRequest"></param>
        /// <remarks>
        ///     https://gateway.sezzle.com/v1/checkouts/{order_reference_id}/complete
        /// </remarks>
        /// <returns></returns>
        public async Task <CompleteCheckoutResponse> CompleteAsync(CompleteCheckoutRequest completeCheckoutRequest)
        {
            var tokenTask = _authenticationEndpoint.CreateTokenAsync();

            //create url and request object
            var requestUrl = UrlStringExtensions.FormatRequestUrl(GetCheckoutsBaseUrl(), $"{completeCheckoutRequest.LocalOrderId}/complete");

            var token    = await tokenTask;
            var response = await _sezzleHttpClient.PostAsync <CompleteCheckoutRequest, CompleteCheckoutResponse>(token.Token, requestUrl, null);

            return(response);
        }
示例#5
0
        public void CanCompleteACheckoutWithMerchantCompletes()
        {
            // TODO: Mark this test as ignored and require a parameter to send the order reference id into it
            var request = new CompleteCheckoutRequest()
            {
                LocalOrderId = "636773928435687781"
            };

            var checkouts = CreateCheckoutClient();

            // Now let's try completing it
            var completeResponse = checkouts.CompleteAsync(request);

            // Per Sezzle, an empty response body is success
            Assert.IsNotNull(completeResponse);
        }
示例#6
0
        public async Task FullWorkflowWithMerchantCompletesEqualsTrue_Positive()
        {
            //** Create the Checkout/Order
            var checkouts             = CreateCheckoutClient();
            var orderReferenceId      = DateTime.UtcNow.Ticks.ToString();
            var createCheckoutRequest = GenerateValidCreateCheckoutRequest(orderReferenceId, false);

            createCheckoutRequest.MerchantCompletes = true;
            var checkoutResponse = await checkouts.CreateAsync(createCheckoutRequest);

            Console.WriteLine(checkoutResponse.CheckoutUrl);

            // ** get order details.
            //verify that order is in customer NotPaid status.
            var orders = new OrdersEndpoint(_baseConfiguration, _authenticationClient, GetDefaultSezzleHttpClient());
            var orderDetailsRequest = new OrderDetailsRequest()
            {
                IncludeShippingInfo = true,
                OrderReferenceId    = orderReferenceId
            };

            // ** check order status. get order details before user has been redirected to the checkout URL
            var orderDetailsBeforeUserChecksOut = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(orderDetailsBeforeUserChecksOut.OrderStatus, Enums.OrderStatusEnum.S0010OrderCreated);

            //***********Existing Customer goes to checkout And completes checkout
            _sezzleCheckoutAutomationHelper.CompleteCheckoutClientSide(checkoutResponse.CheckoutUrl, base.GetCustomerLoginCredentials(), createCheckoutRequest.CheckoutCompleteUrl);

            // verify order status is now in the checked out status
            var orderDetailsBeforeMerchantCompletesCheckout = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(orderDetailsBeforeMerchantCompletesCheckout.OrderStatus, Enums.OrderStatusEnum.S0020UserHasCheckedOut);

            //merchant completes the checkout/order. (we had used merchantcompletes=true)
            var completeCheckoutRequest = new CompleteCheckoutRequest()
            {
                LocalOrderId = orderReferenceId
            };
            await checkouts.CompleteAsync(completeCheckoutRequest);

            //get order details.  order should now be complete, meaning sezzle has captured the funds and we are guaranteed the full amount.
            var orderDetailsAfterMerchantCompletesCheckout = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(Enums.OrderStatusEnum.S0030FundsCapturedAllDoneBoomshakalakaYippiekiyay, orderDetailsAfterMerchantCompletesCheckout.OrderStatus);
        }
示例#7
0
        public async Task FullWorkflowWithMerchantCompletesEqualsTrue_AttemptToCompleteCheckoutWithoutCustomerCompleting_Negative()
        {
            //** Create the Checkout/Order
            var checkouts             = CreateCheckoutClient();
            var orderReferenceId      = DateTime.UtcNow.Ticks.ToString();
            var createCheckoutRequest = GenerateValidCreateCheckoutRequest(orderReferenceId, false);

            createCheckoutRequest.MerchantCompletes = true;
            var checkoutResponse = await checkouts.CreateAsync(createCheckoutRequest);

            // ** get order details.
            //verify that order is in customer NotPaid status.
            var orders = new OrdersEndpoint(_baseConfiguration, _authenticationClient, GetDefaultSezzleHttpClient());
            var orderDetailsRequest = new OrderDetailsRequest()
            {
                IncludeShippingInfo = true,
                OrderReferenceId    = orderReferenceId
            };

            // ** check order status. get order details before user has been redirected to the checkout URL
            var orderDetailsBeforeUserChecksOut = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(orderDetailsBeforeUserChecksOut.OrderStatus, Enums.OrderStatusEnum.S0010OrderCreated);

            Func <Task> act = async() =>
            {
                //merchant completes the checkout/order. (we had used merchantcompletes=true)
                var completeCheckoutRequest = new CompleteCheckoutRequest()
                {
                    LocalOrderId = orderReferenceId
                };
                var response = await checkouts.CompleteAsync(completeCheckoutRequest);
            };

            //exception is thrown from sezzle because you cannot complete a checkout that has not been completed by user.
            act.Should().Throw <SezzleErrorResponseException>();
        }
示例#8
0
        public async Task CanCreateOrder_CustomerCompletes_MerchantCompletes_RefundPartial()
        {
            //arrange
            var orderReferenceId = DateTime.UtcNow.Ticks.ToString();

            var checkoutEndpoint      = new CheckoutEndpoint(_baseConfiguration, _authenticationClient, GetDefaultSezzleHttpClient());
            var createCheckoutRequest = GenerateValidCreateCheckoutRequest(orderReferenceId);

            createCheckoutRequest.MerchantCompletes = true;
            //makes it easier to script completion of checkout by a user.
            createCheckoutRequest.RequiresShippingInfo = false;

            var completeCheckoutRequest = new CompleteCheckoutRequest()
            {
                LocalOrderId = createCheckoutRequest.OrderReferenceId
            };

            var ordersEndpoint = new OrdersEndpoint(_baseConfiguration, _authenticationClient, GetDefaultSezzleHttpClient());

            var request = new OrderDetailsRequest()
            {
                IncludeShippingInfo = true,
                OrderReferenceId    = orderReferenceId
            };

            //create refund request
            var refundAmount         = 123;
            var partialRefundRequest = new OrderRefundRequest()
            {
                Amount = new Price()
                {
                    AmountInCents = refundAmount,
                    Currency      = Enums.CheckoutCurrencyCodeEnum.USD
                },
                IsFullRefund     = false,
                OrderReferenceId = orderReferenceId,
                RefundId         = $"gh_refund_{DateTime.UtcNow.Ticks.ToString()}",
                RefundReason     = "some reason here"
            };

            //act
            //10 create order
            var order = await checkoutEndpoint.CreateAsync(createCheckoutRequest);

            Console.WriteLine(JsonConvert.SerializeObject(order, Formatting.Indented));

            //20 get order details
            var orderDetails = await ordersEndpoint.GetDetailsAsync(request);

            Console.WriteLine(JsonConvert.SerializeObject(orderDetails, Formatting.Indented));

            //30 (user completes checkout - use selenium) complete the checkout
            //todo: use selenium to complete the checkout through user workflow.

            //40 merchant completes the checkout.
            var completedCheckout = await checkoutEndpoint.CompleteAsync(completeCheckoutRequest);

            //partial refund
            var refundResponse = await ordersEndpoint.RefundAsync(partialRefundRequest);

            //test #1, verify order refund is processed and returns data as sent in.
            Assert.AreEqual(refundAmount, refundResponse.Amount.AmountInCents);
            Assert.AreEqual(partialRefundRequest.RefundId, refundResponse.RefundId);

            //get order details again.  the order value should have changed by the amount refunded.
            var orderDetails2 = await ordersEndpoint.GetDetailsAsync(request);

            //test #2, verify order amount has changed after refund
            //todo: this ammount does not actually change like I expected it to.  Perhaps there is a missing endpoint where we can see what modified the order (refunds).
            //long expectedOrderAmountAfterRefund = orderDetails.AmountInCents - refundAmount;
            //Assert.AreEqual(expectedOrderAmountAfterRefund, orderDetails2.AmountInCents);
        }
示例#9
0
        public async Task FullWorkflowWithMerchantCompletesEqualsTrue_ThenRefundFullAmount_Positive()
        {
            //** Create the Checkout/Order
            var checkouts             = CreateCheckoutClient();
            var orderReferenceId      = DateTime.UtcNow.Ticks.ToString();
            var createCheckoutRequest = GenerateValidCreateCheckoutRequest(orderReferenceId, false);

            createCheckoutRequest.MerchantCompletes = true;
            var checkoutResponse = await checkouts.CreateAsync(createCheckoutRequest);

            Console.WriteLine(checkoutResponse.CheckoutUrl);

            // ** get order details.
            //verify that order is in customer NotPaid status.
            var orders = new OrdersEndpoint(_baseConfiguration, _authenticationClient, GetDefaultSezzleHttpClient());
            var orderDetailsRequest = new OrderDetailsRequest()
            {
                IncludeShippingInfo = true,
                OrderReferenceId    = orderReferenceId
            };

            // ** check order status. get order details before user has been redirected to the checkout URL
            var orderDetailsBeforeUserChecksOut = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(orderDetailsBeforeUserChecksOut.OrderStatus, Enums.OrderStatusEnum.S0010OrderCreated);

            //***********Existing Customer goes to checkout And completes checkout
            _sezzleCheckoutAutomationHelper.CompleteCheckoutClientSide(checkoutResponse.CheckoutUrl, base.GetCustomerLoginCredentials(), createCheckoutRequest.CheckoutCompleteUrl);

            // verify order status is now in the checked out status
            var orderDetailsBeforeMerchantCompletesCheckout = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(orderDetailsBeforeMerchantCompletesCheckout.OrderStatus, Enums.OrderStatusEnum.S0020UserHasCheckedOut);

            //merchant completes the checkout/order. (we had used merchantcompletes=true)
            var completeCheckoutRequest = new CompleteCheckoutRequest()
            {
                LocalOrderId = orderReferenceId
            };
            await checkouts.CompleteAsync(completeCheckoutRequest);

            //get order details.  order should now be complete, meaning sezzle has captured the funds and we are guaranteed the full amount.
            var orderDetailsAfterMerchantCompletesCheckout = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(Enums.OrderStatusEnum.S0030FundsCapturedAllDoneBoomshakalakaYippiekiyay, orderDetailsAfterMerchantCompletesCheckout.OrderStatus);

            //**********************up to now, that is just a standard order.
            //now we refund

            var refundAmount = createCheckoutRequest.AmountInCents;

            var refundRequest = new OrderRefundRequest()
            {
                Amount = new Price()
                {
                    AmountInCents = refundAmount,
                    Currency      = Enums.CheckoutCurrencyCodeEnum.USD
                },
                OrderReferenceId = orderReferenceId,
                IsFullRefund     = false,
                RefundId         = Guid.NewGuid().ToString(),
                RefundReason     = "unit test reason"
            };

            var refundResponse = await orders.RefundAsync(refundRequest);

            //verifies amount was refunded
            Assert.AreEqual(refundAmount, refundResponse.Amount.AmountInCents);

            //get order status and verify that it is equal to the full original amount.  there are no endpoints that get the history of the refunds at this time.
            var orderStatusAfterPartialRefund = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(createCheckoutRequest.AmountInCents, orderStatusAfterPartialRefund.AmountInCents);
        }
示例#10
0
        public async Task FullWorkflowWithMerchantCompletesEqualsTrue_ThenRefundInvalidAmount_Negative()
        {
            //** Create the Checkout/Order
            var checkouts             = CreateCheckoutClient();
            var orderReferenceId      = DateTime.UtcNow.Ticks.ToString();
            var createCheckoutRequest = GenerateValidCreateCheckoutRequest(orderReferenceId, false);

            createCheckoutRequest.MerchantCompletes = true;
            var checkoutResponse = await checkouts.CreateAsync(createCheckoutRequest);

            Console.WriteLine(checkoutResponse.CheckoutUrl);

            // ** get order details.
            //verify that order is in customer NotPaid status.
            var orders = new OrdersEndpoint(_baseConfiguration, _authenticationClient, GetDefaultSezzleHttpClient());
            var orderDetailsRequest = new OrderDetailsRequest()
            {
                IncludeShippingInfo = true,
                OrderReferenceId    = orderReferenceId
            };

            // ** check order status. get order details before user has been redirected to the checkout URL
            var orderDetailsBeforeUserChecksOut = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(orderDetailsBeforeUserChecksOut.OrderStatus, Enums.OrderStatusEnum.S0010OrderCreated);

            //***********Existing Customer goes to checkout And completes checkout
            _sezzleCheckoutAutomationHelper.CompleteCheckoutClientSide(checkoutResponse.CheckoutUrl, base.GetCustomerLoginCredentials(), createCheckoutRequest.CheckoutCompleteUrl);

            // verify order status is now in the checked out status
            var orderDetailsBeforeMerchantCompletesCheckout = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(orderDetailsBeforeMerchantCompletesCheckout.OrderStatus, Enums.OrderStatusEnum.S0020UserHasCheckedOut);

            //merchant completes the checkout/order. (we had used merchantcompletes=true)
            var completeCheckoutRequest = new CompleteCheckoutRequest()
            {
                LocalOrderId = orderReferenceId
            };
            await checkouts.CompleteAsync(completeCheckoutRequest);

            //get order details.  order should now be complete, meaning sezzle has captured the funds and we are guaranteed the full amount.
            var orderDetailsAfterMerchantCompletesCheckout = await orders.GetDetailsAsync(orderDetailsRequest);

            Assert.AreEqual(Enums.OrderStatusEnum.S0030FundsCapturedAllDoneBoomshakalakaYippiekiyay, orderDetailsAfterMerchantCompletesCheckout.OrderStatus);

            //**********************up to now, that is just a standard order.

            // try to refund an amount greater than the initial checkout amount.  Verify our framework throws an exception.
            Func <Task> act = async() =>
            {
                //set the refund amount to 1 cent over the entire order.
                var refundAmount = createCheckoutRequest.AmountInCents + 1;

                var refundRequest = new OrderRefundRequest()
                {
                    Amount = new Price()
                    {
                        AmountInCents = refundAmount,
                        Currency      = Enums.CheckoutCurrencyCodeEnum.USD
                    },
                    OrderReferenceId = orderReferenceId,
                    IsFullRefund     = false,
                    RefundId         = Guid.NewGuid().ToString(),
                    RefundReason     = "unit test reason"
                };

                var refundResponse = await orders.RefundAsync(refundRequest);
            };

            //exception is thrown from sezzle because you cannot complete a checkout that has not been completed by user.
            act.Should().Throw <SezzleErrorResponseException>();
        }