sashalenz/vchasno-kasa-api 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

sashalenz/vchasno-kasa-api

Composer 安装命令:

composer require sashalenz/vchasno-kasa-api

包简介

Laravel client for Вчасно.Каса Orders API (deferred fiscal receipts / ПРРО)

README 文档

README

Latest Version on Packagist Tests PHP Version License

Laravel package for integrating with the Vchasno.Kasa Orders API.

Supports deferred fiscal receipts (ETTN) via Nova Poshta, Ukrposhta and Meest, as well as direct cash and IBAN payments.

Requirements

  • PHP 8.4+
  • Laravel 11 / 12 / 13

Installation

composer require sashalenz/vchasno-kasa-api

Publish the config file:

php artisan vendor:publish --tag="vchasno-kasa-config"

Add variables to your .env:

VCHASNO_KASA_TOKEN=your-api-token
VCHASNO_KASA_RRO_FN=1234567890

Configuration

// config/vchasno-kasa.php

return [
    'token'    => env('VCHASNO_KASA_TOKEN'),
    'rro_fn'   => env('VCHASNO_KASA_RRO_FN'),
    'base_url' => env('VCHASNO_KASA_URL', 'https://kasa.vchasno.ua/api/v1'),
    'timeout'  => 30,
    'retry'    => [
        'times' => 3,
        'sleep' => 150,
    ],
];
Option Description
token API token from the Vchasno cabinet: Settings → API
rro_fn Fiscal number of the software cash register (PRRO). Visible in the cabinet or via GET /api/v1/rro
base_url Orders API base URL (change only if necessary)

Usage

Via Facade

use Sashalenz\VchasnoKasaApi\Facades\VchasnoKasa;

Via DI / app()

use Sashalenz\VchasnoKasaApi\VchasnoKasaApi;

$api = app(VchasnoKasaApi::class);

Orders API

1. Deferred receipt — Nova Poshta (COD)

The primary use case: the customer pays upon parcel pickup. The receipt is fiscalized automatically when the customer collects the shipment.

use Sashalenz\VchasnoKasaApi\Facades\VchasnoKasa;
use Sashalenz\VchasnoKasaApi\Data\Requests\Orders\CreatePostalOrderData;
use Sashalenz\VchasnoKasaApi\Data\Requests\Orders\GoodItemData;
use Sashalenz\VchasnoKasaApi\Enums\PostalType;

$order = VchasnoKasa::orders()->createPostal(
    new CreatePostalOrderData(
        ttn: '59000123456789',                     // Nova Poshta tracking number
        rroFn: config('vchasno-kasa.rro_fn'),
        tag: "order-{$order->id}-{$shipment->id}", // unique idempotency key
        postalType: PostalType::NovaPoshta,
        goods: [
            new GoodItemData(
                name: 'BMW E46 front left headlight',
                quantity: 1.0,
                price: 350000,    // in kopecks (3500.00 UAH)
                code: 'SKU-12345',
            ),
        ],
        totalSum: 350000,         // in kopecks
    )
);

echo $order->id;     // order ID in Vchasno
echo $order->status; // OrderStatus::Created

2. Deferred receipt — Ukrposhta / Meest

use Sashalenz\VchasnoKasaApi\Enums\PostalType;

$order = VchasnoKasa::orders()->createPostal(
    new CreatePostalOrderData(
        ttn: '0312345678901',
        rroFn: config('vchasno-kasa.rro_fn'),
        tag: "order-{$order->id}-ukrposhta",
        postalType: PostalType::UkrPoshta,   // or PostalType::Meest
        goods: [...],
        totalSum: 120000,
    )
);

3. Direct cash / card payment

use Sashalenz\VchasnoKasaApi\Data\Requests\Orders\CreateOrderData;
use Sashalenz\VchasnoKasaApi\Enums\PaymentType;

$order = VchasnoKasa::orders()->create(
    new CreateOrderData(
        rroFn: config('vchasno-kasa.rro_fn'),
        tag: "cash-order-{$order->id}",
        goods: [
            new GoodItemData(name: 'Rear bumper', quantity: 1.0, price: 180000),
        ],
        totalSum: 180000,
        paymentType: PaymentType::Cash,   // or PaymentType::Card
    )
);

4. IBAN bank transfer

use Sashalenz\VchasnoKasaApi\Data\Requests\Orders\CreateIbanOrderData;

$order = VchasnoKasa::orders()->createIban(
    new CreateIbanOrderData(
        rroFn: config('vchasno-kasa.rro_fn'),
        tag: "iban-payment-{$payment->id}",
        goods: [...],
        totalSum: 250000,
        iban: 'UA123456789012345678901234567',
        comment: 'Payment for order #12345',
    )
);

5. Get order status

$order = VchasnoKasa::orders()->get($fiscalOrderId);

if ($order->status->isSuccess()) {
    $yourOrder->update([
        'fiscal_receipt_url' => $order->receiptUrl,
        'fiscal_code'        => $order->fiscalCode,
        'fiscalized_at'      => $order->fiscalizedAt,
    ]);
}

6. List orders (cursor pagination)

use Sashalenz\VchasnoKasaApi\Data\Requests\Orders\ListOrdersData;
use Sashalenz\VchasnoKasaApi\Enums\OrderStatus;

$result = VchasnoKasa::orders()->list(
    new ListOrdersData(
        pageSize: 50,
        status: OrderStatus::Fiscalized,
        dateFrom: '2026-04-01T00:00:00Z',
        dateTo: '2026-04-30T23:59:59Z',
    )
);

foreach ($result->items as $order) {
    echo "{$order->id}: {$order->status->label()}";
}

// Next page
if ($result->hasMore) {
    $next = VchasnoKasa::orders()->list(
        new ListOrdersData(cursor: $result->nextCursor, pageSize: 50)
    );
}

7. Cancel an order

$cancelled = VchasnoKasa::orders()->cancel($fiscalOrderId);
echo $cancelled->status->label(); // "Cancelled"

Receipts API

Get a receipt by ID

$receipt = VchasnoKasa::receipts()->get($receiptId);

echo $receipt->receiptUrl;  // PDF URL
echo $receipt->fiscalCode;  // fiscal code from the tax authority

Poll for new receipts

Useful for a background job that syncs fiscalization statuses:

use Sashalenz\VchasnoKasaApi\Data\Requests\Receipts\ListReceiptsData;

$cursor = cache('vchasno_receipts_cursor');

do {
    $result = VchasnoKasa::receipts()->list(
        new ListReceiptsData(cursor: $cursor, pageSize: 100)
    );

    foreach ($result->items as $receipt) {
        Order::where('fiscal_order_id', $receipt->orderId)
            ->update([
                'fiscal_receipt_url' => $receipt->receiptUrl,
                'fiscal_code'        => $receipt->fiscalCode,
                'fiscalized_at'      => $receipt->createdAt,
            ]);
    }

    $cursor = $result->nextCursor;

} while ($result->hasMore);

cache()->put('vchasno_receipts_cursor', $cursor);

Enums

OrderStatus

Case Value Description
Created 0 Created, awaiting processing
WaitingForPickup 10 NP: waiting for customer pickup
Delivered 11 NP: delivered, fiscalization in progress
Fiscalized 101 ✅ Successfully fiscalized
Cancelled 2000 Cancelled
Returned 2001 Returned
Expired 2002 Expired
$status->isSuccess();  // true if Fiscalized
$status->isFinal();    // true if Fiscalized / Cancelled / Returned / Expired
$status->isPending();  // true if Created / WaitingForPickup / Delivered
$status->label();      // 'Fiscalized'

PostalType

Case Value paymentType()
NovaPoshta nova_poshta PaymentType::NovaPoshta (20)
UkrPoshta ukr_poshta PaymentType::PostalOther (15)
Meest meest PaymentType::PostalOther (15)

PaymentType

Case Value Description
Cash 1 Cash
Card 2 Card / terminal
PostalOther 15 Ukrposhta / Meest COD
NovaPoshta 20 Nova Poshta COD

Error handling

use Sashalenz\VchasnoKasaApi\Exceptions\VchasnoKasaRequestException;

try {
    $order = VchasnoKasa::orders()->createPostal($data);
} catch (VchasnoKasaRequestException $e) {
    if ($e->shouldRetry()) {
        // res_action=1 or 2: request can be retried
        // res_action=2 (collision): retry with the same tag
        retry($job);
    }

    if ($e->needsDataFix()) {
        // res_action=3: bad request data, retrying will not help
        Log::error('Vchasno fiscal error', [
            'message'    => $e->getMessage(),
            'res_action' => $e->getResAction(),
        ]);
    }
}

res_action codes

Value Method Action
0 Success
1 shouldRetry() Retry the request
2 isCollision() Collision — retry with the same tag
3 needsDataFix() Bad data — fix the request payload

Idempotency (tag)

The tag field is a required unique key for every order. If a request is repeated with the same tag, Vchasno returns the existing order instead of creating a new one.

Recommended format:

// Nova Poshta shipment
$tag = "order-{$order->id}-{$shipment->id}";

// Cash payment
$tag = "cash-{$order->id}";

// IBAN payment
$tag = "iban-{$payment->id}";

Testing

composer test
composer analyse    # PHPStan
composer format     # Pint

License

MIT. See LICENSE for details.

统计信息

  • 总下载量: 41
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 3
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-04-26

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固