2014-10-30 11 views
9

ApiController 원시 POST 요청을 얻을 protocol나는 페이팔 인스턴트 지불 통지 (IPN)</p> <p>을 구현하기 위해 노력하고있어

  1. 페이팔 HTTP POST를 리스너 당신을 알려주는 IPN 메시지 행사.
  2. 청취자가 PayPal에 빈 HTTP 200 응답을 반환합니다.
  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; 
     } 

내 문제는 내가 같은 순서로 매개 변수를 페이팔에 원래 요청을 보내는 방법을 알아낼 수 없습니다입니다 있습니다. PaypalIPNBindingModel으로 HttpContent을 만들 수 있지만 주문을 보장 할 수 없습니다.

이것을 수행 할 수있는 방법이 있습니까?

감사합니다.

+0

는 그런 다음, 그들은 다시 전송 된 문자열을 POST 당신이 그것을 확인하기 위해 할 일은 무엇이든, 스스로를 역 직렬화 할 수 페이팔에서 문자열로받을 수 없습니다? –

+0

고마워, 그래,하지만 asp.net에서 바인딩 모델을 사용하는 것이 더 우아 할 거라 생각했지만 다른 방법이 없다면 나 자신을 deserialize 할 것이다. – Marc

답변

12

저는 매개 변수 바인딩을 사용하지 말고 그냥 원시 요청을 읽어야한다고 생각합니다. 그 다음에는 모델을 직접 deserialize 할 수 있습니다. 또는 웹 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에 익숙하지 않지만 콘텐츠 유형에 따라야합니다. 사용 가능한 상자 형 미디어 형식 포매터가 있으면 웹 API가 바인딩을 통해이를 수행합니다. – Badri

관련 문제