在ApiController中获取原始帖子请求

Mar*_*arc 11 c# asp.net paypal asp.net-web-api

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

协议

  1. PayPal HTTP向您的侦听器发送IPN消息,通知您事件.
  2. 您的侦听器向PayPal返回一个空的HTTP 200响应.
  3. 您的侦听器HTTP将完整的,未经更改的消息发送回PayPal; 消息必须包含与原始消息相同的字段(按相同顺序),并以与原始消息相同的方式进行编码.
  4. PayPal发回一个单词 - VERIFIED(如果邮件与原始邮件匹配)或INVALID(如果邮件与原始邮件不匹配).

到目前为止我有

        [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;
        }
Run Code Online (Sandbox Code Playgroud)

我的问题是我无法弄清楚如何将原始请求发送到Paypal,参数顺序相同.我可以HttpContent用我建立一个,PaypalIPNBindingModel但我无法保证订单.

有什么办法可以实现吗?

谢谢

Bad*_*dri 13

我相信你不应该使用参数绑定,只是自己阅读原始请求.随后,您可以自己反序列化到模型中.或者,如果您想利用Web API的模型绑定,同时访问原始请求体,这是我能想到的一种方式.

当Web API将请求主体绑定到参数中时,请求主体流被清空.随后,你再也看不懂了.

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

因此,您必须在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,从控制器,您可以检索正文字符串,就像这样.此时,您具有原始请求主体以及参数绑定模型.

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

  • 不要忘记在 WebApiConfig 中注册您的新处理程序。公共静态类 WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new MyHandler ()); // 其他代码未显示... } } (3认同)