无法通过Paypal测试工具测试IPN(HTTP错误代码500)_Asp.net

Posted

技术标签:

【中文标题】无法通过Paypal测试工具测试IPN(HTTP错误代码500)_Asp.net【英文标题】:IPN can't be tested through Paypal test tool (HTTP error code 500) _ Asp.net 【发布时间】:2012-10-04 18:33:28 【问题描述】:

美好的一天 我一直在尝试为 PayPal 运行 IPN 处理程序;我已遵循所有可能的说明(我希望如此),但是在贝宝 IPN 测试工具上,我不断收到代码 500 的错误。 我使用的代码是 johnmendez00 作为开源提供的;该类是通过创建一个实例来调用的

PPIPN objPP = new PPIPN("TEST");
objPP.FromEmail = "email@yourdomain.com";  
objPP.FromEmailPassword = "yourpassword";  
objPP.SmtpHost = "yourSMTPHost";
objPP.SmtpPort = "SMTPHostPort";
objPP.ToEmail = "youremailatPayPal@domain.com";/ 
objPP.MakeHttpPost();
objPP.CheckStatus();

实例的类为:

/// <summary>
/// Project can be found in http://paypalipnclass.codeplex.com/
/// </summary>



using System.Net;
using System.Net.Mail;
using System.IO;
using System.Text;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System;
using System.Configuration;
public class PPIPN
 

string _txnID, _txnType, _paymentStatus, _receiverEmail, _itemName, _itemNumber, _quantity, _invoice, _custom,
_paymentGross, _payerEmail, _pendingReason, _paymentDate, _paymentFee, _firstName, _lastName, _address,
_city, _state, _zip, _country, _countryCode, _addressStatus, _payerStatus, _payerID, _paymentType, _notifyVersion,
_verifySign, _response, _payerPhone, _payerBusinessName, _business, _receiverID, _memo, _tax, _qtyCartItems,
_shippingMethod, _shipping;

private string _postUrl = "";
private string _strRequest = "";
private string _smtpHost, _fromEmail, _toEmail, _fromEmailPassword, _smtpPort;

/// <summary>
/// valid strings are "TEST" for sandbox use 
/// "LIVE" for production use
/// "ELITE" for test use off of PayPal...avoid having to be logged into PayPal Developer
/// </summary>
/// <param name="mode"></param>
public PPIPN(string mode)

    if (mode.ToLower() == "test")
        this.PostUrl = "https://www.sandbox.paypal.com/cgi-bin/webscr";
    else if (mode.ToLower() == "live")
        this.PostUrl = "https://www.paypal.com/cgi-bin/webscr";
    else if (mode.ToLower() == "elite")
        this.PostUrl = "http://www.eliteweaver.co.uk/testing/ipntest.php";
    else
        this.PostUrl = "";

    //this.fillProperties();


#region "Properties"

private string PostUrl

    get  return _postUrl; 
    set  _postUrl = value; 


/// <summary>
/// This is the reponse back from the http post back to PayPal.
/// Possible values are "VERIFIED" or "INVALID"
/// </summary>
private string Response

    get  return _response; 
    set  _response = value; 


private string RequestLength

    get  return _strRequest; 
    set  _strRequest = value; 


/// <summary>
/// Provide your outgoing email server to use are your SMTP host
/// </summary>
public string SmtpHost

    get  return _smtpHost; 
    set  _smtpHost = value; 


/// <summary>
/// Provide the port your outgoing SMTP host uses
/// </summary>
public string SmtpPort

    get  return _smtpPort; 
    set  _smtpPort = value; 


/// <summary>
/// This is the email address that will show to the customer and you. This most likely
/// needs to be a valid email address that your SMTP server will accept
/// Examples would be something like no-reply@yourdomain.com
/// </summary>
public string FromEmail

    get  return _fromEmail; 
    set  _fromEmail = value; 


/// <summary>
/// This is the password that the FromEmail property will use. This needs to be the password
/// for the email account itself
/// </summary>
public string FromEmailPassword

    get  return _fromEmailPassword; 
    set  _fromEmailPassword = value; 


/// <summary>
/// This is the email address that you use for yourself. This should be set to
/// the email that is registered for your PayPal account.
/// </summary>
public string ToEmail

    get  return _toEmail; 
    set  _toEmail = value; 


/// <summary>
/// Email address or Account ID of the payment recipient.  This is equivalent
///  to the value of receiver_email if the payment is sent to the primary account
/// , which is most cases it is.  This value is that value of what is set in the button html
/// markup.  This value also get normalized to lowercase when coming back from PayPal
/// </summary>
private string Business

    get  return _business; 
    set  _business = value; 



/// <summary>
/// Unique transaction ID generated by PayPal. Helpful to use for checking
///  against fraud to make sure the transaction hasn't already occured.
/// </summary>
private string TXN_ID

    get  return _txnID; 
    set  _txnID = value; 


/// <summary>
/// Type of transaction from the customer. Possible values are
/// "cart", "express_checkout", "send_money", "virtual_terminal", "web-accept"
/// </summary>
private string TXN_Type

    get  return _txnType; 
    set  _txnType = value; 


/// <summary>
/// This is the status of the payment from the Customer.Possible values are: 
/// "Canceled_Reversal", "Completed", "Denied", "Expired", "Failed", "Pending",
///  "Processed", "Refunded", "Reversed", "Voided"
/// </summary>
private string PaymentStatus

    get  return _paymentStatus; 
    set  _paymentStatus = value; 


/// <summary>
/// Primary email address of you, the recipient, of the payment.
/// </summary>
private string ReceiverEmail

    get  return _receiverEmail; 
    set  _receiverEmail = value; 


/// <summary>
/// unique account ID of the payment recipient, which is most likely yourself.
/// </summary>
private string ReceiverID

    get  return _receiverID; 
    set  _receiverID = value; 


/// <summary>
/// This is the item name passed by yourself or if the customer if you let them enter in an item name
/// </summary>
private string ItemName

    get  return _itemName; 
    set  _itemName = value; 


/// <summary>
/// This is the item number you set for your own tracking purposes. It is not required by PayPal
/// so if you didn't set it most likely will come back blank.
/// </summary>
private string ItemNumber

    get  return _itemNumber; 
    set  _itemNumber = value; 


/// <summary>
/// Quantity of the item ordered by the customer
/// </summary>
private string Quantity

    get  return _quantity; 
    set  _quantity = value; 


/// <summary>
/// Quantity of the items in the shopping cart from the Customer
/// </summary>
private string QuantityCartItems

    get  return _qtyCartItems; 
    set  _qtyCartItems = value; 


/// <summary>
/// Invoice number passed by yourself, if you didn't pass it to PayPal then this is omitted.
/// </summary>
private string Invoice

    get  return _invoice; 
    set  _invoice = value; 


/// <summary>
/// Custom value passed by yourself with the item.
/// </summary>
private string Custom

    get  return _custom; 
    set  _custom = value; 


/// <summary>
/// Memo entered in by the customer on PayPal website note field
/// </summary>
private string Memo

    get  return _memo; 
    set  _memo = value; 


/// <summary>
/// Amount of tax charged on the payment
/// </summary>
private string Tax

    get  return _tax; 
    set  _tax = value; 


/// <summary>
/// Full USD amount of customer's payment before the PayPal fee is subtracted
/// </summary>
private string PaymentGross

    get  return _paymentGross; 
    set  _paymentGross = value; 


/// <summary>
/// Date Time stamp created by PayPal in the following format: 
/// HH:MM:SS DD Mmm YY, YYYY PST
/// </summary>
private string PaymentDate

    get  return _paymentDate; 
    set  _paymentDate = value; 


/// <summary>
/// PayPal's transaction fees associated with purchase.
/// </summary>
private string PaymentFee

    get  return _paymentFee; 
    set  _paymentFee = value; 



/// <summary>
/// This is the email that the customer used on PayPal or that
/// is registered with PayPal
/// </summary>
private string PayerEmail

    get  return _payerEmail; 
    set  _payerEmail = value; 


/// <summary>
/// Customer's phone number
/// </summary>
private string PayerPhone

    get  return _payerPhone; 
    set  _payerPhone = value; 


/// <summary>
/// Customer's company name if they represent a business
/// </summary>
private string PayerBusinessName

    get  return _payerBusinessName; 
    set  _payerBusinessName = value; 


/// <summary>
/// This variable is only set if the payment_status=Pending. Possible values are the following:
/// "address", "authorization", "echeck", "intl", "multi-currency", "unilateral", "upgrade",
///  "verify", other"
/// </summary>
private string PendingReason

    get  return _pendingReason; 
    set  _pendingReason = value; 


/// <summary>
/// This is indicated from what is set in your PayPal profile settings
/// </summary>
private string ShippingMethod

    get  return _shippingMethod; 
    set  _shippingMethod = value; 


/// <summary>
/// Shipping charges associated with the order.
/// </summary>
private string Shipping

    get  return _shipping; 
    set  _shipping = value; 


/// <summary>
/// Customer's First Name
/// </summary>
private string PayerFirstName

    get  return _firstName; 
    set  _firstName = value; 


/// <summary>
/// Customer's Last Name
/// </summary>
private string PayerLastName

    get  return _lastName; 
    set  _lastName = value; 


/// <summary>
/// Customer's street address
/// </summary>
private string PayerAddress

    get  return _address; 
    set  _address = value; 


/// <summary>
/// Customer's city
/// </summary>
private string PayerCity

    get  return _city; 
    set  _city = value; 


/// <summary>
/// Customer state of address
/// </summary>
private string PayerState

    get  return _state; 
    set  _state = value; 


/// <summary>
/// Zip code of customer's address
/// </summary>
private string PayerZipCode

    get  return _zip; 
    set  _zip = value; 


/// <summary>
/// Customer's country
/// </summary>
private string PayerCountry

    get  return _country; 
    set  _country = value; 


/// <summary>
/// Customer's 2 character country code
/// </summary>
private string PayerCountryCode

    get  return _countryCode; 
    set  _countryCode = value; 


/// <summary>
/// The the address provided is either confirmed or uncomfirmed from PayaPal. Possible values  from PayPal
/// are going to be "confirmed" or "unconfirmed"
/// </summary>
private string PayerAddressStatus

    get  return _addressStatus; 
    set  _addressStatus = value; 


/// <summary>
/// Customer either had a verified or unverified account with PayPal. 
/// Possible return values from PayPal are "verified" or "unverified"
/// </summary>
private string PayerStatus

    get  return _payerStatus; 
    set  _payerStatus = value; 


/// <summary>
/// Customer's unique ID
/// </summary>
private string PayerID

    get  return _payerID; 
    set  _payerID = value; 


/// <summary>
/// Type of payment from Customer. Possible values from PayPal are "echeck" and "instant"
/// </summary>
private string PaymentType

    get  return _paymentType; 
    set  _paymentType = value; 


/// <summary>
/// This is the version number of the IPN that makes the post.
/// </summary>
private string NotifyVersion

    get  return _notifyVersion; 
    set  _notifyVersion = value; 


/// <summary>
/// An encrypted string that is used to validate the transaction. You don't have to use this for anything
///  unless you want to keep it and store it for your records.
/// </summary>
private string VerifySign

    get  return _verifySign; 
    set  _verifySign = value; 


#endregion

#region "Make HTTP POST"

/// <summary>
/// This makes the post back to PayPal to verify the order.
/// </summary>
public void MakeHttpPost()

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(this.PostUrl);

    req.Method = "POST";
    req.ContentLength = this.RequestLength.Length + 21;
    req.ContentType = "application/x-www-form-urlencoded";
    byte[] param = HttpContext.Current.Request.BinaryRead(HttpContext.Current.Request.ContentLength);
    this.RequestLength = Encoding.ASCII.GetString(param);
    this.RequestLength += "&cmd=_notify-validate";
    req.ContentLength = this.RequestLength.Length;

    StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
    streamOut.Write(this.RequestLength);
    streamOut.Close();
    StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
    this.Response = streamIn.ReadToEnd();
    streamIn.Close();


#endregion

#region "Check Status of Order"

/// <summary>
/// This checks the status of the order and notifies you via email the status.
/// </summary>
public void CheckStatus()

    this.fillProperties();
    switch (this.Response)
    
        case "VERIFIED":


            switch (this.PaymentStatus)
            
                case "Completed": //If statement to check and verify the business email and that the script was triggered from the buy_now button.
                    if (this.ReceiverEmail == this.ToEmail)
                    
                        switch (this.TXN_Type)
                        
                            case "cart":
                                this.EmailUs("PayPal: Successful Order from Cart");
                                break;
                            case "express_checkout":
                                this.EmailUs("PayPal: Successful Order from Express Checkout");
                                break;
                            case "send_money":
                                this.EmailUs("PayPal: Successful Order from Send Money");
                                break;
                            case "virtual_terminal":
                                this.EmailUs("PayPal: Successful Order from Virtual Terminal");
                                break;
                            case "web_accept":
                                this.EmailUs("PayPal: Successful Order from Web_Accept");
                                break;
                            default:
                                this.EmailUs("PayPal: Order has been placed");
                                break;
                        
                    
                    else
                    
                        this.EmailUs("PayPal: Unknown order...please check your paypal account");
                    
                    break;
                case "Pending":
                    switch (this.PendingReason)
                    
                        case "address":
                            this.EmailUs("PayPal: Pending Order because of address");
                            break;
                        case "authorization":
                            this.EmailUs("PayPal: Pending Order because of authorization");
                            break;
                        case "echeck":
                            this.EmailUs("PayPal: Pending Order because of echeck");
                            break;
                        case "intl":
                            this.EmailUs("PayPal: Pending Order because of non-US Acccount");
                            break;
                        case "multi-currency":
                            this.EmailUs("PayPal: Pending Order because of multi-currency");
                            break;
                        case "unilateral":
                            this.EmailUs("PayPal: Pending Order because of Unilateral");
                            break;
                        case "upgrade":
                            this.EmailUs("PayPal: Pending Order because of Upgrade");
                            break;
                        case "verify":
                            this.EmailUs("PayPal: Pending Order because of Verification needed");
                            break;
                        case "other":
                            this.EmailUs("PayPal: Pending Order because of other reason");
                            break;
                        default:
                            this.EmailUs(string.Format("PayPal: Pending Order because of unknown reason of 0", this.PendingReason));
                            break;
                    
                    break;
                case "Failed":
                    this.EmailUs("PayPal: Failed order");
                    break;
                case "Denied":
                    this.EmailUs("PayPal: Denied order");
                    break;
            

            this.EmailBuyer("Order Received", "Your order has been received and will begin processing shortly.");

            break;
        case "INVALID":
            this.EmailUs("PayPal: Invalid order, please review and investigate");
            break;
        default:
            this.EmailUs("PayPal: ERROR, response is " + this.Response);
            break;
    



#endregion

#region "Mail Company the Order"
/// <summary>
/// Email yourself/company the order. This requires a subject line. Make sure to set SMTP properties of the PayPal object 
/// and the FromEmail and ToEmail properties as well.
/// </summary>
/// <param name="subject"></param>
private void EmailUs(string subject)

    MailMessage mailObj = new MailMessage();
    mailObj.From = new MailAddress(this.FromEmail);
    mailObj.Subject = subject;
    mailObj.To.Add(new MailAddress(this.ToEmail));
    mailObj.IsBodyHtml = true;
    mailObj.Body = "<br />"
    + "Transaction ID: " + this.TXN_ID + "<br />"
    + "Transaction Type:" + this.TXN_Type + "<br />"
    + "Payment Type: " + this.PaymentType + "<br />"
    + "Payment Status: " + this.PaymentStatus + "<br />"
    + "Pending Reason: " + this.PendingReason + "<br />"
    + "Payment Date: " + this.PaymentDate + "<br />"
    + "Receiver Email: " + this.ReceiverEmail + "<br />"
    + "Invoice: " + this.Invoice + "<br />"
    + "Item Number: " + this.ItemNumber + "<br />"
    + "Item Name: " + this.ItemName + "<br />"
    + "Quantity: " + this.Quantity + "<br />"
    + "Custom: " + this.Custom + "<br />"
    + "Payment Gross: " + this.PaymentGross + "<br />"
    + "Payment Fee: " + this.PaymentFee + "<br />"
    + "Payer Email: " + this.PayerEmail + "<br />"
    + "First Name: " + this.PayerFirstName + "<br />"
    + "Last Name: " + this.PayerLastName + "<br />"
    + "Street Address: " + this.PayerAddress + "<br />"
    + "City: " + this.PayerCity + "<br />"
    + "State: " + this.PayerState + "<br />"
    + "Zip Code: " + this.PayerZipCode + "<br />"
    + "Country: " + this.PayerCountry + "<br />"
    + "Address Status: " + this.PayerAddressStatus + "<br />"
    + "Payer Status: " + this.PayerStatus + "<br />"
    + "Verify Sign: " + this.VerifySign + "<br />"
    + "Notify Version: " + this.NotifyVersion + "<br />";

    SmtpClient objSmtp = new SmtpClient();

    objSmtp.Host = this.SmtpHost;
    objSmtp.Port = System.Int32.Parse(this.SmtpPort);
    objSmtp.UseDefaultCredentials = false;
    objSmtp.Credentials = new System.Net.NetworkCredential(this.FromEmail, this.FromEmailPassword);
    objSmtp.DeliveryMethod = SmtpDeliveryMethod.Network;
    objSmtp.Send(mailObj);


#endregion

#region "Mail the Customer the Order details"

private void EmailBuyer(string subject, string message)

    MailMessage mailObj = new MailMessage();
    mailObj.From = new MailAddress(this.FromEmail);
    mailObj.Subject = subject;
    mailObj.Body = message;
    mailObj.To.Add(new MailAddress(this.PayerEmail));
    mailObj.IsBodyHtml = true;

    SmtpClient objSmtp = new SmtpClient();

    objSmtp.Host = this.SmtpHost;
    objSmtp.Port = System.Int32.Parse(this.SmtpPort);
    objSmtp.UseDefaultCredentials = false;
    objSmtp.Credentials = new System.Net.NetworkCredential(this.FromEmail, this.FromEmailPassword);
    objSmtp.DeliveryMethod = SmtpDeliveryMethod.Network;
    objSmtp.Send(mailObj);


#endregion

#region "Fill Properties"

private void fillProperties()

    this.RequestLength = HttpContext.Current.Request.Form.ToString();
    this.PayerCity = HttpContext.Current.Request.Form["address_city"];
    this.PayerCountry = HttpContext.Current.Request.Form["address_country"];
    this.PayerCountryCode = HttpContext.Current.Request.Form["address_country_code"];
    this.PayerState = HttpContext.Current.Request.Form["address_state"];
    this.PayerAddressStatus = HttpContext.Current.Request.Form["address_status"];
    this.PayerAddress = HttpContext.Current.Request.Form["address_street"];
    this.PayerZipCode = HttpContext.Current.Request.Form["address_zip"];
    this.PayerFirstName = HttpContext.Current.Request.Form["first_name"];
    this.PayerLastName = HttpContext.Current.Request.Form["last_name"];
    this.PayerBusinessName = HttpContext.Current.Request.Form["payer_business_name"];
    this.PayerEmail = HttpContext.Current.Request.Form["payer_email"];
    this.PayerID = HttpContext.Current.Request.Form["payer_id"];
    this.PayerStatus = HttpContext.Current.Request.Form["payer_status"];
   // this.PayerPhone = HttpContext.Current.Request.Form["contact_phone"];
    this.Business = HttpContext.Current.Request.Form["business"];
    this.ItemName = HttpContext.Current.Request.Form["item_name"];
    this.ItemNumber = HttpContext.Current.Request.Form["item_number"];
    this.Quantity = HttpContext.Current.Request.Form["quantity"];
    this.ReceiverEmail = HttpContext.Current.Request.Form["receiver_email"];
    this.ReceiverID = HttpContext.Current.Request.Form["receiver_id"];
    this.Custom = HttpContext.Current.Request.Form["custom"];
   // this.Memo = HttpContext.Current.Request.Form["memo"];
    this.Invoice = HttpContext.Current.Request.Form["invoice"];
    this.Tax = HttpContext.Current.Request.Form["tax"];
    this.QuantityCartItems = HttpContext.Current.Request.Form["num_cart_items"];
    this.PaymentDate = HttpContext.Current.Request.Form["payment_date"];
    this.PaymentStatus = HttpContext.Current.Request.Form["payment_status"];
    this.PaymentType = HttpContext.Current.Request.Form["payment_type"];
    this.PendingReason = HttpContext.Current.Request.Form["pending_reason"];
    this.TXN_ID = HttpContext.Current.Request.Form["txn_id"];
    this.TXN_Type = HttpContext.Current.Request.Form["txn_type"];
    this.PaymentFee = HttpContext.Current.Request.Form["mc_fee"];
    this.PaymentGross = HttpContext.Current.Request.Form["mc_gross"];
    this.NotifyVersion = HttpContext.Current.Request.Form["notify_version"];
   // this.VerifySign = HttpContext.Current.Request.Form["verify_sign"];


#endregion





对这里可能出现的问题有什么想法吗?

【问题讨论】:

已经以某种方式解决了 ASP.NET 只有一个表单的问题,这可能已经存在?您在使用 PayPal 按钮小部件吗? 是的,我正在使用 PayPal 按钮;我如何让它工作是通过在每个按钮上方添加和清空
标记,它可以正常工作。
唯一的问题是没有人知道它为什么会这样工作。希望请求代码会有所帮助.. 【参考方案1】:

来自 PayPal 网站的按钮 HTML 嵌入在表单标签中。 ASP.NET 页面上只能有一个表单,而 ASP.NET 提供了它自己的表单。如果你有一个母版页,那么表单标签就在其中,当它们在运行时与母版合并时,它会应用于站点中的每个页面。

我在 Jeremy Schneider 的博客上找到了一个 elegant solution,它包含一个自定义 HtmlForm 类,可以打开和关闭表单标签呈现。该类称为 GhostForm,并具有一个属性 RenderFormTag。当 RenderFormTag 设置为 false 时,它​​不会呈现开始或结束标签,但会呈现所有内容。引用自定义 GhostForm 类,并在您放置按钮的表单的代码隐藏中,将以下内容放在 Page_Load 中以禁用母版页表单标记:

用法:

public partial class Products : System.Web.UI.Page
 
     protected void Page_Load(object sender, EventArgs e)
     
         GhostForm mainForm = new GhostForm();
         mainForm.RenderFormTag = false;
         .....     
     
         // Send your data to PayPal :-)
     .....
 

重要提示:在发送此请求之前,请确保您已登录沙盒。

更新:观看这些教学视频:http://www.asp.net/mvc/videos/mvc-1/aspnet-mvc-storefront/aspnet-mvc-storefront-part-1-architectural-discussion-and-overview

和你一样,我使用了 John Mendez 的 IPN 代码。这是我从 PayPal 发送和接收的地方:

string strSandbox = "https://www.sandbox.paypal.com/cgi-bin/webscr";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strLive);

//Set values for the request back to PayPal
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
byte[] param = Request.BinaryRead(HttpContext.Current.Request.ContentLength);
string strRequest = Encoding.ASCII.GetString(param);
strRequest += "&cmd=_notify-validate";
req.ContentLength = strRequest.Length;

//Send the request to PayPal 
StreamWriter streamOut = 
    new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
streamOut.Write(strRequest);
streamOut.Close();

// Get the response from PayPal
StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
string strResponse = streamIn.ReadToEnd();
streamIn.Close();

希望这会有所帮助。 500 个错误可以是任何东西...

【讨论】:

确实很有帮助;出于某种原因,我仍然看到错误;但我确实受益匪浅。既然您运行了 John 的代码,是否有可能创建一个关于如何部署它的指南?这将非常有用...谢谢您的麻烦... 我刚刚将 John 的代码合并到我的项目中的一个类中 - 它是我的 Web App DLL 的一部分。我在这里发布了一些关于 PayPal 的博客文章:codersbarn.com/?tag=/paypal 这个博客也帮助了我:west-wind.com/presentations/paypalintegration/… 我在答案中添加了视频链接。 我将您的答案标记为解决方案;我在您发送的视频中找到了我想要的内容....谢谢 谢谢 :-) 出于好奇,您对哪一部分有疑问?

以上是关于无法通过Paypal测试工具测试IPN(HTTP错误代码500)_Asp.net的主要内容,如果未能解决你的问题,请参考以下文章

PayPal IPN - 测试 - 在沙盒中不起作用

在 PayPal 沙盒中使用 IPN 测试拒付/争议

IPN PAYPAL - 无效测试

PayPal IPN HTTP 错误 400 - PHP - 使用 PayPal GIT 代码

测试 IPN 不应该从我的 Paypal 沙盒帐户中取钱吗?

在 PHP 中使用 IPN 的 Paypal 无法在新的 Beta 开发人员沙箱中运行