hochstrasserio / wirecard
Wirecard支付网关的现代客户端
Requires
- php: >=5.4.0
- guzzlehttp/psr7: ^1.0.0
Requires (Dev)
- egeloen/http-adapter: ~0.8.0@dev
- guzzlehttp/guzzle: ^6.0.0
- phpunit/phpunit: 4.*
Suggests
- php-http/httplug: Adapters to existing HTTP clients
- sebastian/money: Robust handling of money amounts
This package is not auto-updated.
Last update: 2020-05-15 17:48:50 UTC
README
从2020年9月30日起,此SDK使用的方法不再由Wirecard支持。
因此,此存储库已存档,不再维护。您可以在许可证条款下自由分支此代码。
Wirecard
一个用于通过Wirecard进行支付的未官方SDK。
有关在您的应用程序中使用Wirecard进行支付的一般信息,请访问Wirecard Integration Wiki。
通过免费注册Wiki的注册页面获得Integration Wiki的账户。
SDK覆盖范围
- Wirecard Checkout Page
- Wirecard无缝结账
- 无缝后端操作
- 结账页面后端操作
安装
在项目目录中使用Composer
$ composer require hochstrasserio/wirecard
使用
设置
此库不包含通过网络发送HTTP请求的功能。您需要获取一个库来完成此操作。任何符合PSR-7规范的库都可以工作,如Guzzle v6+或Ivory HTTP Adapters库。
$ composer require 'guzzlehttp/guzzle:^6.0.0'
然后,使用您的客户ID、客户密钥和可选的商店ID配置Wirecard Context。您应该从Wirecard或Integration Wiki收到这些信息。演示或测试凭据也在Integration Wiki中可用。
<?php use Hochstrasser\Wirecard\Context; // Constructor takes Customer ID, Customer Secret, Language code, and Shop ID: $context = new Context([ 'customer_id' => 'D200001', 'secret' => 'B8AKTPWBRMNBV455FG6M2DANE99WU2', 'language' => 'de', 'shop_id' => 'qmore', 'hashing_method' => Context::HASHING_HMAC, ]);
Context还有一些您可以通过构造函数传递的选项
customer_id
: 您的客户ID,您可以从Wirecard或Integration Wiki获得secret
: 您的客户密钥,您可以从Wirecard或Integration Wiki获得。不要与他人分享此信息language
: Wirecard UI和错误消息的语言shop_id
(可选): 如果多个商店使用一组凭据(如果Wirecard告诉您),请设置此选项javascript_script_version
(可选): 启用PCI DSS SAQ A合规功能user_agent
(可选): 用于HTTP请求的库用户代理,您可以可选地将此设置为您的站点名称hashing_method
(可选): 用于计算指纹散列的使用的算法。如果省略,则出于兼容性原因使用旧方法Context::HASHING_SHA
。新Wirecard客户应使用Context::HASHING_HMAC
,因为它是目前Wirecard的默认值。不过,演示客户仍然使用Context::HASHING_SHA
。
SDK模式
请求
所有请求都是简单的类,它们实现了 WirecardRequestInterface 并可以直接构造。大多数类都有一个特定的命名构造函数,以 with*
开头,例如 withBasket
或 withOrderIdentAndReturnUrl
。应优先使用这些构造函数,而不是简单的构造函数。
发送请求
请求通过 createHttpRequest
方法转换为 PSR-7 兼容的请求。必须在之前设置上下文。然后您可以使用您的 HTTP 客户端发送 PSR-7 兼容的请求消息。发送请求后,createResponse
方法将任何 PSR-7 兼容的响应对象转换为 WirecardResponseInterface。
<?php $client = new \GuzzleHttp\Client; $request = InitDataStorageRequest::withOrderIdentAndReturnUrl('1234', 'http://example.com') ->setContext($context); $httpResponse = $client->send($request->createHttpRequest()); $response = $request->createResponse($httpResponse);
这看起来可能有点麻烦,但它有一个很大的好处,即让您摆脱对特定 HTTP 客户端库(如 Guzzle 或 Buzz)特定版本的依赖。您可以使用最适合您的客户端,或者提供最佳性能的客户端,这始终比这个库能提供的更好、更快,并且具有更多功能。此外,SDK 的依赖与您的应用程序发生冲突的风险很小。
使用 WirecardHelper
包含了一个小的实用工具,即 WirecardHelper
,每次您发出请求时,它都可以为您节省几行代码。使用上下文初始化,并使用配置好的客户端发送请求。
您传递给它两件事:Wirecard 上下文和一个函数,该函数通过电线发送一个 Psr\Http\Message\RequestInterface
并返回一个 Psr\Http\Message\ResponseInterface
。
<?php use Hochstrasser\Wirecard\Helper\WirecardHelper; // Guzzle 6 $guzzle = new Guzzle\Client; $helper = new WirecardHelper($context, function ($request) use ($guzzle) { return $guzzle->send($request); }); // Sets the context, converts the request and makes the http response to a // WirecardResponseInterface $response = $helper->send(InitDataStorageRequest::withOrderIdentAndReturnUrl( '1234', 'http://example.com' )); $dataStorage = $response->toObject();
请注意,该辅助程序仅以同步方式发送请求。如果您想进行异步请求,您必须直接使用您的 HTTP 库。
必需参数
请求知道它们必需的参数。如果缺少已知的必需参数,则抛出 RequiredParameterMissingException。
响应
所有响应都实现了 WirecardResponseInterface。
获取结果
通过使用 toObject
或 toArray
方法检索结果。通常使用 toObject
方法。此方法返回一个模型类,该类具有方便检索返回值的函数。这些函数定义在模型类中,因此您的 IDE 应该能够建议它们。
toArray
方法返回请求返回的原始响应参数。这对于调试和与官方文档核对很有用。
<?php $a = $response->toArray(); var_dump($a['redirectUrl']); $b = $response->toObject(); var_dump($b->getRedirectUrl());
错误
每个响应都有一个 hasErrors
方法,它检查是否有任何返回的错误。可以通过在响应对象上使用 getErrors
来检索所有返回的错误。
<?php if ($response->hasErrors()) { foreach ($response->getErrors() as $error) { echo $error, "<br>"; } }
Wirecard 结账页面
使用 Wirecard 结账页面,您不必处理选择付款类型或存储信用卡数据的 UI。InitCheckoutPageRequest 在另一种方式上也是一个例外:它不能与客户端一起发送,您必须使用一个 HTML 表单,该表单必须由客户自己提交。
InitCheckoutPageRequest与Seamless Checkout中的InitPaymentRequest使用相同的参数,并且以相同的方式初始化。
唯一的区别是
confirmUrl
不是必需的paymentType
不需要在请求对象中设置,可以在表单中设置
<?php use Hochstrasser\Wirecard\Context; use Hochstrasser\Wirecard\Model\Common\PaymentType; use Hochstrasser\Wirecard\Request\CheckoutPage\InitCheckoutPageRequest; $context = new Context(['customer_id' => 'D200001', 'secret' => 'B8AKTPWBRMNBV455FG6M2DANE99WU2', 'language' => 'de']); $request = InitCheckoutPageRequest::with() ->setPaymentType(PaymentType::Select) ->setContext($context) ->setAmount('33.00') ->setCurrency('EUR') ->setOrderDescription("12345") ->setSuccessUrl("http://localhost:8001/") ->setFailureUrl("http://localhost") ->setCancelUrl("http://localhost") ->setServiceUrl("http://localhost") ; ?> <form action="<?= $request->getEndpoint() ?>" method="POST"> <?php foreach ($request->getRequestParameters() as $param => $value): ?> <input type="hidden" name="<?= $param ?>" value="<?= $value ?>"/> <?php endforeach ?> <input type="submit" value="Buy"/> </form>
Checkout页面的另一个主要区别是,successUrl
接收所有支付响应参数作为POST请求,就像confirmUrl
一样。此外,confirmUrl
还可以设置为在用户动作之外接收参数,以便您进行记录和参考。
您可以在这里了解更多信息: 在您的在线商店接收支付过程结果
Wirecard无缝结账
使用Wirecard无缝结账,您的客户将使用您自己定制的页面选择您已为网站启用的支付方式。此UI的外观和工作方式完全由您决定。
您需要发出一些请求
InitDataStorageRequest
:通常您不希望处理PCI合规性,并希望Wirecard来处理。此请求初始化一个数据存储,它在Wirecard的服务器上,并为您安全存储客户的信用卡数据。存储数据的唯一方法是使用JavaScript库。在成功调用后,InitDataStorageRequest
返回包含库的URL。这仅在您接受信用卡付款时才是必要的,并且必须在请求付款之前进行。- 可选的,
ReadDataStorageRequest
:您可以使用此请求显示客户输入的信用卡数据,同时移除所有敏感信息。您可以使用此功能在付款前让客户再次查看输入的支付数据。 InitPaymentRequest
:执行支付并返回一个URL。将客户重定向到该URL以完成请求的支付。如果成功,您的网站将收到Wirecard在确认URL处的POST请求,其中包含支付详情,如交易号。最后,客户将被重定向回您的网站。
InitDataStorageRequest
响应模型: DataStorageInitResult
设置数据存储并返回JavaScript库的URL和存储ID。只有在您的客户打算通过信用卡付款时才需要发出此请求。存储ID可以用来从数据存储中读取掩码数据,并且稍后必须传递给InitPaymentRequest
。
要创建请求,请使用withOrderIdentAndReturnUrl
命名构造函数。"订单标识"应该是结账的唯一值,"返回URL"作为第二个参数传递,用于旧版浏览器。
<?php use Hochstrasser\Wirecard\Request\Seamless\Frontend\InitDataStorageRequest; $request = InitDataStorageRequest::withOrderIdentAndReturnUrl('1234', 'http://example.com') ->setContext($context); $response = $request->createResponse($client->send($request->createHttpRequest())); // Store the storage ID for later usage with the payment request $_SESSION['wirecardDataStorageId'] = $response->toObject()->getStorageId(); var_dump($response->hasErrors()); var_dump($response->toObject()->getStorageId()); var_dump($response->toObject()->getJavascriptUrl());
ReadDataStorageRequest
响应模型: DataStorageReadResult
读取数据存储并返回一个包含掩码的数组客户数据。
<?php use Hochstrasser\Wirecard\Request\Seamless\Frontend\ReadDataStorageRequest; $request = ReadDataStorageRequest::withStorageId($_SESSION['wirecardDataStorageId']) ->setContext($context); $response = $request->createResponse($client->send($request->createHttpRequest())); var_dump($response->hasErrors()); var_dump($response->toObject()->getStorageId()); foreach ($response->toObject()->getPaymentInformation() as $paymentInformation) { var_dump($paymentInformation->getMaskedPan()); }
使用InitPaymentRequest进行支付
响应模型: InitPaymentResult
请求支付并返回一个重定向URL。将客户重定向到此URL以完成支付。
必需的支付参数
amount
:货币的基本单位支付金额,例如12.00
。当使用withBasket
时从购物车设置。设置为字符串以避免四舍五入错误,这可能会发生在浮点数上。currency
:ISO货币代码,例如EUR
。当使用withBasket
时从购物车设置。paymentType
(PaymentType):客户选择的支付类型。您可以使用PaymentType::isValid()
来验证请求的支付类型的标识符。orderDescription
:您的订单描述,可以是关于订单的结构化数据。successUrl
:如果支付成功,则客户将被Wirecard重定向到该URL。failureUrl
:如果在确认结账过程中发生某种类型的失败,则客户将被Wirecard重定向到该URL。cancelUrl
:如果在确认过程中支付被取消(例如,在PayPal屏幕上),则客户将被Wirecard重定向到该URL。serviceUrl
:列出您的服务条款和联系信息的页面,通常是您的“联系我们”或“印记”页面。confirmUrl
:您的网站上的一个端点,该端点通过Wirecard在客户成功确认支付后通过POST请求接收有关支付的详细信息。通常您在此端点发送订单确认电子邮件。consumerUserAgent
和consumerIpAddress
:用于可选的防止重复支付。
这些参数可以是使用请求对象的 addParam
方法或它们的相应 set*
方法设置的,例如 setSuccessUrl
。
支付请求还有很多可选参数,例如创建周期性支付、设置信用卡账单上显示的声明等。有关更多信息,请参阅请求参数文档。
添加购物车
支付请求使用一个填充了 Basket 的 Basket Items 来在PayPal等结账屏幕上显示客户的商品。您也可以使用它轻松设置订单的金额和货币。在大多数情况下,您应该能够从您网站自己的购物车模型中推断出购物车。
注意:如果在支付请求上设置了购物车,Wirecard会在服务器上验证购物车商品的所有价格和总金额是否正确累加。否则,Wirecard会返回错误。
<?php use Hochstrasser\Wirecard\Model\Common\Basket; use Hochstrasser\Wirecard\Model\Common\BasketItem; // Create the basket, this is optional for most payment methods, but probably // can be automatically created from your shop’s cart model $basket = new Basket(); $basket->setAmount('17.00'); $basket->setCurrency('EUR'); $basket->addItem((new BasketItem) ->setArticleNumber('A001') ->setDescription('Product A1') ->setQuantity(1) ->setUnitPrice('10.00') ->setTax('1.00') ); $basket->addItem((new BasketItem) ->setArticleNumber('SHIPPING') ->setDescription('Shipping') ->setQuantity(1) ->setUnitPrice('5.00') ->setTax('1.00') );
添加收货和账单信息
某些支付类型需要收货和账单信息。SDK提供ShippingInformation 和 BillingInformation 类来帮助您完成这些操作。
<?php use Hochstrasser\Wirecard\Model\Common\ShippingInformation; use Hochstrasser\Wirecard\Model\Common\BillingInformation; $shippingInformation = (new ShippingInformation) ->setFirstname('Max') ->setLastname('Mustermann') ->setAddress1('Musterstraße') ->setAddress2('2') ->setZipCode('1234') ->setState('Lower Austria') ->setCity('Musterstadt') ->setCountry('AT') ->setPhone('+431231231234') ->setFax('+431231231234');
如果客户的账单信息与收货信息相匹配,则BillingInformation 类提供了一个方便的命名构造函数。否则,BillingInformation 类具有与ShippingInformation 相同的方法。
<?php $billingInformation = BillingInformation::fromShippingInformation($shippingInformation);
有效的账单信息需要两个附加参数:客户的电子邮件和他们的出生日期(作为 \DateTime
对象)
<?php $billingInformation->setConsumerEmail("max@mustermann.com"); $billingInformation->setConsumerBirthDate(new \DateTime("Sept 1 1970"));
最后,您可以使用 setConsumerShippingInformation
和 setConsumerBillingInformation
方法将配送和账单信息添加到请求中。
请求支付
有了我们的购物车对象,我们现在可以初始化支付请求
<?php use Hochstrasser\Wirecard\Model\Common\PaymentType; use Hochstrasser\Wirecard\Request\Seamless\Frontend\InitPaymentRequest; if (!PaymentType::isValid($_POST['paymentType'])) { // Show error and return } $request = InitPaymentRequest::withBasket($basket) // Set the payment type selected by the user in the frontend ->setPaymentType($_POST['paymentType']) ->setOrderDescription('Some test order') ->setSuccessUrl('http://example.com') ->setFailureUrl('http://example.com') ->setCancelUrl('http://example.com') ->setServiceUrl('http://example.com') // Your callback controller for handling the result of the payment, you will // receive a POST request at this URL ->setConfirmUrl('http://example.com') ->setConsumerShippingInformation($shippingInformation) ->setConsumerBillingInformation($billingInformation) ->setConsumerUserAgent($_SERVER['HTTP_USER_AGENT']) ->setConsumerIpAddress($_SERVER['REMOTE_IP']) ->setContext($context) ; // Set the data storage ID if the data storage was initialized if (isset($_SESSION['wirecardDataStorageId'])) { $request->setStorageId($_SESSION['wirecardDataStorageId']); } $response = $request->createResponse($client->send($request->createHttpRequest()));
使用响应模型,现在您可以重定向客户到 Wirecard 的支付确认流程。然后,此流程将连接到客户选择的支付服务提供商,例如 PayPal 或 3-D secure,在那里他们将确认支付。
<?php if ($response->hasErrors()) { // Show errors in the UI } // Redirect if no errors happened header('Location: '.$response->toObject()->getRedirectUrl());
处理响应参数
之后,Wirecard 将向作为 confirmUrl 传递的 URL 发送一个 POST 请求,并带有支付请求的响应参数。这些参数包含订单号等。存储这些参数以备参考。
您可以使用提供的 Fingerprint 类来验证提供的响应指纹
<?php use Hochstrasser\Wirecard\Fingerprint; $responseParameters = $_POST; $fingerprint = Fingerprint::fromResponseParameters($responseParameters, $context); if (!hash_equals($responseParameters['responseFingerprint'], (string) $fingerprint)) { // Fingerprint is not valid, abort exit; } // Fingerprint is valid. Go on and store the response parameters
变更日志
请参阅 CHANGELOG 了解最近有哪些变化。
测试
$ composer test
贡献
请参阅 CONTRIBUTING 了解详细信息。
安全
如果您发现任何安全相关的问题,请通过电子邮件 christoph@hochstrasser.io 联系我们,而不是使用问题跟踪器。
鸣谢
许可证
MIT 许可证(MIT)。请参阅 许可证文件 了解更多信息。