承接 kejubayer/redx-api-integration 相关项目开发

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

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

kejubayer/redx-api-integration

最新稳定版本:1.0.4

Composer 安装命令:

composer require kejubayer/redx-api-integration

包简介

Laravel package for integrating the RedX API and storing RedX webhook requests.

README 文档

README

kejubayer/redx-api-integration is a Laravel package for RedX courier API integration in Bangladesh. It provides a simple RedX HTTP client, configurable API endpoints, a webhook route, and automatic storage of RedX webhook payloads in a database table.

Use this package to create RedX parcels, track parcels, cancel parcels, call configured RedX API endpoints, and receive RedX delivery status webhook updates in your Laravel application.

Features

  • Laravel auto-discovery support
  • RedX API client using Laravel HTTP client
  • Configurable RedX base URL, API token header, timeout, and endpoints
  • Easy named methods for common RedX endpoints
  • Generic endpoint-name helpers for all custom RedX endpoints
  • Built-in RedX webhook route
  • Stores every webhook request in redx_webhook_requests
  • Extracts searchable webhook fields like tracking number, status, invoice number, and delivery type
  • Optional webhook shared-secret protection
  • Event dispatch after every stored webhook request
  • Supports Laravel 10, Laravel 11, and Laravel 12

Requirements

  • PHP 8.1 or higher
  • Laravel 10, 11, or 12
  • Composer

Installation

Install the package with Composer:

composer require kejubayer/redx-api-integration

Publish the configuration file:

php artisan vendor:publish --tag=redx-config

Publish the migration:

php artisan vendor:publish --tag=redx-migrations

Run the migration:

php artisan migrate

Environment Variables

Add your RedX API credentials to .env:

REDX_BASE_URL=https://openapi.redx.com.bd/v1.0.0-beta
REDX_API_TOKEN="Bearer your-redx-jwt-token"
REDX_TOKEN_HEADER=API-ACCESS-TOKEN
REDX_TIMEOUT=30

REDX_WEBHOOK_ENABLED=true
REDX_WEBHOOK_PATH=redx/webhook

Optional webhook secret protection:

REDX_WEBHOOK_SECRET=your-shared-secret
REDX_WEBHOOK_SECRET_HEADER=X-Redx-Webhook-Secret

RedX expects the token in this HTTP header:

API-ACCESS-TOKEN: Bearer your-redx-jwt-token

So REDX_TOKEN_HEADER is the header name, and REDX_API_TOKEN is the full header value.

Configuration

After publishing, the config file is available at:

config/redx-api-integration.php

Default endpoint configuration:

'endpoints' => [
    'create_parcel' => env('REDX_CREATE_PARCEL_ENDPOINT', '/parcel'),
    'parcel_details' => env('REDX_PARCEL_DETAILS_ENDPOINT', '/parcel/{parcel_id}'),
    'track_parcel' => env('REDX_TRACK_PARCEL_ENDPOINT', '/parcel/track/{tracking_id}'),
    'cancel_parcel' => env('REDX_CANCEL_PARCEL_ENDPOINT', '/parcel/{parcel_id}/cancel'),
    'areas' => env('REDX_AREAS_ENDPOINT', '/areas'),
    'stores' => env('REDX_STORES_ENDPOINT', '/stores'),
],

If your RedX merchant account uses different endpoint paths, update the config or set these .env values:

REDX_CREATE_PARCEL_ENDPOINT=/parcel
REDX_PARCEL_DETAILS_ENDPOINT=/parcel/{parcel_id}
REDX_TRACK_PARCEL_ENDPOINT=/parcel/track/{tracking_id}
REDX_CANCEL_PARCEL_ENDPOINT=/parcel/{parcel_id}/cancel
REDX_AREAS_ENDPOINT=/areas
REDX_STORES_ENDPOINT=/stores

Basic Usage

Use the facade:

use Kejubayer\RedxApiIntegration\Facades\Redx;

$data = Redx::createParcel([
    'customer_name' => 'Customer Name',
    'customer_phone' => '01700000000',
    'delivery_area' => 'Dhaka',
    'delivery_area_id' => 1,
    'customer_address' => 'Dhaka, Bangladesh',
    'cash_collection_amount' => 1000,
    'parcel_weight' => 1,
    'value' => 1000,
]);

Use dependency injection:

use Kejubayer\RedxApiIntegration\RedxApiIntegration;

class ParcelController
{
    public function store(RedxApiIntegration $redx)
    {
        return $redx->createParcel([
            'customer_name' => 'Customer Name',
            'customer_phone' => '01700000000',
            'delivery_area' => 'Dhaka',
            'delivery_area_id' => 1,
            'customer_address' => 'Dhaka, Bangladesh',
            'cash_collection_amount' => 1000,
            'parcel_weight' => 1,
            'value' => 1000,
        ]);
    }
}

Available Methods

Quick method list:

Method Purpose
Redx::createParcel($payload) Create a RedX parcel
Redx::parcelDetails($parcelId) Get parcel details
Redx::trackParcel($trackingId) Track parcel by tracking number
Redx::cancelParcel($parcelId, $payload) Cancel parcel
Redx::areas($query) Get RedX areas
Redx::stores($query) Get RedX stores
Redx::getEndpoint($name, $replacements, $query) Call a configured GET endpoint
Redx::postEndpoint($name, $payload, $replacements) Call a configured POST endpoint
Redx::putEndpoint($name, $payload, $replacements) Call a configured PUT endpoint
Redx::patchEndpoint($name, $payload, $replacements) Call a configured PATCH endpoint
Redx::deleteEndpoint($name, $payload, $replacements) Call a configured DELETE endpoint
Redx::callEndpoint($method, $name, $payload, $replacements) Call any configured endpoint dynamically
Redx::endpoint($name, $replacements) Resolve a configured endpoint path
Redx::get($uri, $query) Raw GET request
Redx::post($uri, $payload) Raw POST request
Redx::put($uri, $payload) Raw PUT request
Redx::patch($uri, $payload) Raw PATCH request
Redx::delete($uri, $payload) Raw DELETE request
Redx::request() Get the configured Laravel HTTP client
Redx::getResponse($uri, $query) Raw GET request with Laravel response object
Redx::postResponse($uri, $payload) Raw POST request with Laravel response object
Redx::putResponse($uri, $payload) Raw PUT request with Laravel response object
Redx::patchResponse($uri, $payload) Raw PATCH request with Laravel response object
Redx::deleteResponse($uri, $payload) Raw DELETE request with Laravel response object

createParcel

Create a new RedX parcel.

use Kejubayer\RedxApiIntegration\Facades\Redx;

$parcel = Redx::createParcel([
    'customer_name' => 'Customer Name',
    'customer_phone' => '01700000000',
    'delivery_area' => 'Dhaka',
    'delivery_area_id' => 1,
    'customer_address' => 'House 1, Road 2, Dhaka',
    'merchant_invoice_id' => 'INV-1001',
    'cash_collection_amount' => '1500',
    'parcel_weight' => 1,
    'instruction' => 'Handle with care',
    'value' => 1500,
    'is_closed_box' => false,
    'pickup_store_id' => 1,
    'parcel_details_json' => [
        [
            'name' => 'Product name',
            'category' => 'Product category',
            'value' => 1500,
        ],
    ],
]);

Required RedX create parcel fields usually include:

customer_name, customer_phone, delivery_area, delivery_area_id,
customer_address, cash_collection_amount, parcel_weight, value

Use merchant_invoice_id for your invoice number when creating a parcel. Webhook payloads may return that value as invoice_number.

parcelDetails

Get RedX parcel details by parcel ID.

$parcel = Redx::parcelDetails(12345);

trackParcel

Track a parcel by RedX tracking number.

$tracking = Redx::trackParcel('25A223SU17V6CH');

cancelParcel

Cancel a parcel by parcel ID.

$result = Redx::cancelParcel(12345, [
    'reason' => 'Customer cancelled the order',
]);

areas

Get RedX delivery areas.

$areas = Redx::areas();

With query parameters:

$areas = Redx::areas([
    'district' => 'Dhaka',
]);

stores

Get RedX stores.

$stores = Redx::stores();

Easy Use For All Endpoints

You can add any RedX API endpoint to config/redx-api-integration.php and call it by name.

Example config:

'endpoints' => [
    'create_parcel' => '/parcel',
    'parcel_details' => '/parcel/{parcel_id}',
    'track_parcel' => '/parcel/track/{tracking_id}',
    'my_custom_endpoint' => '/merchant/custom/{id}',
],

Call a configured GET endpoint:

$data = Redx::getEndpoint(
    name: 'my_custom_endpoint',
    replacements: ['id' => 123],
    query: ['page' => 1]
);

Call a configured POST endpoint:

$data = Redx::postEndpoint(
    name: 'create_parcel',
    payload: [
        'customer_name' => 'Customer Name',
        'customer_phone' => '01700000000',
    ]
);

Call a configured PUT endpoint:

$data = Redx::putEndpoint(
    name: 'my_custom_endpoint',
    payload: ['status' => 'updated'],
    replacements: ['id' => 123]
);

Call a configured PATCH endpoint:

$data = Redx::patchEndpoint(
    name: 'my_custom_endpoint',
    payload: ['status' => 'updated'],
    replacements: ['id' => 123]
);

Call a configured DELETE endpoint:

$data = Redx::deleteEndpoint(
    name: 'my_custom_endpoint',
    payload: ['reason' => 'Not needed'],
    replacements: ['id' => 123]
);

Call any configured endpoint dynamically:

$data = Redx::callEndpoint(
    method: 'post',
    name: 'my_custom_endpoint',
    payload: ['key' => 'value'],
    replacements: ['id' => 123]
);

Resolve only the endpoint path:

$uri = Redx::endpoint('parcel_details', [
    'parcel_id' => 12345,
]);

// Result: /parcel/12345

get

Call any RedX GET endpoint.

$data = Redx::get('/parcel/track/25A223SU17V6CH');

post

Call any RedX POST endpoint.

$data = Redx::post('/parcel', [
    'customer_name' => 'Customer Name',
    'customer_phone' => '01700000000',
]);

put

Call any RedX PUT endpoint.

$data = Redx::put('/parcel/12345', [
    'customer_address' => 'Updated address, Dhaka',
]);

patch

Call any RedX PATCH endpoint.

$data = Redx::patch('/parcel/12345', [
    'customer_address' => 'Updated address, Dhaka',
]);

delete

Call any RedX DELETE endpoint.

$data = Redx::delete('/parcel/12345');

With a request body:

$data = Redx::delete('/parcel/12345', [
    'reason' => 'Duplicate order',
]);

request

Get the configured Laravel HTTP pending request instance.

$response = Redx::request()
    ->withHeaders(['X-Custom-Header' => 'value'])
    ->post('/custom-endpoint', [
        'key' => 'value',
    ]);

Webhook Route

The package registers this route by default:

POST /redx/webhook

You can change the route path:

REDX_WEBHOOK_PATH=api/redx/webhook

You can disable the route:

REDX_WEBHOOK_ENABLED=false

RedX Webhook Payload Structure

Expected RedX webhook JSON payload:

{
    "tracking_number": "<REDX_TRACKING_ID>",
    "timestamp": "<TIMESTAMP>",
    "status": "<STATUS>",
    "message_en": "<MESSAGE_EN>",
    "message_bn": "<MESSAGE_BN>",
    "invoice_number": "<INVOICE_NUMBER>",
    "delivery_type": "<DELIVERY_TYPE>"
}

Example payload:

{
    "tracking_number": "25A223SU17V6CH",
    "timestamp": "2026-05-12 10:30:00",
    "status": "delivered",
    "message_en": "Parcel has been delivered",
    "message_bn": "Bangla delivery status message",
    "invoice_number": "INV-1001",
    "delivery_type": "regular"
}

Webhook Database Structure

Webhook requests are stored in the redx_webhook_requests table.

Column Type Description
id integer Primary key
tracking_number string, nullable RedX tracking number
redx_timestamp timestamp, nullable Timestamp sent by RedX
status string, nullable Parcel status
message_en string, nullable English status message
message_bn string, nullable Bangla status message
invoice_number string, nullable Merchant invoice number
delivery_type string, nullable RedX delivery type
payload json Full webhook payload
headers json, nullable Request headers
ip_address string, nullable Sender IP address
user_agent string, nullable Request user agent
signature string, nullable Signature header value, when available
processed_at timestamp, nullable Processing timestamp for your application
created_at timestamp Created timestamp
updated_at timestamp Updated timestamp

Webhook Model

The default model is:

Kejubayer\RedxApiIntegration\Models\RedxWebhookRequest

Query stored webhooks:

use Kejubayer\RedxApiIntegration\Models\RedxWebhookRequest;

$latest = RedxWebhookRequest::query()
    ->latest()
    ->take(10)
    ->get();

Find webhook requests by tracking number:

$requests = RedxWebhookRequest::query()
    ->where('tracking_number', '25A223SU17V6CH')
    ->get();

Find delivered parcels:

$delivered = RedxWebhookRequest::query()
    ->where('status', 'delivered')
    ->get();

Mark a webhook request as processed:

$webhookRequest->markAsProcessed();

Use your own model:

'webhook_model' => App\Models\RedxWebhookRequest::class,

Your custom model should extend the package model or provide the same fillable columns.

Webhook Event

After storing a webhook request, the package dispatches:

Kejubayer\RedxApiIntegration\Events\RedxWebhookReceived

Listen for the event:

use Illuminate\Support\Facades\Event;
use Kejubayer\RedxApiIntegration\Events\RedxWebhookReceived;

Event::listen(RedxWebhookReceived::class, function (RedxWebhookReceived $event) {
    $webhookRequest = $event->webhookRequest;

    if ($webhookRequest->status === 'delivered') {
        // Update your order status here.
    }
});

Create a listener:

php artisan make:listener ProcessRedxWebhook

Example listener:

namespace App\Listeners;

use Kejubayer\RedxApiIntegration\Events\RedxWebhookReceived;

class ProcessRedxWebhook
{
    public function handle(RedxWebhookReceived $event): void
    {
        $webhookRequest = $event->webhookRequest;

        // Match your order by invoice number or tracking number.
        $invoiceNumber = $webhookRequest->invoice_number;
        $status = $webhookRequest->status;

        $webhookRequest->markAsProcessed();
    }
}

Secure Webhooks

Set a shared secret in your .env:

REDX_WEBHOOK_SECRET=your-shared-secret
REDX_WEBHOOK_SECRET_HEADER=X-Redx-Webhook-Secret

RedX must send the same secret value in the configured header. If the secret does not match, the package returns 403 Forbidden.

Testing Webhook Locally

You can test the webhook route with curl:

curl -X POST "https://your-app.test/redx/webhook" \
  -H "Content-Type: application/json" \
  -d '{
    "tracking_number": "25A223SU17V6CH",
    "timestamp": "2026-05-12 10:30:00",
    "status": "delivered",
    "message_en": "Parcel has been delivered",
    "message_bn": "Bangla delivery status message",
    "invoice_number": "INV-1001",
    "delivery_type": "regular"
  }'

With webhook secret:

curl -X POST "https://your-app.test/redx/webhook" \
  -H "Content-Type: application/json" \
  -H "X-Redx-Webhook-Secret: your-shared-secret" \
  -d '{
    "tracking_number": "25A223SU17V6CH",
    "timestamp": "2026-05-12 10:30:00",
    "status": "delivered",
    "message_en": "Parcel has been delivered",
    "message_bn": "Bangla delivery status message",
    "invoice_number": "INV-1001",
    "delivery_type": "regular"
  }'

Raw Response Usage

Normal package methods return PHP arrays directly. If you need the raw Laravel Illuminate\Http\Client\Response object, use the *Response methods or request().

$response = Redx::getResponse('/parcel/track/25A223SU17V6CH');

if ($response->successful()) {
    return $response->json();
}

if ($response->failed()) {
    report($response->body());
}

$response->throw();

Error Handling

Because normal methods return arrays, RedX validation errors are available directly:

$data = Redx::createParcel($payload);

if (isset($data['validation_errors'])) {
    return $data['validation_errors'];
}

License

The MIT License.

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-05-12

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固