cakasim/payone-sdk

此包已被废弃,不再维护。未建议替代包。

用于PAYONE支付集成的SDK。

v0.2.0 2020-07-18 10:19 UTC

This package is auto-updated.

Last update: 2023-04-18 16:47:36 UTC


README

CI Status Build Status Scrutinizer Code Quality Coverage Status LICENSE Total Downloads

简介

此SDK用于PAYONE支付集成,可以帮助您将支付集成到您的应用程序中。SDK使用功能丰富但已过时的PAYONE服务器API,直接使用可能不太舒适。

功能

  • 现代界面和强大的概念,使使用此SDK成为一种乐趣
  • 灵活的设计和可扩展的结构,用于定制解决方案
  • 简单而强大的PAYONE服务器API使用
  • 自动处理PAYONE通知
  • 安全生成带有状态数据有效负载的重定向URL,用于重定向支付

要求

尽管SDK使用Composer,但它对其他包的依赖性并不广泛。目前,唯一的依赖是PSR接口。

许可

此PAYONE支付集成SDK是开源软件,使用MIT许可

安装SDK

只需运行 composer require cakasim/payone-sdk 通过Composer安装SDK。

核心概念

SDK基于几个核心原则,使其易于使用和灵活集成。

  • 合理的默认值。有用的功能默认配置允许轻松启动SDK,而无需对依赖项进行大量初始化。
  • 控制反转。使用构造函数参数注入的简单IoC实现允许集中修改相关组件。
  • 服务。服务类使SDK的各个组件及其功能易于访问。

PSR接口

使用PSR接口可以使系统高度适应已提供PSR兼容组件的现有系统。

SDK使用了以下PSR接口

使用SDK

本节解释了如何使用SDK。提供了各种代码示例。为了清晰起见,省略了通用代码组件(例如使用语句)。

构建SDK

要使用SDK,必须实例化主类Sdk。有三种不同的方法可以实现。

变体1 – 使用所有默认值

此变体是最容易开始的。SDK将使用所有默认值构建,这需要您安装一些默认PSR实现包

  • cakasim/payone-sdk-http-message (PSR-7, PSR-17)
  • cakasim/payone-sdk-stream-client (PSR-18)
  • cakasim/payone-sdk-silent-logger (PSR-3)

现在您只需一行代码就可以构建SDK

$sdk = new Sdk();

变体2 – 通过提供其他绑定来替换默认值

要更改默认值,您可以覆盖默认容器绑定,使用自己的或甚至第三方实现。这使SDK能够深度集成到任何已提供PSR实现的现有环境中。

// Create the SDK container builder which lets you provide custom bindings
$containerBuilder = new ContainerBuilder();
$container = $containerBuilder->getContainer();

// Use the methods of $container to override default bindings ...

// For example, provide your own PSR-18 HTTP client implementation
$container->bind(\Psr\Http\Client\ClientInterface::class, MyPsr18Client::class);

// Or use an already instantiated PSR-3 logger, maybe provided by you
// or any PSR-3 compatible third-party package like monolog/monolog.
// Assume $logger is any PSR-3 compatible logger instance.
$container->bindInstance(\Psr\Log\LoggerInterface::class, $logger);

// Finally, construct the SDK and provide your customized container
$sdk = new Sdk($containerBuilder->buildContainer());

变体3 – 深度集成到现有IoC环境中

通常您会有一个场景,已经有一个与PSR-11兼容的IoC容器,该容器提供了构造函数参数DI。在这种情况下,您可以用现有的一个完全替换SDK容器。

您必须自己提供所有必要的绑定。查看src/ContainerBuilder.php源代码,了解所需的绑定。

一旦配置了现有的容器,您就可以使用它来实例化SDK

// Assume $existingContainer is an already configured container
$sdk = new Sdk($existingContainer);

对于所有后续示例,我们假设变量$sdk包含Sdk实例。

配置SDK

SDK需要设置各种配置参数。这些参数必须通过Config类提供。一些参数有合理的默认值,而其他则需要设置。请查看下表,其中列出了所有参数。

参数 类型 默认值 描述
api.endpoint 字符串 https://api.pay1.de/post-gateway/ PAYONE服务器API端点
api.merchant_id 字符串 必需 您的PAYONE账户的商户ID
api.portal_id 字符串 必需 可以在您的PAYONE账户中配置的门户ID
api.sub_account_id 字符串 必需 您配置的子账户的ID
api.mode 字符串 测试 API模式,选择测试或实时
api.key 字符串 必需 PAYONE服务器API端点
api.key_hash_type 字符串 sha384 API密钥哈希方法
api.integrator_name 字符串 必需 您的应用程序或公司的名称
api.integrator_version 字符串 必需 您的应用程序版本
notification.sender_address_whitelist 字符串[] 有效的发送者IP列表 有效发送者IP列表
redirect.url 字符串 必需 重定向URL模板,使用$token作为实际令牌值的占位符
redirect.token_lifetime int 3600 重定向令牌生存期(以秒为单位)
redirect.token_encryption_key 字符串 必需 重定向令牌的加密密钥
redirect.token_encryption_method 字符串 aes-256-ctr 重定向令牌的加密方法
redirect.token_signing_key 字符串 必需 重定向令牌的签名密钥
redirect.token_signing_algo 字符串 sha256 重定向令牌的签名算法

以下示例显示了如何设置所有必需的参数。

$config = $sdk->getConfig();

// Your API credentials
$config->set('api.merchant_id', 'your_merchant_id');
$config->set('api.portal_id', 'your_portal_id');
$config->set('api.sub_account_id', 'your_sub_account_id');
$config->set('api.key', 'your_api_key');

// General API config options
$config->set('api.integrator_name', 'YourProjectName');
$config->set('api.integrator_version', '1.0.0');

// The redirect URL template, $token will be replaced by the actual token value.
$config->set('redirect.url', 'https://example.com/redirect/$token');

// Redirect token security settings
$config->set('redirect.token_encryption_key', 'your_secret_encryption_key');
$config->set('redirect.token_signing_key', 'your_secret_signing_key');

发送API请求

以下示例显示了如何发送一个简单的API请求,该请求预先授权了借记支付。不需要设置全局API参数(例如您的API凭证),因为SDK在发送实际请求之前使用配置来设置它们。

// Create your request / response objects
$response = new \Cakasim\Payone\Sdk\Api\Message\Response();
$request = new \Cakasim\Payone\Sdk\Api\Message\Payment\AuthorizationRequest([
    // Perform a pre-authorization which reserves the amount,
    // a follow-up request will be necessary to actually capture the amount
    'request' => 'preauthorization',

    // Set the type of payment to debit payment
    // https://docs.payone.com/display/public/PLATFORM/clearingtype+-+definition
    'clearingtype' => 'elv',

    // Set the IBAN for the debit payment
    // Here you may generate a valid test IBAN:
    // http://randomiban.com
    'iban' => 'DE91500105176688925818',
]);

// Set the transaction currency
// https://docs.payone.com/display/public/PLATFORM/currency+-+definition
$request->setCurrency('EUR');

// Set amount to 15049 fractional monetary units of transaction currency,
// for currency EUR this represents 150,49 €
$request->setAmount(15049);

// Set your transaction reference which identifies the transaction
// in your system (e.g. the order number within an online shop)
// https://docs.payone.com/display/public/PLATFORM/reference+-+definition
$request->setReference('1A2B3C4D5E');

// Send the request to PAYONE
$sdk->getApiService()->sendRequest($request, $response);

// Do something with the response
echo serialize($response);

处理来自PAYONE的通知

使用SDK,可以轻松处理PAYONE通知。SDK在验证和映射通知方面采取了重要步骤。

// Register notification handlers
$sdk->getNotificationService()->registerHandler(new class() implements HandlerInterface {
    public function handleNotification(ContextInterface $context): void
    {
        $message = $context->getMessage();

        if ($message instanceof TransactionStatusInterface) {
            // handle the TX status notification
            echo "Received TX action {$message->getAction()}";
        }
    }
});

// Get the server request factory to create a request from the current environment
/** @var ServerRequestFactoryInterface $requestFactory */
$requestFactory = $sdk->getContainer()->get(ServerRequestFactoryInterface::class);
$request = $requestFactory->createServerRequest($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER);

// Process the server request
$sdk->getNotificationService()->processRequest($request);

重定向服务

对于某些支付方式,客户将被重定向到第三方服务(PayPal、Sofortüberweisung等)以验证和授权支付。

SDK可以为您设置successurlerrorurlbackurl API请求参数,以指定客户在完成第三方服务流程后将被重定向到的目标URL。此外,SDK将令牌附加到目标URL。

令牌包含元数据(例如创建时间戳)以及您可以设置的自定义数据。令牌本身将被加密和签名,这确保了有效载荷数据免受未授权访问和修改的保护。此外,SDK验证令牌的年龄,并确保其不超过配置的最大年龄。

将重定向参数应用于API请求

以下示例显示了如何将重定向参数应用于(预)授权API请求。API响应的状态为REDIRECT,并包含一个redirecturl参数,必须使用此参数将客户重定向。在某些场景中,重定向并不总是必要的,示例中也涵盖了这一点。

use Cakasim\Payone\Sdk\Api\Message\Parameter\BackUrlAwareInterface;
use Cakasim\Payone\Sdk\Api\Message\Parameter\ErrorUrlAwareInterface;
use Cakasim\Payone\Sdk\Api\Message\Parameter\SuccessUrlAwareInterface;
use Cakasim\Payone\Sdk\Api\Message\Payment\AuthorizationRequest;

// Use an inline class to customize the API request.
// The inline class is tagged with the interfaces to support redirect URL parameters.
// This is how the SDK knows which redirect URL parameters are supported and should
// be added to the request by passing it to applyRedirectParameters() later on.
$request = new class() extends AuthorizationRequest
    implements SuccessUrlAwareInterface, ErrorUrlAwareInterface, BackUrlAwareInterface {

    public function __construct()
    {
        parent::__construct([
            // Perform an authorization of a credit card payment,
            // this means the card will be charged immediately.
            'request'      => 'authorization',
            'clearingtype' => 'cc',

            // This identifies the credit card of your customer and is valid within your account scope only.
            // You will obtain this value during a credit card check which should be done in the context
            // of the PAYONE Client API (e.g. in the browser of the customer). This is good for you because
            // you are not getting in touch with the actual credit card data of your customer.
            // https://docs.payone.com/pages/releaseview.action?pageId=1214583
            'pseudocardpan' => '...',
        ]);

        // Set other mandatory parameters
        $this->setCurrency('EUR');
        $this->setAmount(1499);
        $this->setReference('9Z8Y7X6W5V');
    }
};

// Use an inline class to customize the API response
$response = new class() extends \Cakasim\Payone\Sdk\Api\Message\Response {
    public function getRedirectUrl(): ?string
    {
        // Return a valid redirect URL or null
        return $this->getStatus() === 'REDIRECT'
            ? $this->getParameter('redirecturl')
            : null;
    }
};

// Add redirect parameters to the request
$sdk->getRedirectService()->applyRedirectParameters($request, [
    // Provide any custom payload data and encode it securely within the token value
    'order_id' => '9Z8Y7X6W5V',
    // ...
]);

// Send API request to PAYONE
$sdk->getApiService()->sendRequest($request, $response);

// Get the redirect URL. The value can be null which (in this particular case)
// indicates that no redirect is necessary because not every credit card payment
// authorization requires a redirect.
$redirectUrl = $response->getRedirectUrl();

// Check if we have to redirect the customer
if ($redirectUrl !== null) {
    // At this point the customer must be redirected to $redirectUrl.
    // Basically send a status code of 302 and a Location header with the
    // value of $redirectUrl.
    http_response_code(302);
    header("Location: {$redirectUrl}");
    exit;
}

// At this point no redirect was done, just process the payment
// ...

处理重定向令牌

如果客户返回您的应用,您首先需要读取重定向令牌。SDK不对此进行任何假设。基本上,使用简单的查询参数是一个明智且完全有效的方法。

请参阅以下示例,它展示了如何处理令牌并访问令牌有效载荷数据。

use Cakasim\Payone\Sdk\Redirect\Context\ContextInterface;
use Cakasim\Payone\Sdk\Redirect\Handler\HandlerInterface;

// Get the token from the request URL
$token = '...';

$handler = new class() implements HandlerInterface {
    public function handleRedirect(ContextInterface $context): void
    {
        // Get the decoded token from the redirect context
        $token = $context->getToken();

        // Read your custom token payload data
        $orderId = $token->get('order_id');

        // Proceed with your business logic ...
    }
};

$sdk->getRedirectService()->registerHandler($handler);
$sdk->getRedirectService()->processRedirect($token);