luyadev/luya-module-payment

View on GitHub
src/integrators/HeadlessIntegrator.php

Summary

Maintainability
A
0 mins
Test Coverage
F
48%
<?php

namespace luya\payment\integrators;

use luya\headless\Client;
use luya\payment\base\IntegratorInterface;
use luya\payment\base\PayModel;
use luya\payment\integrators\headless\ApiPaymentProcess;
use luya\payment\integrators\headless\ApiPaymentProcessTrace;
use luya\payment\Pay;
use luya\payment\PaymentException;
use yii\base\BaseObject;

/**
 * Headless Payment:
 *
 * You can either pass a callable with returns an headless client object or provide the accesstoken and server url.
 *
 * @author Basil Suter <basil@nadar.io>
 * @since 1.0.0
 */
class HeadlessIntegrator extends BaseObject implements IntegratorInterface
{
    public $accessToken;

    public $serverUrl;

    private $_client;

    public function setClient($client)
    {
        if (is_callable($client)) {
            $client = call_user_func($client);
        }

        if (!$client instanceof Client) {
            throw new PaymentException("The given client must be an instance of luya\headless\Client");
        }

        $this->_client = $client;
    }

    public function getClient()
    {
        if ($this->_client === null) {
            $this->_client = new Client($this->accessToken, $this->serverUrl);
        }

        return $this->_client;
    }

    /**
     * {@inheritDoc}
     */
    public function createModel(PayModel $model)
    {
        $api = new ApiPaymentProcess();
        $api->amount = $model->totalAmount;
        $api->currency = $model->currency;
        $api->order_id = $model->orderId;
        $api->success_link = $model->successLink;
        $api->error_link = $model->errorLink;
        $api->abort_link = $model->abortLink;
        $api->close_state = Pay::STATE_PENDING;
        $api->is_closed = $model->isClosed;
        $api->provider_data = $model->providerData;
        $api->loadItems($model->items);
        if ($api->save($this->getClient())) {
            $model->setId($api->id);
            $model->setAuthToken($api->auth_token);
            $model->setRandomKey($api->random_key);
            return $model;
        }

        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function findByKey($key, $token)
    {
        $api = ApiPaymentProcess::findByKey($key, $token, $this->getClient());

        if (!$api) {
            return false;
        }

        $model = self::createPayModel($api);
        $model->setAuthToken($token);
        return $model;
    }

    /**
     * {@inheritDoc}
     */
    public function findById($id)
    {
        $api = ApiPaymentProcess::viewOne($id, $this->getClient());

        if (!$api) {
            return false;
        }

        return self::createPayModel($api);
    }

    /**
     * {@inheritDoc}
     */
    public function closeModel(PayModel $model, $state)
    {
        $api = ApiPaymentProcess::viewOne($model->getId(), $this->getClient());

        if (!$api || $api->is_closed) {
            return false;
        }

        $api->is_closed = 1;
        $api->close_state = $state;
        if ($api->save($this->getClient(), ['is_closed', 'close_state'])) {
            return true;
        }

        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function addTrace(PayModel $model, $event, $message = null)
    {
        $trace = new ApiPaymentProcessTrace();
        $trace->process_id = $model->getId();
        $trace->event = $event;
        $trace->message = $message;
        return $trace->save($this->getClient());
    }

    /**
     * {@inheritDoc}
     */
    public function saveProviderData(PayModel $model, array $data)
    {
        return ApiPaymentProcess::put()
            ->setEndpoint('{endpointName}/{id}')
            ->setTokens(['id' => $model->id])
            ->setArgs(['provider_data' => $data])
            ->response($this->getClient())
            ->isSuccess();
    }

    /**
     * {@inheritDoc}
     */
    public function getProviderData(PayModel $model): array
    {
        $model = ApiPaymentProcess::view($model->id)
            ->setFields(['id', 'provider_data'])
            ->one($this->getClient());

        if (!$model) {
            throw new PaymentException("Unable to find the given payment model.");
        }

        return $model->provider_data;
    }

    // internal

    private static function createPayModel(ApiPaymentProcess $process)
    {
        $model = new PayModel();
        $model->orderId = $process->order_id;
        $model->totalAmount = $process->amount;
        $model->currency = $process->currency;
        $model->randomKey = $process->random_key;
        $model->id = $process->id;
        $model->errorLink = $process->error_link;
        $model->successLink = $process->success_link;
        $model->abortLink = $process->abort_link;
        $model->providerData = $process->provider_data;

        // assign items from origin process model
        foreach ($process->items as $item) {
            $model->addItem($item['name'], $item['qty'], $item['amount'], $item['total_amount'], $item['is_tax'], $item['is_shipping']);
        }

        $model->closeState = $process->close_state;
        $model->isClosed = $process->is_closed;
        if ($model->validate()) {
            return $model;
        }

        return false;
    }
}