Copied to clipboard

Flag this post as spam?

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


These support forums are now closed for new topics and comments.
Please head on over to http://eureka.ucommerce.net/ for support.

  • yann 13 posts 32 karma points
    Oct 29, 2012 @ 10:01
    yann
    0

    Custom external payment provider guidance

    Hi

    Could anybody provide me with some guidance about how to implement an external Payment provider.
    I guess my issue is to know when the different methods of the PaymentMethodService are called during the process...

    From what I can see, I am looking at UCommerce.Transactions.Payments.ExternalPaymentMethodService. In this class I can see multiple methods that I will need to override:

    • ProcessCallback: this will check the status of the payment and update the order status in UCommerce
    • RequestPayment: I am guessing this is where I will place my bussiness logic to contact my payment provider and get some AccessCode require for the payment later on.
    • ProcessPaymentRequest: Is this where I need to place the actual webservice call with credit card number?
    • AcquirePayment: not sure when this is needed

    So from my shopping cart, checkout usercontrol I will click on Checkout, which I think need to

    • instantiate my IPaymentMethodService:
      IPaymentMethodService paymentMethodService = paymentMethod.GetPaymentMethodService() ?? new DefaultPaymentMethodService();

    • and execute some code such as, which I guess execute some pipeline actions:

      Basket basket = SiteContext.Current.OrderContext.GetBasket(false);
      CheckoutService checkoutService = new CheckoutService();
      PurchaseOrder purchaseOrder = checkoutService.Checkout(basket);

    So at this point I am not sure how the methods in my payment method service will be called and in which order?
    The other way I can see the control working is to call each method manually from the usercontrol:

    IPaymentMethodService paymentMethodService = paymentMethod.GetPaymentMethodService() ?? new DefaultPaymentMethodService();
    PaymentRequest request = new PaymentRequest(purchaseOrder, payment);   
    // Request access Code
    Payment payment2 = paymentMethodService.RequestPayment(request);   

    // Proceed to payment with credit card details
    Payment payment3 = paymentMethodService.ProcessPaymentRequest(request);

    In that case, how do I get the order in ucommerce to be updated?

    Also I may need to store an AccessCode from the payment provider between the RequestPayment and the ProcessPayment as they may be executed in different control, where can I store this information? Can I pass them in the Payment object or do I have to use the Session?

    Thank you very much for your help

     

  • Søren Spelling Lund 1797 posts 2786 karma points
    Nov 02, 2012 @ 09:43
    Søren Spelling Lund
    0

    Hi Yann,

    Integrating with a Payment Gateway using External Payment Windows is exactly what you're after. Specifically you want the swimlane diagram of when individual methods are called.

    There are two approaches to building your payment provider: Client-side post to payment gateway or server-side redirect of the customer to the gateway.

    Here's the process for client-side redirect (details on how this works in general available at Payment Gateway Archetype: Outbound User Post):

    0) RequestPayment() is called to redirect the customer to your local payment form. The trick is to auto-submit this form to the gateway. uCommerce has a facility to do this by redirect to a local URL with the following format:

    string redirectUrl = string.Format("/{0}/{1}/PaymentRequest.axd", payment.PaymentMethod.PaymentMethodId, payment["paymentGuid"]);

    1) RenderForm() will be called by PaymentRequest.axd. This is where you build an HTML which includes values like currency, amount, customer details to the payment gateway. These are auto submitted to the gateway.

    2) ProcessCallback() is called when a callback is receive from the payment gateway, most often when the payment is accepted, but some gateways do notify on failture as well.

    3) Configured pipeline should be called as the final step of ProcessCallback() when the payment is succesfully verified by you. You can do so by calling:

    ExecutePostProcessingPipeline(Payment payment)

    Here's the process for the server-side redirect method:

    0) RequestPayment() creates placeholder payment at the payment gateway and redirects the customer to the server.

    Subsequent steps are the same for both. 

    Hope this helps.

  • yann 13 posts 32 karma points
    Nov 06, 2012 @ 05:55
    yann
    0

    Hi Soren,

    Thank you very much for your reply. This is brilliant. I started the integration with the different methods:

    * Request payment to connect to the gateway and get the Unique Code for transaction
    * Acquire Payment
    * Render Page to render my payment form...

    Then I realised that my HTML/design actually has the customer details and payment details in the same Page which obviously wont work...

    so, for my purpose, I building my RequestPayment to get the unique code and post the card details element to the payment gateway.
    My checkout page with payment information will do the following:

                IPaymentMethodService paymentService = paymentMethod.GetPaymentMethodService();
                ProviderPaymentService providerService= (ProviderPaymentService)paymentService;

                CreditCard cc = GetCreditCard();
                providerService.Card = cc;

                UCommerce.EntitiesV2.Payment payment = providerService.RequestPayment(paymentRequest);

                purchaseOrder.Payments.Add(payment);
                purchaseOrder.Save();

    The status for the payment has not been set to Acquired yet at this point.
    Then it will redirect to a page to check on the payment status - succesful or not. In this OrderVerification page I am looping through my payments and call a AcquirePayment in my external payment service. This method will contact my payment gateway and check on the status of the transaction. If sucessfull, it will update the status:

                payment.PaymentStatus = PaymentStatus.Get((int)paymentStatusCode);
                payment.TransactionId = provdierAuthorizationResponse.TransactionNumber;
                payment["AuthCode"] = providerAuthorizationResponse.AuthCode;

    and if the payment is successfull, the OrderVerification Page will execute the Checkout pipeline:

                if (payment.PaymentStatus.PaymentStatusId == (int)PaymentStatusCode.Acquired)

                {
                    CheckoutService checkoutService = new CheckoutService();
                    PurchaseOrder purchase = checkoutService.Checkout(basket);
                    if (purchase == null)
                    {
                        return "error executing checkout pipeline";
                    }
                }

    This seems to be workiing but I am not sure if this is the best way to integrate with uCommerce. Also I can see the  New Order in the backend in the tree, under "Orders" but it seems like all my orders are under the folder "New Order". Should those be moved to the Paid folder when the payment was successfull?

    Cheers

     

     

  • Søren Spelling Lund 1797 posts 2786 karma points
    Nov 09, 2012 @ 13:06
    Søren Spelling Lund
    0

    Authorized vs Acquired

    First, do you need to capture money immediately or should that be deferred until items are shipped to the customer? If that's the case you should set the payment to "Authorized". "Acquired" is meant for when money are transferred to the store, which typically happens only when items are shipped (some countries have laws to enforce this).

    Updating Payment-/Order Status

    Usually the payment gateway will issue a callback to your server upon successful payment. You usually want to use this to update the payment-/order status and execute the checkout pipeline.

    uCommerce will execute the ProcessPaymentRequest method when a callback is made from the payment gateway to your store server.

    Displaying Order Confirmation

    Displaying the order confirmation should typically do only that and not involve any order processing logic. The reason for this is that the order confirmation is accessible to the customer and could present a security issue if it's able to update payment-/order status.

    Usually you want it to just display information, which makes sense as customers tend to save the link to their confirmaiton page and access that page multiple times.

    Hope this helps.

  • yann 13 posts 32 karma points
    Nov 10, 2012 @ 11:28
    yann
    0

    Hi Soren

    Thank you for all your advices.
    Indeed I think I made some mistake in the implememtation and I am reviewing it. Here are couple of thoughts but not sure if those are correct.

    Adding couple of payment status in the database:
    * AccessCodeAcquired: when the Token and URL to post payment from the provider has been retrieved - no error with the user details
    * UserError: could not get the Token from the provider due to error in the user details
    * PaymentSent: when the payment details have been sent.
    * Declined - UserError: payment has been declined by provider due to invalid user payment details: CC invalid, CC insuffisant found...
    * Declined - OtherError: payment has been declined by provider due to either system error, communication error or provider error
     Those status are to triage the type of error. We dont really want to bother an admin with user error such as insuffisant fund on the CC... the user should just be displayed with the error and can correct it. If the error is to do with communication with the payment provider then administrator help is required...

    Adding a couple of OrderStatus in DB:
    * UserError: when the order has some user errors

    1- Services calls with payment provider

             => GetToken:
             => SubmitPayment
             => QueryTransactionStatus

    2- PaymentService:
             => RequestPayment:
                   - This method create a new payment if needed
                   - Then contact the third party provider to request an AccessCode Token and the post URL for the payment
                   - Set payment status to AccessCodeAcquired or UserError - maybe save the AccessCode temporarly in payment...

             => SendPaymentRequest:
                   - This will prepare the payment details to be sent to the payment gateway: CC, URL to redirect to after payment on the provider side. From the provider, when we sent the payment details and the provider processed the payment, it will call the redirect URL. I dont think it actually post any information about the payment, but I think we can query the payment if we have the access code available. So I was thinking that I could store it temporarly somewhere in the payment so I can use it on the call back. For the redirect URL is there a uCommerce URL I should use, or should I create a page and implement the call to the ProcessCallBack()?
                   - Send Payment Details
                   - Set payment status to PaymentSent
                   - Read the response - which will be the call back to our site, our payment has been updated there

             => ProcessCallBack:
                   - This method will get the access Code from the payment
                   - Call the ProcessPaymentRequest

             => ProcessPaymentRequest:
                   - This method will Query the provider for the status of the payment
                   - Update payment status to Authorised, Declined OtherError, or Declined UserError
                   - Delete the AccessCode from the payment info

    3- Pipelines

             => StartProcessPayment
                      - AssignOrderNumberTask
                      - SetOrderStatusToProcessingTask
                      - CheckRequiredToBeLoggedIn
                      - ProcessPaymentTask
                               -> Instantiate the PaymentService
                               -> Call RequestPayment()
                               -> Check payment status updates:
                                        * if AccessCodeAcquired then continue
                                        * if UserError then
                                            1) move the OrderStatus to UserError.
                                            3) Store error in session so it can be accessed on the checkout user control to display the error to the user and the user can update the payment details and resubmit...
                                            2) return a Pipeline Error to stop the execution
                               -> Call the SendPaymentRequest()
                               -> Check payment status updates:
                                        * if Authorised then
                                            1) move the OrderStatus to Paid.
                                            3) Return success
                                        * if Declined UserError then
                                            1) move the OrderStatus to UserError.
                                            3) Store error in session so it can be accessed on the checkout user control to display the error to the user and the user can update the payment details and resubmit...
                                            2) return a Pipeline Error to stop the execution
                                        * if Declined OtherError then
                                            1) move the OrderStatus to RequireAttention.
                                            3) Store error in session so it can be accessed on the checkout user control to display the error to the user and the user can update the payment details and resubmit...
                                            2) return a Pipeline Error to stop the execution

             => FinaliseOrder
                      - VerifyPaymentTask
       -> check if the payment status is authorised and the amount is the same as the order total
        - Create/Update membership - not sure if this will be needed
                      - Clear basket
                      - Send Email confirmation

    3- Checkout Usercontrol

    The checkout usercontrol contains the user details form and the payment details form. On Submit, it will:
         * Validate the form (.NEt validation)
         * Then if valide Start the Pipeline: StartProcessPayment
         * Check the OrderStatus, Payment Satus and Session for any Error Message
         * If error:
                -> then display the error message to the user and dont clear the basket so user can resubmit payment.
         * If no error:
                -> Call the FinaliseOrder pipeline
                -> Redirect to OrderConfirmation Page - this will only display the order ID, transaction status and ID. no processsing


    Couple of questions:
    * I am wondering if it is possible to add som payment/order status. I guess yes, directly in the DB - but just needed to confirm
    * When executing the pipelines. Can I store error messages in session to get those back from the user control in which I was executing the pipeline?
    * Is it a good idea to execute the Payment process in Pipeline - what is the main difference compare to executing it in the usercontrol - does the pipeline run the actions in separated thread so it is sure to be executed even if the user close its browser?
    * If there is any error during the payment process (.NET crashed...) and we need to manually manipulate the order knowing that a payment has been done. How can we add a payment to an order. And/Or change the payment status order?
    * If I add some order status, do I need to add any action for the backend to ensure that I can move the order from one state to another?

    Sorry for the long email - Thank you for your help

     

  • Søren Spelling Lund 1797 posts 2786 karma points
    Nov 13, 2012 @ 15:58
    Søren Spelling Lund
    0

    I'm still a little fuzzy on whether you're hosting the payment form yourself or if you're redirecting the customer to an external payment form hosted with the payment gateway.

    Here are the answers to your Qs at least:

    Qs:

    You can absolutely add new order-/payment statuses to database. Just make sure that your payment ends up in either "Authorized", "Acquired", or "Cancelled" states if you want to use the default uCommerce pipelinies for Acquire, Refund, or Void.

    You can store messages in session like you describe. It would be better to store it on the order though like so purchaseOrder["_processingMessage"] = "All is well". The underscore makes the dynamic order property not show up in the back end when viewing the order.

    You can do payment procssing in the pipeline. In fact it makes a lot of sense to do so when you're hosting the payment form yourself.

    You can change order-/payment status at any point. You'll have to do it programatically though. uCommerce has a "Required Attention" order status out of the box that we use to place orders which failed in some way that requires human interaction to fix.

    Each new order status defines which previous order status is required to move to it. You can read more about it in Understanding uCommerce Order Statuses.

     

Please Sign in or register to post replies

Write your reply to:

Draft