atendwa/mpesa-artisan

一款专为Laravel项目设计的Laravel包,旨在无缝集成M-Pesa daraja API。

v1.0.0 2024-06-04 12:11 UTC

This package is auto-updated.

Last update: 2024-09-13 19:38:11 UTC


README

Latest Stable Version Total Downloads PHP Version License Quality Score Code Style Status

此Laravel包无缝集成M-Pesa支付服务,允许您轻松地在Laravel应用程序中处理M-Pesa交易。这是寻求可靠移动货币集成的企业和个人的完美解决方案。

带有一点魔力 🥳🤯

此包有很多优点,但我认为您最喜欢以下这些功能

  • 使用IP白名单进行安全的回调:我们的AllowWhitelistedMpesaIps 中间件通过验证发送回调的IP地址是否已列入白名单和有效,增加了额外的安全层。

  • 我已为您实现了M-Pesa的12/13个API,方便您使用。第13个API即将到来!敬请期待更多功能。 🎉🚀

  • 是的,您猜对了 drivers! 使用此包,您可以设置多个驱动来处理您的应用程序的不同M-Pesa凭据。只需将它们添加到mpesa.php配置文件中,然后您就可以开始使用了! 🚗💨

        stk()->driver('web-store')->amount(5); //... chain more methods
    
        stk()->driver('donation')->amount(80); //... chain more methods
  • 我们的包包括一些有用的辅助类和函数,例如电话号码清理器、回调请求类等。此外,大多数类都有相应的全局辅助函数,以增加便利性! 🛠️🌟

       $sanitise = new SanitisePhoneNumber(); 
       $number = SanitisePhoneNumber::index('0712345678'); // returns 254712345678 
       
       //or
    
       $number = sanitise_phone_number('0712345678');
  • 最后,为什么不试试Route::callback() 呢?它允许您在路由文件中轻松设置回调路由。它处理IP白名单删除CSRF令牌验证,使集成变得简单! 🚀✨

     Route::callback('/some-url', [SomeClass, 'do-something'])->name('name');

通过Composer安装

  1. 在终端中运行以下命令以安装此包

    composer require atendwa/mpesa-artisan
  2. 发布配置文件

    安装包后,使用以下Artisan命令发布配置文件

    php artisan mpesa-artisan:install

    发布的配置文件

    配置文件config/mpesa.php应如下所示

    <?php
    
    return [
        // This determines if the application is in 'sandbox' or 'live' mode
        'environment' => env('MPESA_ENVIRONMENT', 'sandbox'),
    
        // These are the base URLs for sandbox and live environments
        'urls' => [
            'sandbox' => env('MPESA_SANDBOX_URL', 'https://sandbox.safaricom.co.ke'),
            'live' => env('MPESA_LIVE_URL', 'https://api.safaricom.co.ke'),
        ],
    
        // These are the various API endpoints used in the application
        'endpoints' => [
            'access_token' => env('MPESA_ACCESS_TOKEN', 'oauth/v1/generate?grant_type=client_credentials'),
            'account_balance' => env('MPESA_ACCOUNT_BALANCE_ENDPOINT', 'mpesa/accountbalance/v1/query'),
            'transaction_status' => env('MPESA_TRANSACTION_STATUS', 'mpesa/transactionstatus/v1/query'),
            'c2b_register_url' => env('MPESA_C2B_REGISTER_URL_ENDPOINT', 'mpesa/c2b/v2/registerurl'),
            'business_buy_goods' => env('MPESA_BUSINESS_BUY_GOODS', 'mpesa/b2b/v1/paymentrequest'),
            'b2b_express_checkout' => env('MPESA_B2B_EXPRESS_ENDPOINT', 'v1/ussdpush/get-msisdn'),
            'business_pay_bill' => env('MPESA_BUSINESS_PAY_BILL', 'mpesa/b2b/v1/paymentrequest'),
            'mpesa_express' => env('MPESA_EXPRESS_ENDPOINT', 'mpesa/stkpush/v1/processrequest'),
            'stk_query' => env('MPESA_EXPRESS_QUERY_ENDPOINT', 'mpesa/stkpushquery/v1/query'),
            'dynamic_qr' => env('MPESA_DYNAMIC_QR_ENDPOINT', 'mpesa/qrcode/v1/generate'),
            'tax_remittance' => env('MPESA_TAX_REMITTANCE', 'mpesa/b2b/v1/remittax'),
            'reversal' => env('MPESA_REVERSAL_ENDPOINT', 'mpesa/reversal/v1/request'),
            'b2c' => env('MPESA_B2C_ENDPOINT', 'mpesa/b2c/v1/paymentrequest'),
        ],
    
        // Contains settings for different MPESA drivers
        'drivers' => [
            'default' => [
                'initiator_name' => env('MPESA_INITIATOR_NAME', ''),
                'passkey' => env('MPESA_PASSKEY', ''),
    
                'security_credential' => env('MPESA_SECURITY_CREDENTIAL', ''),
    
                'shortcodes' => [
                    'business' => env('MPESA_BUSINESS_SHORTCODE', ''),
                    'payment' => env('MPESA_PAYMENT_SHORTCODE', ''),
                ],
    
                'key_pairs' => [
                    'consumer' => [
                        'key' => env('MPESA_CONSUMER_KEY', ''),
                        'secret' => env('MPESA_CONSUMER_SECRET', ''),
                    ],
                    'payment' => [
                        'key' => env('MPESA_PAYMENT_CONSUMER_KEY', ''),
                        'secret' => env('MPESA_PAYMENT_CONSUMER_SECRET', ''),
                    ],
                ],
    
                'callbacks' => [
                    'default' => env('MPESA_DEFAULT_CALLBACK', ''),
                    'default_timeout_url' => env('MPESA_DEFAULT_TIMEOUT_URL', ''),
                ],
            ],
        ],
    
        // Additional configuration settings
        'configuration' => [
            'default_driver' => env('MPESA_DRIVER', 'default'),
            'sanitise_phone_number' => env('SANITISE_PHONE_NUMBER', true),
            'use_whitelist' => env('USE_IP_WHITELIST', true),
        ],
    
        // Cache settings for MPESA responses
        'cache' => [
            'enabled' => env('MPESA_CACHE_ENABLED', true),
            'prefix' => env('MPESA_CACHE_PREFIX', 'mpesa_artisan_cache'),
        ],
    
        // List of IPs allowed to access the application
        'whitelisted_ips' => [
            '196.201.214.200',
            '196.201.214.206',
            '196.201.213.114',
            '196.201.214.207',
            '196.201.214.208',
            '196. 201.213.44',
            '196.201.212.127',
            '196.201.212.138',
            '196.201.212.129',
            '196.201.212.136',
            '196.201.212.74',
            '196.201.212.69',
        ],
    ];
  3. 配置.env文件

    使用必要的M-Pesa凭据更新您的.env文件

    MPESA_ENVIRONMENT="live"
    MPESA_INITIATOR_NAME=""
    MPESA_PASSKEY=""
    MPESA_SECURITY_CREDENTIAL=""
    MPESA_BUSINESS_SHORTCODE=""
    MPESA_PAYMENT_SHORTCODE=""
    MPESA_CONSUMER_KEY=""
    MPESA_CONSUMER_SECRET=""
    MPESA_PAYMENT_CONSUMER_KEY=""
    MPESA_PAYMENT_CONSUMER_SECRET=""
    MPESA_DEFAULT_CALLBACK=""
    MPESA_DEFAULT_TIMEOUT_URL=""

用法

在深入了解可用的API端点之前,让我们看看您如何轻松调用任何服务类。

// instantiate the class
$stk = new STK();
$response = $stk->amount(34)->post();

// use the global helper
stk()->amount(34)->post();

// use the Daraja Facade
\Atendwa\MpesaArtisan\Facades\Daraja::stk()->amount(56)->post();

// use the daraja global helper
daraja()->stk()->buyGoods()->amount(78)->post();

以下是一些需要注意的要点

  • 所有API服务都提供了一个driver('default')方法来动态更改driver。然而,您的自定义驱动必须与默认驱动的配置键匹配。如果驱动配置错误(例如,必须始终存在initiator_name键),将抛出异常。

  • 所有API服务还提供了一个useConsumerKeyPair(true)方法来在密钥对之间切换。默认情况下,使用consumer密钥对。传递false以使用payment密钥,确保它们与提供的短代码匹配。不正确的密钥对可能会锁定您的安全凭据。

  • 所有API服务都返回包含键在camel case中的Illuminate\Support\Collection实例。例如,响应体中的ResponseCode将转换为responseCode

  • amount()方法仅接受整数,而其他方法接受字符串

  • 包中强制执行了类型安全。向方法传递无效类型将抛出异常或使用回退值。如果遇到无效的字符串类型,可以使用空字符串。

  • 不同的API服务假设驱动、密钥对、备注、场合、短代码等默认值,因此您不需要调用每个方法。

        $response = stk_query()->checkoutRequestID($id)->post();
  • 每个API服务都指定了其有效负载的所需属性。如果任何必需属性为空,将抛出异常

  • 要使用不同的API版本,只需在您的.env文件中覆盖所需端点的端点URL

  • 电话号码应采用格式254#########。虽然该包不验证您传递的值,但您可以使用Atendwa\MpesaArtisan\Support\SanitisePhoneNumber类或其全局辅助函数来帮助清理和转换电话号码到正确的格式。

        $number = sanitise_phone_number('0712345678'); // returns 25471234578
        $number = sanitise_phone_number('+254712345678'); // returns 25471234578
        $number = sanitise_phone_number('254712345678'); // returns 25471234578

1. 动态二维码

使用此API生成动态二维码,使拥有My Safaricom App或M-PESA应用的用户能够扫描二维码。他们可以捕获收银机号码和金额,并授权在选择的LIPA NA M-PESA(LNM)商户点支付商品和服务。

https://developer.safaricom.co.ke/APIs/DynamicQRCode

$response = dynamic_qr()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->amount(100) // Required: sets the 'Amount' attribute
                ->buyGoods() // Optional: defaults the TrxCode attribute to 'BG'
                // ->paybill() sets TrxCode to 'PB'
                // ->sendMoney() sets TrxCode to 'SM'
                // ->sendToBusiness() sets TrxCode to 'SB'
                // ->withdrawFromAgent() sets TrxCode to 'WA'
                ->size(400) // Optional: default is 300
                ->merchantName('atendwa') // Required: sets the 'MerchantName' attribute
                ->reference('buy me a coffee') // Required: sets the 'RefNo' attribute
                ->creditPartyIdentifier('123456') // Required: sets the 'CreditPartyIdentifier (CPI)' attribute
                ->post();

2. M-Pesa Express 模拟(STK 推送)

Lipa na M-PESA在线API,也称为M-PESA Express(STK Push/NI 推送),简化了商户/企业发起的C2B(客户对企业)支付。

https://developer.safaricom.co.ke/APIs/MpesaExpressSimulate

$response = stk()
        ->driver('default') // Optional: Specify a custom driver
        ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
        ->partyB('1234567') // Optional: Specify a shortcode, defaults to the business shortcode
        ->buyGoods() // Optional: Choose between 'buyGoods' or 'payBill', defaults to 'buyGoods'
        // ->payBill() // Optional: Choose between 'buyGoods' or 'payBill', defaults to 'buyGoods'
        ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
        ->phoneNumber('254712345678') // Required: Specify the customer's phone number
        ->amount(1) // Required: Specify the amount to be transacted
        ->reference('test') // Required: Specify an account reference
        ->description('test') // Required: Specify a transaction description
        ->post();

3. M-Pesa Express 查询(STK 查询)

使用此API检查Lipa Na M-PESA在线支付的状态。

https://developer.safaricom.co.ke/APIs/MpesaExpressQuery

$response = stk_query()
        ->driver('default')  // Optional: defaults to 'default'
        ->useConsumerKeyPair(true) // Optional: defaults to true
        ->shortCode('1234567') // Optional: the package will attempt to use the business shortcode if not set
        ->checkoutRequestID($someID) // Required: The CheckoutRequestID from the STK push response
        ->post();

4. 客户对企业注册URL

注册URL API通过允许接收支付通知到您的paybill来补充客户对企业(C2B)API。此API允许您注册回调URL,通过这些URL您将收到支付到您的paybill/收银机号码的通知。

https://developer.safaricom.co.ke/APIs/CustomerToBusinessRegisterURL

$response = register_c2b_urls()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret                
                ->shortCode('123456') // Required: Specify the short code
                ->completed() // Optional: the ResponseType is 'Completed' by default
                // ->cancelled() // Optional: sets the ResponseType attribute to 'Cancelled'
                ->confirmationUrl('https://tendwa.dev/package-sale/confirm') // Required: Specify the confirmation URL
                ->validationUrl('https://tendwa.dev/package-sale/validate') // Required: Specify the validation URL
                ->post();

5. 企业对客户(B2C)

B2C API允许企业直接向客户支付,例如工资支付、现金返还、促销支付、奖金、提款和贷款发放。

https://developer.safaricom.co.ke/APIs/BusinessToCustomer

$response = b2c()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(false) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->timeoutUrl('https://tendwa.dev') // Required: Specify the timeout URL
                ->partyA('123456')
                ->partyB('254712345678')
                ->initiator('123456') // Optional: defaults to the initiator name in the config file
                ->amount(100) // Required: Specify the amount. Must be > 50 for safaricom to process the request
                ->remarks('test') // Required: Specify the transaction remarks
                ->occasion('test') // Required: Specify the transaction occasion
                ->post()

6. 交易状态

检查交易状态。

https://developer.safaricom.co.ke/APIs/TransactionStatus

$response = transaction_status()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(false) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->initiator('initiator') // Optional: defaults to the initiator name in the config file
                ->partyA('1234567')
                ->transactionID('NEF61H8J60') // Optional: use this if you have a transaction ID
                // ->originatorConversationID('AG_20190826_0000777ab7d848b9e721') // Optional: use this if you don't have a transaction ID
                ->timeoutUrl('https://tendwa.dev') // Required: Specify the timeout URL
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->remarks('Transaction status request.') // Optional: defaults to 'Transaction status request.'
                ->occasion('Transaction status request.') // Optional: defaults to 'Transaction status request.'
                ->post();

7. 账户余额

账户余额API用于请求短码的余额,适用于B2C、购买商品和支付账单账户。

https://developer.safaricom.co.ke/APIs/AccountBalance

$response = account_balance()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->partyA('123456')
                ->remarks('Get account balance.') // Optional: defaults to 'Get account balance.'
                ->timeoutUrl('https://tendwa.dev') // Required: Specify the timeout URL
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->post();

8. 冲销

https://developer.safaricom.co.ke/APIs/Reversal

$response = reversal()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->occasion('Transaction reversal request.') // Required: Specify the occasion transaction or defaults to 'Transaction reversal request.'.
                ->remarks('Transaction reversal request.') // Required: Specify the occasion transaction or defaults to 'Transaction reversal request.'. 
                ->timeoutUrl('https://tendwa.dev') // Required: Specify the timeout URL
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->initiator('initiator') // Optional: defaults to the initiator name in the config file
                ->receiverParty('1234567')
                ->amount(100) // Required: Specify the amount
                ->transactionID('NEF61H8J60') // Optional: use this if you have a transaction ID
                ->post();

9. 税款缴纳

https://developer.safaricom.co.ke/APIs/TaxRemittance

$response = tax_remittance()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->initiator('initiator') // Optional: defaults to the initiator name in the config file
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->timeoutUrl('https://tendwa.dev') // Required: Specify the timeout URL
                ->partyA('1234567') // Required: Specify the shortcode
                ->partyB('572572') // Required: Specify the shortcode
                ->amount(100) // Required: Specify the amount
                ->remarks('Tax Remittance') // Optional: defaults to 'Tax Remittance'
                ->reference('Tax Remittance') // Optional: defaults to 'Tax Remittance'
                ->post();

10. 企业支付账单

https://developer.safaricom.co.ke/APIs/BusinessPayBill

$response = business_pay_bill()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->initiator('initiator') // Optional: defaults to the initiator name in the config file
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->timeoutUrl('https://tendwa.dev') // Required: Specify the timeout URL
                ->partyA('1234567') // Required: Specify the shortcode
                ->partyB('572572') // Required: Specify the shortcode
                ->amount(100) // Required: Specify the amount
                ->remarks('Business Payment') // Optional: defaults to 'Business Payment'
                ->reference('Business Payment') // Optional: defaults to 'Business Payment'
                ->post();

11. 企业购买商品

https://developer.safaricom.co.ke/APIs/BusinessBuyGoods

$response = business_buy_goods()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->initiator('initiator') // Optional: defaults to the initiator name in the config file
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->timeoutUrl('https://tendwa.dev') // Required: Specify the timeout URL
                ->partyA('1234567') // Required: Specify the shortcode
                ->partyB('572572') // Required: Specify the shortcode
                ->amount(100) // Required: Specify the amount
                ->remarks('Business Payment') // Optional: defaults to 'Business Payment'
                ->reference('Business Payment') // Optional: defaults to 'Business Payment'
                ->post();

12. B2B 快速结账

https://developer.safaricom.co.ke/APIs/B2BExpressCheckout

$response = b2b_express_checkout()
                ->driver('default') // Optional: Specify a custom driver
                ->useConsumerKeyPair(true) // Optional: Toggle key pairs, defaults to true for consumer key and secret
                ->primaryShortCode('1234567') // Required: Specify the primary short code
                ->receiverShortCode('572572') // Required: Specify the receiver short code
                ->amount(100) // Required: Specify the amount
                ->reference('Business Payment') // Required: Specify the reference
                ->callbackUrl('https://tendwa.dev') // Required: Specify the callback URL
                ->requestRefID($someUniqueID) // Required
                ->partnerName($yourStoreName) // Required
                ->post();

辅助工具

查看该包中包含的一些实用的辅助类

Mpesa 回调请求(MpesaCallbackRequest::class)

此类扩展了Laravel的HttpRequest类,并添加了解析M-Pesa回调结果和检查交易成功状态的功能。

  • Illuminate\Http\Request类中的所有方法都可用。

  • fetchResponse()方法自动解析响应体,允许您直接访问结果代码,而无需在嵌套数组中导航以访问不同回调类型(例如,STK、B2C)。

use Atendwa\MpesaArtisan\Http\Requests\MpesaCallbackRequest;

public function handleStkCallback(MpesaCallbackRequest $request)
{
    $response = $request->fetchResponse(); // returns the response body as a collection
    $response->get('resultCode'); // returns the result code from the response body
    
    // for stk push
    $response->get('merchantRequestID');

    // for b2c
    $response->get('TransactionID'); // returns the result code from the response body
    
    $request->log(); // logs the response to your logging system with the info level

    $success = $request->successful(); // returns a boolean indicating if the transaction was successful by checking the result code
}

清理电话号码(SanitisePhoneNumber::class)

此类清理电话号码,将它们转换成所需的格式。它有一个名为index的方法,接受一个电话号码并返回清理后的版本。

$number = sanitise_phone_number('0712345678'); // returns 254712345678

解析响应(ParseResponse::class)

此类解析来自Safaricom的API响应。它有一个名为index的方法,接受一个响应并返回一个解析后的版本。解析后的响应将具有camelCase键、successfulResponsesuccessfulResult指示符表示成功,以及一个表示错误的hasErrors键。此类用于内部以确保一致的响应解析。

$response = parse_response(stk()->post());

$response->get('successfulResponse');  // returns true if the response was successful

$response->get('responseCode');