【问题标题】:PayPal IPN webscr returns an html documentPayPal IPN webscr 返回一个 html 文档
【发布时间】:2014-03-19 21:16:06
【问题描述】:

我在 ASP.NET 中实现了一个 IPN 侦听器,但是每当我尝试验证交易时,paypal webscr 脚本都会返回一个 html 文档,而不是 VERIFIED 或 INVALID。这是代码:

private void Validate(Transaction transaction)
{
    string content = String.Concat(transaction.IpnMessage, "&cmd=_notify-validate");
    byte[] rawContent = Encoding.ASCII.GetBytes(content);

    HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(postBackUrl);
    request.Method = "POST";
    request.ProtocolVersion = HttpVersion.Version11;
    request.KeepAlive = false;
    request.ContentType = "application/x-www-form-urlencoded";

    using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
        writer.Write(rawContent);

    transaction.Save();

    try
    {
        WebResponse response = request.GetResponse();
        StreamReader reader = new StreamReader(response.GetResponseStream());

        string responseContent = reader.ReadToEnd();

        if (responseContent.Equals("VERIFIED"))
            this.Approve(transaction);
        else
            transaction.SetOperation("Rejected", responseContent);
    }
    catch (Exception ex)
    {
        transaction.SetOperation("WebError", ex.Message);
    }
}

下面是如何根据传入请求构建 Transaction 对象:

public static Transaction FromContext(HttpContext context)
{
    StreamReader reader = new StreamReader(context.Request.InputStream);
    Transaction result = new Transaction();
    string ipnMessage;

    reader.BaseStream.Position = 0;
    ipnMessage = reader.ReadToEnd();

    string[] pairs = ipnMessage.Split('&');

    result.data = new Dictionary<string, string>();
    foreach (string pair in pairs)
    {
        if (String.IsNullOrEmpty(pair))
            continue;

        string[] parts = pair.Split('=');
        string field = parts[0];
        string value = (parts.Length > 1) ? (parts[1]) : String.Empty;

        result.data.Add(HttpContext.Current.Server.UrlDecode(field), HttpContext.Current.Server.UrlDecode(value));
    }

    result.ID = result.data["txn_id"];
    result.IpnMessage = ipnMessage;

    if (String.IsNullOrEmpty(result.ID))
        throw new ArgumentException("This is not a valid transaction.");

    return result;
}

如果我通过 REST 控制台(Google Chrome 扩展程序)发送相同的消息,它可以工作。好吧,有点:它返回无效但应该被验证。我没有使用沙盒,我向自己支付了 5 美分。

顺便说一句,我无法设置流的 Content-Length。如果我这样做了,则会抛出一个异常,说明在发送请求之前我没有向流中写入足够的字节(而我写的正是 rawContent.Length 字节)。

postBackUrl 是https://www.paypal.com/cgi-bin/webscr。我正在通过手动向 Web 处理程序发送 IPN 消息的副本来测试这一点。我从我的 PayPal 帐户 IPN 历史记录中复制了它。我也尝试在前面加上 cmd=_notify-validate 而不是追加,但结果是一样的。

我不知道为什么我会收到一个 HTML 文档作为响应。

【问题讨论】:

    标签: asp.net http post paypal paypal-ipn


    【解决方案1】:

    我不在 ASP.NET 中编写代码,但查看 docs,我注意到您的代码以相反的方式连接响应:

    string content = String.Concat(transaction.IpnMessage, "&cmd=_notify-validate");
    

    当它应该是 &cmd=_notify-validateIpnMessage 时,它​​正在使它成为 IpnMessage&cmd=_notify-validate。

    所以,

    string content = String.Concat("&cmd=_notify-validate", transaction.IpnMessage);
    

    不确定这是否是唯一的原因,但请尝试一下。

    另外,请确保在消息和“_notify-validate”之间有一个 &。那是我的问题。所以如果transaction.IpnMessage不以&开头,一定要包含它。

    string content = String.Concat("&cmd=_notify-validate&", transaction.IpnMessage);
    

    【讨论】:

    • 我已经尝试过了,正如我在最后几段中所写的那样。此外,无论其位置如何,都应解析参数...
    • 对不起,我没读过。但我不确定他们是否会解析它,我认为他们是按原样阅读的。事实上,该网站 (developer.paypal.com/webapps/developer/docs/classic/ipn/…) 说:“在您可以信任消息的内容之前,您必须首先验证消息来自 PayPal。要验证消息,您必须将 中的内容发回收到它们的确切顺序,并在其前面加上命令 _notify-validate"。您是否尝试了最后一部分,在验证后加上“&”?
    • 我正在与一个休息客户端发送相同的消息并且它有效(有点)。我收到了无效而不是已验证,但至少我收到了回复。
    • 好吧,无效意味着它的格式正确,但 Paypal 无法识别该消息(即它从未发送过它)。这是意料之中的,除非您让 PayPal 向您发送验证消息。您是否尝试过: string content = String.Concat("&cmd=_notify-validate&", transaction.IpnMessage); ??
    猜你喜欢
    • 2011-10-26
    • 2015-10-14
    • 2011-06-21
    • 2014-05-22
    • 2016-11-28
    • 2018-10-29
    • 2016-03-12
    • 2015-08-16
    相关资源
    最近更新 更多