2014-10-30 3 views
9

Я пытаюсь реализовать Paypal моментальной оплаты Уведомление (IPN)Получить необработанный запрос пост в ApiController

protocol является

  1. PayPal HTTP запросы POST ваш слушатель сообщение IPN, который уведомляет о мероприятие.
  2. Ваш прослушиватель возвращает пустой ответ HTTP 200 на PayPal.
  3. Ваш прослушиватель HTTP POST передает полное, неизмененное сообщение обратно 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; 
     } 

Моя проблема в том, что я не могу понять, как отправить первоначальный запрос на Paypal с параметрами в том же порядке. Я мог бы построить HttpContent с моим PaypalIPNBindingModel, но я не могу гарантировать заказ.

Есть ли способ, которым я мог бы это достичь?

Спасибо

+0

Невозможно получить его в виде строки из PayPal, тогда вы можете десериализовать его самостоятельно, сделать все, что вам нужно, чтобы проверить его, затем POST строку, которую они отправили обратно? –

+0

Спасибо, да, я думаю, но я подумал, что было бы более элегантно использовать модель привязки от asp.net, но если нет другого пути, я сделаю десериализацию себя. – Marc

ответ

12

Я считаю, что вы не должны использовать параметр связывания и просто читать Необработанную просьбу об себя. Впоследствии вы можете десериализовать себя в модели самостоятельно. В качестве альтернативы, если вы хотите использовать привязку модели веб-API и в то же время получить доступ к необработанному тексту запроса, вот один из способов, о котором я мог думать.

Когда веб-API связывает тело запроса с параметром, поток тела запроса опорожняется. Впоследствии вы не сможете прочитать его снова.

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

Итак, вы должны прочитать тело до начала привязки модели в конвейере веб-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"]); 
} 
+0

Спасибо, наконец, я не использовал привязку модели. – Marc

+0

Я предполагаю, что невозможно связать этот необработанный запрос с моделью вручную? – Marc

+0

Что вы подразумеваете под привязкой необработанного запроса к модели вручную? Если вы имеете в виду создание экземпляра вашего модельного объекта на основе необработанного запроса, вы должны сделать это сами. Я не знаком с IPN, но на основе типа контента вы должны это сделать. Если имеется форматор без форматов, Web API сделает это для вас путем привязки. – Badri