Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Keith Donnell 82 posts 187 karma points
    Feb 26, 2015 @ 00:03
    Keith Donnell
    0

    Payments with Stripe provider

    The code below generates an invoice record every time payment fails (i.e. invalid CC#).  How do I prevent this, and append failed payments to a single invoice?  The line attempt = preparation.AuthorizePayment(paymentMethod.Key, args); is what generates the invoice, regardless whether one already exists for an order or not.


    // payment attempt result information
    IPaymentResult attempt = null;
    // get payment method
    var paymentMethod = Payment.GetPaymentGatewayMethodByKey(model.PaymentMethodKey).PaymentMethod;
    // Save the payment method selection
    preparation.SavePaymentMethod(paymentMethod);
    // make sure there is a billing address - it can be empty - it just has to exist
    if
    (!preparation.IsReadyToInvoice()) return Redirect("/cart");

               
    var args = new ProcessorArgumentCollection();
                args
    .Add("cardholderName", preparation.GetBillToAddress().Name);
                args
    .Add("cardNumber", model.CreditCardNumber);
                args
    .Add("expireMonth", model.ExpirationMonth);
                args
    .Add("expireYear", model.ExpirationYear);
                args
    .Add("cardCode", model.Cvv);
                attempt
    = preparation.AuthorizePayment(paymentMethod.Key, args);

               
    // if payment isn't successful, grab some information
               
    if (!attempt.Payment.Success)
               
    {
                    error
    = true;
                    _log
    .CreateAuditLogWithKey("Checkout failed - attempt payment failure", preparation.Customer.ExtendedData);
                   
    return CurrentUmbracoPage();
               
    }
  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Feb 26, 2015 @ 02:29
    Rusty Swayne
    100

    One way to do it -

    If the payment fails you will have

     attempt.Payment.Success == false;
    

    but the invoice has been created and saved to the database ...

     var invoice = attempt.Invoice;  // has not been paid.
     var payment = attempt.Payment.Result;
    

    You can get the invoice key and do something like

     var key = attempt.Invoice.Key;
     CustomerContext.SetValue("invoiceKey", attempt.Invoice.Key.ToString());  // save the invoice key in the Merchello cookie.
    

    and then go back and ask for another form of payment.

    When the customer submits a second payment (or different cc number)

    var dataKey = CustomerContext.GetValue("invoiceKey");
    var invoiceKey = new Guid(dataKey);
    
    var invoice = MerchelloContext.Current.Services.InvoiceService.GetByKey(invoiceKey);
    
    // use the extension directly off off the invoice
    invoice.AuthorizeCapturePayment([payment method], ....)
    
  • Keith Donnell 82 posts 187 karma points
    Feb 26, 2015 @ 16:51
    Keith Donnell
    0

    @Rusty I'm not sure what CustomerContext is in your example above.  The CustomerContext object doesn't expose a SetValue method that I can see.  I think I understand what you're getting at, though - I need to save the failed invoice key, and if it exists, re-use that invoice and attempt another payment.

    I believe I can use

    CustomerContext.CurrentCustomer.ExtendedData.SetValue("invoiceKey", key)

    And

    CustomerContext.CurrentCustomer.ExtendedData.GetValue("invoiceKey")

    However, once the payment is successful (and the order is opened), I will need to make sure I clear out this value, as I assume the customer is still the same, and we don't want a 2nd order to attempt to re-use the invoice from the first order.

    That being said, the issue would still exist that if a customer fails payment, the invoice would still appear in the dashboard, and barely looks different from an open order.  I think my best option might be to actually delete the invoice using the InvoiceService upon payment failure - I think we really only want to see "Open" orders in the dashboard, however this would prevent a customer service rep from being able to administer a failed order.  Hmm.

    I will play around with these two options and see what works best.

  • Keith Donnell 82 posts 187 karma points
    Feb 26, 2015 @ 17:17
    Keith Donnell
    0

     (Moved to separate topic)

  • Alex Lindgren 159 posts 356 karma points
    Feb 26, 2015 @ 22:30
    Alex Lindgren
    2

    Hi Keith,

    As the one who created the Stripe provider, I have been using it for a project that only has anonymous customers and the checkout code is based on earlier examples then what have been published now. So it is quite possible that I missed a bug that is causing your problem. If that's the case, I want to fix it quickly. I'll try to find some time to look at this problem. I'll try to reproduce the problem with the example sites, but if I can't, I may need you to send me more info.

    Thanks,

    Alex

  • Keith Donnell 82 posts 187 karma points
    Feb 26, 2015 @ 23:42
    Keith Donnell
    0

    @Alex Most definitely.  My initial question about the multiple invoices appears to be by design, and I have corrected that particular issue by storing the initial invoice id/key with the customer extended data, and re-using that invoice for future payment attempts.

    Are you saying one or more of the 3 new items above might be the Stripe provider?

  • Alex Lindgren 159 posts 356 karma points
    Feb 27, 2015 @ 00:23
    Alex Lindgren
    0

    I think probably not, as the invoice creation happens in the Merchello core, but I couldn't understand how you got https://our.umbraco.org/projects/collaboration/merchello/merchello/61761-Invoice-dashboard-issues

    I have been planning some updates to the Stripe provider, and wanted to make sure that if there are bugs, I address them.

  • Keith Donnell 82 posts 187 karma points
    May 05, 2015 @ 22:01
    Keith Donnell
    0

    As a follow-up, I have determined that using the method that Rusty mentioned (to store the invoice key and attempt to re-use the same invoice record) causes issues when the user adjusts their cart after their first payment attempt.  Apparently, the invoice record doesn't recalculate the amount based on the current state of the basket, so you will end up invoicing your customer a lesser or greater amount than the current basket's value.  I ended up having to revert back to having the plethora of "junk" invoices in the dashboard :(

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    May 05, 2015 @ 22:54
    Rusty Swayne
    0

    @Keith - can you elaborate on what you mean by the invoice record doesn't recalculate the amount based on the current state of the basket? Once an invoice is created, I would think the basket contents are irrelevant and you are now concerned with the actual sale and not altering what is being sold. Think I'm missing something here ...

  • Keith Donnell 82 posts 187 karma points
    May 06, 2015 @ 00:03
    Keith Donnell
    0

    @Rusty It's a catch-22 for us (again, this may be an issue with the Stripe Provider?).

    When we call preparation.AuthorizeCapturePayment(), an invoice record is created whether the payment is successful or not.  If payment fails (i.e. invalid card number), we show a validation message.  At this point, if they somehow decide that they forgot something, they can add it to their cart, and go through the checkout process again.  The workaround above (saving the original invoice key and calling existingInvoice.AuthorizeCapturePayment() on successive attempts) causes the original invoice to potentially have a different dollar amount than the current state of the basket.

    The original issue was that we were seeing invoices in the dashboard for failed payments, one for each failure.  A single customer failing 5 times generates 5 invoices, and I was hoping to avoid that by keeping a 1-to-1 invoice-to-basket relationship somehow.  If there was a way to just hide unpaid invoices within the dashboard (and search them), I feel that would be sufficient for what I'm trying to accomplish.

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    May 06, 2015 @ 01:13
    Rusty Swayne
    0

    I see. What is happening is a Merchello thing. The basket is coupled to the the SalesPreparation by a version key. The idea is if you start a checkout (not complete it) and then go back and futz around in the basket, the SalePreparation gets invalidated as weights, prices, quantities of items in the basket could have been changed - thus there could be changes in shipping and taxation, etc.

    Merchello assumes that when the invoice is created, the the intent of the customer has been confirmed and whatever items it includes should not be modified. What's happening when you go back and add something to the basket, the version key changes and it invalidates the sales preparation and Merchello thinks it's dealing with a completely new sale - thus the new invoice.

    You could either delete the failed invoice if the basket is modified OR empty the basket and attempt a repayment of the failed invoice. There is probably not too much code to do in order to get your workflow going, but you would have to circumvent the SalesPreparation object. The basket uses the BasketSalesPreparation object which in turn sub classes SalePreparationBase in the Core. Maybe make your own CustomSalePreparation object that sub classed the SalePreparationBase and created "new" version of the AuthorizeCapture ... you'd have to test it pretty well though.

  • Keith R Hubbard 175 posts 403 karma points
    Jan 03, 2018 @ 03:46
    Keith R Hubbard
    0

    Is there a working version of stripe provider? I get error's when trying to build.

Please Sign in or register to post replies

Write your reply to:

Draft