【问题标题】:Get raw post request in an ApiController在 ApiController 中获取原始发布请求
【发布时间】:2014-12-26 23:47:20
【问题描述】:

我正在尝试实施 Paypal 即时付款通知 (IPN)

protocol

  1. PayPal HTTP 向您的听众发送一条 IPN 消息,通知您发生了事件。
  2. 您的侦听器向 PayPal 返回一个空的 HTTP 200 响应。
  3. 您的侦听器 HTTP 将完整的、未更改的消息发送回 贝宝;消息必须包含相同的字段(以相同的顺序) 作为原始消息并以与原始消息相同的方式进行编码 原始消息。
  4. PayPal 发回一个单词 - 已验证(如果消息 匹配原件)或无效(如果消息与原件不匹配) 原创)。

到现在为止

        [Route("IPN")]
        [HttpPost]
        public void IPN(PaypalIPNBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                // if you want to use the PayPal sandbox change this from false to true
                string response = GetPayPalResponse(model, true);

                if (response == "VERIFIED")
                {

                }
            }
        }

        string GetPayPalResponse(PaypalIPNBindingModel model, bool useSandbox)
        {
            string responseState = "INVALID";
            // Parse the variables
            // Choose whether to use sandbox or live environment
            string paypalUrl = useSandbox ? "https://www.sandbox.paypal.com/"
            : "https://www.paypal.com/cgi-bin/webscr";

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(paypalUrl);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));

                //STEP 2 in the paypal protocol
                //Send HTTP CODE 200
                HttpResponseMessage response = client.PostAsync("cgi-bin/webscr", "").Result;

                if (response.IsSuccessStatusCode)
                {
                    //STEP 3
                    //Send the paypal request back with _notify-validate
                    model.cmd = "_notify-validate";
                    response = client.PostAsync("cgi-bin/webscr", THE RAW PAYPAL REQUEST in THE SAME ORDER ).Result;

                    if(response.IsSuccessStatusCode)
                    {
                        responseState = response.Content.ReadAsStringAsync().Result;
                    }
                }
            }

            return responseState;
        }

我的问题是我不知道如何将原始请求与参数以相同顺序发送到 Paypal。 我可以用我的PaypalIPNBindingModel 构建一个HttpContent,但我不能保证顺序。

有什么方法可以实现吗?

谢谢

【问题讨论】:

  • 是不是不能从 PayPal 接收它作为字符串,然后你可以自己反序列化它,做任何你需要做的事情来验证它,然后 POST 他们发回的字符串?
  • 谢谢,是的,我想,但我认为使用 asp.net 的绑定模型会更优雅,但如果没有其他方法,我会自己反序列化。

标签: c# asp.net asp.net-web-api paypal


【解决方案1】:

我认为您不应该使用参数绑定,而应该自己阅读原始请求。随后,您可以自己反序列化到模型中。或者,如果您想利用 Web API 的模型绑定并同时访问原始请求正文,这是我能想到的一种方法。

Web API 将请求体绑定到参数中时,请求体流被清空。随后,您将无法再次阅读。

[HttpPost]
public async Task IPN(PaypalIPNBindingModel model)
{
    var body = await Request.Content.ReadAsStringAsync(); // body will be "".
}

因此,您必须在模型绑定在 Web API 管道中运行之前阅读正文。如果您创建消息处理程序,您可以在那里准备好正文并将其存储在请求对象的属性字典中。

public class MyHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
                                           HttpRequestMessage request, 
                                             CancellationToken cancellationToken)
    {
        if (request.Content != null)
        {
            string body = await request.Content.ReadAsStringAsync();
            request.Properties["body"] = body;
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

然后,您可以从控制器检索正文字符串,如下所示。此时,您拥有原始请求正文以及参数绑定模型。

[HttpPost]
public void IPN(PaypalIPNBindingModel model)
{
    var body = (string)(Request.Properties["body"]);
}

【讨论】:

  • 谢谢,终于不用模型绑定了。
  • 我想没有办法手动将原始请求绑定到模型?
  • 手动将原始请求绑定到模型是什么意思?如果您的意思是根据原始请求创建模型对象的实例,则必须自己执行此操作。我不熟悉 IPN,但根据内容类型,您必须这样做。如果有现成可用的媒体类型格式化程序,Web API 将通过绑定为您完成。
  • 我创建了一个 PaypalIPNBindingModel 类,并使用 Web api 将其与 paypal 请求绑定。现在因为我使用的是原始字符串,我可以像以前的 api 那样手动将它绑定到 PaypalIPNBindingModel 吗?
  • 不要忘记在 WebApiConfig 中注册您的新处理程序。公共静态类 WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new MyHandler ()); // 其他代码未显示... } }
猜你喜欢
  • 1970-01-01
  • 2023-03-16
  • 2017-06-17
  • 1970-01-01
  • 2016-11-16
  • 1970-01-01
  • 2018-08-08
  • 2021-08-18
  • 1970-01-01
相关资源
最近更新 更多