Download the PHP package devrkb21/czbd-courier without Composer

On this page you can find all versions of the php package devrkb21/czbd-courier. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package czbd-courier

CZBD Courier Checker

A Laravel package that checks a customer's delivery history — success count, cancel count, and success ratio — across the major courier services operating in Bangladesh, using a single phone number. Built for e-commerce merchants who want to flag likely-fraudulent or high-cancel-rate customers before dispatching a COD (cash-on-delivery) order.

Latest Version on Packagist Total Downloads License

Table of Contents

What It Does

How It Works

Integration method per courier

Not all five couriers are integrated the same way, because most don't offer a public "check this phone number's fraud history" API — the package logs in as your merchant account and calls the same endpoints their own merchant dashboard uses:

Courier Integration method Session caching
Steadfast Logs into the merchant web portal (steadfast.com.bd), scraping a CSRF token from the login page HTML, then calls the dashboard's internal getbyphone endpoint. Session cookies are maintained via a real Guzzle cookie jar so redirects (e.g. an interstitial page mid-login) don't lose state. Cookies cached ~50 min per account
Pathao Uses Pathao's merchant web login endpoint (merchant.pathao.com/api/v1/login) to obtain a Bearer token, then calls the internal customer-success endpoint. Token cached, TTL follows Pathao's own expires_in when present, else ~50 min
RedX Uses RedX's merchant web login endpoint to obtain a Bearer access token, then calls the internal customer success/return-rate endpoint. Token cached ~50 min per account
Paperfly Uses Paperfly's Merchant Reactor API login endpoint to obtain a token, then calls their "Smart Check" search endpoint and derives success/cancel counts from the returned record statuses. Token cached ~55 min per account
Carrybee Drives Carrybee's NextAuth-based login flow (CSRF → credentials callback → session) to obtain a Bearer token + business ID, then calls the merchant API's customer lookup endpoint. Token + business ID cached ~55 min per account

Because these are internal/merchant-dashboard endpoints rather than documented public APIs, they can change without notice — see Known Limitations.

Supported Couriers

Requirements

Installation

Laravel auto-discovers the service provider (Czbd\CourierChecker\CourierCheckerServiceProvider) and the CourierChecker facade alias via the package's composer.json — no manual registration needed.

Publish the config file (optional — see below):

This creates config/courier-checker.php in your application. You can also use Laravel's generic config tag:

Publishing the config is optional — the package ships with sane defaults (all values pulled from env()), so you only need to publish it if you want to inspect or customize the structure.

Quick Start

The fastest path from zero to a working check:

  1. composer require devrkb21/czbd-courier
  2. Add credentials for at least one courier to your .env (see Environment Configuration — you don't need all five):

  3. Call it:

  4. $report always has a key for every courier plus aggregate — couriers you didn't configure just report {"error": "... is not configured", ...} instead of breaking anything. See Response Shape.

Environment Configuration

Add credentials to your application's .env file. Every courier takes exactly two env vars — one for the credential list, one for the matching secret list. There is no separate "primary account" variable; the first entry in each list is simply tried first.

You only need to configure the couriers you actually want to query. Any courier left blank simply reports {"error": "<courier> is not configured", "message": "..."} in the result instead of breaking the whole check() call — see Error Handling.

Quoting note: wrap every value in double quotes in .env, especially passwords that contain #, spaces, or other special characters — an unquoted # is treated as a comment start by most dotenv parsers and will silently truncate the value.

Multi-Account Failover Pools

Every courier accepts a single comma- or newline-separated list per field (e.g. STEADFAST_USERS / STEADFAST_PASSWORDS). This is how you configure multiple accounts per courier for redundancy and to avoid rate limits:

Rules:

Proxy Routing

Usage

Using the facade

Using dependency injection

Using individual courier service classes

Useful if you only care about one courier, or want to bypass the aggregation:

Every service implements Czbd\CourierChecker\Contracts\CourierServiceInterface, so you can type-hint the interface and swap implementations (e.g. in tests) freely.

A practical example: gating COD orders

Phone number format

Always use the local 11-digit format: 01[3-9]XXXXXXXX (e.g. 01712345678). Do not include +88 or 88 — the package adds the country code internally wherever a specific courier's API requires it. Any other format is rejected before any HTTP request is made (see Error Handling).

Response Shape

CourierChecker::check() / CourierCheckerManager::check() always returns all five courier keys plus an aggregate block, regardless of which couriers succeeded:

Any courier that failed reports an error array instead (see below) in place of its success/cancel/total block, and is simply excluded from the aggregate totals (only couriers that returned numeric success/cancel values are counted). Field reference:

Field Meaning
success Number of delivered/successful orders for this phone number at this courier
cancel Number of cancelled/returned/failed orders
total Total order count considered (courier-specific — see per-courier notes above for Paperfly)
success_ratio success / total * 100, rounded to 2 decimals; 0 if total is 0
customer_rating Pathao only — Pathao's own customer classification (e.g. excellent_customer, new_customer), or null
aggregate.total_deliveries Sum of success + cancel across every courier that returned real data

Error Handling

Errors happen at two levels — a per-courier getDeliveryStats() call never throws; it always returns an array, either real data or an error description:

At the CourierCheckerManager::check() level, if a service somehow throws an uncaught exception anyway, it's caught, logged via Log::error() (message, phone number, and stack trace), and converted into:

Validation: every phone number is validated against ^01[3-9][0-9]{8}$ before any network call is made. An invalid phone number produces an error result for that courier (or, if you call an individual service directly, the same error array) rather than throwing — this keeps the aggregation loop uninterrupted even on bad input.

How to detect an error in your own code:

Performance: Caching and Rate Limiting

Session/token caching (the main speed lever)

Every one of the five services caches its authenticated session per account using Laravel's default cache store, so repeat calls skip the login round-trip entirely instead of re-authenticating on every single check():

Service What's cached TTL
Steadfast Session cookies (as a plain array, rebuilt into a Guzzle cookie jar on reuse) ~50 min
Pathao Bearer access token Follows Pathao's own expires_in when present, else ~50 min
RedX Bearer access token ~50 min
Paperfly Access token ~55 min
Carrybee Bearer access token + business ID ~55 min

Cache keys are namespaced per courier and per account (an MD5 hash of the account's username/phone), so different accounts in the same pool never collide. If a cached session turns out to be stale — the courier redirects back to a login page, or returns a 401 — it's evicted automatically and the account falls back to a fresh login on the very next attempt (not the next check() call — the fallback happens within the same request, so you still get a real result, just without the cache-hit speed benefit for that one call).

In practice: a cold call (no cache yet, or every account's cache expired) authenticates from scratch for every courier — this is the slow path. A warm call (recent cache present) reduces most couriers to a single HTTP request each. In testing, this took a full check() from roughly 18 seconds cold to roughly 8 seconds warm.

Why couriers are fetched one at a time, not concurrently

An earlier version of this package attempted to run all five couriers concurrently using Guzzle's async/promise API. It was reverted after testing showed it was unreliable, not a real improvement: Guzzle's promise-settling mechanism (EachPromise) resolves a batch of promises through an internal sequential wait() loop, which only gives genuine parallelism for flat, single-step requests (exactly what Laravel's Http::pool() is designed for). It does not reliably parallelize the kind of multi-step, stateful flows every courier here uses (login → fetch, with account failover) — in testing, the "concurrent" version was sometimes no faster than sequential and occasionally slower. Sequential-but-cached turned out to be the reliable, correct choice. If you're extending this package and are tempted to reach for getDeliveryStatsAsync() to parallelize things yourself, be aware of this limitation first.

Rate limiting

There is no built-in throttling — no delay between account attempts, no backoff, no cross-call cooldown tracking beyond the session caching described above. What exists is purely reactive, and it works the same way across all five couriers:

Practical takeaway: the more accounts you configure per courier, the more resilient you are to any single account hitting a courier's rate limit or bot detection — since the pool automatically moves to the next one on any failure. A courier with only one configured account has nowhere to fail over to. Session caching also indirectly reduces how often you hit rate limits at all, since it means far fewer login attempts overall.

Testing

From the package root:

Tests use Http::fake() mocked HTTP responses throughout — live courier credentials are not required to run the test suite, and no real network requests are made.

Security Notes

Known Limitations

Troubleshooting

License

This package is licensed under GPL-3.0-only. See LICENSE.md.

Maintainer


All versions of czbd-courier with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/support Version ^8.0|^9.0|^10.0|^11.0|^12.0|^13.0
illuminate/http Version ^8.0|^9.0|^10.0|^11.0|^12.0|^13.0
guzzlehttp/guzzle Version ^7.8
guzzlehttp/promises Version ^2.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package devrkb21/czbd-courier contains the following files

Loading the files please wait ...