linlak/laravel-momo-sdk

这是一个简单的PHP库,旨在帮助Laravel开发者轻松地将MTN Momo API集成到他们的Laravel项目中。

v1.0.1 2020-06-24 10:58 UTC

This package is auto-updated.

Last update: 2024-09-17 15:51:40 UTC


README

这个Laravel库被设计成让 Laravel开发者 轻松地将MTN开放API集成到他们的系统中。

先决条件

在继续之前,我们假设您已经具备了以下条件。

  • 安装了XAMPP或LAMPP,并使用最新的PHP版本,即PHP >= 7.1
  • 使用Composer包安装所需的PHP包。
  • 我们还建议安装Redis或Memchached驱动程序来存储缓存和运行队列
  • 您必须在MTN开发者门户上有一个账户,并订阅API产品。
  • 我们还假设您已经有一个正在运行的Laravel应用程序或项目。

安装

安装此 laravel-momo-sdk 非常简单。只需在终端或cmd中运行以下命令即可。

composer require linlak/laravel-momo-sdk

配置

对于支持自动发现的Laravel版本,您可以跳过此步骤,而对于5.5之前的版本,请将以下代码添加到您的 config/app.php 中的 proveders 数组

'providers' => [
	/*
	*......add this code at the end of the providers array
	*/
	LaMomo\Providers\MomoProvider::class,
],

仍然在同一文件中,定位到 aliases 数组

'aliases'=>[
	//appended at the end of aliases array
	'Remittances' => LaMomo\Facades\Remittances::class,
    'RequestToPay' => LaMomo\Facades\RequestToPay::class,
    'Disbursements' => LaMomo\Facades\Disbursements::class,
],

现在我们已经设置了所需的文件并注册了我们的Provider。

此步骤应由所有用户执行。在您的终端或cmd中运行以下Artisan命令

php artisan vendor:publish --provider=LaMomo\\Providers\\MomoProvider

上面的命令将在配置目录中发布 momosdk.php

环境变量 (.env)

.env 文件中为每个API产品添加以下代码

MOMO_BASE=https://sandbox.momodeveloper.mtn.com/
MOMO_API_VERSION=v1_0
MOMO_ENVIRONMENT=sandbox
DISABLE_TAGS=false

MOMO_HOST=example.com

收款产品

COLLECTIONS_PRIMARY=your collections primary key
COLLECTIONS_SECONDARY=your collections secondary key
COLLECTIONS_API_USER=uuid for apiuser
COLLECTIONS_API_KEY=api key here
COLLECTIONS_CALLBACK_URL=your collections callback url "optional"

支付产品

REMITTANCES_PRIMARY=
REMITTANCES_SECONDARY=
REMITTANCES_API_USER=
REMITTANCES_API_KEY=
REMITTANCES_CALLBACK_URL=

汇款产品

DISBURSEMENTS_PRIMARY=
DISBURSEMENTS_SECONDARY=
DISBURSEMENTS_API_USER=
DISBURSEMENTS_API_KEY=
DISBURSEMENTS_CALLBACK_URL=

如果上面的所有代码片段都捆绑在一起,则 .env 文件必须在末尾附加以下代码。

MOMO_BASE=https://sandbox.momodeveloper.mtn.com/
MOMO_API_VERSION=v1_0
MOMO_ENVIRONMENT=sandbox
DISABLE_TAGS=false
MOMO_HOST=example.com
COLLECTIONS_PRIMARY=
COLLECTIONS_SECONDARY=
COLLECTIONS_API_USER=
COLLECTIONS_API_KEY=
COLLECTIONS_CALLBACK_URL=
REMITTANCES_PRIMARY=
REMITTANCES_SECONDARY=
REMITTANCES_API_USER=
REMITTANCES_API_KEY=
REMITTANCES_CALLBACK_URL=
DISBURSEMENTS_PRIMARY=
DISBURSEMENTS_SECONDARY=
DISBURSEMENTS_API_USER=
DISBURSEMENTS_API_KEY=
DISBURSEMENTS_CALLBACK_URL=

定义

MOMO_BASE: 这是钱包系统的base_uri。我们设计了这个库以适应API的变化。在找到沙箱和实时端点之间的差异后,这个环境变量将帮助您设置正确的端点,例如,对于收款请求的支付,链接是

https://sandbox.momodeveloper.mtn.com/collection/v1_0/requesttopay

在上面的链接中,您会发现我们正在向 https://sandbox.momodeveloper.mtn.com/ 端点发送请求。

MOMO_API_VERSION: 这很直观。这是API端点的版本。默认情况下,其值为 v1_0

MOMO_ENVIRONMENT: 这可以是沙箱或实时

DISABLE_TAGS: 这个库是基于缓存的。Laravel已经使缓存变得尽可能简单。像Redis和Memcached这样的缓存驱动程序支持组件标签,但对于像文件和数据库这样的驱动程序则不支持标签。如果您使用文件或数据库作为默认的缓存驱动程序,请将环境变量设置为 true

DISABLE_TAGS=true

MOMO_HOST: 这是文档中所述的回调主机

COLLECTIONS__PRIMARY: 这是收款产品的primary_key,可以在您的开发者门户个人资料中找到。其他产品以其相应的产品名作为前缀

例如

REMITTANCES_PRIMARY

DISBURSEMENTS_PRIMARY

COLLECTIONS_SECONDARY: 这是收款产品的secondary_key,可以在您的开发者门户个人资料中找到。其他产品以其相应的产品名作为前缀

例如

REMITTANCES_SECONDARY

DISBURSEMENTS_SECONDARY

COLLECTIONS_API_USER: 这是收款产品的apiUser。

COLLECTIONS_API_KEY: 这是收款产品的apiKey。

COLLECTIONS_CALLBACK_URL: 这是集合产品的默认回调URL。这是可选的。

函数定义

集合

  • createApiUser() //仅限沙盒
  • getApiUser() //仅限沙盒
  • getApikey() //仅限沙盒
  • acountHolder($accountHolderIdType, $accountHolderId)
  • requestToPay(DataModel $dataModel, $callback_url)
  • requestToPayStatus($referenceId)

汇款

  • createApiUser() //仅限沙盒
  • getApiUser() //仅限沙盒
  • getApikey() //仅限沙盒
  • acountHolder($accountHolderIdType, $accountHolderId)
  • transferFunds(DataModel $dataModel, $callback_url)
  • transferStatus($referenceId)

支付

  • createApiUser() //仅限沙盒
  • getApiUser() //仅限沙盒
  • getApikey() //仅限沙盒
  • acountHolder($accountHolderIdType, $accountHolderId)
  • transferFunds(DataModel $dataModel, $callback_url)
  • transferStatus($referenceId)

示例

我们将考虑一家销售不同产品的电子商务商店。

产品具有以下属性

  • pdt_name
  • price
  • pdt_no

订单模型

让我们首先创建我们的控制器和模型

这些第一步是为沙盒用户准备的。

完成每一步后,请记住清除配置缓存,以便更改生效。运行

php artisan conf:cache

创建apiUser (集合)

<?php
use LaMomo\Facades\Collections;
Route::get('/collection-create-api-user', function () {
$result=Collections::createApiUser();
	    if($result->isCreated()){
echo 'apiUser:- '.$result->getUid();
	    }else{
	    	echo 'apiUser not created <br>';
	    	echo 'Reason: '.$result->getPhrase();
}
});

创建apiUser (汇款)

<?php
use LaMomo\Facades\Remittances;
Route::get('/remittances-create-api-user', function () {
$result=Remittances::createApiUser();
	    if($result->isCreated()){
echo 'apiUser:- '.$result->getUid();
	    }else{
	    	echo 'apiUser not created <br>';
	    	echo 'Reason: '.$result->getPhrase();
}
});

创建apiUser (支付)

<?php
use LaMomo\Facades\Disbursements;
Route::get('/disbursements-create-api-user', function () {
$result=Disbursements::createApiUser();
	    if($result->isCreated()){
echo 'apiUser:- '.$result->getUid();
	    }else{
	    	echo 'apiUser not created <br>';
	    	echo 'Reason: '.$result->getPhrase();
}
});

注意

apiUser函数返回ApiUserResponse。这有以下功能映射。

这些适用于所有Api产品。

  • isCreated()
  • getUid()

创建apiKey (集合)

<?php
use LaMomo\Facades\Collections;
Route::get('/collection-get-api-key', function () {
$result=Collections::getApikey();
	    if($result->isCreated()){
echo 'apiKey- '.$result->getApiKey();
	    }else{
	    	echo 'apiKey not created <br>';
	    	echo 'Reason: '.$result->getPhrase();
}
});

创建apiKey (汇款)

<?php
use LaMomo\Facades\Remittances;
Route::get('/remittances-get-api-key', function () {
$result=Remittances::getApikey();
	    if($result->isCreated()){
echo 'apiKey:- '.$result->getApiKey();
	    }else{
	    	echo 'apiKey not created <br>';
	    	echo 'Reason: '.$result->getPhrase();
}
});

创建apiKey (支付)

<?php
use LaMomo\Facades\Disbursements;
Route::get('/disbursements-get-api-key', function () {
$result=Disbursements::getApikey();
	    if($result->isCreated()){
echo 'apiKey:- '.$result->getApiKey();
	    }else{
	    	echo 'apiKey not created <br>';
	    	echo 'Reason: '.$result->getPhrase();
}
});

getApikey函数返回ApiKeyResponse。这有以下功能映射。(适用于所有api产品)

  • isCreated()
  • getApiKey()

您应将apiUser和apiKey复制到`.env文件中。阅读配置以了解如何操作。

注意

accessToken将在缓存存储中没有令牌的情况下自动创建。

对于剩余的步骤,我们将使用集合外观,因为函数命名一致,因此当您为其他产品发出请求时,请将集合外观替换为汇款或支付外观。

请求余额(集合)

<?php

	use LaMomo\Facades\Collections;

	Route::get('/collection-get-balance', 'Collectionsontroller@checkBalance');

在我们的控制器中,我们有以下代码

<?php

	public function checkBalance()
	{
		$result = Collections::requestBalance();
		        if ($result->isFound()) {
				echo 'Available balance- ' . $result->getAvailableBalance();
		        } else {
		            echo 'Error fetching balance. <br>';
		            echo 'Reason: ' . $result->getPhrase();
		}
}

checkBalance函数用于检查所有产品的账户余额,即集合、汇款、支付。此函数返回一个LaMomo\Support\Responses\BalanceResponse

BalanceResponse的功能映射

  • isFound()
  • getAvailableBalance()
  • getCurrency()

账户持有人(集合)

<?php

	use LaMomo\Facades\Collections;

	Route::get('/collection-get-account-holder', 'CollectionsController@accountHolder');

在我们的控制器中,我们有以下代码

<?php
	/**
	*
	*@param \Illuminate\Http\Request $request
	*/
	public function accountHolder(Request $request){
		$accountHolderIdType = "";
	        $accountHolderId = "";

	        $result = Collections::acountHolder($accountHolderIdType, $accountHolderId);

	        //let just see the response still working on this

	        dump($result);
	}

acountHolder函数返回AccountHolderResponse,这仍然悬而未决,因为此库已在沙盒环境中进行了测试。但会更新,请保留此文档以供更新和修复错误。

RequestToPay (集合)我们假设您有一个发票模型

<?php

	Route::get('/collection-request-to-pay/{id}', 'CollectionsController@requestToPay');

在我们的控制器中,我们有以下代码

<?php

	use App\Invoice;
	use LaMomo\Models\DataModel;

	public function requestToPay(Request $request, $id)
	    {
	        $callback_url = "";

	        $invoice = Invoice::find($id);

	        $dataModel = new DataModel($invoice->id,  $invoice->total,  $invoice->payment->partyId,  $invoice->payment->partyIdType, 'Pay invoice no. ' . $invoice->invoice_number, 'Invoice payment');

	        $result = Collections::requestToPay($dataModel, $callback_url);

	        if ($result->isAccepted()) {

	            echo 'refrenceId: ' . $result->getReferenceId();
	        } else if ($result->isDuplicate()) {

	            echo 'Status: ' . $result->getCode() . '<br>';

	            echo 'Status: ' . $result->getPhrase();
	        }
	    }

requestToPay函数返回一个RequestToPayResponse,其功能映射如下:-

  • isAccepted()
  • isDuplicate()
  • getReferenceId()
  • getRequestBody()

referenceId是为其生成的,您可以通过调用结果中的函数getReferenceId()来获取它。

WebHooks

我们已为您创建了特质,您可以在控制器中包含回调_url路由。

注意

不要将这些特质放在同一个控制器中,否则您将遇到错误,因为它们具有相同的命名约定。

不要使用CollectionsWebHookTrait为不同产品注册回调路由,否则您将不会得到期望的结果。这些特质已被命名,以便易于识别其所代表的产品。

  • CollectionsWebHookTrait
  • DisbursementsWebHookTrait
  • RemittancesWebHookTrait

所有特质的函数表示(命名相同,功能不同)

  • extractCallbackData(Request $request)
  • momoConfirmed(RequestStatus $result)
  • momoNotConfirmed(RequestStatus $result)

extractCallbackData此函数将Illuminate\Http\Request作为其参数。我们不建议更改此函数的代码,除非您知道自己在做什么。

此函数所做的所有事情只是从请求中获取referenceId并检查钱包系统中的requestToPayStatus或transferStatus。此函数的目的是验证请求是否来自钱包系统。

momoConfirmed: 当资源在钱包系统中找到时,此函数由 extractCallbackData 调用。请在此函数中放置您的验证和激活逻辑。

注意:不要执行 requestToPayStatus 或 transferStatus 请求,因为我们已经在 extractCallbackData 函数中执行过这些操作。

momoConfirmed: 如果资源在钱包系统中未找到,此函数由 extractCallbackData 调用。

推荐

我们建议您始终使用 extractCallbackData 来处理所有回调路由。

您必须执行的操作

  • 为每个回调路由(callback_url)创建一个控制器。
  • 使用 WebHook 特性来处理各自产品的回调_url。例如:对于 collections 产品回调_url,您必须使用 CollectionsWebHookTrait;对于汇款和支付,分别使用 RemittancesWebHookTraitDisbursementsWebHookTrait

注册 WebHook(Collections)

我们假设您的项目有一个名为 CollectionsController 的控制器。

我们的路由将类似于 Route::post('{collections_collback_url}','CollectionsController@extractCallbackData');在我们的 CollectionsController 中将包含以下代码

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use LaMomo\Support\Responses\RequestStatus;
use LaMomo\Support\Traits\CollectionsWebHookTrait;

class CollectionsController extends Controller{
	use CollectionsWebHookTrait;

	protected function momoConfirmed(RequestStatus $result)
	{
		//check if payment is SUCCESSFUL, PENDING or FAILED
	}

	protected function momoNotConfirmed(RequestStatus $result)
	{
		//action to perform
	}
}

注册 WebHook(Remittances)

我们假设您的项目有一个名为 RemittancesController 的控制器。

我们的路由将类似于 Route::post('{remittances_collback_url}','RemittancesController@extractCallbackData');在我们的 RemittancesController 中将包含以下代码

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use LaMomo\Support\Responses\RequestStatus;
use LaMomo\Support\Traits\RemittancesWebHookTrait;

class RemittancesController extends Controller{
	use RemittancesWebHookTrait;

	protected function momoConfirmed(RequestStatus $result)
	{
		//check if payment is SUCCESSFUL, PENDING or FAILED
	}

	protected function momoNotConfirmed(RequestStatus $result)
	{
		//action to perform
	}
}

注册 WebHook(Disbursements)

我们假设您的项目有一个名为 DisbursementsController 的控制器。

我们的路由将类似于 Route::post('{disbursements_collback_url}','DisbursementsController@extractCallbackData');在我们的 DisbursementsController 中将包含以下代码

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use LaMomo\Support\Responses\RequestStatus;
use LaMomo\Support\Traits\DisbursementsWebHookTrait;

class DisbursementsController extends Controller{
	use DisbursementsWebHookTrait;

	protected function momoConfirmed(RequestStatus $result)
	{
		//check if payment is SUCCESSFUL, PENDING or FAILED
	}

	protected function momoNotConfirmed(RequestStatus $result)
	{
		//action to perform
	}
}

RequestStatus 函数映射

  • getReferenceId()//字符串 (uuid)
  • getStatus()//字符串 (SUCCESSFUL, PENDING, FAILED)
  • getReason()//字符串
  • getFinancialTransId() //字符串
  • isSuccess()//布尔值
  • isPending()//布尔值
  • isFailed()//布尔值
  • isRejected()//布尔值
  • isTimeOut()//布尔值
  • resourceExists()//布尔值