bnpl-partners/factoring004

即时购买后付款API SDK

3.2.0 2024-02-01 11:10 UTC

This package is auto-updated.

Last update: 2024-09-30 12:54:13 UTC


README

需求

  • PHP >=5.6
  • JSON扩展
  • PSR-17, PSR-18实现(可选,仅限PHP >=7.x)

版本兼容性

安装

composer require bnpl-partners/factoring004

身份验证

创建 BnplPartners\Factoring004\OAuth\OAuthTokenManager 实例。

use BnplPartners\Factoring004\OAuth\OAuthTokenManager;

$tokenManager = new OAuthTokenManager('https://dev.bnpl.kz/api/users/api/v1', 'username', 'password');

生成访问令牌

$token = $tokenManager->getAccessToken();
$accessToken = $token->getAccess();

刷新访问令牌

$newToken = $tokenManager->refreshToken($oldToken->getRefresh());

缓存访问令牌

use BnplPartners\Factoring004\OAuth\CacheOAuthTokenManager;
use BnplPartners\Factoring004\OAuth\OAuthTokenManager;

$cache = ... // PSR-16 Cache
$tokenManager = new OAuthTokenManager('https://dev.bnpl.kz/api/users/v1', 'username', 'password');
$cacheTokenManager = new CacheOAuthTokenManager($tokenManager, $cache, 'cache key');

$token = $cacheTokenManager->getAccessToken();
$accessToken = $token->getAccess();

缓存令牌刷新策略

有两种策略来刷新缓存令牌。

始终检索

这是默认行为。在这种情况下,任何过期的令牌都将刷新。如果您需要刷新令牌而不是检索,您必须调用 CacheOAuthTokenManager::refreshToken() 方法。

use BnplPartners\Factoring004\OAuth\CacheOAuthTokenManager;
use BnplPartners\Factoring004\OAuth\OAuthTokenRefreshPolicy;

$cacheTokenManager = new CacheOAuthTokenManager($tokenManager, $cache, 'cache key', OAuthTokenRefreshPolicy::ALWAYS_RETRIEVE());

$token = $cacheTokenManager->getAccessToken();
$accessToken = $token->getAccess();

始终刷新

过期的令牌始终会刷新。您不需要通过 CacheOAuthTokenManager::refreshToken() 方法手动刷新它。

use BnplPartners\Factoring004\OAuth\CacheOAuthTokenManager;
use BnplPartners\Factoring004\OAuth\OAuthTokenRefreshPolicy;

$cacheTokenManager = new CacheOAuthTokenManager($tokenManager, $cache, 'cache key', OAuthTokenRefreshPolicy::ALWAYS_REFRESH());

$token = $cacheTokenManager->getAccessToken();
$accessToken = $token->getAccess();

清除缓存令牌

如果您需要清除缓存,您将手动清除缓存。

$cacheTokenManager->clearCache();

如果您遇到身份验证错误,您将手动清除缓存。

use BnplPartners\Factoring004\Exception\AuthenticationException;
use BnplPartners\Factoring004\OAuth\CacheOAuthTokenManager;
use BnplPartners\Factoring004\Order\OrderManager;

$cacheTokenManager = new CacheOAuthTokenManager($tokenManager, $cache, 'cache key');
$orderManager = OrderManager::create('https://dev.bnpl.kz/api', new BearerTokenAuth($cacheTokenManager->getAccessToken()->getAccess()));

try {
    $orderManager->preApp(...);
} catch (AuthenticationException $e) {
    $cacheTokenManager->clearCache();
}

用法

我们建议使用类 BnplPartners\Factoring004\Order\OrderManager 调用我们的端点。

创建实例

use BnplPartners\Factoring004\Order\OrderManager;
use BnplPartners\Factoring004\Auth\BearerTokenAuth;

require_once __DIR__ . '/vendor/autoload.php';

$manager = OrderManager::create('https://dev.bnpl.kz/api', new BearerTokenAuth('Access Token'));

PreApp端点

$response = $manager->preApp([
    'partnerData' => [
        'partnerName' => 'test',
        'partnerCode' => 'test',
        'pointCode' => 'test',
    ],
    'billNumber' => '1',
    'billAmount' => 6000,
    'itemsQuantity' => 1,
    'successRedirect' => 'http://your-store.com/success',
    'postLink' => 'http://your-store.com/internal',
    'items' => [
        [
            'itemId' => '1',
            'itemName' => 'test',
            'itemQuantity' => 1,
            'itemPrice' => 6000,
            'itemSum' => 6000,
        ],
    ],
]);

var_dump($response->getRedirectLink());

交付端点

发送OTP

$response = $manager->delivery($merchantId, $orderId, $amount)->sendOtp();
var_dump($response->getMessage());

检查OTP

$response = $manager->delivery($merchantId, $orderId, $amount)->checkOtp($otp);
var_dump($response->getMessage());

无OTP

$response = $manager->delivery($merchantId, $orderId, $amount)->confirmWithoutOtp();
var_dump($response->getMessage());

完整退货端点

发送OTP

$response = $manager->fullRefund($merchantId, $orderId)->sendOtp();
var_dump($response->getMessage());

检查OTP

$response = $manager->fullRefund($merchantId, $orderId)->checkOtp($otp);
var_dump($response->getMessage());

无OTP

$response = $manager->fullRefund($merchantId, $orderId)->confirmWithoutOtp();
var_dump($response->getMessage());

部分退货端点

发送OTP

$response = $manager->partialRefund($merchantId, $orderId, $amount)->sendOtp();
var_dump($response->getMessage());

检查OTP

$response = $manager->partialRefund($merchantId, $orderId, $amount)->checkOtp($otp);
var_dump($response->getMessage());

无OTP

$response = $manager->partialRefund($merchantId, $orderId, $amount)->confirmWithoutOtp();
var_dump($response->getMessage());

取消端点

$response = $manager->cancel($merchantId, $orderId);
var_dump($response->getMessage());

错误处理

所有方法都可以抛出 BnplPartners\Factoring004\Exception\PackageException 实例。

use BnplPartners\Factoring004\Exception\PackageException;

try {
    $response = $manager->delivery($merchantId, $orderId, $amount)->sendOtp();
} catch (PackageException $e) {
    var_dump($e);
}

高级用法

这些类是低级API,在章节中描述。

创建api实例

use BnplPartners\Factoring004\Api;
use BnplPartners\Factoring004\Auth\BearerTokenAuth;

require_once __DIR__ . '/vendor/autoload.php';

$api = Api::create('https://dev.bnpl.kz/api', new BearerTokenAuth('Access Token'));

PreApp端点

创建预应用

use BnplPartners\Factoring004\PreApp\Item;
use BnplPartners\Factoring004\PreApp\PreAppMessage;
use BnplPartners\Factoring004\PreApp\PartnerData;

$message = new PreAppMessage(
    new PartnerData('test', 'test', 'test'),
    '1',
    6000,
    1,
    'http://your-store.com/success',
    'http://your-store.com/internal',
    [new Item('1', 'test', 1, 6000, 6000)],
);

// Or
$message = PreAppMessage::createFromArray([
    'partnerData' => [
        'partnerName' => 'test',
        'partnerCode' => 'test',
        'pointCode' => 'test',
    ],
    'billNumber' => '1',
    'billAmount' => 6000,
    'itemsQuantity' => 1,
    'successRedirect' => 'http://your-store.com/success',
    'postLink' => 'http://your-store.com/internal',
    'items' => [
        [
            'itemId' => '1',
            'itemName' => 'test',
            'itemQuantity' => 1,
            'itemPrice' => 6000,
            'itemSum' => 6000,
        ],
    ],
]);

//Send request and receive response
$response = $api->preApps->preApp($message);

var_dump($response->getStatus(), $response->getPreAppId(), $response->getRedirectLink());
var_dump($response->toArray(), json_encode($response));

获取预应用状态

通过预应用ID获取状态

$status = $api->preApps->getStatus($preappID)->getStatus();

通过订单ID获取状态

$status = $api->bill->getStatus($orderID)->getStatus();

交付端点

发送OTP

use BnplPartners\Factoring004\Otp\SendOtp;

$sendOtp = new SendOtp('1', '1', 6000);

// or
$sendOtp = SendOtp::createFromArray(['merchantId' => '1', 'merchantOrderId' => '1', 'amount' => 6000]);

// send request and receive response
$response = $api->otp->sendOtp($sendOtp);

var_dump($response->getMsg());
var_dump($response->toArray(), json_encode($response));

检查OTP

use BnplPartners\Factoring004\Otp\CheckOtp;

$checkOtp = new CheckOtp('1', '1', '1111', 6000);

// or
$checkOtp = CheckOtp::createFromArray(['merchantId' => '1', 'merchantOrderId' => '1', 'otp' => '1111', 'amount' => 6000]);

// send request and receive response
$response = $api->otp->checkOtp($checkOtp);

var_dump($response->getMsg());
var_dump($response->toArray(), json_encode($response));

无OTP

use BnplPartners\Factoring004\ChangeStatus\DeliveryOrder;
use BnplPartners\Factoring004\ChangeStatus\DeliveryStatus;
use BnplPartners\Factoring004\ChangeStatus\ErrorResponse;
use BnplPartners\Factoring004\ChangeStatus\MerchantsOrders;
use BnplPartners\Factoring004\ChangeStatus\SuccessResponse;

$orders = new MerchantsOrders('1', [new DeliveryOrder('1', DeliveryStatus::DELIVERY(), 6000)]);

// or
$orders = MerchantsOrders::createFromArray([
    'merchantId' => '1',
    'orders' => [
        ['orderId' => '1', 'status' => 'delivered', 'amount' => 6000],
    ],
]);

// send request and receive response
$response = $api->changeStatus->changeStatusJson($orders);

var_dump(array_map(fn(SuccessResponse $response) => $response->getMsg(), $response->getSuccessfulResponses()));
var_dump(array_map(fn(ErrorResponse $response) => $response->getMessage(), $response->getErrorResponses()));
var_dump($response->toArray(), json_encode($response));

退款端点

发送OTP退货

use BnplPartners\Factoring004\Otp\SendOtpReturn;

$sendOtpReturn = new SendOtpReturn(6000, '1', '1');

// or
$sendOtpReturn = SendOtpReturn::createFromArray(['amountAr' => 6000, 'merchantId' => '1', 'merchantOrderId' => '1']);

// send request and receive response
$response = $api->otp->sendOtpReturn($sendOtpReturn);

var_dump($response->getMsg());
var_dump($response->toArray(), json_encode($response));

检查OTP退货

use BnplPartners\Factoring004\Otp\CheckOtpReturn;

$checkOtpReturn = new CheckOtpReturn(6000, '1', '1', '1111');

// or
$checkOtpReturn = CheckOtp::createFromArray(['amountAr' => 6000, 'merchantId' => '1', 'merchantOrderId' => '1', 'otp' => '1111']);

// send request and receive response
$response = $api->otp->checkOtpReturn($checkOtpReturn);

var_dump($response->getMsg());
var_dump($response->toArray(), json_encode($response));

无OTP

use BnplPartners\Factoring004\ChangeStatus\ErrorResponse;
use BnplPartners\Factoring004\ChangeStatus\MerchantsOrders;
use BnplPartners\Factoring004\ChangeStatus\ReturnOrder;
use BnplPartners\Factoring004\ChangeStatus\ReturnStatus;
use BnplPartners\Factoring004\ChangeStatus\SuccessResponse;

$orders = new MerchantsOrders('1', [new ReturnOrder('1', ReturnStatus::RETURN(), 6000)]);

// or
$orders = MerchantsOrders::createFromArray([
    'merchantId' => '1',
    'orders' => [
        ['orderId' => '1', 'status' => 'return', 'amount' => 6000],
    ],
]);

// send request and receive response
$response = $api->changeStatus->changeStatusJson($orders);

var_dump(array_map(fn(SuccessResponse $response) => $response->getMsg(), $response->getSuccessfulResponses()));
var_dump(array_map(fn(ErrorResponse $response) => $response->getMessage(), $response->getErrorResponses()));
var_dump($response->toArray(), json_encode($response));

取消

use BnplPartners\Factoring004\ChangeStatus\ErrorResponse;
use BnplPartners\Factoring004\ChangeStatus\MerchantsOrders;
use BnplPartners\Factoring004\ChangeStatus\CancelOrder;
use BnplPartners\Factoring004\ChangeStatus\CancelStatus;
use BnplPartners\Factoring004\ChangeStatus\SuccessResponse;

$orders = new MerchantsOrders('1', [new CancelOrder('1', CancelStatus::CANCEL())]);

// or
$orders = MerchantsOrders::createFromArray([
    'merchantId' => '1',
    'orders' => [
        ['orderId' => '1', 'status' => 'canceled'],
    ],
]);

// send request and receive response
$response = $api->changeStatus->changeStatusJson($orders);

var_dump(array_map(fn(SuccessResponse $response) => $response->getMsg(), $response->getSuccessfulResponses()));
var_dump(array_map(fn(ErrorResponse $response) => $response->getMessage(), $response->getErrorResponses()));
var_dump($response->toArray(), json_encode($response));

错误处理

无论API返回什么错误,客户端都会抛出 BnplPartners\Factoring004\Exception\ApiException 实例。

use BnplPartners\Factoring004\Exception\ApiException;
use BnplPartners\Factoring004\Exception\AuthenticationException;
use BnplPartners\Factoring004\Exception\EndpointUnavailableException;
use BnplPartners\Factoring004\Exception\ErrorResponseException;
use BnplPartners\Factoring004\Exception\NetworkException;
use BnplPartners\Factoring004\Exception\PackageException;
use BnplPartners\Factoring004\Exception\TransportException;
use BnplPartners\Factoring004\Exception\UnexpectedResponseException;
use BnplPartners\Factoring004\Exception\ValidationException;

try {
    $api->preApps->preApp($message);
} catch (AuthenticationException $e) {
    // authentication errors, token invalid, token expired, etc
    var_dump($e->getCode(), $e->getMessage(), $e->getDescription());
} catch (EndpointUnavailableException $e) {
    // to catch all internal server errors 500, 503, etc
    var_dump($e->getResponse());
} catch (ErrorResponseException $e) {
    // to catch all client errors 400, 405, etc
    var_dump($e->getErrorResponse());
} catch (UnexpectedResponseException $e) {
    // to catch all responses with unexpected schema
    var_dump($e->getResponse());
} catch (ValidationException $e) {
    // endpoint validation error
    $details = $e->getResponse()->getDetails();
    var_dump($details[0]->getError(), $details[0]->getField());
} catch (ApiException $e) {
    // to catch all api layer exceptions
} catch (NetworkException $e) {
    // network issues, connection refused, etc
} catch (TransportException $e) {
    // to catch all transport layer exceptions
} catch (PackageException $e) {
    // to catch all the package exceptions
}

异常层次结构

  • PackageException
    • ApiException
      • AuthenticationException
      • ValidationException
      • ErrorResponseException
      • UnexpectedResponseException
        • EndpointUnavailableException
    • TransportException
      • NetworkException
      • DataSerializationException

定制

PSR HTTP客户端

首先安装任何PSR-17和PSR-18包。请参阅PSR-17包PSR-18包

例如,我们安装了流行的Guzzle HTTP客户端。自版本7起,它已经实现了PSR-17和PSR-18。

composer require guzzlehttp/guzzle

对于Guzzle 6,您可以使用 GuzzleTransportPsrTransport 与额外的PSR-17和PSR-18适配器。请参阅下面。

安装Guzzle 6的PSR-17和PSR-18适配器。

composer require http-interop/http-factory-guzzle mjelamanov/psr18-guzzle

传输层

传输是HTTP客户端的抽象层。

对于Guzzle 6和7

use BnplPartners\Factoring004\Transport\GuzzleTransport;

require_once __DIR__ . '/vendor/autoload.php';

$transport = new GuzzleTransport(new GuzzleHttp\Client());

对于PSR-17和PSR-18客户端。

use BnplPartners\Factoring004\Transport\PsrTransport;

require_once __DIR__ . '/vendor/autoload.php';

$transport = new PsrTransport(
    new GuzzleHttp\Psr7\HttpFactory(),
    new GuzzleHttp\Psr7\HttpFactory(),
    new GuzzleHttp\Psr7\HttpFactory(),
    new GuzzleHttp\Client(),
);

对于具有PSR-17和PSR-18适配器的Guzzle 6客户端。

use BnplPartners\Factoring004\Transport\PsrTransport;

require_once __DIR__ . '/vendor/autoload.php';

$transport = new PsrTransport(
    new Http\Factory\Guzzle\RequestFactory(),
    new Http\Factory\Guzzle\StreamFactory(),
    new Http\Factory\Guzzle\UriFactory(),
    new Mjelamanov\GuzzlePsr18\Client(new GuzzleHttp\Client()),
);

对于其他PSR-17和PSR-18客户端。

use BnplPartners\Factoring004\Transport\PsrTransport;

require_once __DIR__ . '/vendor/autoload.php';

$transport = new PsrTransport(
    new RequestFactory(), // PSR-17 instance
    new StreamFactory(), // PSR-17 instance
    new UriFactory(), // PSR-17 instance
    new Client() // PSR-18 instance
);

您可以创建自己的传输。只需实现 BnplPartners\Factoring004\Transport\TransportInterface

发送请求

$response = $transport->post('/bnpl/v3/preapp', ['partnerData' => [...]], ['Content-Type' => 'application/json']);

var_dump($response->getStatusCode()); // HTTP response status code
var_dump($response->getHeaders()); // HTTP response headers
var_dump($response->getBody()); // parsed HTTP response body

资源

每个资源是一组分组端点。

use BnplPartners\Factoring004\Auth\BearerTokenAuth;
use BnplPartners\Factoring004\Otp\OtpResource;
use BnplPartners\Factoring004\PreApp\PreAppResource;

require_once __DIR__ . '/vendor/autoload.php';

...

$preApp = new PreAppResource($transport, 'https://dev.bnpl.kz/api', new BearerTokenAuth('Access Token'));
$response = $preApp->preApp(...);

$otp = new OtpResource($transport, 'https://dev.bnpl.kz/api', new BearerTokenAuth('Access Token'));
$response = $otp->sendOtp(...);

测试

./vendor/bin/phpunit