安装 PayPal SDK,您还需要一些扩展功能: PEAR、cURL 和 SSL。 尽管它们可以在
php.ini 中加载,但使用 PHP 编译可得到最佳结果。
充分设置好环境后,您需要下载 PayPal PHP SDK,其中包括服务/ PayPal PEAR
程序包、 PayPal Web 控制台、SDK 文档和 PDF 信息文档。 (参见下方“无法使用 Web 控制台”部分中关于 Web
控制台的重要注意事项。) 在下载和提取此文件后,您需要运行一些命令行操作:
pear install --alldeps /Services_PayPal/package.xml
cp -r /WebConsole
此命令可以安装一些其它的 PEAR 程序包,为您提供一个功能完善的 PayPal SDK。
在浏览器中访问 http://localhost/WebConsole 页面后, PayPal
配置文件管理工具将显示一条问候消息,您可以在此处检查 PayPal SDK 的有效性。 常见问题包括丢失 cURL 或 SSL 的安装,通过修改
php.ini 或重新编译 PHP,然后再次运行 PEAR 命令,这些问题将得到修复。 如果因为托管限制或安全性问题而无法安装 PEAR
或某种必要的扩展功能,您还可以使用下方描述的标准结帐。
采用稳妥的方式……
通过 SDK 使用 API 是使用 PayPal 功能的一种灵活、有效的方式。 API 支持的两种支付方式包括:
直接付款:使用此方式可以收集网站上的详细帐单,从用户的信用卡收费,全
部工作在自己网站上完成。 这种方法适合拥有 https 安全应用程序和基础架构(用于存储客户和购物车信息)的大型机构。
快速结帐:这种方式允许用户使用
PayPal 帐户信息和选择发货方式,不需要在网站上重新输入信息,从而节省了时间。同时,
这种方式不需要应用程序存储购买者信息的本地副本,管理此方式时只需要最少的额外安全性基础架构。
其它 API 特性(文中并未完全涉及)包括:
慈善捐款:根据用户的购物情况,提供有关
慈善捐款的实时信息。
发货:如果
销售的是现实产品,则允许用户选择发货商、发货方式、保险和其它属性。
在用户确实购买货物之前,您就可以向用户提供发货的成本,或者也可以使用此特性在产品显示页面提供更准确的价格。
退款:提供向用户退款的方法。
税款:根据每件货物或每个购物车收税,并适当地将税款显示在收据和发票
上。
订阅:
灵活地定义现实货物和数字货物的循环订阅。
SDK 还提供了广泛的 eBay 支持,尽管其价值不在我们讨论的范围内。
……或者采用简易方式
如果 SDK 的功能远远超出用户的需求,在此情况下,PayPal 提供了另一种解决方案。 标准结帐不使用
SOAP,只依赖于在应用程序与 PayPal 安全服务器间传递 HTML 表单值。 要使用标准结帐,您只需要生成一个表单,该表单可以提交适当的
POST 变量,如下面的示例所示:
<form
action="https://sandbox.paypal.com/cgi-bin/webscr" method="post">
<input
type="hidden" name="cmd" value="_cart">
<input type="hidden" name="upload"
value="1">
<input
type="hidden" name="business" value="sales@widgetco.com">
<input
type="hidden" name="item_name_1" value="Big Widget">
<input
type="hidden" name="amount_1" value="100.00">
<input type="hidden"
name="item_name_2" value="Little Widget">
<input type="hidden" name="amount_2"
value="1.00">
<input type="submit" value="PayPal">
</form>
提交表单后,用户将进入 PayPal 的服务器,输入帐单信息。
在完成信息验证和帐单授权机制后,用户将返回您在网站上定义的一个位置。 如果您仅仅是收集捐款,而不是销售物品,那么您的工作已经完成了!
然而,对于其它情况,用户可使用大量的变量来定制功能、货币和显示方面的体验。 (参见参考指南。)
使用带有 notify_url 变量的即时付款通知 (IPN)
时,一旦用户在指定的地点完成付款,您的应用程序就会得到通知 —
您可以使用定制的链接提供专用用户标识,例如,允许对在线内容进行即时访问或触发一个批发商的订单。
另外,通过使用发票和定制变量,您可以创建一个机构,将 PayPal 的记录限制在您自己的域中。
如果应用程序已经保存了用户名和地址信息,您可以通过一组变量(包括 address1 、city 和 country)将这些信息传递给
PayPal ,以便预先填充相应的字段。
标准结帐的基本方式
中也包含 API 为收集非盈利性资金而提供的许多特性, 例如,可以应用到每个购物车或每件货物的税款、处理和发货变量。
cpp_ 系列变量(包括
cpp_header_image、cpp_headerback_color、cpp_headerborder_color 和
cs)允许您精确调整用户在 PayPal 服务器上的体验,这些变量用于设置支付页面的背景颜色。
如果这种方法能够满足应用程序的需求,标准结帐将是一种非常经济有效的解决方案。 与基于 API
的直接付款方式不同,标准结帐并不确定每月的费用,并且实施期间的开发工作非常少。
准备付款
要使用 PayPal API,首先要熟悉开发人员中心。 您将在开发人员中心建立帐户,以便在 Sandbox
中创建买方与卖方的示例帐户。 示例帐户创建完毕后,使用该帐户登录到 Sandbox 将显示拥有资金的有效 PayPal 帐户。
您的买方可以从其他 Sandbox 帐户购买物品,您的卖方可以将货款退还给其他 Sandbox 帐户,这些都不需要现金转移,也不需要收费代理。
PayPal 的集成中心提供了极好的逐步指南(注意,第 3 步是我在前面介绍的安装过程),我将在此处提供该指南的概述。
首先,您需要在 developer.paypal.com
注册一个帐户,此网页是访问各种开发人员资源的中心点,用于创建 Sandbox 帐户。 之后,您将在 developer.paypal.com 的
Sandbox 选项卡中创建一个买方示例和一个卖方示例。这项工作非常简单,为了使创建的内容有意义,您只需要足够的创造力。
例如,在提示您输入银行帐户信息时,为了方便使用,建议您将系统提供的虚拟帐户号作为银行的名称。
另外,您可以为买方帐户和卖方帐户使用相同的密码,因为此服务器发生密码泄露的风险很低。 在 Sandbox
中学习的特性与生产时使用的特性完全相同,从而减少了培训和测试时间。
在 Sandbox 中最后一个重要的步骤是创建测试证书,这是一个小型文本文件,其中包含将与每个 API 调用一起使用的密钥。
要创建一个证书,您需要登录到卖方 Sandbox 帐户,单击 Profile,然后依次选择 API Access 和 View or
Remove Credentials。 记录此文件和密码;您将在配置应用程序时用到它们。
回到 developer.paypal.com,您可以查看测试证书的信息,也可以从 Test
Certificates 选项卡下载测试证书。 此处不能查看 API 密码;要获得此信息,您必须重新登录到
http://www.sandbox.paypal.com,然后访问上述位置。
直接付款处理
与 PayPal 交互的最灵活的方式是通过 SDK 来完成,SDK 会将基于 SOAP 的请求抽象成可管理的信息。
不同调用要完成的目标不同,但执行的步骤基本相同: 认证、操作和响应流程。 第一个步骤,认证,来自 SDK
示例,同样需要用在下方的快速结帐方法中。 显示的值用于 Sandbox 测试: 需要为生产创建带有认证详细信息的新证书。
$certfile = dirname(__FILE__) .
'/sdk-seller_cert.pem';
$apiusername = '';
$apipassword = '';
$subject = null;
$environment = 'Sandbox';
$handler =&
ProfileHandler_Array::getInstance(array(
'username' => $apiusername,
'certificateFile' => $certfile,
'subject' => $subject,
'environment' =>
$environment));
$profile =&
APIProfile::getInstance($apiusername, $handler);
$profile->setAPIPassword($apipassword);
$caller =&
Services_PayPal::getCallerServices($profile);
认证完成后,应用程序已经准备好处理 API 请求。
在直接付款时,您的应用程序必须有能力、有责任创建和存储订单的状态,并为订单创建收据:
在下一个示例中,我们将假定应用程序已将所有相关信息存储到以下表格中: Customer、Billing_Method、Order 和
Line_item。 本示例使用 PHP 数据对象 (PDO),在此情况下,传统的 OCI8 方法同样有效。
$db = new PDO('oci:', 'scott',
'tiger' 'HR', 'HR');
$dbcustomer
= $dbh->query("SELECT * " .
"FROM customer " .
"WHERE customerid = '{$_SESSION'}");
$dborder =
$dbh->query("SELECT * " .
"FROM order " .
"WHERE customerid = '{$_SESSION}' " .
"AND orderid =
'{$_SESSION}'");
$dbbilling
= $dbh->query("SELECT * " .
"FROM billing_method " .
"WHERE billingid = '{$dborder}'");
$dblineitemtotals =
$dbh->query("SELECT sum(amount) total " .
"FROM line_item " .
"WHERE customerid =
'{$_SESSION}' " .
"AND orderid = '{$_SESSION}'");
$name =&
Services_PayPal::getType('PersonNameType');
$name->setFirstName($dbcustomer['fname']);
$name->setLastName($dbcustomer['lname']);
$address =&
Services_PayPal::getType('AddressType');
$address->setStreet1($dbbilling['street1']);
$address->setCityName($dbbilling['city']);
$address->setStateOrProvince($dbbilling['state']);
$address->setCountry($dbbilling['country']);
$address->setPostalCode($dbbilling['zip']);
$payer =&
Services_PayPal::getType('PayerInfoType');
$payer->setPayerName($name);
$payer->setPayerCountry('US');
$payer->setAddress($address);
$cc =&
Services_PayPal::getType('CreditCardDetailsType');
$cc->setCreditCardType($dbbilling['cardtype']);
$cc->setCreditCardNumber($dbbilling['cardnumber']);
$cc->setExpMonth($dbbilling['expmonth']);
$cc->setExpYear($dbbilling['expyear']);
$cc->setCardOwner($payer);
$amount =&
Services_PayPal::getType('BasicAmountType');
$amount->setval($dblineitemtotals['total']);
$amount->setattr('currencyID',
'USD');
$pdt
=& Services_PayPal::getType('PaymentDetailsType');
$pdt->setOrderTotal($amount);
$details =&
Services_PayPal::getType('DoDirectPaymentRequestDetailsType');
$details->setPaymentAction('Authorization');
$details->setPaymentDetails($pdt);
$details->setCreditCard($cc);
$details->setIPAddress('127.0.0.1');
$details->setMerchantSessionId('merchantId');
$ddp =&
Services_PayPal::getType('DoDirectPaymentRequestType');
$ddp->setDoDirectPaymentRequestDetails($details);
此时, PayPal
执行请求的直接付款。 为了解发生的情况,现在,应用程序会获取第三步中的信息: 响应处理。
$response =
$caller->DoDirectPayment($ddp);
此响应中返回的各种字段提供了有关事务成功的信息,以及事务的 ID。通过存储此 ID 并将它提供给后面的
API 调用,应用程序将能够获取有关事务的详细信息,并将根据这些信息生成另一个表格。
$d =&
Services_PayPal::getType('GetTransactionDetailsRequestType');
$d->setTransactionId('');
$response =
$caller->GetTransactionDetails($d);
无法使用 Web 控制台
在撰写本文时,随上述 SDK 下载一起提供的 Web 控制台由于丢失了重要目录而停止工作。
然而,此时可以下载包含所有必需文件的存档。 控制台能够测试 API 调用,生成 PHP 代码片断,从而达成您的目标。 通过本文和 SDK
参考中的一些调查,您可以通过浏览器方便地查看从 Sandbox 发出的所有 API 调用。
快速结帐流程
快速结帐方式介于强大的直接付款方式和简捷的标准结帐方式之间。 利用快速结帐和基于 API
的方法,用户可以在您的网站完成订单创建过程,然后转至 PayPal 处理所有帐单和发货信息。
在使用快速结帐时,用户只需为所有商品输入一次帐户信息,而您的应用程序也不需要存储这些信息 — 这在安全性和开发方面具有明显的优势。
同直接付款方式相同,通过存储事务 ID,应用程序可以利用其他 API 调用获取事物的详细信息。 快速结帐可以利用上文中描述的
IPN,从而允许其它实时处理选项。 下面的代码段来自 SDK 示例。
$amount =&
Services_PayPal::getType('BasicAmountType');
$amount->setval();
$amount->setattr('currencyID',
'USD');
$ecd =&
Services_PayPal::getType('SetExpressCheckoutRequestDetailsType');
$ecd->setOrderTotal($amount);
$ecd->setReturnURL('http://widgetco.com/return');
$ecd->setCancelURL('http://widgetco.com/cancel');
$ec =&
Services_PayPal::getType('SetExpressCheckoutRequestType');
$ec->setSetExpressCheckoutRequestDetails($ecd);
$response =
$caller->SetExpressCheckout($ec);
此调用的结果将提供一个令牌,您可以将其添加到一个链路,或者在网站上将其重定向到 PayPal 。
然后,用户使用 PayPal 处理业务。在操作成功或失败后,系统将用户重定向到您的网站。 在本示例中,调用的页面返回将向您的应用程序发送以下
API 调用:
$ecd
=& Services_PayPal::getType('GetExpressCheckoutDetailsRequestType');
$ecd->setToken('');
$response =
$caller->GetExpressCheckoutDetails($ecd);
这里包含您需要的所有事务信息,但不包含信用卡号等敏感信息。
用户在您的网站上对这些值进行确认后,由最终 API 调用处理资金事务:
$amount =&
Services_PayPal::getType('BasicAmountType');
$amount->setval();
$amount->setattr('currencyID',
'USD');
$pdt =&
Services_PayPal::getType('PaymentDetailsType');
$pdt->setOrderTotal($amount);
$details =&
Services_PayPal::getType('DoExpressCheckoutPaymentRequestDetailsType');
$details->setPaymentAction('Sale');
$details->setToken('');
$details->setPayerID('juser@jisp.com');
$details->setPaymentDetails($pdt);
$ecprt =&
Services_PayPal::getType('DoExpressCheckoutPaymentRequestType');
$ecprt->setDoExpressCheckoutPaymentRequestDetails($details);
$response =
$caller->DoExpressCheckoutPayment($ecprt);
同样,在对 updateChart 进行连续调用时,ChartData 将引发
onResult 方法:
_root.chartData.onResult
= function() {
_root.chart.throbber._visible
= false;
drawChart(this);
}
快速结帐几乎与直接付款具有相同的定制
性,同时还保持了标准结帐的保密和安全优势。
PayPal 支付处理的任何一种形式都提供了收集在线付款的有效方式。 由实施者决定哪种方式更加适合:
标准结帐为小型机构提供了收集付款的能力,且不需要这些机构投资其它安全体系结构;在与当前的企业应用程序集成时,直接付款是理想的解决方案;而快速结帐
介于两者之间,适合将其更改成第三方产品。 选择灵活性、安全性和实施便捷性之间的平衡点将允许您利用现有的 Oracle 基础架构获得在线支付功能。