levizwannah/mpesa-sdk-php

PHP的独立Mpesa SDK。此包为PHP应用程序提供Safaricom Mpesa API的简洁实现。

v1.2.1 2024-08-28 15:48 UTC

README

一个用于与Safaricom Daraja API交互的简洁、优雅和独立 PHP SDK。该SDK纯粹面向对象,易于理解和使用。它没有依赖关系,因此可以用于任何PHP项目:普通或基于框架的项目。

需求

  • PHP版本 >= 7.4
  • 您已阅读Daraja API的文档:此SDK主要为您抽象了一切,使集成M-Pesa变得容易。因此,请确保您已查看Daraja文档。不需要理解它,只需知道正在发送和接收哪些数据即可。这有助于您理解此SDK。

使用Composer获取

composer require levizwannah/mpesa-sdk-php

然后开始使用。

不使用composer

下载代码的zip版本。包括位于下载的src文件夹中的self-autoload.php文件。

文档

设置

首先创建一个具有必要配置的Mpesa对象。

消费者密钥、消费者密钥和业务简码始终是必需的。

如果您使用的是收银机号,则需要till密钥,否则只需要业务简码。

注意:业务简码与Paybill号码相同。对于收银机号码,则不同。

require('path/to/vendor/autoload.php');

use LeviZwannah\MpesaSdk\Mpesa;

$config = [
  "key" => "consumer-key", // consumer key
  "secret" => "consumer-secret", // consumer secret
  "code" => "12345", // business short code
  
  "till" => "67891", // optional till number
  "passkey" => "xxxx", // optional passkey
  "initiator" => "levizwannah", // optional initiator name
  "credential" => "levi-cred++=="  // optional security credential
]

$mpesa = Mpesa::new()->configure($config);

方法链与configure($configure)

$config数组中的每个键都是对象的setter方法。例如,以下代码与上面的代码等价。

require('path/to/vendor/autoload.php');

use LeviZwannah\MpesaSdk\Mpesa;

$mpesa = Mpesa::new();

$mpesa->key("consumer-key")
      ->secret("consumer-secret")
      ->code(12345)
      ->till(67891) // optional
      ->passkey('stk-passkey') // optional
      ->initiator("levizwannah") // optional
      ->credential("levi-cred++=="); // optional

每个用于与特定API交互的对象都扩展了父Mpesa对象。因此,相同的规则也适用于它们。您可以使用配置数组和使用configure方法或仅使用单个setter方法。

警告:不要直接从子类创建对象,始终使用mpesa对象来获取子对象,您将在文档的后面看到。

环境

您可以在$config数组中使用'env'键或使用env("env")方法来设置环境。环境值可以是livesandbox。默认情况下,环境是"live"。有一个Constant类可以帮助您避免写入字面字符串。

//...other code
use LeviZwannah\MpesaSdk\Helpers\Constant;

$mpesa->configure([
    'env' => Constant::SANDBOX, 
    // or
    'env' => Constant::LIVE, // default value
]);

// or
$mpesa->env(Constant::SANDBOX);
$mpesa->env(Constant::LIVE); // default value

记住:以下使用的每个setter方法都可以用作$config数组中的键,并使用configure($config)方法设置。

电话号码

SDK将254添加到电话号码。以下格式受支持

0746987654
+254746987654
+2540746987654
254746987654
746987654

异常

在请求期间,如果缺少必要的数据,SDK将抛出异常。例如,在发出Reversal请求之前,需要发起人名称和安全凭证。如果没有找到它们,将抛出一个带有语义信息的异常,告知您问题所在。

处理响应

SDK提供了一种统一的方法来检查Mpesa的即时响应。在与SDK交互的任何API中使用以下代码片段。

//... request made

if($client->accepted()) {
    // ... mpesa accepted the request for processing
    // This means the ResponseCode == 0
    $response = $client->response();
}
else {
    // The response code is not == 0 or there is an error.
    $error = $client->error(); // get an error object
    echo "error: $error->code, $error->message";
}

// you can always get the latest response using
$response = $client->response(); // returns an object

$conversationId = $response->ConversationID;
$responseCode = $response->ResponseCode;
// ...

注意:响应对象中的数据与Daraja文档中的数据相同。没有进行额外的格式化。

处理回调时的安全性

SDK有两个静态辅助方法,可帮助您在回调中处理mpesa响应。

  1. verifyOrigin(): bool:如果回调响应来自Mpesa,则返回true,否则返回false
  2. data($asArray = false): object|array:从mpesa获取回调数据,并根据其参数将其作为对象或数组返回。
require('path/to/vendor/autoload.php');

use LeviZwannah\MpesaSdk\Mpesa;

$isFromMpesa = Mpesa::verifyOrigin();
$result = Mpesa::data();

//...

处理回调负载

注意: Response 表示您在发起请求时从 Mpesa 获得的内容。Result 是发送到您的回调 URL 的负载。

负载格式

请参阅 Daraja 文档(https://developer.safaricom.co.ke),以了解预期的负载。为了向前兼容,SDK 不会修改 Mpesa 的响应或负载。

令人困惑的部分

在每一个 Response 中,都会存在独特的键。例如,STK 推送响应中的 MerchantRequestIDCheckoutRequestID,以及其他 API 响应中的 OriginatorConversationIDConversationID。这些键用于标识 Mpesa 上的交易。请将这些键保存在您的数据库或存储中,与待处理的交易一起。

在发送到您的回调的 Result 负载中,这些键将存在。因此,您可以使用它们来更新存储或数据库中相应的交易。

Mpesa Express (STK Push) API

用于发起 STK Push 请求。

要求

确保这些值在设置部分中已设置。

  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)
  • 收银机号 (till) 对于收银机号
  • 密码 (passkey)

用法

//..setup...

$stk = $mpesa->stk();

// for till numbers
// ensure that the till number is set during setup
// or set it up using $stk->till(123455)

$stk->phone('0724786543')
    ->amount(1)
    ->buygoods() // for till numbers
    ->paybill() // for paybill numbers
    ->callback('https://my-domain.com/path/to/callback')
    ->description('optional description') // optional
    ->push();

// check if the request was accepted by mpesa.
if(!$stk->accepted()) {
    $error = $stk->error();
    echo "error: $error->code, $error->message";
    // exit...
}

// accepted for processing
$response = $stk->response(); // returns an object

$merchantRequestId = $response->MerchantRequestID;
$checkoutRequestId = $response->checkoutRequestID;

//...

请注意,使用收银机号和付款单号之间的区别在于在调用 push() 方法之前使用 paybill()buygoods() 方法。同时,在使用收银机号时,请确保已设置 till 值。

Mpesa Express STK 查询

用于查询 STK 推送请求的状态。这与正常的交易状态查询不同。

要求

确保这些值在设置部分中已设置。

  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)
  • 密码 (passkey)
  • 收银机 (till) 用于收银机账户

用法

请参阅下面的代码片段

//...setup...

$query = $mpesa->stk()->query();

$query->checkoutId('checkout-request-id')
      ->paybill() // for paybill number
      ->buygoods() // for till numbers
      ->make();

// check if it's not accepted
if(!$query->accepted()){
  $error = $query->error();
  echo "$error->code $error->message";
  // exit;
}

$response = $query->response();
$resultCode = $response->ResultCode;
$merchantId = $response->MerchantRequestID;
// ...

注意:如果您正在查询为付款单号发起的 STK 请求,请使用 paybill(),否则请使用 buygoods()。默认情况下,它查询为付款单号发起的 STK 请求。

C2B URLs 注册 API

允许您注册您的 C2B URLs。SDK 还为您提供了易于使用的确认和验证脚本响应方法。

不需要 validation url,除非您明确要求 Mpesa 团队为您启用它。

要求

确保这些值在设置部分中已设置。

  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

注册

请参阅下面的代码片段。

// ...setup...
// c2b url registration
$urls = $mpesa->urls();

$urls->confirmation('https://my.url/path/to/confirmation')
     ->validation('https://my.url/path/to/validation') // optional
     ->register();

if(!$urls->accepted()) {
  $error = $urls->error();
  echo "Error: $error->code - $error->message";
  // exit;
}

回调助手

当 Mpesa 将负载发送到您的确认或验证 URL 时,您需要发送格式化的确认或拒绝负载。您可以使用 SDK 的静态方法来完成此操作。请参阅以下内容。

require('path/to/vendor/autoload.php');

use LeviZwannah\MpesaSdk\Mpesa;

# confirmation.url

// your code ...
Mpesa::confirm(); // echos the formatted response
// your code...
// send SMS ... etc

#================#

# validation.url

// your code ...
if(!true) {
    Mpesa::deny();
}
else {
    Mpesa::confirm();
}

// your code ...

注意:您只能在验证处理程序中使用 Mpesa::deny()

反向 API

允许您进行 Mpesa 交易的撤销。

要求

确保这些值在设置部分中已设置。

  • 发起人名称 (initiator)
  • 安全凭证 (credential)
  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

请参阅如何使用此 SDK 的代码片段。

// ...setup...

$reversal = $mpesa->reversal();

$reversal->timeoutUrl('https://my.url/path/to/reversal/timeout')
        ->resultUrl('https://my.url/path/to/reversal/result')
        ->transId('1X1Y1ZNME') // transaction ID to reverse
        ->amount(100) // amount paid
        ->remarks('optional remarks') // optional
        ->occasion('optional occasion') // optional
        ->make();

if(!$reversal->accepted()) {
  $error = $reversal->error();
  echo "$error->code - $error->message";
  // exit;
}

// reversal initiated
$response = $reversal->response();
$originatorId = $response->OriginatorConversationID;
$conversationId = $response->ConversationID;
//...

在您的回调脚本中,请确保遵循此文档 安全部分 中的建议。

交易查询 API

交易查询 API 允许您检查发送到或从您的业务简码进行的交易的状态。

要求

确保这些值在设置部分中已设置。

  • 发起人名称 (initiator)
  • 安全凭证 (credential)
  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

用法

请参阅以下如何使用此 SDK 的代码片段。

// Transaction query
$query = $mpesa->query();

$query->transId('1X1Y1ZNME')
      ->resultUrl('https://my.url/path/to/timeout')
      ->timeoutUrl('https://my.url/path/to/result')
      ->remarks('optional remarks') // optional
      ->occasion('optional occasion') // optional
      ->make();

if(!$query->accepted()) {
  $error = $query->error();
  echo "$error->code - $error->message";
  // exit;
}

$response = $query->response();
$originatorId = $response->OriginatorConversationID;
$conversationId = $response->ConversationID;
//...

余额查询 API

余额查询 API 允许您查询业务账户中的余额。

要求

确保这些值在设置部分中已设置。

  • 发起人名称 (initiator)
  • 安全凭证 (credential)
  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

用法

请参阅代码片段

//...setup...

$balance = $mpesa->balance();

$balance->timeoutUrl('https://my.url/path/to/timeout')
        ->resultUrl('https://my.url/path/to/result')
        ->remarks('optional remarks') // optional
        ->check();

if(!$balance->accepted()){
  $error = $balance->error();
  echo "$error->code $error->message";
  // exit;
}

$response = $balance->response();
$originatorId = $response->OriginatorConversationID;
$conversationId = $response->ConversationID;
//...

B2B API

B2B API 允许您从您的业务简码向付款单或收银机号进行付款。

要求

确保这些值在设置部分中已设置。

  • 发起人名称 (initiator)
  • 安全凭证 (credential)
  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

用法

请参阅下面的代码片段

// ...setup...
$b2b = $mpesa->b2b();
$b2b->amount(100)
    ->receiver('123456') // business you are paying to
    ->resultUrl('https://my.url/path/to/result')
    ->timeoutUrl('https://my.url/path/to/timeout');

# if receiver is a paybill number
$b2b->paybill()
    ->account('account-number'); 

# if receiver is a till number
$b2b->buygoods();

# optional
$b2b->remarks('optional remarks')
    ->occasion('optional occasion')
    ->requester('0712345678'); // the customer on
                               // whose behalf the money is
                               // being paid.

# make payment
$b2b->pay();

if(!$b2b->accepted()) {
  $error = $b2b->error();
  echo "$error->code $error->message";
  // exit;
}

$response = $b2b->response();
$originatorId = $response->OriginatorConversationID;
$conversationId = $response->ConversationID;
//...

//... save to db, etc

B2C API

B2C API 允许您从您的业务简码向手机号码进行付款。

要求

确保这些值在设置部分中已设置。

  • 发起人名称 (initiator)
  • 安全凭证 (credential)
  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

用法

请参阅下面的代码片段

$b2c = $mpesa->b2c();

$b2c->amount(100)
    ->phone('0712345678')
    ->resultUrl('https://my.url/path/to/result')
    ->timeoutUrl('https://my.url/path/to/timeout');

# set payment purpose
$b2c->salary() // for salary payment
    ->promotion() // for promotion payment
    ->payment(); // for business payment

# optional
$b2c->remarks('optional-remarks')
    ->occasion('optional-occasion');

# pay
$b2c->pay();

if(!$b2c->accepted()) {
  $error = $b2c->error();
  echo "$error->code $error->message";
  // exit;
}

$response = $b2c->response();
$originatorId = $response->OriginatorConversationID;
$conversationId = $response->ConversationID;
//...

//... save to db, etc

税务汇款 API

税务汇款 API 允许您向 KRA 进行税务付款。

要求

确保这些值在设置部分中已设置。

  • 发起人名称 (initiator)
  • 安全凭证 (credential)
  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

用法

请参阅下面的代码片段

// ...setup...

$remit = $mpesa->remitTax();

$remit->amount(1000)
      ->resultUrl('https://my.url/path/to/result')
      ->timeoutUrl('https://my.url/path/to/timeout')
      ->remarks('optional-remarks') // optional
      ->pay();

if(!$remit->accepted()) {
  $error = $remit->error();
  echo "$error->code $error->message";
  // exit;
}

$response = $remit->response();
$originatorId = $response->OriginatorConversationID;
$conversationId = $response->ConversationID;
//...

//... save to db, etc

动态二维码 API

启用您为不同交易生成二维码。请参阅Daraja文档

使用此API生成动态二维码,允许拥有My Safaricom App或M-PESA应用的安全集团M-PESA客户扫描和捕获账单号码和金额,然后授权在选定的LIPA NA M-PESA (LNM)商户网点支付商品和服务。 -- Daraja

要求

确保这些值在设置部分中已设置。

  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码(code

用法

请参阅以下代码片段

//...setup...
$qr = $mpesa->qr();

$qr->size(300) // QR Code size (300x300)
   ->merchantName('Business Name')
   ->reference('account-number') // transaction reference
   ->amount(100);

# the receiver of the payment
# can be Till Number, Agent number, phone number
# paybill number, or business number
# Correspond to CPI in the Daraja doc
$qr->receiver('123457');

# sets the receiver type
# corresponds to TrxCode in the Daraja Doc
$qr->buygoods(); // receiver is a till number
$qr->paybill(); // receiver is a paybill number
$qr->sendMoney(); // receiver is a phone number
$qr->withdraw(); // receiver is an agent number
$qr->sendToBusiness(); // receiver is a business number

# generate code
$qr->generate();

if(!$qr->accepted()) {
  $error = $qr->error();
  echo "$error->code $error->message";
  // exit;
}

$response = $qr->response();
$qrCode = $response->QRCode;
$requestId = $response->RequestID;
//...

业务到批量API

此API允许您将资金从活动账户直接加载到用于B2C支付的公用事业账户。

要求

确保这些值在设置部分中已设置。

  • 发起人名称 (initiator)
  • 安全凭证 (credential)
  • 消费者密钥 (key)
  • 消费者密钥 (secret)
  • 业务简码 (code)

用法

// ...setup...
$btb = $mpesa->btb();
$btb->amount(100)
    ->receiver('123456') // short code of the receiver 
    ->resultUrl('https://my.url/path/to/result')
    ->timeoutUrl('https://my.url/path/to/timeout');

# if in the same organization use
$btb->amount(100)
    ->toSelf() // accepts an optional short code param for sub-organizations
    ->resultUrl('https://my.url/path/to/result')
    ->timeoutUrl('https://my.url/path/to/timeout');

# optional
$btb->remarks('optional remarks') // optional
    ->requester('0712345678'); // optional - the customer on
                               // whose behalf the transfer is
                               // being made.

# make the transfer
$btb->transfer();

if(!$btb->accepted()) {
  $error = $btb->error();
  echo "$error->code $error->message";
  // exit;
}

$response = $btb->response();
$originatorId = $response->OriginatorConversationID;
$conversationId = $response->ConversationID;
//...

//... save to db, etc

快速笔记

如果您对处理回调中的结果感到困惑,请参阅此README文件的早期部分。

报告错误

如果在代码中发现错误,请打开一个问题。

表达喜爱

  • 收藏此仓库
  • 如果您喜欢它,请为我买杯咖啡。