承接 mervit/idoklad-v3 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

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

mervit/idoklad-v3

Composer 安装命令:

composer require mervit/idoklad-v3

包简介

PHP třída pro ulehčení požadavků na iDoklad api v3.

README 文档

README

Open Source Love

iDoklad v3

PHP třída pro zasílání požadavků na iDoklad api v3.

Dokumentace iDoklad api v2

Dokumentace iDoklad api v3

Děkuji @malcanek za vytvoření v2, knihovnu jsem upgradoval na verzi 3 a dávám jí tímto k dispozici ostatním zájemcům

Změny v kodu proti verzi v2 od /iDoklad-v2

  • Podstattná změna je v odpovědích, kdy bylo u listů TotalItems a TotalPages přesunuto pod parametr data. Položky listů tedy již nelze načíst metodou getData ale nově vzniklou metodou getItems. U existujících aplikací je tedy nutné při přechodu z verze 2 na verzi 3 zasáhnout do všech callu které vrací list výsledků.
  • Přepracované jsou filtry, které nyní umožňují seskupování a zanořování podmínek a kombinací logických operátorů or a and
  • Requesty GET nově podporují parametr select pro omezení dat ve výsledcích
  • Requesty GET nově podporují také parametr include který umožňuje zahrnout do odpovědi i data z připojených entit

Vložení knihovny do projektu

Knihovnu vložíme do projektu naincludováním souboru src/iDoklad.php, nebo si knihovnu přidáme pomocí composeru. Následně se na knihovnu odkážeme pomocí use.

composer require mervit/idoklad-v3

Zadáme naše client ID, client secret a v případě, že chceme použít OAuth2 autentifikaci i redirect URI. Nakonec si zavoláme objekt iDokladu, který zajišťuje veškerou komunikaci.

include_once 'src/iDoklad.php';
            
use mervit\iDoklad\iDoklad;
use mervit\iDoklad\auth\iDokladCredentials;
use mervit\iDoklad\iDokladException;

$clientId = 'Your client ID';
$clientSecret = 'Your client secret';
$redirectUri = 'Your redirect URI for OAuth2';

$iDoklad = new iDoklad($clientId, $clientSecret, $redirectUri);

Autorizace pomocí OAuth2 - Authorization code flow

Autorizace pomocí OAuth probíhá v několika krocích. Jako client ID a client secret používáme údaje získané z developer portálu.

Nejdříve nabídneme uživateli URL adresu, kde zadá své přihlašovací údaje. Tu získáme pomocí nasledující metody:

echo '<a href="'.$iDoklad->getAuthenticationUrl().'">Odkaz</a>';

Po zadání přihlašovacích údajů je uživatel přesměrován na zadanou redirect URI i s kódem, pomocí kterého získáme jeho credentials údaje. Kód zpracujeme následujícím způsobem:

$iDoklad->requestCredentials($_GET['code']);

Nyní jsou v instanci objektu založeny credentials a můžeme odesílat dotazy na iDoklad api. Credentials můžeme získat 2 způsoby. Získání credentials přímo z objektu:

$credentials = $iDoklad->getCredentials();
echo $credentials->toJson();

Zpracování credentials pomocí credentials callbacku:

Callback funguje tak, že knihovna zavolá callback funkci vždy, když jsou změněny credentials. To se hodí, jelikož automaticky probíhá refresh tokenu po jeho vypršení.

$iDoklad->setCredentialsCallback(function($credentials){
    file_put_contents('credentials.json', $credentials->toJson());
});

Nahrání credentials do iDoklad objektu

Založení objektu s již existujícími credentials

$iDoklad = new iDoklad($clientId, $clientSecret, $redirectUri, $credentials);

Vložení credentials do již existujícího objektu

$iDoklad->setCredentials($credentials);

Poté co objekt obsahuje credentials, lze provádět dotazy do iDoklad api.

Autorizace pomocí OAuth2 - Client credentials flow

Tato metoda je jednodušší. Credentials získáme na základě client id a client secret, které získáme z nastavení účtu uživatele. Po založení objektu pouze zavoláme:

$iDoklad->authCCF();

Jako u OAuth2 - Authorization code flow i zde funguje credentials callback.

Odesílání požadavků na iDoklad api

Pro odeslání požadavku na api slouží iDokladRequest objekt. Ten lze v nejjednodušší podobě založit pouze s jedním parametrem, který určuje akci dle dokumentace, a poté rovnou odeslat na api.

$request = new iDokladRequest('IssuedInvoices');
$response = $iDoklad->sendRequest($request);

Získání dat z api

Pokud požadavek proběhne úspěšně, jsou zpět vrácena data v podobě iDokladResponse objektu. Nejdříve zkontrolujeme, zda požadavek proběhl v pořádku (návratová hodnota by měla být 200):

$response->getCode();

Poté můžeme získat samotná data v poli:

$response->getData();

Odchytávání chyb

Třída vyhazuje vyjímky typu iDokladException.

Vytvoření nové faktury

$request->addMethodType('POST');
$data = array(
    'PurchaserId' => 3739927,
    'IssuedInvoiceItems' => [array(
        'Name' => 'Testovaci polozka',
        'UnitPrice' => 100,
        'Amount' => 1
    )]
);
$request->addPostParameters($data);

Případně můžeme nově zadat method type pomocí fce, což by nyní vypadalo následovně:

$data = array(
    'PurchaserId' => 3739927,
    'IssuedInvoiceItems' => [array(
        'Name' => 'Testovaci polozka',
        'UnitPrice' => 100,
        'Amount' => 1
    )]
);
$request->post()->addPostParameters($data);

Použití filtru a třídění

Pro použití filtru použijeme třídu iDokladFilter. Parametry můžeme zadat hned při založení třídy, první parametr je jméno pole, které chceme filtrovat, druhý parametr je operátor, poslední parametr je hodnota.

$filter = new iDokladFilter('DocumentNumber', '==', '20170013');
$request->addFilter($filter);

Vztahy mezi jednotlivými filtry můžeme definovat pomocí metody setFilterType.

$request->setFilterType('and');

Filtrů můžeme přidat několik a pomocí filterGroup třídy je můžeme seskupit.

$filterGroup = new \mervit\iDoklad\request\iDokladFilterGroup('or');
$filter2 = new \mervit\iDoklad\request\iDokladFilter('Id', '!eq', '123');
$filterGroup->addFilter($filter2);
$filter3 = new \mervit\iDoklad\request\iDokladFilter('Id', 'eq', '456');
$filterGroup->addFilter($filter3);
$request->addFilter($filterGroup);

Pro použití třídění použijeme třídu iDokladSort. Opět můžeme hned přidávat parametry, kdy první parametr je jméno pole a druhý parametr je dobrovolný a lze zadat, zda řadit vzestupně (asc) či sestupně (desc).

$sort = new iDokladSort('DocumentNumber', 'desc');
$request->addSort($sort);

Stránkování a počet vrácených položek

$request->setPage(2);
$request->setPageSize(5);

Omezení výsledku

Pomocí metody addSelect můžeme omezit data, které API vrací a výrazně tím dobu zpracování požadavku

$request->addSelect('Id');
$request->addSelect('CurrencyId');

Zanořená data odělujeme tečkou

$request->addSelect('DeliveryAddress.Name');

Můžeme přidat i více proměných odělené čárkou

$request->addSelect('Items.Id,Items.Name');

Načtení připojených entit

Pomocí metody addInclude můžeme naopak rozšířit vrácené data o detaily připojených entit. Díky této funkci již nemusíme načítat detail připojené entity samostatným callem.

$request->addInclude('Currency');

Zanořená data odělujeme tečkou

$request->addInclude('Items.PriceListItem.Currency');

Můžeme přidat i více proměných odělené čárkou

$request->addInclude('Currency,Items.PriceListItem.Currency');

Vyhazování exception při návratových kódech vyšších nebo rovno 400

Pokud chceme zapnout vyhazování exception při http návratových kódech vyšších rovno 400, stačí nám zavolat fci

$iDoklad->httpExceptionsOn()

Upload přílohy

Pokud chceme uploadovat přílohu, stačí nám použít metodu addFile nad request objektem.

$request = new \mervit\iDoklad\request\iDokladRequest('Attachments/{documentId}/{documentType}');
$request->addFile(new CURLFile(path_to_your_file));
$response = $iDoklad->sendRequest($request);

Jiné úpravy

Pokud potřebujeme použít metody POST, PUT, PATCH, DELETE, použijeme k tomu metodu addMethodType nad objektem iDokladRequest.

Příklady

Příklady použití lze vidět v souborech acf.php a ccf.php. acf.php obsahuje příklad použití authorization code flow, ccf obsahuje příklad na client credentials flow, stačí doplnit vlastní client ID, client secret a redirect URI.

Příklad vytvoření faktury

// Generate company name
        $companyName = $order->getFirstname() . ' ' . $order->getLastname();
        if($order->getCompanyName()){
            $companyName = $order->getCompanyName();
        }

        // Try to find existing company in address book
        $filter = new iDokladFilter('CompanyName', '==', $companyName);
        $contactRequest = new iDokladRequest('Contacts');
        $contactRequest->addFilter($filter);
        $contactResponse = $this->sendRequest($contactRequest);
        if($contactResponse->getTotalItems() > 0){
            $contactId = $contactResponse->getItems()[0]["Id"];
        }

        // Create or update company in address book
        $contactRequest = new iDokladRequest('Contacts');
        $contactRequestPostParameters = [];
        $contactRequestPostParameters['CountryId'] = 1;
        $contactRequestPostParameters['Email'] = $order->getEmail();
        $contactRequestPostParameters['Mobile'] = $order->getPhone();
        $contactRequestPostParameters['Firstname'] = $order->getFirstname();
        $contactRequestPostParameters['Surname'] = $order->getLastname();
        $contactRequestPostParameters['CompanyName'] = $companyName;
        if($order->getCin()) {
            $contactRequestPostParameters['IdentificationNumber'] = $order->getCin();
        }
        if($order->getVat()){
            $contactRequestPostParameters['VatIdentificationNumber'] = $order->getVat();
        }
        if($order->getAddress()){
            $contactRequestPostParameters['Street'] = $order->getAddress();
        }
        if(isset($contactId)){
            $contactRequestPostParameters['Id'] = $contactId;
            $contactRequest->addMethodType('PATCH');
        } else {
            $contactRequest->addMethodType('POST');
        }
        $contactRequest->addPostParameters($contactRequestPostParameters);

        $contactResponse = $this->sendRequest($contactRequest);
        $contact = $contactResponse->getData();

        // Get default numeric sequence
        $numericSequenceRequest = new iDokladRequest('NumericSequences');
        $numericSequenceRequest->addFilter(new iDokladFilter('IsDefault', '==', 'true'));
        $numericSequenceRequest->addFilter(new iDokladFilter('DocumentType', '==', '0')); // 0 = IssuedInvoices
        $numericSequenceResponse = $this->sendRequest($numericSequenceRequest);
        $numericSequences = $numericSequenceResponse->getItems();
        $defaultNumericSequenceId = $numericSequences[0]['Id'];
        $lastDocumentSerialNumber = $numericSequences[0]['LastNumber'];

        // Get default payment option
        $paymentOptionRequest = new iDokladRequest('PaymentOptions');
        $paymentOptionResponse = $this->sendRequest($paymentOptionRequest);
        $paymentOptions = $paymentOptionResponse->getItems();
        $paymentOptionId = null;
        foreach($paymentOptions as $po){
            if($po['IsDefault'] == 'true'){
                $paymentOptionId = $po['Id'];
                break;
            }
        }

        // Create Issued Invoice
        $dateOfIssue = new \DateTime();
        $dateOfMaturity = clone $dateOfIssue;
        $dateOfMaturity->modify('+14 days');
        $invoicePostParameters = [];
        $invoicePostParameters['PartnerId'] = $contact['Id'];
        $invoicePostParameters['CurrencyId'] = 1;
        $invoicePostParameters['Description'] = 'Nákup v eshopu';
        $invoicePostParameters['DateOfIssue'] = $dateOfIssue->format('Y-m-d');
        $invoicePostParameters['DateOfMaturity'] = $dateOfMaturity->format('Y-m-d');
        $invoicePostParameters['DateOfTaxing'] = $dateOfIssue->format('Y-m-d');
        $invoicePostParameters['DocumentSerialNumber'] = (string)((int) $lastDocumentSerialNumber + 1);
        $invoicePostParameters['IsEet'] = false;
        $invoicePostParameters['IsIncomeTax'] = true;
        $invoicePostParameters['NumericSequenceId'] = $defaultNumericSequenceId;
        $invoicePostParameters['PaymentOptionId'] = $paymentOptionId;
        $invoicePostParameters['Items'] = [];

        foreach ($order->getItems() as $item) {
            $invoiceItem = [];
            $invoiceItem['Amount'] = $item->getQuantity();
            $invoiceItem['PriceType'] = 0; // Cena s daní
            $invoiceItem['VatRateType'] = 1; // Základní sazba DPH
            $invoiceItem['UnitPrice'] = $item->getPrice();
            $invoiceItem['Name'] = $item->getName();
            $invoiceItem['DiscountPercentage'] = 0;
            $invoiceItem['IsTaxMovement'] = false;
            $invoicePostParameters['Items'][] = $invoiceItem;
        }

        $invoiceRequest = new iDokladRequest('IssuedInvoices');
        $invoiceRequest->addMethodType('POST');
        $invoiceRequest->addPostParameters($invoicePostParameters);
        return $this->sendRequest($invoiceRequest);

mervit/idoklad-v3 适用场景与选型建议

mervit/idoklad-v3 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 23.72k 次下载、GitHub Stars 达 2, 最近一次更新时间为 2024 年 03 月 02 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「idoklad」 「fakturace」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 mervit/idoklad-v3 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 mervit/idoklad-v3 我们能提供哪些服务?
定制开发 / 二次开发

基于 mervit/idoklad-v3 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

与 mervit/idoklad-v3 相关的其它包

同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:

统计信息

  • 总下载量: 23.72k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 6
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-03-02