承接 njoguamos/laravel-pesapal 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

njoguamos/laravel-pesapal

Composer 安装命令:

composer require njoguamos/laravel-pesapal

包简介

A Laravel package for interacting with https://www.pesapal.com api

README 文档

README

Laravel 11+ package for interacting with Pesapal API

Latest Version on Packagist GitHub Actions Test Status GitHub Actions Workflow Status GitHub Actions PHPStan Status Total Downloads

This package provides a way of interacting with Pesapal API. It provides a way of generating access_token and storing Instant Payment Notifications (IPNs) in the database. It also provides a way of submitting order requests and checking the status of a transaction.

Why use this package

  • To provide a way of generating Pesapal api access_token which normally expires after 5 minutes
  • Offer a gateway to interacting with Pesapal v3 API
  • Provide a way of storing Instant Payment Notifications (IPNs) in the database
  • Saves you time from writing the same code over and over again

Playground

If you are looking to test this package, I have created a playground where you can test the package without having to create a new Laravel project.

Installation

Version Supported Laravel
1.x 10.x, 11.x
2.x 11.x, 12.x

You can install the package via composer:

composer require njoguamos/laravel-pesapal

This packages comes with the following tables

  • pesapal_tokens - to store the access_token and expires_at for the Pesapal API
  • pesapal_ipns - to store the Instant Payment Notifications

Publish and run the migrations

php artisan vendor:publish --tag="pesapal-migrations"
php artisan migrate

You can optionally publish the config file

php artisan vendor:publish --tag="pesapal-config"

Update your environment variables in your application.

PESAPAL_LIVE=
PESAPAL_CONSUMER_KEY=
PESAPAL_CONSUMER_SECRET=

Usage

1. Generate access_token

To generate an access_token you can run the following command:

php artisan pesapal:auth

The command will get a fresh access_token from Pesapal API using the CONSUMER_KEY and CONSUMER_SECRET and save it in the database. The access_token is valid for 5 minutes therefore is wise to schedule the command to run every 4 minutes. In addition, when you have set model:prune command, all expired access_token will be deleted from the database since they are no longer useful.

 # 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();

You can also call the createToken' in Pesapalclass directly to generate theaccess_token. The method will return null or an new PesapalToken` instance.

use NjoguAmos\Pesapal\Pesapal;

$token = Pesapal::createToken();

The results of createToken is an instance of PesapalToken Eloquent Model. Which mean you can call Eloquent methods e.g.

$data = $token->toArray();
[
 'access_token' => "eyJhbGciOiJIUzI1NiIs...6pVj1_DS37ghMGQ",
 'expires_at' => Carbon\Carbon instance
]

2. Create Instant Payment Notification

To create an instant payment notification, you can use the createIpn method in the Pesapal class. The method will return an instance of PesapalIpn or null if the request fails.

info Ensure that that your pesapal_tokens table as an access_token that is not expired.

use NjoguAmos\Pesapal\Pesapal;

$ipn = Pesapal::createIpn(
    url: 'https://www.yourapp.com/ipn',
    ipnType: IpnType::GET,
);

The results of createIpn is an instance of PesapalIpn Eloquent Model. Which mean you can call Eloquent methods e.g.

$data = $ipn->toArray();
[
    'url' => 'https://www.yourapp.com/ipn'
    'ipn_id' => 'e32182ca-0983-4fa0-91bc-c3bb813ba750'
    'type' => 'GET'
    'status' => 'Active'
]

info The url should be a public url that can be accessed by pesapal.com. The ipnType can be either IpnType::GET or IpnType::POST.

You can go ahead and use the ipn_id to submit a Submit Order Requests.

info Ensure that that your pesapal_tokens table as an access_token that is not expired. Of course, if you scheduled the pesapal:auth command, you should not worry about the access_token being expired.

3. Get Registered IPNs Endpoint

There are two ways to get the registered IPNs.

  1. You can use the getIpns method in the Pesapal class to get a IPN from Pesapal API. This method returns an array for successful response or an instance of Saloon Response for failed response.
use NjoguAmos\Pesapal\Pesapal;

$response = Pesapal::getIpns();

Sample successful response

[
    [
        "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"
    ]
]
  1. or get the IPNs from the database.
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. Submit Order Request Endpoint

To submit an order request, you can use the createOrder method in the Pesapal class. You will need to construct a DTO for PesapalOrderData and PesapalAddressData as shown below. This method returns an array for successful response or an instance of Saloon Response for failed response.

info You must provide a registered 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,
);

Sample successful response

[
    "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"
]

You can now re-direct the user to the redirect_url to complete the payment.

5. Get Transaction Status Endpoint

You can check the status of a transaction using OrderTrackingId issued when creating an order. You can do so by using the getTransactionStatus method in the Pesapal class. This method returns an array for successful response or an instance of Saloon Response for failed response.

use NjoguAmos\Pesapal\Pesapal;

 $transaction = Pesapal::getTransactionStatus(
    orderTrackingId: 'b945e4af-80a5-4ec1-8706-e03f8332fb04',
);

// $transaction either an array or an instance of Saloon Response

Sample successful 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. Recurring / Subscription Based Payments

  • TODO: Add documentation for recurring payments

7. Refund Request

  • TODO: Add documentation for refund request

8. Retrying Requests

If for some reason, the payment did not complete and you have the order tracking ID, you can retry the payment by redirecting the user to the Pesapal payment page.

use NjoguAmos\Pesapal\Pesapal;

$redirectUrl = Pesapal::getRedirectUrl(orderTrackingId: $orderTrackingId);
// https://pay.pesapal.com/iframe/PesapalIframe3/Index?OrderTrackingId=db80f574-a759-40b3-a6ec-dc68ef3dc1e6

A note about responses

For flexibility and simplicity, the Pesapal static method returns an array for successful responses or an instance of Saloon Response for failed responses.

Example, when getting the transaction status using getTransactionStatus will either return an array of transaction details or an instance of Saloon Response if the request was not successful.

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.
}

You can learn more about the [Saloon Response(https://docs.saloon.dev/the-basics/responses). You can use the response to diagnose the issue with the request.

Testing

Info Where possible, the tests uses real sandbox credentials, and as such the request is not mocked. The resulting response is saved at tests/Fixtures and used in future tests. Where it is impossible to use real credentials, the request is mocked. You can recreate the fixtures by deleting tests/Fixtures and running the tests.

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

njoguamos/laravel-pesapal 适用场景与选型建议

njoguamos/laravel-pesapal 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3.38k 次下载、GitHub Stars 达 8, 最近一次更新时间为 2024 年 03 月 17 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「payment」 「laravel」 「pesapal」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 njoguamos/laravel-pesapal 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 njoguamos/laravel-pesapal 我们能提供哪些服务?
定制开发 / 二次开发

基于 njoguamos/laravel-pesapal 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 3.38k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 8
  • 点击次数: 9
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 8
  • Watchers: 1
  • Forks: 3
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-03-17