getsafepay / sfpy-php
Safepay PHP 库
Requires
- php: >=5.6.0
- ext-curl: *
- ext-json: *
- ext-mbstring: *
Requires (Dev)
- friendsofphp/php-cs-fixer: 3.5.0
- phpstan/phpstan: ^1.2
- phpunit/phpunit: ^5.7 || ^9.0
README
Safepay PHP 库提供了从用 PHP 语言编写的应用程序中对 Safepay API 的便捷访问。它包含一组预定义的类,用于初始化 API 资源,这些类可以从 API 响应中动态初始化,这使得它与 Safepay API 的多种版本兼容。
要求
PHP 5.6.0 及以上版本。
Composer
您可以通过 Composer 安装绑定。运行以下命令:
composer require getsafepay/sfpy-php
要使用绑定,使用 Composer 的 自动加载
require_once 'vendor/autoload.php';
手动安装
如果您不想使用 Composer,可以下载 最新版本。然后,要使用绑定,包括 init.php
文件。
require_once '/path/to/safepay-php/init.php';
依赖项
绑定需要以下扩展才能正常工作:
如果您使用 Composer,这些依赖项应该会自动处理。如果您手动安装,请确保这些扩展可用。
入门指南
简单用法如下
$safepay = new \Safepay\SafepayClient('BQokikJOvBiI2HlWgH4olfQ2'); $tracker = $safepay->order->setup([ "merchant_api_key" => "sec_8dcac601-4b70-442d-b198-03aadd28f12b", "intent" => "CYBERSOURCE", "mode" => "payment", "currency" => "PKR", "amount" => 600000 // in the lowest denomination ]); echo $tracker;
沙盒
要在沙盒环境中使用 SDK,请将 base_url
设置为 https://sandbox.api.getsafepay.com
。
$safepay = new \Safepay\SafepayClient([ 'api_key' => 'BQokikJOvBiI2HlWgH4olfQ2', 'api_base' => 'https://sandbox.api.getsafepay.com' ]);
结账 URL
当集成 Safepay 时,您可能希望从您的客户那里收集付款详情,以安全地标记其卡或进行付款。对于所有这些不同的场景,您的应用程序都需要生成一个 URL,将您的客户重定向到以完成他们那一侧的必要步骤。此代码片段显示了您如何生成一个结账 URL,通过该 URL 您的客户可以将其卡保存在文件中。
$safepay = new \Safepay\SafepayClient('BQokikJOvBiI2HlWgH4olfQ2'); try { // You need to generate a tracker with mode 'instrument' // to tell Safepay that you wish to set up a tracker to // tokenize a customer's card $session = $safepay->order->setup([ "merchant_api_key" => "sec_8dcac601-4b70-442d-b198-03aadd28f12b", "intent" => "CYBERSOURCE", "mode" => "instrument", "currency" => "PKR" ]); // You need to either create a customer or retreive the customer // from your backend so you have access to the customer ID $customer = $safepay->customer->create([ "first_name" => "Hassan", "last_name" => "Zaidi", "email" => "hzaidi@getsafepay.com", "phone_number" => "+923331234567", "country" => "PK" ]); // You can optionally create an address object if you have // access to the customer's billing details $address = $safepay->address->create([ // required "street1" => "3A-2 7th South Street", "city" => "Karachi", "country" => "PK", // optional "postal_code" => "75500", "province" => "Sindh" ]); // You need to create a Time Based Authentication token $tbt = $safepay->passport->create(); // Finally, you can create the Checkout URL $checkoutURL = \Safepay\Checkout::constructURL([ "environment" => "production", // one of "development", "sandbox" or "production" "tracker" => $session->tracker->token, "user_id" => $customer->token, "tbt" => $tbt->token, "address" => $address->token, "source" => "mobile" // important for rendering in a WebView ]); echo($checkoutURL); return $checkoutURL; } catch(\UnexpectedValueException $e) { // Invalid payload http_response_code(400); exit(); }
订阅 URL
Safepay 通过允许客户订阅计划来支持原生订阅。为了实现这一点,您的系统需要生成一个安全的 URL,将客户重定向到以完成订阅。Safepay 创建了一个安全的主机页面,用于从您的客户那里收集敏感信息并允许他们订阅您的计划。代码片段显示了您如何生成一个订阅 URL,通过该 URL 您的客户可以订阅您的计划。
$safepay = new \Safepay\SafepayClient('BQokikJOvBiI2HlWgH4olfQ2'); try { // Change this ID to reflect the ID of the Plan you have created // either through the merchant dashboard or through the API. $plan_id = "plan_d4869a78-0036-4d66-97bd-6afeb5282bcd" // You need to create a Time Based Authentication token $tbt = $safepay->passport->create(); // To ease reconciliation, you may associate a reference // that you generate in your system. This will be returned // in webhooks received when the subscription is created. $reference = "0950fa13-1a28-4529-80bf-89f6f4e830a5" // Finally, you can create the Subscribe URL $subscribeURL = \Safepay\SubscriptionsCheckout::constructURL([ "environment" => "production", // one of "development", "sandbox" or "production" "plan_id" => $plan_id, "tbt" => $tbt, "reference" => $reference "cancel_url" => "https://mywebiste.com/subscribe/cancel", "redirect_url" => "https://mywebiste.com/subscribe/success", ]); echo($subscribeURL); return $subscribeURL; } catch(\UnexpectedValueException $e) { // Invalid payload http_response_code(400); exit(); }
Webhooks
当构建 Safepay 集成时,您可能希望您的应用程序在 Safepay 账户中发生事件时接收事件,以便您的后端系统可以相应地执行操作。
要启用 webhook 事件,您需要注册 webhook 端点。注册后,当您的 Safepay 账户中发生事件时,Safepay 可以将实时事件数据推送到您的应用程序 webhook 端点。Safepay 使用 HTTPS 将 webhook 事件作为 JSON 负载发送到您的应用程序,其中包含事件对象。
接收 webhook 事件对于监听异步事件特别有用,例如当客户的银行确认付款、客户对收费提出异议、周期性付款成功或收集订阅付款时。
一旦在服务器上设置了接收Safepay网络钩子的端点,您将希望根据收到的事件类型执行某些操作。执行完成后,您必须向Safepay发送一个200
响应代码,以确认已收到网络钩子。如果Safepay没有收到200
响应代码,网络钩子将被再次触发。
此代码片段是一个配置为检查是否收到事件类型、处理事件并返回200响应的网络钩子函数。
$payload = @file_get_contents('php://input'); $event = null; try { $event = \Safepay\Event::constructFrom( json_decode($payload, true) ); } catch(\UnexpectedValueException $e) { // Invalid payload http_response_code(400); exit(); } // Handle the event switch ($event->type) { case 'payment.succeeded': $payment = $event->data; break; case 'payment.failed': $payment = $event->data; break; // ... handle other event types default: echo 'Received unknown event type ' . $event->type; } http_response_code(200);
保护Webhooks
注意 Safepay需要请求的原始正文来进行签名验证。如果您正在使用框架,请确保它不会修改原始正文。对请求原始正文的任何修改都会导致验证失败。
// Set your secret key. Remember to switch to your live secret key in production. // See your keys here: https://getsafepay.com/dashboard/developers \Safepay\Safepay::setApiKey('sec_4eC39HqLyjWDarjtT1zdp7dc'); // You can ind your endpoint's secret in your webhook settings in the Developer Dashboard $webhook_secret = '234hjkasd....'; $payload = @file_get_contents('php://input'); $sig_header = $_SERVER['X-SFPY-SIGNATURE']; $event = null; try { $event = \Safepay\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload http_response_code(400); echo json_encode(['Error parsing payload: ' => $e->getMessage()]); exit(); } catch(\Safepay\Exception\SignatureVerificationException $e) { // Invalid signature http_response_code(400); echo json_encode(['Error verifying webhook signature: ' => $e->getMessage()]); exit(); } // Handle the event switch ($event->type) { case 'payment.succeeded': $payment = $event->data; break; case 'payment.failed': $payment = $event->data; break; // ... handle other event types default: echo 'Received unknown event type ' . $event->type; } http_response_code(200);