olssonm/swish-php

Swish API 包装器。兼容 Laravel

v3.0 2024-08-12 20:07 UTC

README

Supported PHP-versions Latest Version on Packagist Build Status Software License

PHP 中 Swish-API 的简单易用包装器。还包括用于快速设置 Laravel 的提供者和外观。

先决条件

此包支持 PHP ^8.1。已针对 Laravel 10 和 11 进行测试。PHP 需要编译了 cURL 和 SSL 扩展(在大多数情况下,它们应该默认可用)。

使用较旧的 PHP 或 Laravel 版本?请查看此包的 v1 和 v2 版本。

安装

composer require olssonm/swish-php

设置

您需要访问您的 Swish 证书才能在生产中使用此包。然而,在开发期间,您可以使用他们的测试/商户 Swish 模拟器环境,而不必成为 Swish 客户。

有关他们在 MSS 环境中测试的更多信息,请参阅他们的 官方文档。有关使用/创建 Swish 证书的快速概述,请参阅此处(瑞典语)(瑞典语)

创建客户端时,您必须设置您正在使用的环境(否则默认为生产环境,https://cpc.getswish.net/swish-cpcapi/api/),您可以使用以下选项之一

Client::TEST_ENDPOINT // https://mss.cpc.getswish.net/swish-cpcapi/api/
Client::PRODUCTION_ENDPOINT // https://cpc.getswish.net/swish-cpcapi/api/
Client::SANDBOX_ENDPOINT // https://staging.getswish.pub.tds.tieto.com/swish-cpcapi/api/
use Olssonm\Swish\Certificate;
use Olssonm\Swish\Client;

$certificate = new Certificate( 
    '/path/to/client.pem', 
    'client-passphrase',
    '/path/to/root.pem', // Can also be omitted for "true" to verify peer
    '/path/to/signing.key', // Path to signing certificate, only used for payouts
    'signing-passphrase' // Only used for payouts
);
$client = new Client($certificate, $endpoint = Client::TEST_ENDPOINT)

重要

证书路径应该是绝对的。您可以使用 realpath -s YOUR_CERT.pem 来实现这一点。

Laravel

使用 Laravel 服务提供者和外观,您可以更优雅地处理包。只需要求包并发布配置

php artisan vendor:publish --provider="Olssonm\Swish\Providers\SwishServiceProvider"

/config/swish.php 中,您可以根据需要进行设置

return [
    'certificates' => [
        'client' => env('SWISH_CLIENT_CERTIFICATE_PATH'),
        'password' => env('SWISH_CLIENT_CERTIFICATE_PASSWORD'),
        'root' => env('SWISH_ROOT_CERTIFICATE_PATH', true),
        'signing' => env('SWISH_SIGNING_CERTIFICATE_PATH', null),
        'signing_password' => env('SWISH_CLIENT_SIGNING_PASSWORD', null),
    ],
    'endpoint' => env('SWISH_URL', \Olssonm\Swish\Client::PRODUCTION_ENDPOINT),
];

这也可以是一个保存您的付款人别名、回调 URL 等的好地方,然后您可以使用 config('swish.payee_alias') 等方式访问它们。

用法

创建 Swish 付款的典型情况。

use Olssonm\Swish\Certificate;
use Olssonm\Swish\Client;
use Olssonm\Swish\Payment;

$certificate = new Certificate(
    '/path/to/client.pem', 
    'client-passphrase'
);
$client = new Client($certificate);

// Create a new payment-object
$payment = new Payment([
    'callbackUrl' => 'https://callback.url',
    'payeePaymentReference' => 'XVY77',
    'payeeAlias' => '123xxxxx',
    'payerAlias' => '321xxxxx',
    'amount' => '100',
    'currency' => 'SEK',
    'message' => 'A purchase of my product',
]);

// Perform the request
$response = $client->create($payment);

// $response->id = '11A86BE70EA346E4B1C39C874173F088'
// $response->location = 'https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests/11A86BE70EA346E4B1C39C874173F088'
// $response->paymentRequestToken = 'a-unique-token'

使用 Laravel,您还可以使用外观并节省一些代码(在此示例中,Olssonm\Swish\Facades\Swish 已别名为 Swish

use Swish;
use Olssonm\Swish\Payment;

$response = Swish::create(new Payment([
    'callbackUrl' => 'https://callback-url.com',
    'payeePaymentReference' => 'XVY77',
    'payeeAlias' => '123xxxxx',
    'payerAlias' => '321xxxxx',
    'amount' => '100',
    'currency' => 'SEK',
    'message' => 'My product',
]));

支付和退款

提示

有关 支付退款 的更多信息,请参阅官方文档

始终在使用客户端时使用支付和退款类,即使只需要操作 ID,例如

$payment = $client->get(Payment(['id' => '5D59DA1B1632424E874DDB219AD54597']));

支付

提示

有关 支付 的更多信息,请参阅官方文档

支付需要使用 SHA512 进行散列并使用签名证书进行签名后才能发送到 Swish - 不要担心,此包将自动处理大部分工作。只需确保已设置签名证书的路径即可

$certificate = new Certificate(
    '/path/to/client.pem', 
    'client-passphrase',
    true,
    '/path/to/signing.key',
    'signing-passphrase'
);
$client = new Client($certificate);

$payout = $client->create(new Payout([]));

此外,您的证书(注意:您的签名证书,而不是您的客户端证书)序列号需要提供。您可以使用以下任一方法

$certificate = new Certificate(/**/);
$payout = new Payout([
    'signingCertificateSerialNumber' => $certificate->getSerial()
])

或自己分配(查看 gist 以提取序列号

$payout = new Payout([
    'signingCertificateSerialNumber' => '4512B3EBDA6E3CE6BFB14ABA6274A02C'
])

重要

请注意,Payouts 使用 payoutInstructionUUID 而不是 ID,您应该 自行设置以跟踪它。如果它缺失,则在创建时将自动设置。

关于 IDs/UUIDs

本包使用 Swish API 的 v2 版本,UUID 由商家设置。本包将自动处理所有这些方面,但您可以手动设置 ID/instructionUUID(无论是 Swish 的格式还是默认的 v4 格式)。

$id = 'EBB5C73503084E3C9AEA8A270AEBFE15';
// or
$id = 'ebb5c735-0308-4e3c-9aea-8a270aebfe15';

$payment = new Payment([
    'id' => $id
]);

在动态生成 UUID 时,本包使用 Ramsey/Uuid 生成 RFC4122(v4)UUID。如果选择自行设置 UUID,Swish 接受 V1、3、4 和 5 UUID。

如果使用无效的 UUID,将抛出 Olssonm\Swish\Exceptions\InvalidUuidException

注意

无论您是设置自己的 UUID 还是让包处理生成,UUID 总会自动格式化为 Swish 格式(去除连字符并转换为大写)。

可用方法

本包处理与 Swish 相关的常见任务;检索、创建和取消付款。检索和创建付款、退款以及退款可以创建和检索。所有这些操作都是通过 Olssonm\Swish\Client 实现的;

$client->get(Payment $payment | Refund $refund | Payout $payout);  
$client->create(Payment $payment | Refund $refund | Payout $payout);  
$client->cancel(Payment $payment);

异常处理

遇到验证错误时,将抛出 Olssonm\Swish\Exceptions\ValidationException。对象将包含请求、响应以及 getErrorCode()getErrorMessage() 辅助函数。

try {
    $response = $client->create($payment);
} catch (ValidationException $exception) {
    $errors = $exception->getErrors();
    foreach ($errors as $error) {
        $error->errorCode;
        // AM03
        $error->errorMessage;
        // Invalid or missing Currency.
    }
}

对于 4xx 错误,将抛出 \Olssonm\Swish\Exceptions\ClientException,而对于 5xx 错误,将抛出 \Olssonm\Swish\Exceptions\ServerException。这两个异常都实现了 Guzzle 的 BadResponseException,这使得在需要时可以访问请求和响应对象。

回调

Swish 建议不要使用 payments 端点来获取付款或退款的状态(即使他们在一些示例中使用它...),而应使用回调。

本包包括一个简单的辅助函数,用于从包含 Swish 所有数据的回调中检索 PaymentRefundPayout 对象。

use Olssonm\Swish\Callback;

$paymentOrRefund = Callback::parse();

// get_class($paymentOrRefund) = \Olssonm\Swish\Payment::class, \Olssonm\Swish\Refund::class, \Olssonm\Swish\Payout::class

辅助函数自动检索当前 HTTP 请求(通过 file_get_contents('php://input'))。但是,如果您需要(例如,如果您已经有了 Laravel 请求对象),也可以注入自己的数据。

class SwishController 
{
    public function Callback(Request $request)
    {
        $data = Callback::parse($request->getContent());

        if(get_class($data) == \Olssonm\Swish\Payment::class) {
            // Handle payment callback
        } else if(get_class($data) == \Olssonm\Swish\Refund::class) {
            // Handle refund callback
        } else if(get_class($data) == \Olssonm\Swish\Payout::class) {
            // Handle payout callback
        }
    }
}

在真实世界的场景中,您可能希望为退款、付款和支付使用不同的回调 URL,以避免像上面示例中那样的不必要解析。

注意

请注意,Swish 的回调既未加密也未进行编码,相反,您应确保回调来自一个 有效的 IP 范围

许可证

MIT 许可证(MIT)。有关更多信息,请参阅 LICENSE

© 2022-2024 Marcus Olsson