jarrin/wefact-php-sdk
Composer 安装命令:
composer require jarrin/wefact-php-sdk
包简介
Modern, strongly-typed, PSR-compliant PHP client for the WeFact v2 API.
README 文档
README
A modern, strongly-typed, PSR-compliant PHP 8.3+ client for the WeFact v2 API — the Dutch invoicing / billing / bookkeeping SaaS. Works standalone and under Laravel.
- Typed end-to-end. Every controller is a resource, every response object a readonly DTO, every documented code a backed enum. No associative-array guessing, full IDE autocompletion, PHPStan-max clean.
- One obvious way to call it.
$wefact->debtors()->get(code: 'DB10000')— a lazy accessor per controller, a typed method per action. - Hand-written from the official reference and verified against the live API. Not generated; every endpoint is confirmed by an integration test.
use Jarrin\WeFactApiClient\WeFact; $wefact = new WeFact('your-api-key'); $debtor = $wefact->debtors()->get(code: 'DB10000'); $invoice = $wefact->invoices()->create([ 'DebtorCode' => $debtor->code, 'InvoiceLines' => [ ['ProductCode' => 'P0001', 'Number' => 2], ['Description' => 'Consultancy', 'PriceExcl' => 95.0, 'Number' => 3, 'TaxCode' => 'V21'], ], ]); echo $invoice->code, ' — €', $invoice->amountIncl;
Requirements
- PHP 8.3+
- A WeFact v2 API key (WeFact control panel → Settings → API)
- The calling server's IP must be whitelisted for that key (a non-whitelisted IP returns HTTP 403)
Installation
composer require jarrin/wefact-php-sdk
Quick start (standalone)
Construct with an API key, or with a Config for full control:
use Jarrin\WeFactApiClient\WeFact; use Jarrin\WeFactApiClient\Config; $wefact = new WeFact('your-api-key'); // or: $wefact = new WeFact(new Config( apiKey: 'your-api-key', timeout: 15, ));
Then reach the API through one accessor per controller:
// Fetch, addressed by id OR code (never both). $debtor = $wefact->debtors()->get(id: 42); $debtor = $wefact->debtors()->get(code: 'DB10000'); // List with filtering, sorting and paging. $page = $wefact->debtors()->list(searchAt: 'EmailAddress', searchFor: 'a@b.nl', limit: 20); foreach ($page as $debtor) { echo $debtor->companyName, PHP_EOL; } echo $page->totalResults; // total matching records, not just this page // Create — pass a plain array or a DTO. $product = $wefact->products()->create([ 'ProductName' => 'Hosting', 'PriceExcl' => 10.0, 'TaxCode' => 'V21', ]); // Update, identified by id or code. $wefact->products()->update(['PriceExcl' => 12.5], code: $product->code); // Delete. $wefact->products()->delete(code: $product->code);
The call pattern
$wefact->{resource}()->{action}(named args…): DTO | Collection<DTO> | void
{resource}()— a lazy, memoised accessor per WeFact controller (debtors(),invoices(),products(), …). See the resource map.{action}()— a typed method per API action (get,list,create,update,delete, plus lifecycle actions likeinvoices()->credit()orinvoices()->markAsPaid()).- Reads return a readonly DTO (or a
Collection<DTO>for lists); mutations return the updated DTO orvoid.
Addressing records: id: or code:
Every identifiable record is addressed by either its numeric id: or its
human-readable code: (DebtorCode, InvoiceCode, …) — never both, never neither.
Passing both or neither throws a ValidationException before any request is sent. Some
records (groups, subscriptions, tasks, …) have no code and take only id:.
$wefact->invoices()->get(id: 10); // ok $wefact->invoices()->get(code: 'F2024-0001'); // ok $wefact->invoices()->get(); // ValidationException — missing identifier $wefact->invoices()->get(id: 10, code: 'F…'); // ValidationException — ambiguous
Error handling
Every failure is a typed exception extending Jarrin\WeFactApiClient\Exceptions\WeFactException:
| Exception | When |
|---|---|
ValidationException |
Bad arguments caught locally (ambiguous/missing identifier) — no request sent |
AuthenticationException |
HTTP 403 — blocked key or non-whitelisted IP |
ApiException |
The API returned an error envelope (carries ->errors, ->apiController, ->apiAction) |
TransportException |
Network failure or an undecodable/unexpected response |
use Jarrin\WeFactApiClient\Exceptions\ApiException; use Jarrin\WeFactApiClient\Exceptions\WeFactException; try { $wefact->debtors()->get(code: 'DB-does-not-exist'); } catch (ApiException $e) { report($e->errors); // list<string> of API messages } catch (WeFactException $e) { // any other client failure }
Laravel
The package auto-registers a service provider and a WeFact facade — no manual wiring.
php artisan vendor:publish --tag=wefact-config
// config/wefact.php reads WEFACT_API_KEY / WEFACT_BASE_URI / WEFACT_TIMEOUT from .env use Jarrin\WeFactApiClient\WeFact; use WeFact as WeFactFacade; // the registered facade alias public function handle(WeFact $wefact) // resolved from the container as a singleton { $wefact->invoices()->list(limit: 10); } WeFactFacade::debtors()->get(code: 'DB10000'); // or via the facade
The standalone client never loads Laravel; the Laravel layer is optional and dev-only in this package's own test suite. See docs/configuration.md.
CLI: seeding a test administration
The package ships a small Symfony Console binary for populating a dedicated test administration with a known, reversible fixture set (all through the typed client):
vendor/bin/wefact seed # find-or-create the fixtures (idempotent) vendor/bin/wefact seed --wipe # remove the deletable ones again vendor/bin/wefact seed --fresh # wipe, then re-seed
It reads WEFACT_API_KEY (falling back to API_SECRET) from the environment. See
docs/testing.md.
Development
The entire toolchain runs in one pinned PHP 8.3 Docker image, so contributing needs no
PHP on your host. The bin/dev wrapper runs any command in it:
bin/dev composer test # offline suite bin/dev composer stan # PHPStan (max) bin/dev composer docs:api # regenerate the API reference (phpDocumentor) bin/dev bin/wefact seed # seed a test administration
The pre-commit hook (composer hooks:install) runs the full gate in that image. See
docs/development.md and docs/testing.md.
Documentation
- Getting started
- Configuration
- Resources & the call pattern
- DTOs & enums
- Error handling
- Testing, Docker & seeding
- Development & extending the client
- Generated API reference — per-class, produced by
composer docs:api
License
MIT.
jarrin/wefact-php-sdk 适用场景与选型建议
jarrin/wefact-php-sdk 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 07 月 15 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「api」 「client」 「laravel」 「billing」 「invoicing」 「wefact」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 jarrin/wefact-php-sdk 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 jarrin/wefact-php-sdk 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 jarrin/wefact-php-sdk 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A PSR-7 compatible library for making CRUD API endpoints
Mock PSR-18 HTTP client
Asynchronous MQTT client built on React
Client for Google Directions API to add interpolated points to a route consisting of given coordinates.
Alfabank REST API integration
A Flickr wrapper to allow you to call the Flickr api with Guzzle as the backend.Goal is to have 100% Flickr api coverage rather than just upload/display photos (currently at 23%).
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-15