ASP.net WebForms PayPal IPN错误地标记为成功

问题描述

我正在解决网站购物车/付款系统的问题。我们的网站使用C#ASP.NET WebForms

编写

问题是来自PayPal的IPN响应似乎未在运行。查看相关记录中的PayPal IPN历史记录,PayPal会从我的站点显示200成功响应。

我在网站上添加了日志记录功能,因此对该页面的任何点击都将被记录下来,并且我的通知页面没有看到点击。

有人知道我是否做错了什么,或者他们是否更改了我需要检查的内容才能使它更稳定?

这是我的网站处理PayPal交易的方式:

使用发票号,项目的一些文本以及总费用,我填充了一个命名值集合并将信息发布到PayPal:

NameValueCollection nvc = new NameValueCollection();
nvc.Add("cmd",HttpUtility.HtmlAttributeEncode("_xclick"));
nvc.Add("business",HttpUtility.HtmlAttributeEncode("email@example.com"));
nvc.Add("currency_code",HttpUtility.HtmlAttributeEncode("USD"));
nvc.Add("item_name",HttpUtility.HtmlAttributeEncode(InvoiceText));
nvc.Add("no_shipping",HttpUtility.HtmlAttributeEncode("1"));
nvc.Add("notify_url",HttpUtility.HtmlAttributeEncode("https://example.com/ipn_PayPal.aspx"));
nvc.Add("invoice",InvoiceID);
nvc.Add("amount",HttpUtility.HtmlAttributeEncode(TotalCharge.ToString()));
nvc.Add("image_url",HttpUtility.HtmlAttributeEncode("https://example.com/Content/images/Logo.png"));
nvc.Add("return",HttpUtility.HtmlAttributeEncode("https://example.com/?PayPalThanks=" + InvoiceID));
nvc.Add("rm",HttpUtility.HtmlAttributeEncode("2"));
HttpHelper.RedirectAndPOST(this.Page,PPFee.PostPage,nvc);

作为参考,她是HttpHelper类:

public class HttpHelper
{
    /// <summary>
    /// This method prepares an Html form which holds all data in hidden field in the addetion to form submitting script.
    /// </summary>
    /// <param name="url">The destination Url to which the post and redirection will occur,the Url can be in the same App or ouside the App.</param>
    /// <param name="data">A collection of data that will be posted to the destination Url.</param>
    /// <returns>Returns a string representation of the Posting form.</returns>
    /// <Author>Samer Abu Rabie</Author>
    private static String PreparePOSTForm(string url,NameValueCollection data)
    {
        //Set a name for the form
        string formID = "PostForm";

        //Build the form using the specified data to be posted.
        StringBuilder strForm = new StringBuilder();
        strForm.Append("<form id=\"" + formID + "\" name=\"" + formID + "\" action=\"" + url + "\" method=\"POST\">");
        foreach (string key in data)
        {
            strForm.Append("<input type=\"hidden\" name=\"" + key + "\" value=\"" + data[key] + "\">");
        }
        strForm.Append("</form>");

        //Build the JavaScript which will do the Posting operation.
        StringBuilder strScript = new StringBuilder();
        strScript.Append("<script language='javascript'>");
        strScript.Append("var v" + formID + " = document." + formID + ";");
        strScript.Append("v" + formID + ".submit();");
        strScript.Append("</script>");

        //Return the form and the script concatenated. (The order is important,Form then JavaScript)
        return strForm.ToString() + strScript.ToString();
    }

    public static void RedirectAndPOST(Page page,string destinationUrl,NameValueCollection data)
    {
        //Prepare the Posting form
        string strForm = PreparePOSTForm(destinationUrl,data);
        //Add a literal control the specified page holding the Post Form,this is to submit the Posting form with the request.
        page.Controls.Add(new LiteralControl(strForm));
    }
}

交易确实转到PayPal,人们可以正常付款,但是在重定向回我的感谢页面之后,IPN似乎从未发送出去。

在我的IPN页面上,首先检查发票,然后将其记录到数据库:

int Invoice = Utils.ReturnInt(Request.Form["invoice"],-1);
if (Invoice == -1)
    Invoice = Utils.ReturnInt(Request.QueryString["invoice"],0);
LogInvHit(Invoice);

如果页面在此上中断,我预计贝宝(PayPal)的IPN历史记录中会出现错误,因此它已经超越了这一要求,或者在达到200成功之前从未到达过它

此外,作为参考,这是我告诉PayPal是否成功的方法:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strPayPalResponse);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
byte[] param = Request.BinaryRead(HttpContext.Current.Request.ContentLength);
string strRequest = Encoding.ASCII.GetString(param);
strRequest += "&cmd=_notify-validate";
req.ContentLength = strRequest.Length;

StreamWriter streamOut = new StreamWriter(req.GetRequestStream(),System.Text.Encoding.ASCII);
streamOut.Write(strRequest);
streamOut.Close();
StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
string strResponse = streamIn.ReadToEnd();
streamIn.Close();

据我估计,如果页面被点击,我至少应该有一个条目,但我没有,所以我怀疑我的页面实际上是错误的或者是从PayPal获得IPN匹配。

总而言之,我认为IPN通知工作不正确,但是假设我做错了什么。寻找一些有助于排除我可以纠正的潜在问题的帮助

解决方法

您误解了IPN交付和验证的工作原理。

当PayPal向您的监听器发布消息时,您的监听器将以一些HTTP状态代码进行响应。如果它以2xx状态响应,则IPN被标记为成功交付。如果它没有以2xx状态进行响应,则IPN将重试,如果没有收到2xx成功作为响应,则IPN最终将失败。


您突出显示的代码,页面的中断位置以及将IPN发送回PayPal进行验证的位置,与上述内容完全无关(因为它不影响返回的HTTP状态代码)。

将收到的IPN消息发回PayPal进行验证是出于您自己的目的,因此您知道消息来自PayPal而不是其他实体。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...