定制 parcora/parcora-php 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

parcora/parcora-php

Composer 安装命令:

composer require parcora/parcora-php

包简介

PHP SDK for the Parcora shipping API.

README 文档

README

The official PHP SDK for the Parcora shipping API — one REST API for parcel delivery across Europe: shipments, bulk batches, labels, lockers, rates, tracking and webhooks.

  • Typed, read-only models and enums — full IDE autocomplete, no array guessing.
  • Works with any PSR-18 HTTP client.
  • Automatic idempotency keys on writes, cursor auto-pagination, and a typed exception per error category.

Requirements

  • PHP 8.2+
  • A PSR-18 HTTP client and PSR-17 factories (e.g. guzzlehttp/guzzle or symfony/http-client + nyholm/psr7).

Installation

composer require parcora/parcora-php guzzlehttp/guzzle

Any PSR-18 client works; Guzzle is just the easiest to start with. The SDK auto-discovers an installed client, or you can inject your own (see Configuration).

Quick start

$client = new \Parcora\Client('dp_test_…'); // your secret API key

$shipment = $client->shipments->create([
    'carrier' => 'omniva',
    'service' => 'omniva.courier',
    'sender'   => ['name' => 'Shop', 'line1' => 'Gedimino 1', 'city' => 'Vilnius', 'postcode' => '01103', 'country' => 'LT'],
    'receiver' => ['name' => 'Anna', 'line1' => 'Brivibas 1', 'city' => 'Riga', 'postcode' => 'LV-1010', 'country' => 'LV'],
    'parcels'  => [['weight_grams' => 1000]],
]);

echo $shipment->id;                 // shp_…
echo $shipment->status->value;      // "registered"  (ShipmentStatus enum)
echo $shipment->trackingCode;       // dp_trk_…

file_put_contents('label.pdf', $client->shipments->label($shipment->id, ['format' => 'pdf_a4']));

Use a dp_test_… key for test mode and dp_live_… for production — same code, different key.

Resources

Shipments

$client->shipments->create([...]);
$client->shipments->retrieve('shp_123');
$client->shipments->cancel('shp_123');
$client->shipments->addLeg('shp_123', ['type' => 'return', 'carrier' => 'omniva', 'service' => 'omniva.courier']);
$client->shipments->label('shp_123', ['format' => 'pdf_a4']); // raw bytes
$client->shipments->slip('shp_123');                          // raw PDF bytes
$client->shipments->trackingEvents('shp_123');                // list<TrackingEvent>

foreach ($client->shipments->all(['status' => 'in_transit'])->autoPaging() as $shipment) {
    // …every shipment across every page
}

Bulk batches

$batch = $client->shipmentBatches->create([
    'shipments' => [ [...], [...], [...] ], // same shape as shipments->create
]);

$batch = $client->shipmentBatches->retrieve($batch->id);
echo $batch->status->value;          // processing → completed / completed_with_errors
echo $batch->counts->succeeded;

foreach ($client->shipmentBatches->items($batch->id)->autoPaging() as $item) {
    echo $item->status->value;       // succeeded / failed
    echo $item->shipment ?? $item->error?->message;
}

file_put_contents('labels.pdf', $client->shipmentBatches->labels($batch->id)); // merged sheet

Carriers, pickup points, rates, trackers

foreach ($client->carriers->all() as $carrier) {
    echo $carrier->carrier->value, $carrier->connected ? '' : '';
}

$client->pickupPoints->all(['carrier' => 'omniva', 'country' => 'EE']);
$client->rates->calculate(['sender' => [...], 'receiver' => [...], 'parcels' => [...]]); // list<Rate>
$client->trackers->retrieve('dp_trk_…'); // Tracker with its event timeline

Webhook endpoints

$endpoint = $client->webhookEndpoints->create([
    'url'    => 'https://example.com/webhooks/parcora',
    'events' => ['shipment.delivered', 'shipment_batch.completed'],
]);
echo $endpoint->secret; // shown once — store it to verify deliveries

$client->webhookEndpoints->all();
$client->webhookEndpoints->retrieve($endpoint->id);
$client->webhookEndpoints->delete($endpoint->id);

Pagination

List methods return a Collection. Use it directly for one page, or ->autoPaging() to stream every page lazily (the SDK passes starting_after for you):

$page = $client->shipments->all(['limit' => 100]);
count($page);          // items on this page
$page->hasMore;        // is there another page?
$page->first();

foreach ($page->autoPaging() as $shipment) { /* all pages */ }

Errors

Every API error throws a typed exception extending Parcora\Exception\ApiErrorException, chosen from the error type:

Exception When
InvalidRequestException validation_error (422) — see ->param
AuthenticationException authentication_error (401)
PermissionException permission_error (403)
NotFoundException not_found (404)
RateLimitException rate_limit_error (429) — see ->retryAfter
BillingException billing_error (402)
CarrierException carrier_error — see ->carrierMessage
IdempotencyException idempotency_error
ApiException server / unexpected errors
ApiConnectionException the request never reached the API
use Parcora\Exception\InvalidRequestException;
use Parcora\Exception\ApiErrorException;

try {
    $client->shipments->create([...]);
} catch (InvalidRequestException $e) {
    echo $e->param;        // "receiver.postcode"
    echo $e->getMessage();
} catch (ApiErrorException $e) {
    echo $e->errorType, $e->errorCode, $e->requestId;
}

Idempotency

Writes (POST) automatically carry an Idempotency-Key so transient network retries can't double-create. Pass your own to make a specific call replay-safe:

$client->shipments->create([...], ['idempotency_key' => 'order-12345']);

Verifying webhooks

use Parcora\Webhook;
use Parcora\Exception\SignatureVerificationException;

try {
    $event = Webhook::constructEvent(
        $payload,                              // raw request body
        $request->header('Webhook-Signature'), // the signature header
        $endpointSecret,                       // from webhookEndpoints->create()->secret
    );
} catch (SignatureVerificationException $e) {
    http_response_code(400);
    exit;
}

echo $event->type;          // "shipment.delivered"
echo $event->data['id'];    // the event's data.object

Configuration

$client = new \Parcora\Client('dp_live_…', [
    'base_url'            => 'https://api.parcora.eu', // override for self-hosted
    'http_client'         => $myPsr18Client,           // inject any PSR-18 client
    'request_factory'     => $myPsr17RequestFactory,
    'stream_factory'      => $myPsr17StreamFactory,
    'max_network_retries' => 2,                        // retry transport / 5xx / 429
]);

Development

composer install
composer test    # pest
composer stan    # phpstan (max)
composer lint    # pint --test

License

MIT — see LICENSE.

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-16

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固