Skip to content

poweringsrl/cakephp-soldo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Soldo plugin for CakePHP

License Last commit Last release

Installation

You can install this plugin into your CakePHP application using composer:

$ composer require nedgen/cakephp-soldo

Load the plugin

Launch the following command:

$ bin/cake plugin load Soldo -b

You should see this in src/Application.php:

class Application extends BaseApplication
{
    public function bootstrap()
    {
        $this->addPlugin('Soldo', ['bootstrap' => true]);

        // ...
    }

    // ...
}

Configure the datasource

Add the following to the Datasources item in the config/app.php file:

return [
    // ...
    'Datasources' => [
        // ...
        'soldo' => [
            'className' => \Muffin\Webservice\Connection::class,
            'service' => \Soldo\Webservice\Driver\Soldo::class,
            'client_id' => '', // Replace with the actual value
            'client_secret' => '', // Replace with the actual value
            'token' => '', // Replace with the actual value
            'private_key' => '', // Replace with the RSA private key you shared with Soldo, encoded in Base64
            'environment' => '', // One of "production" or "demo"
            'autologin' => true, // Whether to try to authenticate as soon as the plugin is initialized, or wait until needed
        ],
    ],
];

The token and private_key items are optional, but they are both needed if you need to make requests where the advanced authentication is required.

Examples:

return [
    // ...
    'Datasources' => [
        // ...
        'soldo' => [
            'className' => \Muffin\Webservice\Connection::class,
            'service' => \Soldo\Webservice\Driver\Soldo::class,
            'client_id' => 'sHR2rMC7yVAxWxkgRPg0LEIHpCXmpj1s',
            'client_secret' => 'LTVBbG2EnUB1mc30ep3pTgheyCh5WK8O',
            'environment' => 'demo',
            'autologin' => true,
        ],
    ],
];
return [
    // ...
    'Datasources' => [
        // ...
        'soldo' => [
            'className' => \Muffin\Webservice\Connection::class,
            'service' => \Soldo\Webservice\Driver\Soldo::class,
            'client_id' => 'NF1gtE1dhuwR6Yk5bDcUsdGXtnSgTaGW',
            'client_secret' => 'g50Xc5TOzMqa2jdBa3dNZ8H7ysKd9mYl',
            'token' => 'VK6AEW2IAF3SR29SJW4L',
            'private_key' => 'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpjYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkCm9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2wKZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zbwpsZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zCm9sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC0Kc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocAotc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBoCnAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXAKaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZQpwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrCmVwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2EKa2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvYwpha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvCmNha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGQKb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbApkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvCmxkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXMKb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLQpzb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwCi1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGgKcC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcApocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlCnBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWsKZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYQprZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaAotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ==',
            'environment' => 'production',
            'autologin' => false,
        ],
    ],
];

Usage

The following Soldo resources are currently supported:

Note: For all the resources listed above, only read queries are currently supported, except for internal transfers.

Reading

The following code shows an example for the Card resource:

namespace App\Controller;

/**
 * ...
 *
 * @property \Soldo\Model\Endpoint\CardsEndpoint $Cards
 */
class CardsController extends AppController
{
    public function initialize()
    {
        $this->loadModel('Soldo/Soldo.Cards', 'Endpoint');
    }

    public function index()
    {
        $cards = $this->Cards->find()
            ->select([
                'id',
                'number' => 'masked_pan',
                'custom_field' => 'foo',
            ])
            ->where([
                // GET parameters as expected from Soldo for this resource
                'type' => 'wallet',
                'customreferenceId' => '1368e647-842b-4d17-9a1a-2ad225e6dc1a',
            ])
            ->order(['name' => 'DESC'])
            ->limit(10)
            ->toArray();

        $card = $this->Cards->get('ef12ee12-5cfa-4175-b7e6-665d112aea0e', [
            'conditions' => [
                // GET parameters as expected from Soldo for this resource
                'showSensitiveData' => 'true',
            ]
        ]);
    }
}

$cards will look like this:

array (size=10)
  0 =>
    object(Muffin\Webservice\Model\Resource)[2554]
      public 'id' => string 'df832760-e49b-4699-b34a-46824060bf40' (length=36)
      public 'number' => string '098765******4321' (length=16)
      public 'custom_field' => string 'foo' (length=3)
  1 =>
    object(Muffin\Webservice\Model\Resource)[3094]
      public 'id' => string 'a438c8d6-1d94-4ed3-8895-d4565246f647' (length=36)
      public 'number' => string '123456******7890' (length=16)
      public 'custom_field' => string 'foo' (length=3)
  ...

$card will look like this:

object(Muffin\Webservice\Model\Resource)[2555]
  public 'id' => string 'ef12ee12-5cfa-4175-b7e6-665d112aea0e' (length=36)
  public 'name' => string 'Bar' (length=12)
  public 'masked_pan' => string '012345******6789' (length=16)
  public 'expiration_date' => string '2025-12-31T23:59:59Z' (length=20)
  public 'creation_time' => string '2022-12-10T19:11:18Z' (length=20)
  public 'last_update' => string '2023-04-11T08:07:38Z' (length=20)
  public 'type' => string 'PLASTIC' (length=7)
  public 'status' => string 'Normal' (length=6)
  public 'owner_type' => string 'company' (length=7)
  public 'wallet_id' => string 'a73b9699-9436-4381-951d-a9da2fd6d439' (length=36)
  public 'currency_code' => string 'EUR' (length=3)
  public 'emboss_line4' => string 'Baz' (length=13)
  public 'active' => boolean true
  public 'method3ds' => string 'USER' (length=4)
  public 'sensitive_data' =>
    array (size=3)
      'encrypted_full_pan' => string 'MDEyMzQ1MDAwMDAwNjc4OWNha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHA=' (length=344)
      'encrypted_cvv' => string 'MTIzY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHA=' (length=344)
      'encrypted_pin' => string 'MTIzNGNha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGhwLXNvbGRvY2FrZXBocC1zb2xkb2Nha2VwaHAtc29sZG9jYWtlcGg=' (length=344)
  public 'assignees' =>
    array (size=0)
      empty

Internal transfers

The only non-reading request currently supported by this plugin are internal transfers.

The following code shows an example on how to make one:

namespace App\Controller;

/**
 * ...
 *
 * @property \Soldo\Model\Endpoint\TransfersEndpoint $Transfers
 */
class WalletsController extends AppController
{
    public function initialize()
    {
        $this->loadModel('Soldo/Soldo.Transfers', 'Endpoint');
    }

    public function add()
    {
        $transfer = $this->Transfers->newEntity([
            'fromWalletId' => '288ae0a2-4d53-4d3f-b8f9-63cbe3b06429',
            'toWalletId' => '655192d7-80eb-4018-a9d3-2b9843aa4a64',
            'amount' => 10,
            'currencyCode' => 'EUR'
        ]);

        $result = $this->Transfers->save($transfer);
    }
}

$result will look like this:

object(Muffin\Webservice\Model\Resource)[1319]
  public 'amount' => int 10
  public 'currency' => string 'EUR' (length=3)
  public 'datetime' => string '2024-03-01T07:36:29.509Z' (length=24)
  public 'from_wallet' =>
    array (size=7)
      'id' => string '288ae0a2-4d53-4d3f-b8f9-63cbe3b06429' (length=36)
      'name' => string 'Foo' (length=3)
      'currency_code' => string 'EUR' (length=3)
      'available_amount' => float 90
      'blocked_amount' => float 0
      'primary_user_type' => string 'main' (length=4)
      'visible' => boolean true
  public 'to_wallet' =>
    array (size=8)
      'id' => string '655192d7-80eb-4018-a9d3-2b9843aa4a64' (length=36)
      'name' => string 'Bar' (length=3)
      'currency_code' => string 'EUR' (length=3)
      'available_amount' => float 10
      'blocked_amount' => float 0
      'primary_user_type' => string 'employee' (length=8)
      'primary_user_public_id' => string 'ABCD1234-000000' (length=15)
      'visible' => boolean true

Decrypting encrypted data

There are cases in which the data returned by Soldo is encrypted. In case you need to decrypt them, this plugin has a specific static function that allows you to do so.

Below is an example:

namespace App\Controller;

use Soldo\Utility\Fingerprint;

/**
 * ...
 *
 * @property \Soldo\Model\Endpoint\CardsEndpoint $Cards
 */
class CardsController extends AppController
{
    public function initialize()
    {
        $this->loadModel('Soldo/Soldo.Cards', 'Endpoint');
    }

    public function index()
    {
        $card = $this->Cards->get('ef12ee12-5cfa-4175-b7e6-665d112aea0e', [
            'conditions' => [
                'showSensitiveData' => 'true',
            ]
        ]);

        $decrypted_full_pan = Fingerprint::decrypt($card->sensitive_data['encrypted_full_pan']);
    }
}

$decrypted_full_pan will look like this:

'0123450000006789' (length=16)