Mark Payment Method as Paid From Return url query parameters.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
5 years ago
Hi, I'm trying to set the payment status after order has been paid in an external site and customer redirected back to the site. On site return, the payment site returns http query parameters on the url. I need to capture the "status" query string and set the payment status to paid or another if "status" matches a certain string. The payment site has specified the ipn url for verifying the payment result and it returns the status code. I've followed the paypal standard method in developing the plugin for nopcommerce 4.1 but I feel stuck. Can you help me in the best redirection and verification process so that the order can be marked as completed?
5 years ago
The Paypal Standard Payment Controller has a routine so it needs to be similar to that

        public IActionResult PDTHandler()

routes are registered via the plugin

            //PDT
            routeBuilder.MapRoute("Plugin.Payments.PayPalStandard.PDTHandler", "Plugins/PaymentPayPalStandard/PDTHandler",
                 new { controller = "PaymentPayPalStandard", action = "PDTHandler" });

when the command line is called

                //PDT, IPN and cancel URL
                ["return"] = $"{storeLocation}Plugins/PaymentPayPalStandard/PDTHandler",
5 years ago
Hello, I've set up the return url to the PDT handler and also the IPN url for verification. In the payment controller, I have specified the url parameters that are needed for verifying payments but when I'm redirected back to site after payment, I get a 401 unauthorized error Httpcontext exception. How can I fix this error?

An unhandled exception occurred while processing the request.
WebException: The remote server returned an error: (401) Unauthorized.
System.Net.HttpWebRequest.GetResponse()

Stack Query Cookies Headers
WebException: The remote server returned an error: (401) Unauthorized.
System.Net.HttpWebRequest.GetResponse()
Nop.Plugin.Payments.IpayAfrica.IpayAfricaPaymentProcessor.GetPdtDetails(string tx, out Dictionary<string, string> values, out string response)
Nop.Plugin.Payments.IpayAfrica.PaymentIpayAfricaController.PDTHandler()
lambda_method(Closure , object , object[] )
Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
StackExchange.Profiling.MiniProfilerMiddleware.Invoke(HttpContext context) in MiniProfilerMiddleware.cs
Nop.Services.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) in AuthenticationMiddleware.cs
+
            await _next(context);
Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
Nop.Core.Http.InstallUrlMiddleware.Invoke(HttpContext context, IWebHelper webHelper) in InstallUrlMiddleware.cs
+
            await _next(context);
Nop.Core.Http.KeepAliveMiddleware.Invoke(HttpContext context, IWebHelper webHelper) in KeepAliveMiddleware.cs
+
            await _next(context);
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
Nop.Web.Framework.Infrastructure.Extensions.ApplicationBuilderExtensions+<>c.<UseNopExceptionHandler>b__1_1(HttpContext context) in ApplicationBuilderExtensions.cs
+
                        ExceptionDispatchInfo.Throw(exception);
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)


But I can see that the query parameters are being received, and these are the ones that I need for verification purposes

Stack Query Cookies Headers
Variable  Value
afd  **********
agt  
channel  MPESA
hsh  **************************************************************************
id  6
ifd  ************
ivm  6
mc  25.00
msisdn_id  ****** ******
msisdn_idnum  ***********
p1  
p2  
p3  
p4  
poi  *************
qwh  **********
status  aei7p7yrx4ae34
txncd  ***************
uyt  *********


How can I proceed from here as the success status code should be like the one specified in the query
5 years ago
Not sure I understand but if you have the query parameters being received
Do you mean after making payment you are redirected back to the nopCommerce site ?
i.e. you have a response from the remote server

Then why do you need to do another request of the remote server url in GetPdtDetails which is giving you the error
WebException: The remote server returned an error: (401) Unauthorized.

If you already have the response then just interrogate that response to get the status of the transaction
5 years ago
How can I do that to remove the error and capture the status response. The new error I'm getting is:

WebException: The remote server returned an error: (401) Unauthorized.
Nop.Web.Framework.Infrastructure.Extensions.ApplicationBuilderExtensions+<>c.<UseNopExceptionHandler>b__1_1(HttpContext context) in ApplicationBuilderExtensions.cs
-
                            EngineContext.Current.Resolve<ILogger>().Error(exception.Message, exception, currentCustomer);
                        }
                    }
                    finally
                    {
                        //rethrow the exception to show the error page
                        throw exception;
                    }
                });
            });
        }
        /// <summary>
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Show raw exception details
System.Net.WebException: The remote server returned an error: (401) Unauthorized.
   at Nop.Web.Framework.Infrastructure.Extensions.ApplicationBuilderExtensions.<>c.<UseNopExceptionHandler>b__1_1(HttpContext context) in F:\My Sites\nopCommerce-master\src\Presentation\Nop.Web.Framework\Infrastructure\Extensions\ApplicationBuilderExtensions.cs:line 83
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
5 years ago
So I assume you have been looking at this page

https://dev.ipayafrica.com/

So you got the successful response = aei7p7yrx4ae34

You get need to that out of the query string received and act on the values and write to the order
You have the id for the order you sent

As a quick example you could do Something like

                    //mark order as paid
                    if (Status == Success) // aei7p7yrx4ae34
                    {
                        // Read the order from the id

                        var order = GetOrderById(int orderId)

                        if (_orderProcessingService.CanMarkOrderAsPaid(order))
                        {
                            order.AuthorizationTransactionId = txn_id;

                            _orderService.UpdateOrder(order);

                            _orderProcessingService.MarkOrderAsPaid(order);
                        }
                    }

Also there are other fields in the order you can also use to store info as required

i.e.        
        public string AuthorizationTransactionCode { get; set; }
        public string AuthorizationTransactionResult { get; set; }
        public string CaptureTransactionId { get; set; }
        public string CaptureTransactionResult { get; set; }
        public string SubscriptionTransactionId { get; set; }
        public DateTime? PaidDateUtc { get; set; }
5 years ago
Thanks so much. Let me try to implement this guide
5 years ago
Finally, I managed to get through this. I assigned values to new variables from the returning query parameters using HttpContext.Request.Query[""] and I using streamreader to read the response from the verification url

                string verify_url = "verification_url";

                string html = string.Empty;
                string url = verify_url;
              
                //use web request to read the response from verification_url
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                using (Stream stream = response.GetResponseStream())
                using (StreamReader reader = new StreamReader(stream))
                {
                    html = reader.ReadToEnd();
                }
                if (html.Contains("success_code")
                {
                    if (_orderProcessingService.CanMarkOrderAsPaid(order))
                    {
                        _orderProcessingService.MarkOrderAsPaid(order);
                    }
                    return RedirectToRoute("CheckoutCompleted", new { orderId = order.Id });
                }
                else
                {
                    return //something else;
                }


I hope this might help someone else. Thanks.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.