nazan/agnopay

马尔代夫在线支付收款服务提供商的聚合器。

dev-master 2021-07-20 07:58 UTC

README

在线支付收款框架/库。此库可让您免于实现通过以下列表中任何支付提供商收集付款所需的所有步骤。

已实现的支付提供商

  • 马尔代夫银行连接
  • 奥瑞杜奥移动货币(M-Faisa)

如何设置

步骤 1

实现接口 'SurfingCrab\AgnoPay\DataModels\DataLayerInterface'。在 'SurfingCrab\AgnoPay\Reference\PdoSqliteDataLayer' 中提供了一个基于 PDO 的参考实现。请注意,名称中错误地包含 'Sqlite',这将在未来的版本中更正为 'MySql'。

步骤 2

构建主服务类 'SurfingCrab\AgnoPay\Service' 的实例。有关如何执行此操作的示例,请参阅 'tests' 目录下 'ServiceTest' 类的 'setUp()' 方法。

一旦创建了服务实例,将其存储在一个可以轻松检索的地方,例如在您选择的框架中包含的 IOC 容器中。

如何使用

基本思想是,收款过程始终是一系列必须顺序执行的步骤。每当调用主服务实例的 'proceed(...)' 方法时,它将尝试执行流程中的下一个操作或提示调用者输入更多信息。因此,有两种情况之一:它要求输入更多信息或进入下一步。因此,此库的用户必须连续调用 'proceed(...)' 方法,直到返回一个类型为 'ResultModel::TYPE_COMPLETE' 的 'ResultModel' 实例。

请注意,对于用户输入,服务类接受基于 Psr7 的 HTTP 请求实例。诚然,每次需要输入时都构建 HTTP 请求实例可能有点不自然。做出此设计决策是因为,大多数情况下,此库预期将用于某种 HTTP 层之下。这意味着,此库的用户不必手动构建 HTTP 请求实例,而是他们选择的框架将自动为他们完成这项工作。毕竟,在线支付是在网络上收集的,因此这是一个合理的假设。

收集付款的基本流程如下。

  • 创建一个新的付款请求并获取其句柄。付款请求通过类 'SurfingCrab\AgnoPay\DataModels\RequestModel' 模型化。付款请求的身份可以通过 'getAlias()' 方法获得。请注意,在此库中始终使用此别名身份传递付款请求对象。

  • 调用上述步骤 2 中构建的主服务类的 'proceed(RequestModel $newRequest, PsrRequest $input)' 方法。此调用将始终返回一个 'SurfingCrab\AgnoPay\DataModels\ResultModel' 实例,表示几种状态之一。必须重复调用此方法,直到所有步骤都完成,并返回一个类型为 'ResultModel::TYPE_COMPLETED' 的 'ResultModel' 实例。

示例使用场景

重要:前缀为双下划线 '__' 的函数/方法不存在。它们是作为伪代码来澄清过程的。

创建一个新的付款收款请求

use SurfingCrab\AgnoPay\Service as AgnoPayService;
use SurfingCrab\AgnoPay\Reference\PdoSqliteDataLayer;

// Create the main service instance.
$service = new AgnoPayService(new PdoSqliteDataLayer(new \PDO("mysql:host=example;dbname=example", 'user', 'password')));

/*
First, enable the payment service providers that you need.
From the supported ones, a subset can also be activated.
*/
$service->activateAllVendorProfiles();

// Create a new payment collection request by specifying amount and currency.
$subject = $service->create(1.99, 'MVR');

收集付款

use SurfingCrab\AgnoPay\Service as AgnoPayService;
use SurfingCrab\AgnoPay\Reference\PdoSqliteDataLayer;
use SurfingCrab\AgnoPay\DataModels\ResultModel;
use SurfingCrab\AgnoPay\Exceptions\Exception as MyException;

// Create the main service instance.
$service = new AgnoPayService(new PdoSqliteDataLayer(new \PDO("mysql:host=example;dbname=example", 'user', 'password')));

$alias = __getAliasFromUserInput();

// Retrieve the payment collection request object.
$subject = $service->get($alias);

try {
    if($userInput = __userHasProvidedInput()) {
        $result = $service->proceed($subject->getAlias(), $userInput);
    } else {
        $result = $service->proceed($subject->getAlias());
    }

    if($result->getType() === ResultModel::TYPE_FAILED) {
        /*
        The payment request will be aborted and the service will not allow further proceedings.
        Show failed message to user and stop further calls to $service->proceed(...).
        */
        return __buildResponse("Failed with: {$result->getMessage()}");
    }

    if($result->getType() == ResultModel::TYPE_FEEDBACK) {
        $feedbackMessage = $result->getMessage();

        // Return with feedback message to user.
        return __buildResponse($feedbackMessage);
    }

    if($result->getType() == ResultModel::TYPE_INPUT_COLLECTOR) {
        $inputForm = __makeInputForm($result->getInputModel());
        
        // Return with form for user input collection.
        return __buildResponse($inputForm);
    }

    if($result->getType() == ResultModel::TYPE_INPUT_COLLECTOR_REDIRECT) {
        $inputFormOrRedirectTargetLink = __makeRedirectFormOrLink($result->getInputModel());
        
        // Redirect user or return with post form with external URI.
        return __buildResponse($inputFormOrRedirectTargetLink);
    }
} catch(MyException $excp) {
    /*
    This indicates an error condition and must never happen.
    This error must be logged and end-user must be notified about it.
    */
    return __buildResponse("Failed with: {$excp->getMessage()}");
}

// Show success message to user and end.
return __buildResponse("Success");

为了更好地理解,请参阅 'tests' 目录下 'ServiceTest' 类中的以下测试用例。

  • testBmlProceed()
  • testOoredooProceed()

参与其中

此项目的 Docker 开发环境提供在以下 Github 仓库中。

Docker 开发环境