![](/img/trans.png)
[英]Paypal IPN sample code has no ActionResult. How am i meant to give a url if there is no view?
[英]Is there any sample for PayPal IPN
我有一個Asp.Net WEB API 2項目,我想實現一個即時支付通知(IPN)監聽器控制器。
我找不到任何示例和nuget包。 我只需要承認用戶使用Paypal上的標准html按鈕付款。 這很簡單。
所有nuget包都是創建發票或自定義按鈕。 這不是我需要的
paypal上的示例適用於經典的asp.net,而不適用於MVC或WEB API MVC
我確定有人已經這樣做了,當我開始編碼時,我感覺我正在重新發明輪子。
有沒有IPN監聽器控制器示例?
至少一個PaypalIPNBindingModel綁定Paypal查詢。
[Route("IPN")]
[HttpPost]
public IHttpActionResult IPN(PaypalIPNBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
return Ok();
}
編輯
到目前為止,我有以下代碼
[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/";
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.PostAsJsonAsync("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;
}
但對於第3步,我試圖將我的模型發布為json,但paypal返回HTML頁面而不是VALIDATED或INVALID。 我發現我必須使用application/x-www-form-urlencoded
,並且參數的順序相同。
如何獲取請求URL?
我會使用查詢Url並&cmd=_notify-validate
添加&cmd=_notify-validate
基於已接受的答案,我提出了以下代碼實現ASP.NET MVC的IPN偵聽器。 該解決方案已經部署並且似乎正常運行。
[HttpPost]
public async Task<ActionResult> Ipn()
{
var ipn = Request.Form.AllKeys.ToDictionary(k => k, k => Request[k]);
ipn.Add("cmd", "_notify-validate");
var isIpnValid = await ValidateIpnAsync(ipn);
if (isIpnValid)
{
// process the IPN
}
return new EmptyResult();
}
private static async Task<bool> ValidateIpnAsync(IEnumerable<KeyValuePair<string, string>> ipn)
{
using (var client = new HttpClient())
{
const string PayPalUrl = "https://www.paypal.com/cgi-bin/webscr";
// This is necessary in order for PayPal to not resend the IPN.
await client.PostAsync(PayPalUrl, new StringContent(string.Empty));
var response = await client.PostAsync(PayPalUrl, new FormUrlEncodedContent(ipn));
var responseString = await response.Content.ReadAsStringAsync();
return (responseString == "VERIFIED");
}
}
編輯:
讓我分享一下我的經驗 - 上面的代碼到目前為止工作得很好,但突然之間它正在處理一個IPN失敗,即responseString == "INVALID"
。
問題原來是我的帳戶設置為使用charset == windows-1252
,這是PayPal的默認值。 但是, FormUrlEncodedContent
使用UTF-8進行編碼,因此驗證失敗,因為國家字符如“ř”。 解決方案是將charset
設置為UTF-8,可以在Profile>我的銷售工具> PayPal按鈕語言編碼>更多選項中完成,請參閱此SO線程 。
這是我的代碼
隨意回顧是有問題的
[Route("IPN")]
[HttpPost]
public IHttpActionResult IPN()
{
// if you want to use the PayPal sandbox change this from false to true
string response = GetPayPalResponse(true);
if (response == "VERIFIED")
{
//Database stuff
}
else
{
return BadRequest();
}
return Ok();
}
string GetPayPalResponse(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/";
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.PostAsJsonAsync("cgi-bin/webscr", "").Result;
if (response.IsSuccessStatusCode)
{
//STEP 3
//Send the paypal request back with _notify-validate
string rawRequest = response.Content.ReadAsStringAsync().Result;
rawRequest += "&cmd=_notify-validate";
HttpContent content = new StringContent(rawRequest);
response = client.PostAsync("cgi-bin/webscr", content).Result;
if(response.IsSuccessStatusCode)
{
responseState = response.Content.ReadAsStringAsync().Result;
}
}
}
return responseState;
}
擴展Michal Hosala的答案 ,與PayPal成功握手需要兩件事
首先,在向PayPal發出請求之前設置安全協議
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
其次,避免使用字典,因為要進行驗證,PayPal要求數據以相同的順序發回,並以cmd變量開頭。 我最終這樣做了
Request.InputStream.Seek(0, SeekOrigin.Begin);
string rawRequestBody = new StreamReader(Request.InputStream).ReadToEnd();
var ipnVarsWithCmd = rawRequestBody.Split('&').Select(x => new KeyValuePair<string, string>(x.Split('=')[0], x.Split('=')[1])).ToList();
ipnVarsWithCmd.Insert(0, new KeyValuePair<string, string>("cmd", "_notify-validate"));
我也在尋找類似OP的原始問題的解決方案Is there any IPN listener controller example? At least a PaypalIPNBindingModel to bind the Paypal query.
Is there any IPN listener controller example? At least a PaypalIPNBindingModel to bind the Paypal query.
我到了這個頁面。 我嘗試了這個線程中提到的其他解決方案,它們都工作但我真的需要PayPal查詢到模型解決方案所以我谷歌搜索直到我偶然發現Carlos Rodriguez的創建PayPal IPN Web API Endpoint博客帖子。
以下是卡洛斯所做的概述:
創建一個模型。 根據您從PayPal獲得的ipn響應,在模型中定義屬性。
public class IPNBindingModel { public string PaymentStatus { get; set; } public string RawRequest { get; set; } public string CustomField { get; set; } }
創建一個PayPal Validator類。
public class PayPalValidator { public bool ValidateIPN(string body) { var paypalResponse = GetPayPalResponse(true, body); return paypalResponse.Equals("VERIFIED"); } private string GetPayPalResponse(bool useSandbox, string rawRequest) { string responseState = "INVALID"; string paypalUrl = useSandbox ? "https://www.sandbox.paypal.com/" : "https://www.paypal.com/"; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 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")); HttpResponseMessage response = client.PostAsJsonAsync("cgi-bin/webscr", "").Result; if (response.IsSuccessStatusCode) { rawRequest += "&cmd=_notify-validate"; HttpContent content = new StringContent(rawRequest); response = client.PostAsync("cgi-bin/webscr", content).Result; if (response.IsSuccessStatusCode) { responseState = response.Content.ReadAsStringAsync().Result; } } } return responseState; } }
創建您的控制器。
[RoutePrefix("paypal")] public class PayPalController : ApiController { private PayPalValidator _validator; public PayPalController() { this._validator = new PayPalValidator(); } [HttpPost] [Route("ipn")] public void ReceiveIPN(IPNBindingModel model) { if (!_validator.ValidateIPN(model.RawRequest)) throw new Exception("Error validating payment"); switch (model.PaymentStatus) { case "Completed": //Business Logic break; } } }
創建一個模型綁定器,用於定義Web Api如何自動為您創建模型。
public class IPNModelBinder : IModelBinder { public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType != typeof(IPNBindingModel)) { return false; } var postedRaw = actionContext.Request.Content.ReadAsStringAsync().Result; Dictionary postedData = ParsePaypalIPN(postedRaw); IPNBindingModel ipn = new IPNBindingModel { PaymentStatus = postedData["payment_status"], RawRequest = postedRaw, CustomField = postedData["custom"] }; bindingContext.Model = ipn; return true; } private Dictionary ParsePaypalIPN(string postedRaw) { var result = new Dictionary(); var keyValuePairs = postedRaw.Split('&'); foreach (var kvp in keyValuePairs) { var keyvalue = kvp.Split('='); var key = keyvalue[0]; var value = keyvalue[1]; result.Add(key, value); } return result; } } }
將模型綁定器注冊到WebApiConfig.cs。 config.BindParameter(typeof(IPNBindingModel), new IPNModelBinder());
希望這有助於其他人。 感謝Carlos Rodriguez提供的令人驚嘆的代碼。
這里有一個官方的c#示例: https : //github.com/paypal/ipn-code-samples in path \\c#\\paypal_ipn_mvc.cs
C#示例顯示了一個ASP.NET MVC控制器,其中包含響應IPN的操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.