Trying to troubleshoot some legacy Classic ASP Paypal IPN code. The legacy code works perfectly for Selling products. However, processing a REFUND from the Paypal account seems to be causing some issue for Paypal IPN. The IPN listener receives the Refund IPN message and processes the business logic correctly, marking the transaction Refunded. But, Paypal still marks the transaction IPN History as "Retrying" for some reason. Below is the sample code from GitHub that was used to create the IPN listener we're troubleshooting.
Does the post back to Paypal need to be different for Selling vs Refunding?
Any help is greatly appreciated. Cheers
<%#LANGUAGE="VBScript"%>
<%
Dim Item_name, Item_number, Payment_status, Payment_amount
Dim Txn_id, Receiver_email, Payer_email
Dim objHttp, str
' read post from PayPal system and add 'cmd'
str = Request.Form & "&cmd=_notify-validate"
' post back to PayPal system to validate
set objHttp = Server.CreateObject("Msxml2.ServerXMLHTTP")
' set objHttp = Server.CreateObject("Msxml2.ServerXMLHTTP.4.0")
' set objHttp = Server.CreateObject("Microsoft.XMLHTTP")
objHttp.open "POST", "https://www.paypal.com/cgi-bin/webscr", false
objHttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
objHttp.Send str
' assign posted variables to local variables
Item_name = Request.Form("item_name")
Item_number = Request.Form("item_number")
Payment_status = Request.Form("payment_status")
Payment_amount = Request.Form("mc_gross")
Payment_currency = Request.Form("mc_currency")
Txn_id = Request.Form("txn_id")
Receiver_email = Request.Form("receiver_email")
Payer_email = Request.Form("payer_email")
' Check notification validation
if (objHttp.status <> 200 ) then
' HTTP error handling
elseif (objHttp.responseText = "VERIFIED") then
' check that Payment_status=Completed and other variables
Execute business process code, mark transaction Completed or Refunded from payment_status works successfully
elseif (objHttp.responseText = "INVALID") then
' log for manual investigation
else
' error
end if
set objHttp = nothing%>
The postback to PayPal does not influence whether an IPN is marked as successfully received. The postback step is for your own verification that the IPN is from PayPal.
For an IPN to be successfully received, the HTTP response status must be 200 OK.
Related
This error keeps happening on my website every so often. It's been working fine now for about 6 months but now decided to do it again.
I use 1&1 ionos hosting. The website uses asp.net and vb.net for the code. Its an online food delivery website which I set up myself by copying and changing some code that was written for me on another website. That site still works fine and is hosted with a different company so I don't know if it's something with ionos. When a customer orders, the payment clears in my PayPal but it doesn't tell my website that its cleared because the ipn is retrying a HTTP 500 error.
VB CODE TO CALL PAYPAL
Dim paypalURLString As String = "https://www.paypal.com/cgi-bin/webscr?" ' Live
Dim paypalParameterString As New StringBuilder
paypalParameterString.Append("cmd=_xclick&")
paypalParameterString.Append("notify_url=https://bozzafodder.co.uk/IPNListener.aspx&") 'POST address for notification
paypalParameterString.Append("bn=SlikkDesign_BuyNow_WPS_GB&")
paypalParameterString.Append("amount=" & session("total") + 1 + session("deliveryCharge") + ddlTip.SelectedValue & "&")
paypalParameterString.Append("item_name=Food Delivery&")
paypalParameterString.Append("currency_code=GBP&")
paypalParameterString.Append("custom=" & imgBtnPaypal.CommandArgument.ToString & "&")
paypalParameterString.Append("custom=" & order.orderID.ToString & "&")
paypalParameterString.Append("business=E4RYLU66FFE3L&") 'Live
paypalParameterString.Append("paymentaction=sale&")
paypalParameterString.Append("return=https://bozzafodder.co.uk/wait.aspx?orderID=" & order.orderID.ToString & "&")
paypalParameterString.Append("cancel_return=https://bozzafodder.co.uk/placeOrder.aspx?msgID=1&")
paypalParameterString.Append("rm=2&")
paypalParameterString.Append("cbt=Return to bozzafodder.co.uk&")
Dim displayParameters As New StringBuilder
displayParameters.Append("showHostedThankyouPage=false")
Response.Redirect(paypalURLString & paypalParameterString.ToString & displayParameters.ToString)
IPN LISTENER
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
'Post back to either sandbox or live
Dim strLive As String = "https://ipnpb.paypal.com/cgi-bin/webscr"
'SSL Error Code
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim req As HttpWebRequest = CType(WebRequest.Create(strLive), HttpWebRequest)
'Set values for the request back
req.Method = "POST"
req.ContentType = "application/x-www-form-urlencoded"
Dim Param() As Byte = Request.BinaryRead(HttpContext.Current.Request.ContentLength)
Dim strRequest As String = Encoding.ASCII.GetString(Param)
strRequest = strRequest + "&cmd=_notify-validate"
req.ContentLength = strRequest.Length
'Send the request to PayPal and get the response
Dim streamOut As StreamWriter = New StreamWriter(req.GetRequestStream(), Encoding.ASCII)
streamOut.Write(strRequest)
streamOut.Close()
Dim streamIn As StreamReader = New StreamReader(req.GetResponse().GetResponseStream())
Dim strResponse As String = streamIn.ReadToEnd()
streamIn.Close()
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(strRequest)
If LEN(qscoll("custom")) >= 32 Then
'Insert the paypal response
Dim order As New orders
order.InsertPaypalResponse(qscoll("txn_id"), qscoll("custom"), strRequest)
If strResponse = "VERIFIED" Then
order.UpdateOrderFromPaypal(qscoll("custom"), qscoll("txn_id"), qscoll("payment_status"))
ElseIf strResponse = "INVALID" Then
'log for manual investigation
order.UpdateOrderFromPaypal(qscoll("custom"), qscoll("txn_id"), qscoll("payment_status"))
Else
'Response wasn't VERIFIED or INVALID, log for manual investigation
order.UpdateOrderFromPaypal(qscoll("custom"), qscoll("txn_id"), "ERROR")
End If
End If
End Sub
End Class
In the attached photos you can see the errors in the PayPal IPN history. The ones that are SENT are from my other website which works fine on a different website. The IPN code is the same though, I've compared the 2.
Your IPN listener is "Unable to connect to the remote server" when attempting to verify an IPN, and so returns a 500 HTTP status.
Your IPN listener must return a 2xx HTTP status for the IPN to be marked as successfully received. PayPal will retry up to ~20 times until this happens, and then mark the IPN as failed if there is still no 2xx success response from your listener.
Since the error is "Unable to connect to the remote server", that is what you must investigate and debug within your environment (listener code and server). Why is it not able to connect to https://ipnpb.paypal.com/cgi-bin/webscr?cmd=_notify-validate ?
Below is my IPN Listener which has always worked fine on my website for customer PayPal payments. It sets up orders for my site in the Guid format (32 digits with 4 dashes). However, I use the same PayPal account for my Ebay selling and I have just sold an item which when paid for, caused the following error:
System.FormatException
Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
In the IPN history the Payment Status is COMPLETED but the HTTP Response Code is 500 and Delivery Status is 'Retrying'. I'm getting email warnings from PayPal about this, which worry me as I need IPN for my website.
I have checked the Ebay transaction and 'Custom' is EBAY_ENSDX00001030330553110 so I'm guessing my IPN code doesn't like that. Is there a way I can keep Ebay transactions away from my IPN Listener within PayPal? Or is there a way I can edit my IPN code below to deal with a custom ID which isn't in the 32 digit format?
IPN Listener..
Imports System.Net
Imports System.IO
Imports System.Net.Cache
Partial Class IPNListener
Inherits System.Web.UI.Page
Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
'Post back to either sandbox or live
'Dim strSandbox As String = "https://www.sandbox.paypal.com/cgi-bin/webscr"
Dim strLive As String = "https://ipnpb.paypal.com/cgi-bin/webscr"
'SSL Error Code
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim req As HttpWebRequest = CType(WebRequest.Create(strLive), HttpWebRequest)
'Set values for the request back
req.Method = "POST"
req.ContentType = "application/x-www-form-urlencoded"
Dim Param() As Byte = Request.BinaryRead(HttpContext.Current.Request.ContentLength)
Dim strRequest As String = Encoding.ASCII.GetString(Param)
strRequest = strRequest + "&cmd=_notify-validate"
req.ContentLength = strRequest.Length
'Send the request to PayPal and get the response
Dim streamOut As StreamWriter = New StreamWriter(req.GetRequestStream(), Encoding.ASCII)
streamOut.Write(strRequest)
streamOut.Close()
Dim streamIn As StreamReader = New StreamReader(req.GetResponse().GetResponseStream())
Dim strResponse As String = streamIn.ReadToEnd()
streamIn.Close()
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(strRequest)
'Insert the paypal response
Dim order As New orders
order.InsertPaypalResponse(qscoll("txn_id"), qscoll("custom"), strRequest)
If strResponse = "VERIFIED" Then
order.UpdateOrderFromPaypal(qscoll("custom"), qscoll("txn_id"), qscoll("payment_status"))
ElseIf strResponse = "INVALID" Then
'log for manual investigation
order.UpdateOrderFromPaypal(qscoll("custom"), qscoll("txn_id"), qscoll("payment_status"))
Else
'Response wasn't VERIFIED or INVALID, log for manual investigation
order.UpdateOrderFromPaypal(qscoll("custom"), qscoll("txn_id"), "ERROR")
End If
End Sub
End Class
In the case of an EBAY transaction, you can simply skip over the verification and exit successfully, since you don't need to do anything with it.
All PayPal needs you to do is return HTTP 200, so they can mark the IPN as successfully delivered. (The problem is you are currently returning HTTP 500 or similar, causing PayPal to mark the delivery as failed.)
An alternative solution is to specify your site's notify_url at your website's transaction level, as a parameter in each transaction's API setup (or HTML redirect if no API), which overrides any setting (or lack of a setting) in your PayPal account. Then in your PayPal account you can blank out the IPN listener URL, and you won't get any more IPNs for Ebay transactions.
I am really struggling with something which is pretty basic and need some help as it was not forthcoming from godaddy support!
For some reason the code below is not sending out any emails.
Code seems to be executed property and riddled it with lots of debug msgs but to no helping!
Te "From" email address is valid and has no issues! Any ideas? Port?
cheers, Jay
<%
Dim objNewMail
Set objNewMail = Server.CreateObject("CDO.Message")
objNewMail.From = "info#example.com"
objNewMail.To = "info#example.com"
objNewMail.Subject = "Interesting property sent by xxx"
objNewMail.TextBody = "Click the following link to see the property :" '& vbcr & vbcr & "http://www.maltawide.eu/default.asp?pid="
' GoDaddy SMTP Settings
'I had to remove the smpt settings as I dont have enough rep to post two links!
Response.Write ("Message sent successfully!")
%>
I'm not sure why your message failed, but here is code from a working mail form hosted at GoDaddy. All you need to do is build the form page to submit the form fields used in the script, or change the form field names in the script to match your existing form, or replace the forms with strings. Examples of both form entry and assigned variable values are included in the example's ' Create the message part of the code.
<%
Dim strBody
Dim strToAddress
Dim strFromAddress
Dim strReplyAddress
Dim strBlindCC
' Create the message
strBody = Request.Form("Message")
strToAddress = Request.Form("ToAddress")
strFromAddress = Request.Form("FromAddress")
strReplyAddress = "NoReply#WebSite.com"
strBlindCC = "BlindCC#WebSite.com"
' Include the schemas
sendUrl="http://schemas.microsoft.com/cdo/configuration/sendusing"
smtpUrl="http://schemas.microsoft.com/cdo/configuration/smtpserver"
' Set the mail server configuration
Set objConfig=CreateObject("CDO.Configuration")
objConfig.Fields.Item(sendUrl)=2 ' cdoSendUsingPort
objConfig.Fields.Item(smtpUrl)="relay-hosting.secureserver.net"
objConfig.Fields.Update
' Send the message
Set objMail=CreateObject("CDO.Message")
Set objMail.Configuration=objConfig
objMail.From=strFromAddress
objMail.ReplyTo=strReplyAddress
objMail.To=strToAddress
objMail.BCC=strBlindCC
objMail.Subject=strSubject
objMail.HTMLBody = strBody
objMail.Send
%>
Paypal has been sending emails warning IPN is failing.
I've not made any changes to my code, and it is really old code.... has been working for 5+ years.... been so long that I've had to do anything on this site.
I searched the server logs for more information... this is what I found repeatedly
|35|80040e14|Syntax_error_(missing_operator)_in_query_expression_'OrderID='.
I checked the code on the ipn page of the site, and I'm stumped.
Nothing is changed but it stopped working
This is line 34 thru 36 of the code of the ipn page:
MM_Cmd.CommandText = "UPDATE Orders SET txn_id='" & txn_id & "',payment_status='" & payment_status & "' WHERE OrderID=" & Item_number
MM_Cmd.Execute
end function
UPDATE:
Here is the full code that shows Item_number:
<%
str = Request.Form & "&cmd=_notify-validate"
' post back to PayPal system to validate
set objHttp = Server.CreateObject("Msxml2.ServerXMLHTTP")
objHttp.open "POST", "https://www.paypal.com/cgi-bin/webscr", false
objHttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
objHttp.Send str
' assign posted variables to local variables
Item_number = Request("item_number")
Payment_status = Request("payment_status")
Txn_id = Request("txn_id")
if (objHttp.status <> 200 ) then
' HTTP error handling
elseif (objHttp.responseText = "VERIFIED") then
if Payment_status = "Completed" then 'only update database if the response text is verified and the payment complete
UpdateOrder
end if
elseif (objHttp.responseText = "INVALID") then
' log for manual investigation
else
' error
end if
set objHttp = nothing
function UpdateOrder
'on error resume next
Set MM_Cmd = Server.CreateObject("ADODB.Command")
MM_Cmd.ActiveConnection = MM_CharonCart_STRING
MM_Cmd.CommandText = "UPDATE Orders SET txn_id='" & txn_id & "',payment_status='" & payment_status & "' WHERE OrderID=" & Item_number
MM_Cmd.Execute
end function
%>
The problem is with your variable Item_number. There's a small chance that if you rewrite the end of your query as
... where OrderID=" & Cint(Item_number)
then you will solve your problem, however you probably need to look at the code which assigns a value to Item_number
Overview of problem:
I have implemented the IPN listener and I know that PayPal is directing to it (because of a generated text file), the correct parameters are sent through to me in the QueryString however when I append "&cmd=notify-validate" to the query string for the validation to take place and send it to PayPal, I get the following HTML response:
.
When I copy and paste that returned HTML into a blank HTML document I see the following:
Initially I thought my session had expired but when I accessed the Sandbox via my browser, I was automatically logged in. I have even tried clicking on the link in my html document to ensure I am logged in and tried processing another test IPN through the simulator in the sandbox but I keep getting this result. I just can't see what I am doing wrong and the sad thing is that it was working correctly about an hour ago :(
My IPN listener code to send and get the validation response:
Dim payPalUrl As String = PayPalPayment.PayPalURL 'This returns https://www.sandbox.paypal.com/cgi-bin/webscr
Dim req As HttpWebRequest = CType(WebRequest.Create(payPalUrl), HttpWebRequest)
'Set values for the request back
req.Method = "POST"
req.ContentType = "application/x-www-form-urlencoded"
Dim params() As Byte = Request.BinaryRead(Request.ContentLength)
Dim ipnRequest As String = Encoding.ASCII.GetString(params)
Dim ipnPost As String = ipnRequest
ipnRequest &= "&cmd=notify-validate"
req.ContentLength = ipnRequest.Length
myUtility.AuditIPN(filename, ipnRequest)
''for proxy
'Dim proxy As New WebProxy(New System.Uri("http://url:port#"))
'req.Proxy = proxy
'Send the request to PayPal and get the response
Dim streamOut As New StreamWriter(req.GetRequestStream(), Encoding.ASCII)
streamOut.Write(ipnRequest)
streamOut.Close()
Dim streamIn As New StreamReader(req.GetResponse().GetResponseStream())
Dim ipnResponse = streamIn.ReadToEnd()
streamIn.Close()
'Rest of the code here... not necessary for this problem
Posting the payment to PayPal (if needed). NOTE: I build the form and Response.Write() it in a page. This is the form generation:
Dim form As New StringBuilder
form.AppendLine("<!DOCTYPE html>")
form.AppendLine("<html xmlns=""http://www.w3.org/1999/xhtml"">")
form.AppendLine("<head runat=""server"">")
form.AppendLine(String.Format("<title>{0} {1}</title>", "PayPal payment for", ItemName))
form.AppendLine("<link href=""../css/paypal.css"" rel=""stylesheet"" />")
form.AppendLine("</head>")
form.AppendLine("<body>")
form.AppendLine("<div class=""paypal""></div>")
form.AppendLine(String.Format("<p>Accessing PayPal to process your payment for the {0}.</p>", ItemName))
form.AppendLine("<div class=""loading""></div>")
form.AppendLine("<form id=""myform"" action=""https://www.sandbox.paypal.com/cgi-bin/webscr"" method=""post"">")
form.AppendLine("<input type=""hidden"" name=""cmd"" value=""_xclick"">")
form.AppendLine(String.Format("<input type=""hidden"" name=""business"" value=""{0}"">", BusinessEmail))
form.AppendLine(String.Format("<input type=""hidden"" name=""item_name"" value=""{0}"">", ItemName))
form.AppendLine(String.Format("<input type=""hidden"" name=""amount"" value=""{0}"">", Amount))
form.AppendLine(String.Format("<input type=""hidden"" name=""currency_code"" value=""{0}"">", Currency))
form.AppendLine(String.Format("<input type=""hidden"" name=""return"" value=""{0}"">", ReturnURL))
form.AppendLine("<input type=""hidden"" name=""button_subtype"" value=""products"">")
form.AppendLine("<input type=""hidden"" name=""bn"" value=""HHMRKWQT8NRTW:PP-BuyNowBF_P"">")
form.AppendLine("<input type=""hidden"" name=""no_note"" value=""0"">")
form.AppendLine("</form>")
form.AppendLine("<script type=""text/javascript"">")
form.AppendLine(" document.forms[""myform""].submit();")
form.AppendLine("</script>")
return form.ToString()
If I need to post anything else regarding this issue, please let me know as my brain is completely fried at the moment.
Your time and help will greatly be appreciated!
NOTE: Although my code is in VB.NET I develop in C# too, so C# sample code will definitely not be frowned upon!
Answer:
If you receive HTML in return, then the notify-validate is not correctly sent through to PayPal. It needs to be &cmd=_notify-validate (with the underscore directly after the cmd key) I must have somehow identically deleted it in my hazy stupor. My IPN listener is now successfully returning VERIFIED :)
If you receive HTML in return, then the notify-validate is not correctly sent through to PayPal. It needs to be &cmd=_notify-validate (with the underscore directly after the cmd key) I must have somehow accidentally deleted it in my hazy stupor. My IPN listener is now successfully returning VERIFIED :)