65.9K
CodeProject 正在变化。 阅读更多。
Home

C# - ASP.NET 开发者 PayPal 入门

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (237投票s)

2009年10月7日

CPOL

24分钟阅读

viewsIcon

1440185

downloadIcon

40380

针对C#开发者,概述所有PayPal集成选项。

目录

注意事项,2017年更新

我大约8年前写了这篇文章。请注意,许多事情已经发生了变化。虽然这里描述的集成在大多数情况下仍然有效,但PayPal的技术和开发支持在过去几年中一直在稳步下降。最重要的是——PayPal的客户支持现在比以往任何时候都差。基本上,PayPal的问题在于您的资金可能在没有任何充分理由的情况下随时被冻结。当这种情况发生时,没有人可以沟通。我个人在几个项目中经历过这种情况,我提供建议的资金充足、合法初创公司的PayPal账户被冻结了。

几年前(2012年之前),您至少可以与决策者沟通,并使用常识解冻账户。现在看来,大多数理智的人都离开了PayPal,当您的账户被冻结时,没有人会花时间与您公开交谈。这里有一些记录完好的恐怖故事,人们因最奇怪的原因被冻结了大量资金

现在,我完全支持公司保护自己。如果PayPal正在处理您网站上的信用卡购买,并且流量突然增加,他们就会面临风险。如果人们开始要求退款,他们需要有能力退还这笔钱。如果您从PayPal提款到银行而不合作,他们就会处于弱势。

但我不知道PayPal运营团队是如何从这一点跳到我们完全关闭您的账户——自己处理吧。我的意思是,他们基本上是在给企业判死刑。如果公司账户上有定期付款怎么办?如果公司需要向客户退款怎么办?如果您不仅使用PayPal收款,还用于汇款和支付承包商费用怎么办?

现在,对于我合作的每个客户,如果他们要求我进行PayPal集成,我都会要求他们签署弃权书。我强烈建议您也这样做。如果您对这个话题有任何疑问,请随时留言,我会尽力帮助您。

开始使用 PayPal

对于那些真正想深入了解 PayPal 并且愿意花钱的人,我推荐 Pro PayPal E-Commerce 这本书——我最终通过它理解了 PayPal 集成的概念。对于那些不太愿意付费的人——别担心,这就是为什么有这篇文章……我将涵盖这本书中的大部分内容,但以更简洁明了的方式。

首先,理解 PayPal 提供的集成类型,我敢说,是成功开始您的开发之旅最重要的事。一个常见的错误(我也犯过)是立即开始使用 PayPal API 和 Express Checkout。我的意思是这很自然——我们是开发者,当他们告诉我们与某个东西集成时,我们首先寻找的是 SDK 和 API……PayPal API 就会出现……我们对自己说“就是它了”……然后开始工作。问题是——大多数支付场景可以通过一种更简单的方法处理——作为网站支付标准的一部分的 HTML 表单。

所以,事不宜迟,这是 PayPal 集成的分类

  • 网站标准支付 (HTML)
  • 支付后处理
    • 自动返回
    • 支付数据传输(PDT)
    • 即时支付通知 (IPN)
  • PayPal API
    • 快捷结账
    • 直接支付 (网站支付专业版)
  • Payflow Gateway

分类中的项目也按照我建议大家遵循的方式进行排序。所以,如果您是 PayPal 新手——首先学习网站支付标准 (HTML) 中的所有选项。然后,如果您需要添加一些基本的支付后处理,看看自动返回或 PDT 是否能解决您的问题……如果不能,IPN 是您可用的更可靠的选项。

下一个级别将涉及 PayPal API 和实现 Express Checkout,这是最灵活的 PayPal 集成解决方案。最后,如果您渴望能够在您的网站上直接处理信用卡,您将向 PayPal 支付月费并实现直接支付(实际上是获得所谓的网站支付专业版)。

另一方面,我们分类中的最后一项——Payflow Gateway,是一个不同的东西。它不像前面提到的技术那样“更新堆栈”。它是一个专门针对那些拥有/想要互联网商家账户 (IMA) 并且只需要支付网关的企业而设计的解决方案。为了保持文章的一致性,我将跳过解释 Payflow Gateway 的细节。但是,如果您有任何相关问题,请随时在评论区留言,我会尽力回答。

话虽如此,让我们开始设置一个测试 PayPal 账户,然后我们将深入探讨上述集成。

设置测试账户

请注意——即使您已经拥有一个真实的 PayPal 账户,您也需要遵循此步骤。使用测试账户有两个原因

  • 你不想用真钱测试和玩耍
  • 您想访问不同类型的PayPal账户
    • 个人账户 – 大多数人拥有此类账户;一个允许您在线支付时使用 PayPal 的账户。理论上,您可以使用个人账户收款;但请注意,您将受到严格限制 – 每月收款限额为500美元,并且只能使用网站支付标准 (HTML) 接受一次性付款。个人账户的最大优点是收款时无需支付任何交易费用。但是请注意,如果您在一个月内收款超过500美元,系统将提示您升级到高级账户/商业账户或拒绝付款。
    • 高级账户 – 个人账户的升级版;适用于任何想经营个人在线业务的人。此类账户拥有所有集成选项(接受信用卡、定期付款、PayPal API)。然而,大多数人直接从个人账户跳到商业账户,因为高级账户的交易费用相同(大多数情况下,每笔交易2.9% + 0.30美元),但缺少商业账户的报告、多用户访问和其他高级商家服务。
    • 企业账户 – 拥有高级账户的所有功能,外加一些(例如,能够以您的企业名称运营)。如果您正在开发一个需要接受付款的网站,99% 的情况下您会选择此类型账户。

首先,访问 PayPal 沙盒并注册一个新账户。过程很简单,大多数开发者应该都能轻松完成。但是,这里有一些图片可以帮助您完成整个过程

Signing up for sandbox account

注册沙盒账户

Filling in details of your sandbox account

填写沙盒账户详细信息

完成沙盒账户详细信息输入后,您需要检查您提供的电子邮件以完成注册。之后,您将能够登录并开始创建沙盒 PayPal 账户。点击 **测试账户** (左侧菜单),然后点击创建账户:**预配置** - 您将获得如下所示的表单

Creating a Sandbox Test Account

创建沙盒测试账户

账户类型单选按钮的说明:选择买家将创建个人账户,选择卖家将创建企业账户。为了测试大多数集成场景,您需要两个账户,所以请务必创建它们。点击 **测试账户** 后,您的屏幕上最终应该会显示以下内容

Overview of your testing accounts

您的测试账户概览

勾选列表中任意账户旁的单选按钮,然后点击“进入沙盒测试网站”应会显示沙盒 PayPal 网站,该网站允许您像普通 PayPal 账户一样登录和管理您的账户。唯一的区别是您会看到一个巨大的 PayPal 沙盒标题和显示您开发者账户电子邮件地址的文本。要了解我在说什么,请查看下图

Administering PayPal Sandbox account

管理 PayPal 沙盒账户

最后但并非最不重要的一点是——为了使用您的沙盒账户进行测试,您需要登录您的开发者账户。如果您未登录并点击某个支付链接,您将看到以下屏幕

Login to use the PayPal Sandbox features

登录以使用PayPal沙盒功能

网站支付标准 (HTML)

在本节中,我将为您提供一些示例,演示如何创建自己的 HTML 表单以通过 PayPal 收款。您将了解如何使用不同的变量来影响支付详情。在我们深入了解细节之前,让我们先看看两个最基本的变量

  • 表单的 `action` 属性 - 大多数情况下,它应该是 `https://www.paypal.com/cgi-bin/webscr`。如果您正在使用 Sandbox 测试支付,您将把它改为 **https://www.sandbox.paypal.com/cgi-bin/webscr** - 实际上,您只需在 URL 中插入单词 **sandbox** (这对于其他一些集成也适用;例如,PayPal API)。对于即将到来的示例,我将不使用 Sandbox URL,因为你们中的大多数人只会看到“登录以使用 PayPal Sandbox 功能”屏幕(请查看图片)。
  • 表单的业务子项 - 大多数示例中我将使用 *youremailaddress@yourdomain.com*;如果您复制粘贴代码,您需要将其替换为您的 PayPal 账户电子邮件。

基本支付

好的,假设您已经开通了 PayPal 账户,并且只想为通过您的网站销售的一幅画作接受 10 美元的付款。只需将以下 HTML 插入您的页面,您就可以开始了

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">

    <input type="hidden" name="cmd" value="_xclick" />
    <input type="hidden" name="business" value="youremailaddress@yourdomain.com" />

    <input type="hidden" name="item_name" value="My painting" />
    <input type="hidden" name="amount" value="10.00" /> 
    <input type="submit" value="Buy!" />

</form>

运费和手续费

接下来想到的事情是,您希望在表单中添加运费和/或手续费。这很容易——只需添加更多参数

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">

    <input type="hidden" name="cmd" value="_xclick" />
    <input type="hidden" name="business" value="youremailaddress@yourdomain.com" />

    <input type="hidden" name="item_name" value="My painting" />
    <input type="hidden" name="amount" value="10.00" />

    <input type="hidden" name="shipping" value="3.00" /> 
    <input type="hidden" name="handling" value="2.00" />

    <input type="submit" value="Buy with additional parameters!" />
</form>

捐赠和文本链接

如果您不销售任何商品,而是为某个事业接受捐赠——您只需将 `cmd` 变量的值更改为 `_donations`。如果我们将此与常见的将超链接而不是按钮的要求结合起来——我们将得到以下 URL(当然,您可以将此 URL 创建方法用于其他 PayPal 支付类型)

  • https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=youremailaddress@yourdomain.com&item_name=拯救北极熊!&amount=10.00

结果

购物车系统

如果您有大量不同的产品可供选择,并且您只想要一个简单的购物车系统而无需实现任何功能,PayPal 可以满足您的需求。基本上,您只需使用 `cmd` 变量,同时保持表单的其余部分与基本支付相同。让我们看看如何为两个产品执行此操作;一个产品定价为 10 美元,不含运费,另一个产品定价为 5 美元,含 1 美元运费。我们还需要一个“查看购物车”按钮

My Cart Item 1:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="paypal">

    <input type="hidden" name="cmd" value="_cart">
    <input type="hidden" name="add" value="1">

    <input type="hidden" name="business" value="youremailaddress@yourdomain.com">
    <input type="hidden" name="item_name" value="My Cart Item 1">

    <input type="hidden" name="amount" value="10.00">
    <input type="hidden" name="shopping_url" 
           value="http://www.yourwebsite.com/shoppingpage.html">

    <input type="hidden" name="return" value="http://www.yourwebsite.com/success.html">
    <input type="hidden" name="cancel_return" value="http://www.yourwebsite.com/cancel.html">

    <input type="hidden" name="bn" value="PP-ShopCartBF:x-click-but22.gif:NonHosted">
    <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but22.gif" border="0"

        name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
    <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1"

        height="1">
</form>

My Cart Item 2:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="paypal">

    <input type="hidden" name="cmd" value="_cart">
    <input type="hidden" name="add" value="1">

    <input type="hidden" name="business" value="youremailaddress@yourdomain.com">
    <input type="hidden" name="item_name" value="My Cart Item 2">

    <input type="hidden" name="amount" value="5.00">
    <input type="hidden" name="shipping" value="1.00">

    <input type="hidden" name="shopping_url" 
        value="http://www.yourwebsite.com/shoppingpage.html">
    <input type="hidden" name="return" value="http://www.yourwebsite.com/success.html">

    <input type="hidden" name="cancel_return" value="http://www.yourwebsite.com/cancel.html">
    <input type="hidden" name="bn" value="PP-ShopCartBF:x-click-but22.gif:NonHosted">

    <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but22.gif" border="0"
        name="submit" alt="Make payments with PayPal - it's fast, free and secure!">

    <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1"
        height="1">
</form>

View Cart:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="paypal">
    <input type="hidden" name="cmd" value="_cart">

    <input type="hidden" name="display" value="1">
    <input type="hidden" name="business" value="youremailaddress@yourdomain.com">

    <input type="hidden" name="shopping_url" 
        value="http://www.yourwebsite.com/shoppingpage.html">
    <input type="image" src="https://www.paypal.com/en_US/i/btn/view_cart_02.gif" 
           name="submit" alt="Make payments with PayPal - it's fast, free and secure!">

</form>

定期付款

如果您销售的是月度服务而非产品,您会对 PayPal 提供的定期付款选项感兴趣。同样,这是在玩弄具有不同含义的不同变量。假设您希望设置 3 天的免费试用期,之后用户每月需要支付 10.00 美元才能继续使用该服务。以下 HTML 表单应该可以解决问题

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
    <input type="hidden" name="cmd" value="_xclick-subscriptions"/> 
    <input type="hidden" name="business" value="youremailaddress@yourdomain.com"/> 
    <input type="hidden" name="item_name" value="Something"/> 
    <input type="submit" value="Subscribe!" /> 

    <input type="hidden" name="a1" value="0"/> 
    <input type="hidden" name="p1" value="3"/> 
    <input type="hidden" name="t1" value="D"/> 
    <input type="hidden" name="a3" value="10.00"/> 
    <input type="hidden" name="p3" value="1"/> 
    <input type="hidden" name="t3" value="M"/> 
    <input type="hidden" name="src" value="1"/> 
    <input type="hidden" name="srt" value="0"/> 
    <input type="hidden" name="sra" value="1"/> 

</form>

HTML变量和资源

阅读完前面的例子后,您可能想知道某些变量是做什么的 (a1? p1? srt?)。幸运的是,PayPal 提供了一个“网站支付标准 HTML 变量”页面,您可以在其中阅读任何您感兴趣的变量。

此外,另一个很棒的资源(我希望在我第一次开始 PP 集成时有人向我推荐它)是“滑雪者的 PayPal 示例”。您会找到几乎所有你能想到的支付场景的示例——因此,我不会用更多示例来使本文变得混乱,而是鼓励您访问该页面,如果您希望实现更高级的 PayPal HTML 表单。

支付后处理

当您设置 PayPal HTML 表单时,您可能会问的第一个问题是——用户支付后,我能否有一些支付后处理逻辑?这并非没有道理;我们可以想到许多支付后场景——从发送简单的“谢谢”电子邮件到更新网站数据库并允许用户访问他已付费的受限资源。根据您的知识和支付后处理逻辑所需的健壮性级别,有三种方法可以选择;好消息是您可以将它们结合使用。

自动返回

自动返回是您拥有的最简单的支付后处理解决方案——用户支付后,他将**自动***重定向到您网站上的指定页面,您可以在该页面上显示一些确认文本。如果您仔细阅读了“网站支付标准 HTML 变量”,您就知道可以使用 **return** 变量在 HTML 表单中指定自动返回 URL。如果您希望使用默认的自动返回 URL,请遵循以下步骤

  1. 登录您的高级或企业账户
  2. 点击“个人资料”子选项卡
  3. 在“销售偏好”列中点击“网站支付偏好”
  4. 点击“自动返回”标签旁边的“开启”单选按钮
  5. 在标记为“返回 URL”的文本框中输入您希望用户返回的 URL
  6. 点击页面底部的“保存”按钮

Providing AutoRetremoved removed in your PayPal profile

在您的PayPal资料中提供自动返回URL

请注意,如果您在个人资料中同时设置了自动返回 URL 并在 HTML 表单中提供了 **return** 变量,则 **return** 变量将覆盖个人资料中的 URL 值。

现在,当您的返回页面被访问时,您将收到允许您自定义页面显示和记录支付的变量

  • tx - 交易ID
  • st - 付款状态
  • amt - 付款金额
  • cc - 货币代码

在本节结束前,还有一件事。我在第一句话中将“自动”这个词斜体显示的原因是:如果用户使用信用卡支付,他将不会自动重定向到您的返回 URL;他需要点击“返回商家”按钮。如果这听起来很奇怪,请知道您并不孤单;然而,由于法律问题,PayPal 过去和现在都拒绝更改使用 AutoReturn 处理信用卡支付的方式。

支付数据传输(PDT)

查看了自动返回提供的变量列表后,您可能想知道——我能否获得更多关于已发生交易的详细信息?这正是 PDT 的用武之地——它建立在自动返回功能之上。因此,您需要在您的个人资料中同时启用自动返回和 PDT;以下是操作方法

  1. 登录您的高级或企业账户
  2. 点击“个人资料”子选项卡
  3. 在“销售偏好”列中点击“网站支付偏好”
  4. 点击“自动返回”标签旁边的“开启”单选按钮
  5. 输入将处理从PayPal发送的PDT HTTP请求的脚本URL
  6. 在“支付数据传输”下,点击“开启”单选按钮
  7. 单击“保存”。

完成这些步骤后,您应该会获得一个 PDT 身份令牌,该令牌是查询 PayPal 所必需的。如果您在点击“保存”后没有复制粘贴该令牌,请注意,您始终可以在“网站支付偏好”中查看它

Payment Data Transfer and Identity Token

支付数据传输和身份令牌

现在您有了身份令牌,您可以在您的返回 URL 被访问后查询 PayPal 获取更多详细信息。以下是利用 PDT 时流程的运作方式

SUCCESS
first_name=Firstname
last_name=Lastname
payment_status=Completed
payer_email=firstname%40lastname.com
payment_gross=50.00
mc_currency=USD
custom=Custom+value+you+passed+with+your+HTML+form
etc.
  1. 用户付款并被重定向到您的自动返回页面,例如:http://www.yourdomain.com/Thanks.aspx?tx=[TransactionID]
  2. Thanks.aspx 的代码后台,您将解析 `tx` 值并向 https://www.paypal.com/cgi-bin/webscr 发送一个 HTTP POST 请求,其中包含以下参数:cmd=_notify-synch&tx=[TransactionID]&at=[PDTIdentityToken]。(如果您正在使用沙盒,您当然会向 https://www.sandbox.paypal.com/cgi-bin/webscr 发送 HTTP POST 请求。)
  3. PayPal将以以下格式响应您的HTTP POST
  4. 随心所欲地处理这些数据。

以下是前面几行所述内容在C#代码中的体现

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        authToken = WebConfigurationManager.AppSettings["PDTToken"];

        //read in txn token from querystring
        txToken = Request.QueryString.Get("tx");


        query = string.Format("cmd=_notify-synch&tx={0}&at={1}", 
                              txToken, authToken);

        // Create the request back
        string url = WebConfigurationManager.AppSettings["PayPalSubmitUrl"];
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);

        // Set values for the request back
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
        req.ContentLength = query.Length;

        // Write the request back IPN strings
        StreamWriter stOut = new StreamWriter(req.GetRequestStream(), 
                                 System.Text.Encoding.ASCII);
        stOut.Write(query);
        stOut.Close();

        // Do the request to PayPal and get the response
        StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
        strResponse = stIn.ReadToEnd();
        stIn.Close();

        // sanity check
        Label2.Text = strResponse;

        // If response was SUCCESS, parse response string and output details
        if (strResponse.StartsWith("SUCCESS"))
        {
            PDTHolder pdt = PDTHolder.Parse(strResponse);
            Label1.Text = 
                string.Format("Thank you {0} {1} [{2}] for your payment of {3} {4}!",
                pdt.PayerFirstName, pdt.PayerLastName, 
                pdt.PayerEmail, pdt.GrossTotal, pdt.Currency);
        }
        else
        {
            Label1.Text = "Oooops, something went wrong...";
        }
    }
}

在本文附带的代码中,在 *PDT* 目录下,您会看到更多类,这些类将帮助您遵循前面提到的流程。

而且,与自动返回一样,在结束本主题之前,请注意 PayPal 响应您的 HTTP POST 中的 `custom` 变量。您可能希望利用此变量,因为它允许您将一些信息从您的支付页面传递到您的后处理页面,而无需向用户显示。举个例子,在我的某些 PayPal 实现中,我用它来跟踪用户——他何时开始支付过程,以及何时/是否完成支付。

即时支付通知(IPN)

PDT 的一个主要缺点是它是一个用户驱动的过程,这意味着——如果用户在完成支付后、但在重定向到您的网站之前关闭了浏览器,您将失去运行支付后处理逻辑的机会。这就是为什么建议您将 PDT 与 IPN 结合用于任何与 PayPal 的严肃集成。

IPN是一种后端机制,它向您的页面发送HTTP POST请求,通知您重要的事件。它不仅用于支付后处理,还用于处理后续事件,例如用户取消定期支付。

作为一种后端技术,它比 PDT 更难实现和调试。在开始实现 IPN 之前,您应该注意以下几点

  • IPN消息有时可能会延迟。我知道,我知道……这与IPN中的“即时”一词相悖,但事实就是如此。
  • IPN 服务存在已知的历史问题;最近两次事件发生在2009年10月2日(延迟2小时)和2009年9月6日(延迟6小时)。
  • 每当您遇到 IPN 问题时,请务必查看 **实时状态** 页面,看看是否有事件通知,然后再深入调试和更改您的脚本。还有一个类似的 **沙盒状态** 页面。

在能够接收 IPN 消息之前,您需要激活此服务;请遵循以下步骤

  1. 登录您的高级或企业账户
  2. 点击“个人资料”子选项卡
  3. 在“销售偏好”列中点击“即时付款通知”
  4. 点击“编辑 IPN 设置”按钮以更新您的设置
  5. 选择“接收IPN消息”(已启用)并输入您的IPN处理程序URL
  6. 点击“保存”,您应该会收到一条消息,表明您已成功激活 IPN

Activating Instant Payment Notification

激活即时支付通知

与自动返回一样,您可以通过添加 `notify_url` 变量来覆盖个人资料中设置的 IPN 处理程序 URL(请参阅 HTML 变量参考)。请注意,这将不仅影响初始 IPN 消息,还会影响与该交易相关的所有未来消息(它们都将发送到 `notify_url`)。

要处理 IPN 消息,您需要在网站上的某个位置创建一个 HTTP 处理程序。当发生重要事件(例如,用户完成付款)时,将发生以下流程

  1. PayPal将向您的IPN处理程序发送一个包含多个变量的HTTP POST。
  2. 收到 HTTP POST 并解析后,您需要将完整的消息正文提交回 https://www.paypal.com/cgi-bin/webscr(或沙盒账户的 https://www.sandbox.paypal.com/cgi-bin/webscr)。在执行此操作时,请务必以您收到的精确格式发送消息;您唯一允许做的事情是添加 **cmd=_notify-validate**。这样做是为了验证 HTTP POST 是真实的,并且是由 PayPal 发送的。
  3. PayPal 将以 VERIFIED 或 INVALID 响应。收到此响应后,请务必发送 200 OK,以防止 PayPal 再次尝试发送 IPN。如果您不以 200 OK 结束循环,PayPal 将开始重新发送 IPN(从 4 秒开始,然后加倍——8 秒、16 秒、32 秒……最长可达 4 天)。

这是一个通用的 C# IPN 处理程序(更多代码请查看文章附带的 zip 文件)

protected void Page_Load(object sender, EventArgs e)
{    
    string postUrl = ConfigurationManager.AppSettings["PayPalSubmitUrl"];
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(postUrl);

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

    //for proxy
    //WebProxy proxy = new WebProxy(new Uri("http://url:port#"));
    //req.Proxy = proxy;

    //Send the request to PayPal and get the response
    StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), 
                             System.Text.Encoding.ASCII);
    streamOut.Write(strRequest);
    streamOut.Close();
    
    StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
    string strResponse = streamIn.ReadToEnd();
    streamIn.Close();

    // logging ipn messages... be sure that you give write
    // permission to process executing this code
    string logPathDir = ResolveUrl("Messages");
    string logPath = string.Format("{0}\\{1}.txt", 
                     Server.MapPath(logPathDir), DateTime.Now.Ticks);
    File.WriteAllText(logPath, ipnPost);
    //

    if (strResponse == "VERIFIED")
    {
        //check the payment_status is Completed
        //check that txn_id has not been previously processed
        //check that receiver_email is your Primary PayPal email
        //check that payment_amount/payment_currency are correct
        //process payment
    }
    else if (strResponse == "INVALID")
    {
        //log for manual investigation
    }
    else
    {
        //log response/ipn data for manual investigation
    }
}

如果您收到 INVALID 响应,这可能意味着两件事

  • 有人试图向您的IPN处理程序发送恶意消息。
  • 您的实施并不完美。

如果是恶意消息,您需要自行处理(记录 IP,采取适当措施),但对于不完善的实现,请访问 PayPal 开发者论坛上的IPN 故障排除主题;它充满了有用的提示,应该能帮助您解决 INVALID 响应。

另外,在您的 IPN 处理程序上线之前,请务必使用即时支付通知 (IPN) 模拟器对其进行彻底测试。由于 IPN 处理程序将在后台运行,您需要在上线并依赖其处理之前尽可能多地对其进行测试。

如果您正在实现 IPN,您还需要访问 ScriptGenerator2 页面……它可以用您选择的语言快速生成一个 IPN 处理程序。有趣的是——他们缺少一个 ASP.NET/C# 的生成器;为此,请查看本文附带的代码存档中的 IPN 目录和这些代码示例

最后,在 PayPal 开发者中心,有一个很好的页面列出了大多数 IPN 和 PDT 变量。我说“大多数”是因为上面缺少一些变量(请查看此页面上的评论),但该列表绝不是无用的。

PayPal API

正如引言中所述,大多数开发者,即使他们以前没有使用 PayPal 的经验,也会直接从 API 开始。Google 搜索会显示API 参考SDK 和下载页面,然后开始浏览文档。我并不是说使用 PayPal API 进行支付有什么问题;我想说的是,在大多数情况下,没有必要走那条路。

PayPal API 远不止是一种支付机制——如果您查看提供的API 参考页面,您会发现有很多方法与“用户执行支付”没有直接关系。您可以使用 API 浏览您的交易历史记录、退款或更新定期支付档案。那么,您如何开始使用它呢?

首先,您需要启用您账户的 API 访问权限;请按照以下步骤操作

  1. 登录您的高级或企业账户
  2. 点击“个人资料”子选项卡
  3. 点击“账户信息”标题下的“API 访问”链接
  4. 点击“请求API凭据/查看API证书”链接
  5. 选择 API 签名或 API 证书

Step 5 from activating API Access

激活 API 访问的第 5 步

我建议您选择 API 签名,接下来的示例将假定您做出了此选择。选择 API 证书没有任何问题;我只是觉得从设置角度来看它更麻烦。

现在您有了进行 API 调用的凭据,如何执行它们呢?适用于所有平台的通用方法是下载 SDK,针对适当的 API 端点,然后使用名称-值对或 SOAP 开始进行 HTTP 调用。

然而,对于 .NET 开发者,我推荐一种不同的方法。考虑到 Visual Studio 拥有出色的 WSDL 解析器,我强烈建议您只需向 https://www.paypal.com/wsdl/PayPalSvc.wsdl 添加一个 Web 服务引用。稍后,您将拥有一个最新的类,可以为您提供强类型的所有优势——无需构建 HTTP 请求,无需复制粘贴字段名称,也无需繁琐地解析响应。您也可以在沙盒环境中获得同样的功能,地址是:https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl

快捷结账

Express Checkout 是最灵活的 PayPal 集成解决方案。用户被重定向到 PayPal 只是为了进行身份验证和确认他希望为您的服务付款,之后所有操作都在您的网站上完成;您将在后台调用 PayPal API。下图描述了该过程(摘自此页面

Step 5 from activating API Access

快捷结账流程
  1. 您将添加一个 PayPal 结账按钮,点击后它会调用 PayPal API 的 `SetExpressCheckout` 方法。
    1. 如果您为一次性付款调用此方法,则只需包含必填字段即可。如果您销售在线服务,将 `NOSHIPPING` 变量设置为 1 很重要(它将帮助您跳过发货信息页面)。
    2. 如果您正在调用此方法以设置定期付款,请务必将 `L_BILLINGTYPE0` 设置为 `RecurringPayments`,并将 `L_BILLINGAGREEMENTDESCRIPTION0` 设置为您的服务的有效描述。
  2. `SetExpressCheckout` 将返回一个 20 字符的令牌,该令牌将唯一标识您的交易。此令牌有效期为 3 小时。收到令牌后,将用户重定向到 https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=[TOKEN](您能猜到沙盒的 URL 是什么,对吗?)。
  3. 用户将审查支付信息,如果一切正常,则输入登录凭据。之后,PayPal 会将他重定向到您在调用 `SetExpressCheckout` 时使用 `RETURNURL` 指定的 URL。
  4. 当您的 `RETURNURL` 被访问时,您需要调用 `GetExpressCheckoutDetails` 方法并查看实际交易的详细信息;验证一切是否正常。
  5. 现在,剩下的就是提交交易了。根据您在步骤1中所做的操作,可以完成两件事。
    1. 对于一次性付款,您只需调用 `DoExpressCheckoutPayment` 并转发相应的变量。
    2. 对于定期付款,您将调用 `CreateRecurringPayments` 方法。您必须包含 DESC 字段,并使其与您在调用 `SetExpressCheckout` 时输入的 L_BILLINGAGREEMENTDESCRIPTION0 值匹配。

简而言之——就是这样。再次强调,我已在本文附带的存档(API 目录下)中提供了遵循上述流程的代码示例。如果您愿意,也可以使用 PayPal 快捷结账集成向导来生成参考代码。

直接支付(网站支付专业版)

大多数开发人员没有意识到 PayPal 平台可以仅用于信用卡处理。PayPal API 的这一部分称为直接支付,当与 Express Checkout(仅服务于拥有 PayPal 账户的客户)结合使用时,您将获得在 PayPal 开发者中心被称为 网站支付专业版 的服务。

要能够调用属于直接支付的方法(`DoDirectPayment``CreateRecurringPayments`),您首先需要满足一些条件

  1. 拥有一个在美国、英国或加拿大注册的商业账户
  2. 承诺在您的网站上同时实施 Express Checkout 和 Direct Payment
  3. 通过您的 PayPal 账户提交 Website Payments Pro 申请并获得批准
  4. 支付月费(目前每月 30 美元)

在您拥有 Website Payments Pro 账户后,调用 Direct Payment 方法非常简单——如有疑问,请访问 API 参考页面,或查看本文附带的代码。请注意,如果您尝试在未启用 Pro 的账户上调用任何 Direct Payment 方法,您将收到错误代码 10501(这是 Sandbox 论坛中报告的最常见问题之一)。

最后,一旦您开始处理信用卡,您就需要处理 PCI 合规性;这里有一个不错的论坛帖子提供了更多相关信息

结论

我希望本文能为您提供 PayPal 集成选项的良好概述。如果做到了,我将心安理得——因为一旦您理解了本文中阐述的概念,您将轻松地从提供的链接中获取所需的详细信息。当然,有些主题我们没有涉及,例如加密网站支付PayPal API 证书Payflow Gateway,但我认为一旦您完全理解了这里写的所有内容,即使这些您也能自行解决。

如果您遇到任何问题,我建议您首先访问 PayPal 开发者社区并在相应的论坛中提问。许多优秀、知识渊博的开发者会关注这些论坛,您很可能在不到一小时内得到几乎所有 PayPal 问题的答案。我也有一个该网站的账户 (lepipele),只要有时间就会尝试回答问题;所以如果您路过或遇到麻烦,请随时给我发私信。

历史

  • 2009年11月5日 - 因PayPal X重组更新链接
  • 2009年10月1日 - 文章初始版本。
© . All rights reserved.