njoguamos / laravel-pesapal
一个用于与 https://www.pesapal.com api 交互的 Laravel 扩展包
Requires
- php: ^8.1 | ^8.2 | ^8.3
- illuminate/contracts: ^10.0 | ^11.0
- saloonphp/saloon: ^3.7.0
- spatie/laravel-data: ^4.4
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^2.9
- laravel/pint: ^1.14
- nunomaduro/collision: ^v7.10 | ^v8.1
- orchestra/testbench: ^8.22 | ^9.0
- pestphp/pest: ^2.34
- pestphp/pest-plugin-arch: ^2.7
- pestphp/pest-plugin-laravel: ^2.3
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^1.1
- phpstan/phpstan-phpunit: ^1.3
- dev-main
- v1.2.26
- v1.2.22
- v1.1.20
- v1.1.14
- v1.1.11
- v1.1.7
- v1.1.3
- v1.1.0
- v1.0.26
- v1.0.22
- v1.0.18
- v1.0.13
- v1.0.10
- v1.0.7
- v1.0.2
- v1.0.1
- v1.0.0
- v1.0-beta.5
- v1.0-beta.4
- v1.0-beta.3
- v1.0-beta.2
- v1.0-beta.1
- v0.0.5
- v0.0.4
- v0.0.3
- v0.0.2
- v0.0.1
- dev-dependabot/composer/phpstan/extension-installer-1.4.3
- dev-dependabot/composer/spatie/laravel-data-4.9.0
- dev-dependabot/composer/phpstan/phpstan-deprecation-rules-1.2.1
- dev-dependabot/composer/laravel/pint-1.17.3
- dev-dependabot/composer/spatie/laravel-package-tools-1.16.5
- dev-remove-dev-instructions
This package is auto-updated.
Last update: 2024-09-19 20:26:42 UTC
README
Laravel 10+ 扩展包,用于与 Pesapal API 交互
此扩展包提供了一种与 Pesapal API 交互的方式。它提供了生成 access_token
和将即时支付通知(IPN)存储在数据库中的方法。它还提供了一种提交订单请求和检查交易状态的方法。
为什么使用这个扩展包
- 提供一种生成 Pesapal api
access_token
的方法,该 token 通常在 5 分钟后过期 - 提供与 Pesapal v3 API 交互的网关
- 提供一种将即时支付通知(IPN)存储在数据库中的方法
- 节省您重复编写相同代码的时间
游乐场
如果您想测试此扩展包,我创建了一个 游乐场,您可以在其中测试扩展包,而无需创建新的 Laravel 项目。
安装
您可以通过 composer 安装此扩展包
composer require njoguamos/laravel-pesapal
此扩展包包含以下表
pesapal_tokens
- 用于存储 Pesapal API 的access_token
和expires_at
pesapal_ipns
- 用于存储即时支付通知
发布并运行迁移
php artisan vendor:publish --tag="pesapal-migrations"
php artisan migrate
您可以选择发布配置文件
php artisan vendor:publish --tag="pesapal-config"
更新您的应用程序中的环境变量。
PESAPAL_LIVE= PESAPAL_CONSUMER_KEY= PESAPAL_CONSUMER_SECRET=
使用方法
1. 生成 access_token
要生成 access_token
,您可以运行以下命令
php artisan pesapal:auth
该命令将使用 CONSUMER_KEY
和 CONSUMER_SECRET
从 Pesapal API 获取新的 access_token
并将其保存到数据库中。该 access_token
有效期为 5 分钟,因此建议每 4 分钟运行一次命令。此外,当您设置了 model:prune
命令时,所有过期的 access_token
将从数据库中删除,因为它们不再有用。
# Laravel 10 -> app/Console/Kernel.php use NjoguAmos\Pesapal\Models\PesapalToken; class Kernel extends ConsoleKernel { protected function schedule(Schedule $schedule): void { # Other scheduled commands $schedule->command('pesapal:auth')->everyFourMinutes(); Schedule::command('model:prune', ['--model' => [PesapalToken::class]])->everyFiveMinutes(); } }
# Laravel 11 -> routes/console.php use Illuminate\Support\Facades\Schedule; use NjoguAmos\Pesapal\Models\PesapalToken; Schedule::command('pesapal:auth')->everyFourMinutes(); Schedule::command('model:prune', ['--model' => [PesapalToken::class]])->everyFiveMinutes();
您还可以直接在 Pesapal
类中调用 createToken
方法来生成 access_token
。该方法将返回 null 或新的 PesapalToken
实例。
use NjoguAmos\Pesapal\Pesapal; $token = Pesapal::createToken();
createToken
的结果是 PesapalToken
Eloquent 模型的一个实例。这意味着您可以调用 Eloquent 方法,例如。
$data = $token->toArray();
[ 'access_token' => "eyJhbGciOiJIUzI1NiIs...6pVj1_DS37ghMGQ", 'expires_at' => Carbon\Carbon instance ]
2. 创建即时支付通知
要创建即时支付通知,您可以使用 Pesapal
类中的 createIpn
方法。该方法将返回 PesapalIpn
实例或 null(如果请求失败)。
info 确保您的
pesapal_tokens
表中有一个未过期的access_token
。
use NjoguAmos\Pesapal\Pesapal; $ipn = Pesapal::createIpn( url: 'https://www.yourapp.com/ipn', ipnType: IpnType::GET, );
createIpn
的结果是 PesapalIpn
Eloquent 模型的一个实例。这意味着您可以调用 Eloquent 方法,例如。
$data = $ipn->toArray();
[ 'url' => 'https://www.yourapp.com/ipn' 'ipn_id' => 'e32182ca-0983-4fa0-91bc-c3bb813ba750' 'type' => 'GET' 'status' => 'Active' ]
info 该 URL 应该是一个公开 URL,可以由 pesapal.com 访问。该
ipnType
可以是IpnType::GET
或IpnType::POST
。
您可以使用 ipn_id
提交订单请求。
info 确保您的
pesapal_tokens
表中有一个未过期的access_token
。当然,如果您已安排了pesapal:auth
命令,您不必担心access_token
会过期。
3. 获取已注册IPN端点
获取已注册IPN有两种方式。
- 您可以使用
Pesapal
类中的getIpns
方法从Pesapal API获取IPN。该方法在成功响应时返回一个数组,在失败响应时返回一个Saloon Response实例。
use NjoguAmos\Pesapal\Pesapal; use NjoguAmos\Pesapal\Pesapal; $response = Pesapal::getIpns();
示例成功响应
[ [ "url" => "https://www.myapplication.com/ipn", "created_date" => "2022-03-03T17:29:03.7208266Z", "ipn_id" => "e32182ca-0983-4fa0-91bc-c3bb813ba750", "error" => null, "status" => "200" ], [ "url"=> "https://ipn.myapplication.com/application2", "created_date"=> "2021-12-05T04:23:45.5509243Z", "ipn_id"=> "c3bb813ba750-0983-4fa0-91bc-e32182ca", "error"=> null, "status"=> "200" ] ]
- 或者从数据库中获取IPNs。
use NjoguAmos\Pesapal\Models\PesapalIpn; $ips = PesapalIpn::all();
[ [ "id" => 1 "url" => "http://kautzer.com/omnis-ut-qui-illo-id-laborum-numquam" "ipn_id" => "767e3275-d504-41a0-920a-dd752aafb5ac" "type" => 0 "status" => 1 "created_at" => "2024-03-18T08:10:32.000000Z" "updated_at" => "2024-03-18T05:10:32.000000Z" ], [ "id" => 2 "url" => "http://www.cole.org/qui-fugiat-accusamus-molestiae-aspernatur-sequi-eum-non-quae.html" "ipn_id" => "de07604f-c06b-4ccf-9cb5-dd75aaaff99f" "type" => 0 "status" => 1 "created_at" => "2024-03-18T08:10:33.000000Z" "updated_at" => "2024-03-18T05:10:33.000000Z" ] ]
4. 提交订单请求端点
要提交订单请求,您可以使用Pesapal
类中的createOrder
方法。您需要构建如以下所示的PesapalOrderData
和PesapalAddressData
的DTO。该方法在成功响应时返回一个数组,在失败响应时返回一个Saloon Response实例。
info 您必须提供一个已注册的
PesapalIpn
。
use NjoguAmos\Pesapal\Enums\ISOCurrencyCode; use NjoguAmos\Pesapal\Enums\ISOCountryCode; use NjoguAmos\Pesapal\Enums\RedirectMode; use NjoguAmos\Pesapal\Pesapal; use NjoguAmos\Pesapal\DTOs\PesapalOrderData; use NjoguAmos\Pesapal\DTOs\PesapalAddressData; $ipnId = PesapalIpn::latest()->first()->ipn_id; $orderData = new PesapalOrderData( id: fake()->uuid(), currency: ISOCurrencyCode::KES, amount: fake()->randomFloat(nbMaxDecimals: 2, min: 50, max: 500), description: 'Test order', callbackUrl: fake()->url(), notificationId: $ipnId, cancellationUrl: fake()->url(), redirectMode: RedirectMode::PARENT_WINDOW, ); // All fields are optional except either phoneNumber or emailAddress $billingAddress = new PesapalAddressData( phoneNumber: '0700325008', emailAddress: 'test@xample.com', countryCode: ISOCountryCode::KE firstName: 'Amos', middleName: 'Njogu' // lastName: '' line2: "Gil House, Nairobi, Tom Mboya Street", // city: "", // state: "", // postalCode: "", // zipCode: "", ); $order = Pesapal::createOrder( orderData: $orderData, billingAddress: $billingAddress, );
示例成功响应
[ "order_tracking_id" => "b945e4af-80a5-4ec1-8706-e03f8332fb04", "merchant_reference" => "TEST1515111119", "redirect_url" => "https://cybqa.pesapal.com/pesapaliframe/PesapalIframe3/Index/?OrderTrackingId=b945e4af-80a5-4ec1-8706-e03f8332fb04", "error" => null, "status" => "200" ]
现在,您可以重定向用户到redirect_url
以完成支付。
5. 获取交易状态端点
您可以使用创建订单时发放的OrderTrackingId
来检查交易状态。您可以通过使用Pesapal
类中的getTransactionStatus
方法来实现。该方法在成功响应时返回一个数组,在失败响应时返回一个Saloon Response实例。
use NjoguAmos\Pesapal\Pesapal; $transaction = Pesapal::getTransactionStatus( orderTrackingId: 'b945e4af-80a5-4ec1-8706-e03f8332fb04', ); // $transaction either an array or an instance of Saloon Response
示例成功响应
[ "payment_method" => "MpesaKE" "amount" => 6.0 "created_date" => "2024-03-19T20:08:46.39" "confirmation_code" => "SCJ8JQ26SW" "order_tracking_id" => "af2234da-03ee-4b60-b2dd-dd746bcda1bd" "payment_status_description" => "Completed" "description" => null "message" => "Request processed successfully" "payment_account" => "2547xxx56689" "call_back_url" => "http://127.0.0.1:8000/pesapal-callback?OrderTrackingId=af2234da-03ee-4b60-b2dd-dd746bcda1bd&OrderMerchantReference=1" "status_code" => 1 "merchant_reference" => "1" "payment_status_code" => "" "currency" => "KES" "error" => [ "error_type" => null "code" => null "message" => null ] "status" => "200" ]
6. 定期/订阅支付
- TODO: 添加定期支付文档
7. 退款请求
- TODO: 添加退款请求文档
关于响应的说明
为了灵活性和简单性,Pesapal
静态方法在成功响应时返回一个array
,在失败响应时返回一个Saloon Response
实例。
例如,使用getTransactionStatus
获取交易状态时,将返回交易详情的数组或如果请求失败,返回一个Saloon Response
实例。
use NjoguAmos\Pesapal\Pesapal; $transaction = Pesapal::getTransactionStatus( orderTrackingId: 'b945e4af-80a5-4ec1-8706-e03f8332fb04', ); if (is_array($transaction)) { // The API call was successful and response is an array // [ // "payment_method" => "MpesaKE" // "amount" => 6.0 // "created_date" => "2024-03-19T20:08:46.39" // "confirmation_code" => "SCJ8JQ26SW" // "....more field" // ] } else { // The API call was not successful. The response is an instance of Saloon Response // $transaction->status() ---> response status code. // $transaction->headers() ---> Returns all response headers // $transaction->getPendingRequest() ---> PendingRequest class that was built up for the request. }
您可以了解更多关于[Saloon Response(https://docs.saloon.dev/the-basics/responses)的信息。您可以使用响应来诊断请求的问题。
测试
Info 在可能的情况下,测试使用真实的沙盒凭据,因此请求不是模拟的。结果响应被保存在
tests/Fixtures
中,并在未来的测试中使用。如果无法使用真实凭据,请求将被模拟。您可以通过删除tests/Fixtures
并运行测试来重新创建固定装置。
composer test
变更日志
请参阅CHANGELOG以获取有关最近更改的更多信息。
贡献
请参阅CONTRIBUTING以获取详细信息。
安全漏洞
请审查我们的安全策略以了解如何报告安全漏洞。
致谢
许可
MIT许可(MIT)。请参阅许可文件以获取更多信息。