Umbraco.Commerce Custom Payment Provider: Unsure h...
# help-with-umbraco
a
I'm creating a custom payment provider based on Braintree, and basically I create a new c# controller to handle payment to the braintree api (and this works) but then I need to return to the ProcessCallbackAsync() method. It isnt clear to me how to do that, even after looking at sample payment provider code examples for Stripe & Paypal. It appears ProcessCallbackAsync() only gets called if FinalizeAtContinueUrl => true. I'm usure how to actually fire the correct webhook after payment processing is complete. Any pointers? I only want to finalize the order and empty the user's shopping cart if payment completed successfully. Of course I could manually finalize the order via the Umbraco Commerce API, but I'm trying to do this as standard as possible. https://cdn.discordapp.com/attachments/1294414029082726461/1294414029309083678/image.png?ex=670aec81&is=67099b01&hm=3775cc9a779438ac9d0d33c30842f362eef0748152b2379d920a348342bcf1ce&
Also, shouldn't ProcessCallbackAsync()'s CallbackResult.BadRequest() stop finalization of the order? Why does this let finalization continue even if there was an error in processing?
ok I may have found my answer. I just found documentation on the webhook configuration. I'll try this and see if I can get it to fire. https://github.com/umbraco/UmbracoDocs/blob/main/commerce-add-ons/payment-providers/stripe/configuring-stripe.md#step-3-webhook I'm also now thinking that ProcessCallbackAsync() should only fire when an order finalization should happen. I'll try to avoid hitting it until I get a successful payment kickoff.
m
That’s correct. The callback method is usually triggered as a webhook but can also be triggered on continue if expressly set by the provider (this is usually only necessary for gateways that don’t support webhooks). When using the callback handler via webhooks there are two approaches. 1) if the gateway can accept a callback url per order, UC provides one two you in the context.URLs property. This is already scoped to the order. 2) where the gateway supports a single callback url for all order (like stripe) you have to manually configure the callback url like the Stripe docs outline and then your provider needs to also implement the method that can parse out an order reference from the webhook body before the callback method is called. It’s generally nicer to use option 1 if you can, but it depends on the gateway. Re Braintree, I think I did look at this a while back but they seemed to have a bit of a weird setup I couldn’t get to fit into the provider model, but you are welcome to try. Just a possible heads up if you do get into difficulties.
a
Thanks Matt!
@Matt Brailsford question, is there any reason why finalizing an order via code would not complete before the confirmation page shows? I'm experiencing that sometimes the order isn't final on the confirmation page - but the page loads after the finalization. I wish I could wait until finalization is complete. _commerceApi.Uow.Execute(uow => { _commerceApi.GetCurrentOrder(storeGuid) .AsWritable(uow) .InitializeTransaction() .Finalize(amountAuthorized, transactionResult.Target?.Id, BraintreeCheckoutPaymentProvider.GetPaymentStatus(transactionResult)); _commerceApi.SaveOrder(order); result.Success = true; uow.Complete(); });
m
From the code snippet it looks like you are not saving the writable order to a variable, so when you are calling SaveOrder it’s potentially the order before you made the changes.
a
thanks for the catch. The issue persists, however I can get the order confirmation page to render the finalized order correctly 100% of the time if I ajax request the confirmation page, wait for it to load, then redirect to the confirmation page. (basically the second load works 100% of the time). I'm guessing that somehow the system doesn't know the order is finalized until after the next cart fetch request.
m
There should be middleware that moves the current order to the current finalized order in the session once it becomes finalized. You could probably force it my calling the session manager SetCurrentFinalizedOrder (this may be wrong as I’m trying to remember off the top of my head, but it’s something like that)
a
wow, thanks. I actually got it to work by calling ISessionManager.CheckAndMoveSessionOrders(): _commerceApi.SaveOrder(writeableOrder); _commerceSessionManager.CheckAndMoveSessionOrders(); this seems to kickstart the finalization for pending finalized orders
m
Glad it worked, but it’s definitely weird. That is exactly what the middleware calls so it should be automatic, but hey, if it works (there is no harm in manually calling it)
a
one more PaymentProvider question - I've set CanFetchPaymentStatus, enabled it in the backoffice, and added an override for FetchPaymentStatusAsync. It seems **FetchPaymentStatusAsync **isn't being called yet. Am I missing a step, or does it fire at long intervals, say once every 24hrs? I am using Umbraco 14, maybe this functionality isn't done yet.
m
I think it’s only really fetched when you open the order to edit. TBH if you have webhook support setup, it’s probably not needed as the webhook can update the state whenever it changes. The fetching is only necessary if there is no alternative way to update the state.
10 Views