Page 1 of 1

Check out programmatically

Posted: Mon Oct 10, 2016 3:24 am
by jason2
I have a mobile app which connects to an older version of AbleCommerce (R5). I've written my own web services layer to look up an existing customer (or create an anonymous user), manipulate the basket, handle shipping, taxes, payment, and coupons. But I'm stuck at the last step and actually checking out the basket. Checkout through the Able store itself works just fine.

Example code:

Code: Select all

var basket = BasketDataSource.Load(basketId);
var checkoutService = new CommerceBuilder.Services.Checkout.CheckoutService();
var checkoutRequest = new CheckoutRequest(basket, payment);
var checkoutResponse = checkoutService.ExecuteCheckout(checkoutRequest);
The payment variable is created from another method which is essentially a copy of what is in the CreditCaardPaymentForm web control.

Code: Select all

public Payment GetPayment(double amount, int paymentMethodId, string nameOnCard, string cardNumber, string expirationMonth, string expirationYear, string cvv)
{
    var payment = new Payment
    {
        PaymentMethod = PaymentMethodDataSource.Load(paymentMethodId),
        Amount = AlwaysConvert.ToDecimal(amount)
    };

    var instrumentBuilder = new AccountDataDictionary
    {
        ["AccountName"] = nameOnCard,
        ["AccountNumber"] = cardNumber,
        ["ExpirationMonth"] = expirationMonth,
        ["ExpirationYear"] = expirationYear,
        ["SecurityCode"] = cvv
    };

    payment.ReferenceNumber = Payment.GenerateReferenceNumber(cardNumber);
    payment.AccountData = instrumentBuilder.ToString();
    return payment;
}
I'm getting the following message:
"There was a problem processing your payment: (TESTMODE) The merchant login ID or password is invalid or the account is inactive."
It looks like what is happening is that the CheckoutService that I'm creating is being initialized with default values (such as empty strings) and being returned without any of the merchant gateway (and other settings) that would normally be initialized if those were created through the normal checkout process using AbleContext.Resolve<CommerceBuilder.Services.Checkout.ICheckoutService>();

I can peek into these classes with my version of Visual Studio and I don't see any properties or other constructors/methods that are exposed to allow for setting these values manually. I do see several mentions of AbleContext.Current in these classes, so that's what leads me to believe that they were only coded to initialize properly from a normal session of a user on the web site.

Is there any way around this, or another approach that I can take for checking out a user?

Re: Check out programmatically

Posted: Mon Oct 10, 2016 8:14 am
by jason2
So a solution (a workaround) is to put this checkout code in an ASPX page somewhere within the AbleCommerce site instead of a clean, modern API, so that sending the page a post request initializes the AbleContext (session) which will in turn properly initializes the CheckoutService and Payment service when created.

It's kind of a shame that Able goes to the trouble of using principles like IoC only to tightly couple the inner workings and initialization of its components so that they can only be used when in the context of a person/request hitting a web page from within the site. That really defeats the whole purpose of using IoC for extensibility to begin with.

Re: Check out programmatically

Posted: Mon Oct 10, 2016 11:28 am
by jguengerich
When you say you've written your own web services layer, does that mean you are not customizing the CommerceBuilder.WebApi project that is part of the AbleCommerce source code?

Re: Check out programmatically

Posted: Mon Oct 10, 2016 12:49 pm
by jason2
Do you mean this?

http://wiki.ablecommerce.com/index.php/ ... d_Web_Api

It appears that is just a set of endpoints for CRUD operations with products. Web API practically auto-generates that given an entity, but what I needed in this case was to hook into the actual checkout business logic and call it. It has been a long day of fighting with something called "Able" (the irony is actually hilarious the more I think about it), so I'll call this solved with the workaround that I found above.

Re: Check out programmatically

Posted: Mon Oct 10, 2016 11:27 pm
by mazhar
Make sure the payment gateway associated with your payment method is configured in ablecommerce and has working merchant account details. Also why not use Windsor container to resolve ablecommerce service instead of creating new instance? You should be able to use AbleContext.Container.Resolve<ICheckoutService>() and use the returned service object to process your calls.

Re: Check out programmatically

Posted: Tue Oct 11, 2016 3:50 am
by jguengerich
jason2 wrote:It appears that is just a set of endpoints for CRUD operations with products.
Out of the box, that is correct (R12 added Users and Orders). However, if you have purchased the AbleCommerce source, you can add you own functionality to it. I was just trying to clarify if that is what you were doing, in case that would help someone determine the answer to your question.

Re: Check out programmatically

Posted: Wed Oct 12, 2016 4:43 am
by AbleMods
jason2 wrote:Is there any way around this, or another approach that I can take for checking out a user?
I built a full REST api for a client to use with their iOS mobile app. It exposes practically everything needed to drive an Able store through the API. Basket management, user management, checkout etc. We get about 400 orders a month through the app.

It works really well. I could share my checkout endpoint code with you if you'd like to see how I do it?