devinweb / laravel-youcan-pay
Laravel的YouCanPay包,提供了一种简单的方式来实现最佳体验。
Requires
- php: ^7.4|^8.0
- illuminate/support: ^7.0|^8.0|^9.0|^10.0
- laravel/framework: 8.*|9.*|10.*
- spatie/laravel-enum: ^2.0|^3.0
- youcanpay/payment-sdk: *
Requires (Dev)
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.0
- vimeo/psalm: ^4.30
This package is auto-updated.
Last update: 2024-09-15 21:18:40 UTC
README
Laravel YouCanPay
简介
Laravel YouCanPay提供了一种轻松的体验,用于生成支付表单,并处理所有与支付相关的操作。
安装
您可以通过composer安装此包
composer require devinweb/laravel-youcan-pay
数据库迁移
LaravelYouCanPay包提供自己的数据库来管理不同步骤中的用户交易,迁移将创建一个新的transactions
表来存储所有用户的交易。
php artisan migrate
如果您需要覆盖LaravelYouCanPay提供的迁移,您可以使用Artisan命令vendor:publish来发布它们
php artisan vendor:publish --tag="youcanpay-migrations"
配置
要发布配置文件,您可以使用以下命令
php artisan vendor:publish --tag="youcanpay-config"
然后您可以在config/youcanpay.php
中找到配置文件
账单模型
如果您希望包根据用户模型管理交易,请将Billable
特征添加到您的用户模型中。此特征提供各种方法来执行交易任务,例如创建交易、获取paid
、failed
和pending
交易。
use Devinweb\LaravelYouCanPay\Traits\Billable; class User extends Authenticatable { use Billable; }
LaravelYouCanPay假定您的用户模型将是App\Models\User
,如果您使用不同的用户模型命名空间,您应该使用方法useCustomerModel
指定它。此方法通常应在AppServiceProvider
类的boot方法中调用
use App\Models\Core\User; use Devinweb\LaravelYouCanPay\LaravelYouCanPay;; /** * Bootstrap any application services. * * @return void */ public function boot() { LaravelYouCanPay::useCustomerModel(User::class); }
如果您需要在每次交易中包都使用每个用户的计费数据,请确保在您的用户模型中包含一个getCustomerInfo()
方法,该方法返回一个包含我们所需所有数据的数组。
/** * Get the customer info to send them when we generate the form token. * * @return array */ public function getCustomerInfo() { return [ 'name' => $this->name, 'address' => '', 'zip_code' => '', 'city' => '', 'state' => '', 'country_code' => 'MA', 'phone' => $this->phone, 'email' => $this->email, ]; }
YouCanPay密钥
接下来,您应该在应用程序的.env
中配置您的环境
# YouCanPay env keys
SANDBOX_MODE=
PRIVATE_KEY=
PUBLIC_KEY=
CURRENCY=MAD
SUCCCESS_REDIRECT_URI=
FAIL_REDIRECT_URI=
客户
检索客户
您可以使用findBillable
方法通过您CanPay ID检索客户。此方法将返回账单模型的实例
use Devinweb\LaravelYouCanPay\Facades\LaravelYouCanPay; $user = LaravelYouCanPay::findBillable($order_id);
生成令牌
如果您需要从用户模型生成令牌,客户信息将直接从getCustomerInfo
方法附加
$data= [ 'order_id' => '123', 'amount' => 2000 // amount=20*100 ]; $token = $user->getPaymentToken($data, $request);
如果您需要添加元数据,您可以使用
$data= [ 'order_id' => '123', 'amount' => 2000 // amount=20*100 ]; $metadata = [ 'key' => 'value' ]; $token = $user->getPaymentToken($data, $request, $metadata);
如果您需要从用户模型获取支付URL,您可以使用与以下相同参数的getPaymentURL
方法。
$payment_url = $user->getPaymentURL($data, $request, $metadata);
生成支付URL
使用方法
在开始使用包之前,请确保使用正确的值更新您的config/youcanpay.php
。
令牌化
获取令牌ID
我们需要的第一步是创建一个基于凭据的令牌,使用您从YouCanPay仪表板获取的getId()
方法。
注意
金额应该是* 100,例如,如果您的产品价格为20$,您应该发送
amount = 20*100 = 200,使用 currency='USD'
use Devinweb\LaravelYouCanPay\Facades\LaravelYouCanPay; use Illuminate\Support\Str; public function tokenization(Request $request) { $order_data = [ 'order_id' => (string) Str::uuid(), 'amount' => 200 ]; $token= LaravelYouCanPay::createTokenization($order_data, $request)->getId(); $public_key = config('youcanpay.public_key'); $isSandbox = config('youcanpay.sandboxMode'); $language = config('app.locale'); // You can at this point share a lot of data with the front end, // the idea behind this is making the backend manage the environment keys, // we don't need to store the keys in many places. return response()->json(compact('token', 'public_key', 'isSandbox', 'language')); }
获取支付URL
独立集成,您可以使用方法getPaymentUrl()
生成支付URL
$paymentUrl= LaravelYouCanPay::createTokenization($data, $request)->getPaymentURL();
然后您可以将该URL放在您的HTML页面上
<a href="{{ $paymentUrl }}">Pay Now</a>
客户信息
如果您需要在令牌化期间添加客户数据,请保留以下数组键(name
、address
、zip_code
、city
、state
、country_code
、phone
和email
)。您可以使用
use Devinweb\LaravelYouCanPay\Facades\LaravelYouCanPay; $customerInfo = [ 'name' => '', 'address' => '', 'zip_code' => '', 'city' => '', 'state' => '', 'country_code' => '', 'phone' => '', 'email' => '', ]; $token= LaravelYouCanPay::setCustomerInfo($customerInfo)->createTokenization($data, $request)->getId();
元数据
您可以使用元数据发送可以在响应后或在webhook中检索的数据。
use Devinweb\LaravelYouCanPay\Facades\LaravelYouCanPay; $customerInfo = [ 'name' => '', 'address' => '', 'zip_code' => '', 'city' => '', 'state' => '', 'country_code' => '', 'phone' => '', 'email' => '', ]; $metadata = [ // Can you insert what you want here... 'key' => 'value' ]; $token= LaravelYouCanPay::setMetadata($metadata) ->setCustomerInfo($customerInfo) ->createTokenization($data, $request)->getId();
生成支付表单
此时,我们从后端接收到令牌,所以在我们 blade 或任何其他 HTML 页面中,您可以在 head
中放置此脚本
<html> ... <head> <!--Add this line --> <script src="https://pay.youcan.shop/js/ycpay.js"></script> </head> ... </html>
然后,要显示表单,您的逻辑将类似于以下代码
<script type="text/javascript"> // Create a YouCan Pay instance. const ycPay = new YCPay( // String public_key (required): Login to your account. // Go to Settings and open API Keys and copy your key. "public_key", // Optional options object { formContainer: "#payment-card", // Defines what language the form should be rendered in, supports EN, AR, FR. locale: "en", // Whether the integration should run in sandbox (test) mode or live mode. isSandbox: false, // A DOM selector representing which component errors should be injected into. // If you omit this option, you may alternatively handle errors by chaining a .catch() // On the pay method. errorContainer: "#error-container", } ); // Select which gateways to render ycPay.renderAvailableGateways(["CashPlus", "CreditCard"]); // Alternatively, you may use gateway specific render methods if you only need one. ycPay.renderCreditCardForm(); </script>
要开始支付,您需要一个操作,您可以使用按钮
document.getElementById("pay").addEventListener("click", function () { // execute the payment ycPay.pay(tokenId).then(successCallback).catch(errorCallback); }); function successCallback(response) { //your code here } function errorCallback(response) { //your code here }
有关更多信息,请查看此 链接。
处理YouCanPay Webhooks
YouCan Pay 使用 webhook 通知您的应用程序当您的账户中发生事件时。Webhook 对于处理后端上的异步事件的反应非常有用,例如成功支付、失败支付、成功退款以及其他许多实时事件。Webhook 允许 YouCan Pay 通过 HTTPS 传输 JSON 有效负载将实时通知推送到您的应用程序。
Webhook 和 CSRF 保护
YouCanPay webhook 需要无障碍地到达您的 URI,因此您需要禁用 webhook URI 的 CSRF 保护,为此请确保将您的路径添加到应用程序的
App\Http\Middleware\VerifyCsrfToken
中间件中的异常数组中。protected $except = [ 'youcanpay/*', ]
Webhook URL
为确保您的应用程序可以处理 YouCanPay webhook,请确保在 YouCanPay 控制面板中配置 webhook URL。默认情况下,该软件包包含一个内置的 webhook,使用 URL youcanpay/webhook
,您可以通过在应用程序中使用 php artisan route:list
列出所有路由来找到它,该 webhook 验证接收到的有效负载相关的签名,并分配一个事件。
Webhook 中间件
如果您需要在处理任何操作之前尝试验证 webhook 签名,则可以使用中间件 verify-youcanpay-webhook-signature
,该中间件验证从 YouCanPay 接收到的有效负载相关的签名。
use Illuminate\Http\Request; use Illuminate\Routing\Controller; class WebHookController extends Controller { /** * Create a new WebhookController instance. * * @return void */ public function __construct() { $this->middleware('verify-youcanpay-webhook-signature'); } //... }
Webhook事件
LaravelYouCanPay 处理常见的 YouCanPay webhook 事件,如果您需要处理需要的事件,则可以监听由软件包分配的事件。
- Devinweb\LaravelYouCanPay\Events\WebhookReceived
您需要注册一个可以处理事件的监听器
<?php namespace App\Listeners; use Devinweb\LaravelYouCanPay\Events\WebhookReceived; class YouCanPayEventListener { /** * Handle received Stripe webhooks. * * @param \Devinweb\LaravelYouCanPay\Events\WebhookReceived $event * @return void */ public function handle(WebhookReceived $event) { if ($event->payload['event_name'] === 'transaction.paid') { // Handle the incoming event... } } }
一旦您的监听器已被定义,您可以在应用程序的 EventServiceProvider
中注册它
<?php namespace App\Providers; use App\Listeners\YouCanPayEventListener; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Devinweb\LaravelYouCanPay\Events\WebhookReceived; class EventServiceProvider extends ServiceProvider { protected $listen = [ WebhookReceived::class => [ YouCanPayEventListener::class, ], ]; }
手动验证 webhook 签名
从 YouCanPay 接收到的 webhook 数据看起来像这样
[
'id' => 'bbbb832c-dd13-4ce7-a642-6059885d9a7e',
'event_name' => 'transaction.paid',
'sandbox' => true,
'payload' => [
'transaction' => [
'id' => 'fdd795ab-9f8a-4cf7-886c-dca9ce3ab6c0',
'status' => 1,
'order_id' => 'cc984e79-0de1-4e84-a654-74c102c3ba66',
'amount' => '2000',
'currency' => 'MAD',
'base_currency' => NULL,
'base_amount' => NULL,
'created_at' => '2022-11-22T13:20:52.000000Z',
],
'payment_method' => [
'id' => 1,
'name' => 'credit_card',
'card' => [
'id' => '2e42d52d-ab0a-4440-b1e2-9a41fb843dad',
'country_code' => NULL,
'brand' => NULL,
'last_digits' => '4242',
'fingerprint' => 'df276a45f62277bd43775616827f0718',
'is_3d_secure' => false,
],
],
'token' => [
'id' => '811dd60e-4655-41da-b576-a1a537cda071',
],
'event' => [
'name' => 'transaction.paid',
],
'customer' => [
'id' => 'edc6fb6f-415f-4ac3-8b86-c70bead4770e',
'email' => NULL,
'name' => NULL,
'address' => NULL,
'phone' => NULL,
'country_code' => NULL,
'city' => NULL,
'state' => NULL,
'zip_code' => NULL,
],
'metadata' => [],
],
]
但有趣的部分是在请求头中,您可以使用键 x-youcanpay-signature
找到签名值。
在处理任何逻辑或操作之前验证 webhook 签名。
<?php namespace App\Http\Controllers; use Devinweb\LaravelYouCanPay\Facades\LaravelYouCanPay; use Illuminate\Http\Request; class YouCanPayWebhooksController extends Controller { public function handle(Request $request) { $signature = $request->header('x-youcanpay-signature'); $payload = json_decode($request->getContent(), true); if (LaravelYouCanPay::verifyWebhookSignature($signature, $payload)) { // you code here } } }
手动验证 webhook 签名
验证具有与验证相同的影响,但验证会抛出一个异常,您可以在日志文件中检查它。
<?php namespace App\Http\Controllers; use Devinweb\LaravelYouCanPay\Facades\LaravelYouCanPay; use Illuminate\Http\Request; class YouCanPayWebhooksController extends Controller { public function handle(Request $request) { LaravelYouCanPay::validateWebhookSignature($signature, $payload) // you code here } }
命令
如果您需要清理挂起的交易,有一个命令
php artisan youcanpay:clean-pending-transactions
您可以将它添加到调度程序,以便每次运行命令,因此清理将是自动的,并且取决于在 youcanpay
配置文件中定义的 tolerance
值。
测试和测试卡
测试
composer test
变更日志
有关最近更改的更多信息,请参阅 变更日志。
贡献
有关详细信息,请参阅 贡献。
安全
如果您发现任何与安全相关的问题,请通过电子邮件 imad@devinweb.com 而不是使用问题跟踪器。
鸣谢
许可证
MIT 许可证(MIT)。请参阅 许可证文件 了解更多信息。
Laravel YouCanPay 模板
此软件包是使用 Laravel YouCanPay 模板 生成的。