PHPackages                             mirrorps/yii2-taler - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. mirrorps/yii2-taler

ActiveYii2-extension[API Development](/categories/api)

mirrorps/yii2-taler
===================

Yii2 extension for GNU Taler REST API integration

v1.2.1(1mo ago)01↓100%MITPHPPHP &gt;=8.1CI passing

Since May 4Pushed 1mo agoCompare

[ Source](https://github.com/mirrorps/yii2-taler)[ Packagist](https://packagist.org/packages/mirrorps/yii2-taler)[ RSS](/packages/mirrorps-yii2-taler/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (6)Versions (2)Used By (0)

yii2-taler
==========

[](#yii2-taler)

Yii2 extension for GNU Taler REST API integration.

Installation
------------

[](#installation)

```
composer require mirrorps/yii2-taler
```

Configuration
-------------

[](#configuration)

Add the Taler component to your application configuration:

```
'components' => [
    'taler' => [
        'class'   => \mirrorps\Yii2Taler\Taler::class,
        'baseUrl' => 'https://backend.demo.taler.net/instances/sandbox',
        'token'   => 'Bearer secret-token:sandbox',
        // OR credential-based auth:
        // 'username' => 'merchant',
        // 'password' => 'secret',
        // 'instance' => 'sandbox',
    ],
],
```

Logging
-------

[](#logging)

`yii2-taler` integrates with Yii's logging subsystem by default. The component passes a PSR-3 logger adapter to `taler-php`, so request failures, protocol warnings, and optional debug request/response logs are written through Yii log targets.

Configure logging at the application config level:

```
'components' => [
    'taler' => [
        'class'               => \mirrorps\Yii2Taler\Taler::class,
        'baseUrl'             => 'https://backend.demo.taler.net/instances/sandbox',
        'token'               => 'Bearer secret-token:sandbox',
        'loggerCategory'      => 'taler',
        'debugLoggingEnabled' => YII_DEBUG,
    ],
],
```

The `loggerCategory` defaults to `yii2-taler`. Route it like any other Yii log category:

```
'components' => [
    'log' => [
        'targets' => [
            [
                'class'      => \yii\log\FileTarget::class,
                'categories' => ['taler', 'yii2-taler'],
                'levels'     => ['error', 'warning', 'info', 'trace'],
            ],
        ],
    ],
],
```

For advanced use cases, provide any PSR-3 logger instance or Yii object definition via `logger`. Set `logger` to `false` to disable logging for the underlying Taler client:

```
'taler' => [
    'class'  => \mirrorps\Yii2Taler\Taler::class,
    'baseUrl' => 'https://backend.demo.taler.net/instances/sandbox',
    'token'  => 'Bearer secret-token:sandbox',
    'logger' => [
        'class'    => \mirrorps\Yii2Taler\Log\YiiLogger::class,
        'category' => 'payments.taler',
    ],
],
```

Runtime changes are supported before the underlying client is created:

```
Yii::$app->taler->loggerCategory = 'payments.taler';
Yii::$app->taler->debugLoggingEnabled = true;

$client = Yii::$app->taler->getClient();
```

After `getClient()` or an API service method has been called, the underlying client is memoized; change logging configuration in application config for long-lived components.

Config API
----------

[](#config-api)

The Config API is accessible via `Yii::$app->taler->configs()`.

### Get Merchant Config

[](#get-merchant-config)

```
use Taler\Api\Config\Dto\MerchantVersionResponse;

$config = Yii::$app->taler->configs()->getConfig();

if ($config instanceof MerchantVersionResponse) {
    echo $config->name . PHP_EOL;      // taler-merchant
    echo $config->version . PHP_EOL;   // libtool format current:revision:age
    echo $config->currency . PHP_EOL;  // default currency

    foreach ($config->currencies as $code => $spec) {
        echo $code . ' => ' . $spec->name . PHP_EOL;
    }

    foreach ($config->exchanges as $exchange) {
        echo $exchange->base_url . PHP_EOL;
    }
}
```

### Async Config Call

[](#async-config-call)

```
$promise = Yii::$app->taler->configs()->getConfigAsync();
$config = $promise->wait();
```

### Credential Health Check

[](#credential-health-check)

```
$report = Yii::$app->taler->configCheck();

if ($report['ok']) {
    echo "All checks passed" . PHP_EOL;
} else {
    print_r($report);
}
```

Order API
---------

[](#order-api)

The Order API is accessible via `Yii::$app->taler->orders()`.

### List Orders

[](#list-orders)

```
use Taler\Api\Order\Dto\GetOrdersRequest;

// List all orders (default limit)
$orderHistory = Yii::$app->taler->orders()->getOrders();

foreach ($orderHistory->orders as $entry) {
    echo $entry->order_id . ' — ' . $entry->summary . ' — ' . $entry->amount . PHP_EOL;
}

// With filters
$orderHistory = Yii::$app->taler->orders()->getOrders(
    new GetOrdersRequest(paid: true, limit: 10)
);
```

### Get Order Details

[](#get-order-details)

```
use Taler\Api\Order\Dto\GetOrderRequest;
use Taler\Api\Order\Dto\CheckPaymentPaidResponse;
use Taler\Api\Order\Dto\CheckPaymentUnpaidResponse;
use Taler\Api\Order\Dto\CheckPaymentClaimedResponse;

$order = Yii::$app->taler->orders()->getOrder('my-order-id-2025-1');

if ($order instanceof CheckPaymentPaidResponse) {
    echo 'Paid! Deposit total: ' . $order->deposit_total . PHP_EOL;
} elseif ($order instanceof CheckPaymentUnpaidResponse) {
    echo 'Unpaid. Payment URI: ' . $order->taler_pay_uri . PHP_EOL;
} elseif ($order instanceof CheckPaymentClaimedResponse) {
    echo 'Claimed by wallet.' . PHP_EOL;
}
```

### Create Order

[](#create-order)

```
use Taler\Api\Order\Dto\Amount;
use Taler\Api\Order\Dto\OrderV0;
use Taler\Api\Order\Dto\PostOrderRequest;

$order = new OrderV0(
    summary: 'T-Shirt (GNU Taler demo)',
    amount: new Amount('KUDOS:10.00'),
    fulfillment_message: 'Thank you for purchasing a T-Shirt!',
);

$response = Yii::$app->taler->orders()->createOrder(
    new PostOrderRequest(order: $order)
);

echo 'Created order: ' . $response->order_id . PHP_EOL;
if ($response->token !== null) {
    echo 'Claim token: ' . $response->token . PHP_EOL;
}
```

### Refund Order

[](#refund-order)

```
use Taler\Api\Order\Dto\RefundRequest;

$refundResponse = Yii::$app->taler->orders()->refundOrder(
    'my-order-id-2025-1',
    new RefundRequest(
        refund: 'KUDOS:5.00',
        reason: 'Customer requested refund',
    )
);

echo 'Refund URI: ' . $refundResponse->taler_refund_uri . PHP_EOL;
```

### Delete Order

[](#delete-order)

```
Yii::$app->taler->orders()->deleteOrder('my-order-id-2025-1');
echo 'Order deleted.' . PHP_EOL;
```

### Forget Order Fields

[](#forget-order-fields)

```
use Taler\Api\Order\Dto\ForgetRequest;

Yii::$app->taler->orders()->forgetOrder(
    'my-order-id-2025-1',
    new ForgetRequest(fields: ['$.delivery_location'])
);

echo 'Fields forgotten.' . PHP_EOL;
```

Instance API
------------

[](#instance-api)

The Instance API is accessible via `Yii::$app->taler->instances()`.

### List Instances

[](#list-instances)

```
$list = Yii::$app->taler->instances()->getInstances();

foreach ($list->instances as $instance) {
    echo $instance->id . ' — ' . $instance->name . PHP_EOL;
}
```

> NOTE: If your backend returns `404`, you are likely using a per-instance base URL such as `https://backend.demo.taler.net/instances/sandbox`. In that setup, use the single-instance private endpoint instead: `GET https://backend.demo.taler.net/instances/sandbox/private`

### Get Instance Details

[](#get-instance-details)

```
$details = Yii::$app->taler->instances()->getInstance('shop-1');

echo $details->name;         // e.g., "My Shop"
echo $details->merchant_pub; // EddsaPublicKey
```

### Create Instance

[](#create-instance)

```
use Taler\Api\Instance\Dto\InstanceConfigurationMessage;
use Taler\Api\Instance\Dto\InstanceAuthConfigToken;
use Taler\Api\Dto\Location;
use Taler\Api\Dto\RelativeTime;

$config = new InstanceConfigurationMessage(
    id: 'shop-1',
    name: 'My Shop',
    auth: new InstanceAuthConfigToken(password: 'super-secret'),
    address: new Location(country: 'DE', town: 'Berlin'),
    jurisdiction: new Location(country: 'DE', town: 'Berlin'),
    use_stefan: true,
    default_wire_transfer_delay: new RelativeTime(3600_000_000),
    default_pay_delay: new RelativeTime(300_000_000),
    email: 'merchant@example.com',
);

Yii::$app->taler->instances()->createInstance($config);
```

### Update Instance

[](#update-instance)

```
use Taler\Api\Instance\Dto\InstanceReconfigurationMessage;
use Taler\Api\Dto\Location;
use Taler\Api\Dto\RelativeTime;

$patch = new InstanceReconfigurationMessage(
    name: 'My Shop GmbH',
    address: new Location(country: 'DE', town: 'Berlin'),
    jurisdiction: new Location(country: 'DE', town: 'Berlin'),
    use_stefan: true,
    default_wire_transfer_delay: new RelativeTime(7200_000_000),
    default_pay_delay: new RelativeTime(600_000_000),
    website: 'https://shop.example.com',
);

Yii::$app->taler->instances()->updateInstance('shop-1', $patch);
```

### Delete Instance

[](#delete-instance)

```
use Taler\Api\TwoFactorAuth\Dto\ChallengeResponse;

// Disable instance
$result = Yii::$app->taler->instances()->deleteInstance('shop-1');

if ($result instanceof ChallengeResponse) {
    echo '2FA required. Challenge ID: ' . $result->getChallengeId() . PHP_EOL;
}

// Purge instance (irreversible)
Yii::$app->taler->instances()->deleteInstance('shop-1', purge: true);
```

### Authentication &amp; Access Tokens

[](#authentication--access-tokens)

```
use Taler\Api\Instance\Dto\LoginTokenRequest;
use Taler\Api\Instance\Dto\GetAccessTokensRequest;
use Taler\Api\Dto\RelativeTime;

// Request a login token
$token = Yii::$app->taler->instances()->getAccessToken(
    'shop-1',
    new LoginTokenRequest(
        scope: 'order-full',
        duration: new RelativeTime(3_600_000_000),
        description: 'Backoffice session',
    )
);
echo $token->access_token . PHP_EOL;

// List issued tokens
$tokens = Yii::$app->taler->instances()->getAccessTokens(
    'shop-1',
    new GetAccessTokensRequest(limit: -20)
);
if ($tokens !== null) {
    foreach ($tokens->tokens as $t) {
        echo $t->serial . ' ' . $t->scope . PHP_EOL;
    }
}

// Revoke current token
Yii::$app->taler->instances()->deleteAccessToken('shop-1');

// Revoke token by serial
Yii::$app->taler->instances()->deleteAccessTokenBySerial('shop-1', 123);
```

### Update Auth

[](#update-auth)

```
use Taler\Api\Instance\Dto\InstanceAuthConfigToken;

$result = Yii::$app->taler->instances()->updateAuth(
    'shop-1',
    new InstanceAuthConfigToken(password: 'new-secret')
);
```

### Forgot Password

[](#forgot-password)

```
use Taler\Api\Instance\Dto\InstanceAuthConfigToken;

$result = Yii::$app->taler->instances()->forgotPassword(
    'shop-1',
    new InstanceAuthConfigToken(password: 'new-password')
);
```

### KYC Status

[](#kyc-status)

```
use Taler\Api\Instance\Dto\GetKycStatusRequest;

$kyc = Yii::$app->taler->instances()->getKycStatus('shop-1');

if ($kyc !== null) {
    foreach ($kyc->kyc_data as $entry) {
        echo $entry->exchange_url . PHP_EOL;
    }
}
```

### Merchant Statistics

[](#merchant-statistics)

```
use Taler\Api\Instance\Dto\GetMerchantStatisticsAmountRequest;
use Taler\Api\Instance\Dto\GetMerchantStatisticsCounterRequest;

$amounts = Yii::$app->taler->instances()->getMerchantStatisticsAmount(
    'shop-1',
    'ORDERS',
    new GetMerchantStatisticsAmountRequest(by: 'BUCKET')
);

$counters = Yii::$app->taler->instances()->getMerchantStatisticsCounter(
    'shop-1',
    'VISITS',
    new GetMerchantStatisticsCounterRequest(by: 'INTERVAL')
);
```

Templates API
-------------

[](#templates-api)

The Templates API is accessible via `Yii::$app->taler->templates()`.

### List Templates

[](#list-templates)

```
$response = Yii::$app->taler->templates()->getTemplates();

foreach ($response->templates as $template) {
    echo $template->template_id . ' — ' . $template->template_description . PHP_EOL;
}
```

### Get Template Details

[](#get-template-details)

```
$details = Yii::$app->taler->templates()->getTemplate('coffee-small');

echo $details->template_description . PHP_EOL;
echo $details->template_contract->summary . PHP_EOL;
echo $details->template_contract->amount . PHP_EOL;
echo $details->template_contract->minimum_age . PHP_EOL;
```

### Create Template

[](#create-template)

```
use Taler\Api\Dto\RelativeTime;
use Taler\Api\Templates\Dto\TemplateAddDetails;
use Taler\Api\Templates\Dto\TemplateContractDetails;

Yii::$app->taler->templates()->createTemplate(
    new TemplateAddDetails(
        template_id: 'coffee-small',
        template_description: 'Small coffee in paper cup',
        template_contract: new TemplateContractDetails(
            minimum_age: 0,
            pay_duration: new RelativeTime(900_000_000),
            summary: 'Small coffee',
            currency: 'KUDOS',
            amount: 'KUDOS:2.50'
        ),
        otp_id: null,
        editable_defaults: ['extra_note' => true]
    )
);
```

### Update Template

[](#update-template)

```
use Taler\Api\Dto\RelativeTime;
use Taler\Api\Templates\Dto\TemplatePatchDetails;
use Taler\Api\Templates\Dto\TemplateContractDetails;

Yii::$app->taler->templates()->updateTemplate(
    'coffee-small',
    new TemplatePatchDetails(
        template_description: 'Small coffee (updated)',
        template_contract: new TemplateContractDetails(
            minimum_age: 0,
            pay_duration: new RelativeTime(1_200_000_000),
            summary: 'Small coffee (updated)',
            currency: 'KUDOS',
            amount: 'KUDOS:2.80'
        ),
        otp_id: null,
        editable_defaults: ['extra_note' => true]
    )
);
```

### Delete Template

[](#delete-template)

```
Yii::$app->taler->templates()->deleteTemplate('coffee-small');
```

Token Families API
------------------

[](#token-families-api)

The Token Families API is accessible via `Yii::$app->taler->tokenFamilies()`.

### List Token Families

[](#list-token-families)

```
$families = Yii::$app->taler->tokenFamilies()->getTokenFamilies();

foreach ($families->token_families as $family) {
    echo $family->slug . ' — ' . $family->name . ' — ' . $family->kind . PHP_EOL;
}
```

### Get Token Family Details

[](#get-token-family-details)

```
$family = Yii::$app->taler->tokenFamilies()->getTokenFamily('loyalty-token');

echo $family->slug . PHP_EOL;
echo $family->name . PHP_EOL;
echo $family->description . PHP_EOL;
echo $family->kind . PHP_EOL;
echo 'issued=' . $family->issued . ', used=' . $family->used . PHP_EOL;
```

### Create Token Family

[](#create-token-family)

```
use Taler\Api\Dto\RelativeTime;
use Taler\Api\Dto\Timestamp;
use Taler\Api\TokenFamilies\Dto\TokenFamilyCreateRequest;

Yii::$app->taler->tokenFamilies()->createTokenFamily(
    new TokenFamilyCreateRequest(
        slug: 'loyalty-token',
        name: 'Loyalty Program',
        description: 'Discount token family for recurring buyers',
        valid_before: new Timestamp(1750000000),
        duration: new RelativeTime(86400000000),
        validity_granularity: new RelativeTime(3600000000),
        start_offset: new RelativeTime(0),
        kind: 'discount',
        description_i18n: ['de' => 'Rabatt-Tokenfamilie'],
        extra_data: ['trusted_domains' => ['merchant.example']],
        valid_after: new Timestamp(1710000000)
    )
);
```

### Update Token Family

[](#update-token-family)

```
use Taler\Api\Dto\Timestamp;
use Taler\Api\TokenFamilies\Dto\TokenFamilyUpdateRequest;

Yii::$app->taler->tokenFamilies()->updateTokenFamily(
    'loyalty-token',
    new TokenFamilyUpdateRequest(
        name: 'Loyalty Program (Updated)',
        description: 'Updated description for recurring buyers',
        valid_after: new Timestamp(1710000000),
        valid_before: new Timestamp(1755000000),
        description_i18n: ['de' => 'Aktualisierte Rabatt-Tokenfamilie'],
        extra_data: ['trusted_domains' => ['merchant.example', 'shop.example']]
    )
);
```

### Delete Token Family

[](#delete-token-family)

```
Yii::$app->taler->tokenFamilies()->deleteTokenFamily('loyalty-token');
```

Inventory API
-------------

[](#inventory-api)

The Inventory API is accessible via `Yii::$app->taler->inventories()`.

### List Categories

[](#list-categories)

```
$categories = Yii::$app->taler->inventories()->getCategories();

foreach ($categories->categories as $category) {
    echo $category->category_id . ' — ' . $category->name . PHP_EOL;
}
```

### Create Category

[](#create-category)

```
use Taler\Api\Inventory\Dto\CategoryCreateRequest;

$created = Yii::$app->taler->inventories()->createCategory(
    new CategoryCreateRequest(
        name: 'Beverages',
        name_i18n: ['de' => 'Getranke']
    )
);

echo 'New category id: ' . $created->category_id . PHP_EOL;
```

### List Products

[](#list-products)

```
use Taler\Api\Inventory\Dto\GetProductsRequest;

$products = Yii::$app->taler->inventories()->getProducts(
    new GetProductsRequest(limit: 20)
);

foreach ($products->products as $entry) {
    echo $entry->product_id . ' serial=' . $entry->product_serial . PHP_EOL;
}
```

### Create Product

[](#create-product)

```
use Taler\Api\Inventory\Dto\ProductAddDetail;

Yii::$app->taler->inventories()->createProduct(
    new ProductAddDetail(
        product_id: 'coffee-small',
        description: 'Small brewed coffee',
        unit: 'cup',
        price: 'KUDOS:2.50',
        total_stock: 100,
        product_name: 'Coffee Small',
        categories: [1]
    )
);
```

### Update Product

[](#update-product)

```
use Taler\Api\Inventory\Dto\ProductPatchDetail;

Yii::$app->taler->inventories()->updateProduct(
    'coffee-small',
    new ProductPatchDetail(
        description: 'Small brewed coffee (updated)',
        unit: 'cup',
        price: 'KUDOS:2.80',
        total_stock: 120,
        product_name: 'Coffee Small',
        categories: [1]
    )
);
```

### Lock Product

[](#lock-product)

```
use Taler\Api\Dto\RelativeTime;
use Taler\Api\Inventory\Dto\LockRequest;

Yii::$app->taler->inventories()->lockProduct(
    'coffee-small',
    new LockRequest(
        lock_uuid: '123e4567-e89b-12d3-a456-426614174000',
        duration: new RelativeTime(60_000_000),
        quantity: 2
    )
);
```

### Delete Product / Category

[](#delete-product--category)

```
Yii::$app->taler->inventories()->deleteProduct('coffee-small');
Yii::$app->taler->inventories()->deleteCategory(1);
```

Webhooks API
------------

[](#webhooks-api)

The Webhooks API is accessible via `Yii::$app->taler->webhooks()`.

### List Webhooks

[](#list-webhooks)

```
$response = Yii::$app->taler->webhooks()->getWebhooks();

foreach ($response->webhooks as $webhook) {
    echo $webhook->webhook_id . ' — ' . $webhook->event_type . PHP_EOL;
}
```

### Get Webhook Details

[](#get-webhook-details)

```
$details = Yii::$app->taler->webhooks()->getWebhook('order-paid-hook');

echo $details->event_type . PHP_EOL;
echo $details->http_method . PHP_EOL;
echo $details->url . PHP_EOL;
```

### Create Webhook

[](#create-webhook)

```
use Taler\Api\Dto\Url;
use Taler\Api\Webhooks\Dto\WebhookAddDetails;

Yii::$app->taler->webhooks()->createWebhook(
    new WebhookAddDetails(
        webhook_id: 'order-paid-hook',
        event_type: 'ORDER_PAID',
        url: Url::fromString('https://merchant.example/webhooks/order-paid'),
        http_method: 'POST',
        header_template: "Content-Type: application/json",
        body_template: '{"order_id":"{{order_id}}","event":"{{event_type}}"}'
    )
);
```

### Update Webhook

[](#update-webhook)

```
use Taler\Api\Dto\Url;
use Taler\Api\Webhooks\Dto\WebhookPatchDetails;

Yii::$app->taler->webhooks()->updateWebhook(
    'order-paid-hook',
    new WebhookPatchDetails(
        event_type: 'ORDER_PAID',
        url: Url::fromString('https://merchant.example/webhooks/order-paid-v2'),
        http_method: 'POST',
        header_template: "Content-Type: application/json",
        body_template: '{"order_id":"{{order_id}}","event":"{{event_type}}","updated":true}'
    )
);
```

### Delete Webhook

[](#delete-webhook)

```
Yii::$app->taler->webhooks()->deleteWebhook('order-paid-hook');
```

Wire Transfers API
------------------

[](#wire-transfers-api)

The Wire Transfers API is accessible via `Yii::$app->taler->wireTransfers()`.

### List Wire Transfers

[](#list-wire-transfers)

```
use Taler\Api\WireTransfers\Dto\GetTransfersRequest;

$transfers = Yii::$app->taler->wireTransfers()->getTransfers(
    new GetTransfersRequest(limit: 20)
);

foreach ($transfers->transfers as $transfer) {
    echo '#' . $transfer->transfer_serial_id
        . ' ' . $transfer->credit_amount
        . ' ' . $transfer->payto_uri . PHP_EOL;
}
```

### List Wire Transfers With Filters

[](#list-wire-transfers-with-filters)

```
use Taler\Api\WireTransfers\Dto\GetTransfersRequest;

$transfers = Yii::$app->taler->wireTransfers()->getTransfers(
    new GetTransfersRequest(
        payto_uri: 'payto://iban/DE75512108001245126199?receiver-name=Merchant',
        expected: 'true',
        before: '100',
        after: '1',
        limit: 10
    )
);
```

### Delete Wire Transfer

[](#delete-wire-transfer)

```
Yii::$app->taler->wireTransfers()->deleteTransfer('transfer-serial-id-42');
```

Async Support
-------------

[](#async-support)

All API methods support asynchronous execution by appending `Async` to the method name. Async methods return a promise that resolves to the same typed DTO as the synchronous variant.

```
// Example: create an order asynchronously
$promise = Yii::$app->taler->orders()->createOrderAsync(
    new PostOrderRequest(order: $order)
);

$response = $promise->wait();
echo 'Created order (async): ' . $response->order_id . PHP_EOL;

// Example: list instances asynchronously
$promise = Yii::$app->taler->instances()->getInstancesAsync();
$list = $promise->wait();
```

Bank Accounts API
-----------------

[](#bank-accounts-api)

The Bank Accounts API is accessible via `Yii::$app->taler->bankAccounts()`.

### List Bank Accounts

[](#list-bank-accounts)

```
$accounts = Yii::$app->taler->bankAccounts()->getAccounts();

foreach ($accounts->accounts as $entry) {
    echo $entry->h_wire . ' ' . $entry->payto_uri . PHP_EOL;
}
```

### Get Bank Account Details

[](#get-bank-account-details)

```
$account = Yii::$app->taler->bankAccounts()->getAccount('h_wire_hash_here');

echo $account->payto_uri . PHP_EOL;
echo $account->active ? 'active' : 'inactive';
```

### Create Bank Account

[](#create-bank-account)

```
use Taler\Api\BankAccounts\Dto\AccountAddDetails;
use Taler\Api\BankAccounts\Dto\AccountAddResponse;
use Taler\Api\TwoFactorAuth\Dto\ChallengeResponse;

$result = Yii::$app->taler->bankAccounts()->createAccount(
    new AccountAddDetails(
        payto_uri: 'payto://iban/DE75512108001245126199?receiver-name=Merchant'
    )
);

if ($result instanceof ChallengeResponse) {
    echo '2FA required: ' . $result->getChallengeId() . PHP_EOL;
} elseif ($result instanceof AccountAddResponse) {
    echo 'h_wire: ' . $result->h_wire . PHP_EOL;
}
```

### Update Bank Account

[](#update-bank-account)

```
use Taler\Api\BankAccounts\Dto\AccountPatchDetails;

Yii::$app->taler->bankAccounts()->updateAccount(
    'h_wire_hash_here',
    new AccountPatchDetails(
        credit_facade_url: 'https://bank-facade.example'
    )
);
```

### Delete Bank Account

[](#delete-bank-account)

```
Yii::$app->taler->bankAccounts()->deleteAccount('h_wire_hash_here');
```

OTP Devices API
---------------

[](#otp-devices-api)

The OTP Devices API is accessible via `Yii::$app->taler->otpDevices()`.

### List OTP Devices

[](#list-otp-devices)

```
$response = Yii::$app->taler->otpDevices()->getOtpDevices();

foreach ($response->otp_devices as $device) {
    echo $device->otp_device_id . ' — ' . $device->device_description . PHP_EOL;
}
```

### Get OTP Device Details

[](#get-otp-device-details)

```
use Taler\Api\OtpDevices\Dto\GetOtpDeviceRequest;

$details = Yii::$app->taler->otpDevices()->getOtpDevice(
    'pos-terminal-1',
    new GetOtpDeviceRequest(price: 'KUDOS:1.00')
);

echo $details->device_description . PHP_EOL;
echo $details->otp_algorithm . PHP_EOL;
echo $details->otp_timestamp . PHP_EOL;
echo ($details->otp_code ?? '(none)') . PHP_EOL;
```

### Create OTP Device

[](#create-otp-device)

```
use Taler\Api\OtpDevices\Dto\OtpDeviceAddDetails;

Yii::$app->taler->otpDevices()->createOtpDevice(
    new OtpDeviceAddDetails(
        otp_device_id: 'pos-terminal-1',
        otp_device_description: 'Front desk terminal',
        otp_key: 'JBSWY3DPEHPK3PXP',
        otp_algorithm: 'TOTP_WITHOUT_PRICE',
    )
);
```

### Update OTP Device

[](#update-otp-device)

```
use Taler\Api\OtpDevices\Dto\OtpDevicePatchDetails;

Yii::$app->taler->otpDevices()->updateOtpDevice(
    'pos-terminal-1',
    new OtpDevicePatchDetails(
        otp_device_description: 'Front desk terminal (updated)',
        otp_algorithm: 'TOTP_WITH_PRICE',
    )
);
```

### Delete OTP Device

[](#delete-otp-device)

```
Yii::$app->taler->otpDevices()->deleteOtpDevice('pos-terminal-1');
```

Two-Factor Auth API
-------------------

[](#two-factor-auth-api)

The Two-Factor Auth API is accessible via `Yii::$app->taler->twoFactorAuth()`.

### Request Challenge Transmission

[](#request-challenge-transmission)

```
$response = Yii::$app->taler->twoFactorAuth()->requestChallenge(
    'sandbox',
    'challenge-id-123',
    ['resend' => true]
);

echo 'solve_expiration: ' . $response->solve_expiration->t_s . PHP_EOL;
echo 'earliest_retransmission: ' . $response->earliest_retransmission->t_s . PHP_EOL;
```

### Confirm Challenge

[](#confirm-challenge)

```
use Taler\Api\TwoFactorAuth\Dto\MerchantChallengeSolveRequest;

Yii::$app->taler->twoFactorAuth()->confirmChallenge(
    'sandbox',
    'challenge-id-123',
    new MerchantChallengeSolveRequest(tan: '123456')
);
```

### Async Two-Factor Calls

[](#async-two-factor-calls)

```
use Taler\Api\TwoFactorAuth\Dto\MerchantChallengeSolveRequest;

$requestPromise = Yii::$app->taler->twoFactorAuth()->requestChallengeAsync(
    'sandbox',
    'challenge-id-123',
    []
);
$challenge = $requestPromise->wait();

$confirmPromise = Yii::$app->taler->twoFactorAuth()->confirmChallengeAsync(
    'sandbox',
    'challenge-id-123',
    new MerchantChallengeSolveRequest(tan: '123456')
);
$confirmPromise->wait();
```

Donau Charity API
-----------------

[](#donau-charity-api)

The Donau Charity API is accessible via `Yii::$app->taler->donauCharities()`.

### List Linked Donau Charity Instances

[](#list-linked-donau-charity-instances)

```
$response = Yii::$app->taler->donauCharities()->getInstances();

foreach ($response->donau_instances as $instance) {
    echo '#' . $instance->donau_instance_serial . ' ' . $instance->charity_name . PHP_EOL;
}
```

### Link a Donau Charity

[](#link-a-donau-charity)

```
use Taler\Api\DonauCharity\Dto\PostDonauRequest;
use Taler\Api\TwoFactorAuth\Dto\ChallengeResponse;

$result = Yii::$app->taler->donauCharities()->createDonauCharity(
    new PostDonauRequest(
        donau_url: 'https://donau.example',
        charity_id: 42,
    )
);

if ($result instanceof ChallengeResponse) {
    echo '2FA required: ' . $result->getChallengeId() . PHP_EOL;
}
```

### Unlink a Donau Charity by Serial

[](#unlink-a-donau-charity-by-serial)

```
Yii::$app->taler->donauCharities()->deleteDonauCharityBySerial(42);
```

Testing
-------

[](#testing)

```
vendor/bin/phpunit
```

Funding
-------

[](#funding)

This project is funded through [NGI TALER Fund](https://nlnet.nl/taler), a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu) program. Learn more at the [NLnet project page](https://nlnet.nl/project/TalerPHP).

[![NLnet foundation logo](https://camo.githubusercontent.com/b2f4296f9a60d61a382b0bbaa9e688d8f75dd688d9769b10ca67b4889481d636/68747470733a2f2f6e6c6e65742e6e6c2f6c6f676f2f62616e6e65722e706e67)](https://nlnet.nl)

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance93

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

36d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/10708724?v=4)[mirrorps](/maintainers/mirrorps)[@mirrorps](https://github.com/mirrorps)

---

Top Contributors

[![mirrorps](https://avatars.githubusercontent.com/u/10708724?v=4)](https://github.com/mirrorps "mirrorps (21 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mirrorps-yii2-taler/health.svg)

```
[![Health](https://phpackages.com/badges/mirrorps-yii2-taler/health.svg)](https://phpackages.com/packages/mirrorps-yii2-taler)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.8M710](/packages/sylius-sylius)[craftcms/cms

Craft CMS

3.6k3.6M2.9k](/packages/craftcms-cms)[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k11](/packages/tempest-framework)[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3751.2M45](/packages/tencentcloud-tencentcloud-sdk-php)[theodo-group/llphant

LLPhant is a library to help you build Generative AI applications.

1.7k371.6k5](/packages/theodo-group-llphant)[telnyx/telnyx-php

Official Telnyx PHP SDK — APIs for Voice, SMS, MMS, WhatsApp, Fax, SIP Trunking, Wireless IoT, Call Control, and more. Build global communications on Telnyx's private carrier-grade network.

35729.6k2](/packages/telnyx-telnyx-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
