PayPal IPN webscr返回一个html文档

时间:2014-02-19 13:40:29

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

我在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控制台(谷歌浏览器扩展程序)发送相同的消息,它可以正常工作。嗯,有点:它返回INVALID但应该是VERIFIED。我没有使用沙盒,我向自己付了5美分。

顺便说一下,我无法设置流的Content-Length。如果我这样做,会抛出一个异常,说我在发出请求之前没有向流写入足够的字节(当我写完正确的rawContent.Length字节时)。

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

我无法弄清楚为什么我会收到回复的HTML文档。

1 个答案:

答案 0 :(得分:0)

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

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

它应该是IpnMessage&amp; cmd = _notify-validate,当它应该是&amp; cmd = _notify-validateIpnMessage。

所以,

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

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

另外,请确保有&amp;在消息和&#34; _notify-validate&#34;之间。这是我的问题。因此,如果transaction.IpnMessage不以&amp;开头,请确保包含它。

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