smart-dato / sf-express-sdk
SF Express international open API SDK for Laravel
Fund package maintenance!
Requires
- php: ^8.2|^8.5
- ext-openssl: *
- illuminate/contracts: ^10.0||^11.0||^12.0||^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^2.9||^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^10.0.0||^9.0.0||^8.22.0
- pestphp/pest: ^3.0
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: ^3.0
- phpstan/extension-installer: ^1.3||^2.0
- phpstan/phpstan-deprecation-rules: ^1.1||^2.0
- phpstan/phpstan-phpunit: ^1.3||^2.0
- spatie/laravel-ray: ^1.35
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-23 07:28:17 UTC
README
A Laravel package for the SF Express international open API. It creates shipments, queries order details and fetches tracking, handling the API's AES message encryption and request signing for you.
Requirements
- PHP 8.2+
- Laravel 10 – 13
- The
opensslPHP extension
Installation
composer require smart-dato/sf-express-sdk
Usage
Construct the client with your SF Express base URL and credentials:
use SmartDato\SfExpress\SfExpress; $sf = new SfExpress( baseUrl: 'https://api-ifsp-sit.sf.global', // SF's SIT (sandbox) environment appKey: 'your-app-key', appSecret: 'your-app-secret', encodingAesKey: 'your-encoding-aes-key', );
The constructor authenticates immediately — it calls /openapi/api/token and throws SfExpressGenericException if SF rejects the credentials. Build the client when you are about to make calls, not eagerly at boot.
A config file maps
SF_EXPRESS_API_KEYandSF_EXPRESS_SECRETtosf-express-sdk.app.keyand.secret, but it is only consulted for the token request. The base URL has no config fallback, and the app key is also needed for signing, so pass all four arguments explicitly. For the same reason the registeredSfExpressfacade cannot be used as-is.
Every method takes the request as a JSON string. The payload classes build that string for you with toJson().
Create a shipment
Sends an IUOP_CREATE_ORDER message.
use SmartDato\SfExpress\Enums\Shipment\CurrencyEnum; use SmartDato\SfExpress\Enums\Shipment\InterProductCodeEnum; use SmartDato\SfExpress\Payloads\ParcelInfoPayload; use SmartDato\SfExpress\Payloads\PaymentInfoPayload; use SmartDato\SfExpress\Payloads\ShipmentPayload; use SmartDato\SfExpress\Payloads\ShippingPartyPayload; $payload = new ShipmentPayload( customerCode: 'your-customer-code', interProductCode: InterProductCodeEnum::INT0014, parcelQuantity: 1, customerOrderNumber: 'order-1001', parcels: [ new ParcelInfoPayload( amount: 25.0, name: 'Gloves', eName: 'Gloves', originCountry: 'CN', quantity: 1, unit: 'your-unit', ), ], paymentInfo: new PaymentInfoPayload( payMethod: 'your-pay-method', payMonthCard: 'your-monthly-account', taxPayMethod: 'your-tax-pay-method', taxPayMonthCard: '', ), receiverInfo: new ShippingPartyPayload( address: 'Werner-Heisenberg-Allee 25', regionSecond: '106A', contact: 'Jane Doe', country: 'DE', postCode: '80939', regionFirst: 'München', phoneNumber: '+49 89 000000', email: 'jane@example.com', ), senderInfo: new ShippingPartyPayload( address: 'Bismarckstraße 122', regionSecond: '11A', contact: 'Sender GmbH', country: 'DE', postCode: '51373', regionFirst: 'Leverkusen', phoneNumber: '+49 214 000000', ), declaredValue: 25.0, declaredCurrency: CurrencyEnum::EUR, parcelTotalWeight: 0.4, parcelWeightUnit: 'kg', parcelTotalLength: 30, parcelTotalWidth: 20, parcelTotalHeight: 5, ); $result = $sf->createShipment($payload->toJson());
ShipmentPayload also accepts pickup, customs, extended-info and added-service details — see its constructor for the full list.
Query shipment details
Sends an IUOP_QUERY_ORDER message.
use SmartDato\SfExpress\Payloads\ShipmentDetailsPayload; $details = $sf->getShipmentDetails( (new ShipmentDetailsPayload(customerCode: 'your-customer-code', sfWaybillNumber: 'SF0000000000000'))->toJson() );
Track a shipment
Sends a GTS_QUERY_TRACK message.
use SmartDato\SfExpress\Payloads\TrackingPayload; $tracking = $sf->getTrackingStatus( (new TrackingPayload(sfWaybillNumbers: ['SF0000000000000'], phoneNumber: '0000'))->toJson() );
Each method returns the decrypted response decoded into an array. A non-zero apiResultCode from SF raises SfExpressGenericException with the code and message.
Testing
composer test
The tests that call SF's sandbox are skipped by default, since they need real credentials.
Changelog
Please see CHANGELOG for more information on what has changed recently.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.