{"id":49521835,"url":"https://github.com/aliziodev/laravel-biteship","last_synced_at":"2026-05-02T00:02:35.064Z","repository":{"id":354982788,"uuid":"1226291276","full_name":"aliziodev/laravel-biteship","owner":"aliziodev","description":"Package Laravel untuk integrasi API Biteship - aggregator pengiriman. Mempermudah perhitungan ongkir, pembuatan order, pelacakan, dan penanganan webhook di aplikasi Laravel Anda.","archived":false,"fork":false,"pushed_at":"2026-05-01T09:15:48.000Z","size":89,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-01T10:22:22.107Z","etag":null,"topics":["laravel-package","shipping-api"],"latest_commit_sha":null,"homepage":"https://deepwiki.com/aliziodev/laravel-biteship","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aliziodev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-01T07:53:09.000Z","updated_at":"2026-05-01T09:15:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aliziodev/laravel-biteship","commit_stats":null,"previous_names":["aliziodev/laravel-biteship"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/aliziodev/laravel-biteship","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliziodev%2Flaravel-biteship","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliziodev%2Flaravel-biteship/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliziodev%2Flaravel-biteship/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliziodev%2Flaravel-biteship/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aliziodev","download_url":"https://codeload.github.com/aliziodev/laravel-biteship/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliziodev%2Flaravel-biteship/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32517232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel-package","shipping-api"],"created_at":"2026-05-02T00:02:31.179Z","updated_at":"2026-05-02T00:02:35.057Z","avatar_url":"https://github.com/aliziodev.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel Biteship\n\n[![Tests](https://github.com/aliziodev/laravel-biteship/workflows/Tests/badge.svg)](https://github.com/aliziodev/laravel-biteship/actions)\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/aliziodev/laravel-biteship.svg)](https://packagist.org/packages/aliziodev/laravel-biteship)\n[![Total Downloads](https://img.shields.io/packagist/dt/aliziodev/laravel-biteship.svg)](https://packagist.org/packages/aliziodev/laravel-biteship)\n[![PHP Version](https://img.shields.io/packagist/php-v/aliziodev/laravel-biteship.svg)](https://packagist.org/packages/aliziodev/laravel-biteship)\n[![Laravel Version](https://img.shields.io/badge/Laravel-12.0%2B-orange.svg)](https://laravel.com/)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/aliziodev/laravel-biteship)\n\nLaravel package untuk integrasi [Biteship API](https://biteship.com/id/docs/intro). Mendukung Rates, Orders, Tracking, Couriers, Location Search, Label Print, Webhook Events, dan optional DB layer via `HasBiteship` trait.\n\n---\n\n## Requirements\n\n- PHP 8.3+\n- Laravel 12 atau 13\n\n---\n\n## Installation\n\n```bash\ncomposer require aliziodev/laravel-biteship\n```\n\n```bash\nphp artisan biteship:install\n```\n\nCommand ini akan mempublish config dan menanyakan apakah ingin menggunakan optional DB layer.\n\n### Environment\n\n```env\nBITESHIP_API_KEY=biteship_live.xxxxxxxxxxxx\n\n# Sandbox — gunakan key dengan prefix biteship_test.*\n# BITESHIP_API_KEY=biteship_test.xxxxxxxxxxxx\n\n# Optional: default origin (dipakai oleh -\u003edefaultOrigin())\nBITESHIP_ORIGIN_AREA_ID=IDNP6...\nBITESHIP_ORIGIN_CONTACT_NAME=Nama Pengirim\nBITESHIP_ORIGIN_CONTACT_PHONE=0812xxxxxxxx\nBITESHIP_ORIGIN_ADDRESS=Jl. Contoh No. 1\n\n# Optional: default courier (dipakai oleh -\u003edefaultCourier())\nBITESHIP_COURIER_COMPANY=jne           # kurir untuk order\nBITESHIP_COURIER_TYPE=reg              # tipe layanan untuk order\nBITESHIP_COURIER_INSURANCE=true        # opsional\nBITESHIP_COURIER_FILTER=jne,sicepat    # kurir untuk rate check (CSV), override COMPANY\n\n# Optional: default shipper branding (nama di label cetak)\nBITESHIP_SHIPPER_CONTACT_NAME=Nama Toko\nBITESHIP_SHIPPER_CONTACT_PHONE=021xxxxxxx\nBITESHIP_SHIPPER_ORGANIZATION=PT Nama Perusahaan\n\n# Optional: webhook signature verification\nBITESHIP_WEBHOOK_SIGNATURE_KEY=X-My-Header\nBITESHIP_WEBHOOK_SIGNATURE_SECRET=my-secret-value\n```\n\n---\n\n## Usage\n\nSemua fitur diakses via Facade `Biteship::`.\n\n```php\nuse Aliziodev\\Biteship\\Facades\\Biteship;\n```\n\n---\n\n## Location Search\n\nAutocomplete area pengiriman berdasarkan teks input. Gunakan `area_id` dari hasil ini untuk Rates dan Orders.\n\n```php\n$areas = Biteship::locations()-\u003esearch('Menteng');\n// $areas → Collection of array\n\nforeach ($areas as $area) {\n    // $area['id'], $area['name'], $area['postal_code']\n}\n```\n\n---\n\n## Rates (Ongkir)\n\nRates API menerima multi-kurir — hasilnya adalah daftar harga dari semua kurir yang diminta, untuk ditampilkan sebagai pilihan ke user.\n\n```php\nuse Aliziodev\\Biteship\\DTOs\\Rate\\RateRequest;\n\n$request = (new RateRequest)\n    -\u003edefaultOrigin()                          // dari config BITESHIP_ORIGIN_*\n    -\u003edestinationAreaId('IDNP6...')\n    -\u003edestinationContact('Budi', '08123456789')\n    -\u003edestinationAddress('Jl. Merdeka No. 10')\n    -\u003eaddItem([\n        'name'     =\u003e 'Sepatu',\n        'value'    =\u003e 350000,\n        'weight'   =\u003e 500,    // gram\n        'quantity' =\u003e 1,\n        'length'   =\u003e 30, 'width' =\u003e 20, 'height' =\u003e 15,\n    ]);\n\n$response = Biteship::rates()-\u003echeck($request);\n\n// $response-\u003epricing → Collection\u003cCourierRate\u003e\nforeach ($response-\u003epricing as $rate) {\n    // $rate-\u003ecourier_name, $rate-\u003ecourier_code, $rate-\u003eprice, $rate-\u003eetd\n}\n```\n\n**Filter kurir** — default cek semua kurir aktif di akun Biteship (`'biteship'`):\n\n```php\n// Eksplisit per-request\n$request-\u003ecouriers(['jne', 'sicepat', 'jnt']);\n\n// Atau dari config BITESHIP_COURIER_FILTER=jne,sicepat,jnt\n$request-\u003edefaultCourier();\n```\n\n**Cache \u0026 fresh:**\n\n```php\n// Bypass cache — selalu hit API\n$response = Biteship::rates()-\u003efresh()-\u003echeck($request);\n\n// Invalidate cache untuk payload tertentu\nBiteship::rates()-\u003eforget($request);\n```\n\n\u003e **Cache**: hasil ongkir di-cache otomatis (default 15 menit). Konfigurasikan via `config/biteship.php`.\n\n---\n\n## Orders\n\n### Create Order\n\nOrder hanya bisa dibuat dengan **1 kurir spesifik** (`company` + `type`). Kurir biasanya didapat dari pilihan user di checkout berdasarkan hasil Rates.\n\n```php\nuse Aliziodev\\Biteship\\DTOs\\Order\\OrderRequest;\n\n$request = (new OrderRequest)\n    -\u003edefaultOrigin()\n    -\u003edestinationAreaId('IDNP6...')\n    -\u003edestinationContact('Budi', '08123456789')\n    -\u003edestinationAddress('Jl. Merdeka No. 10')\n    -\u003ecourier('jne', 'reg')                    // company + type dari pilihan user\n    -\u003eaddItem([\n        'name'     =\u003e 'Sepatu',\n        'value'    =\u003e 350000,\n        'weight'   =\u003e 500,\n        'quantity' =\u003e 1,\n    ])\n    -\u003ereferenceId('INV-2025-001')              // optional: ID order dari sistem kamu\n    -\u003enotes('Jangan dilipat');                 // optional\n\n// Dengan asuransi\n$request-\u003ecourier('jne', 'reg', 'true');\n\n// COD\n$request-\u003ecashOnDelivery(350000);             // jumlah dalam rupiah\n\n// Kurir dari config — cocok kalau toko sudah lock ke satu kurir (misal kontrak eksklusif)\n$request-\u003edefaultCourier();                   // dari BITESHIP_COURIER_COMPANY + BITESHIP_COURIER_TYPE\n\n// Shipper branding (override .env default)\n$request-\u003eshipper('Toko Elektronik', '021xxxxxxx', organization: 'PT Toko Jaya');\n\n$response = Biteship::orders()-\u003ecreate($request);\n\n// $response-\u003eid              → Biteship order ID\n// $response-\u003estatus          → OrderStatus enum\n// $response-\u003ewaybill_id       → resi kurir (mungkin null saat baru dibuat)\n// $response-\u003eprice           → ongkir final\n// $response-\u003eraw             → raw array dari API\n```\n\n### Find, Update, Cancel\n\n```php\n// Get detail\n$order = Biteship::orders()-\u003efind($orderId);\n\n// Cancel\n$order = Biteship::orders()-\u003ecancel($orderId, 'Pembeli membatalkan');\n\n// Update (misal koreksi alamat sebelum pickup)\n$order = Biteship::orders()-\u003eupdate($orderId, [\n    'destination_address' =\u003e 'Jl. Baru No. 5',\n]);\n```\n\n### OrderStatus Enum\n\n```php\nuse Aliziodev\\Biteship\\Enums\\OrderStatus;\n\n$status = $response-\u003estatus;\n\n$status-\u003elabel();        // label Bahasa Indonesia\n$status-\u003eisFinal();      // sudah terminal (delivered/cancelled/dll)\n$status-\u003eisSuccess();    // delivered\n$status-\u003eisInTransit();  // sedang dalam perjalanan\n$status-\u003eisProblem();    // on_hold / return_in_transit\n$status-\u003ecanCancel();    // masih bisa dicancel via API\n```\n\n**14 values:** `confirmed`, `scheduled`, `allocated`, `picking_up`, `picked`, `dropping_off`, `delivered`, `on_hold`, `return_in_transit`, `returned`, `rejected`, `disposed`, `courier_not_found`, `cancelled`\n\n---\n\n## Tracking\n\n```php\n// Track via Biteship order ID\n$tracking = Biteship::tracking()-\u003etrackByOrderId($orderId);\n\n// Track via resi + kode kurir (public tracking — tidak perlu order dari Biteship)\n$tracking = Biteship::tracking()-\u003etrackByWaybill('JD000000000', 'jne');\n\n// $tracking-\u003estatus     → TrackingStatus enum\n// $tracking-\u003ewaybill_id\n// $tracking-\u003ehistory    → Collection\u003cTrackingHistory\u003e\n\nforeach ($tracking-\u003ehistory as $h) {\n    // $h-\u003estatus, $h-\u003enote, $h-\u003eupdatedAt\n}\n```\n\n**TrackingStatus** memiliki 13 values (sama dengan OrderStatus minus `cancelled` — tracking tidak expose cancelled karena order sudah tidak ada di kurir).\n\n---\n\n## Couriers\n\n```php\n$couriers = Biteship::couriers()-\u003eall();\n// Collection of array: \n//   available_collection_method\n//   available_for_cash_on_delivery\n//   available_for_proof_of_delivery\n//   available_for_instant_waybill_id\n//   courier_name\n//   courier_code\n//   courier_service_name\n//   courier_service_code\n//   tier\n//   description\n//   service_type\n//   shipping_type\n//   shipment_duration_range\n//   shipment_duration_unit\n```\n\n---\n\n## Label Print\n\nBuat label pengiriman dari raw response order (zero API call tambahan).\n\n```php\n$label = Biteship::label()-\u003efromRaw($response-\u003eraw);\n\n// Render HTML string\n$html = Biteship::label()-\u003erender($label);\n\n// Return HTTP response siap di-print di browser\nreturn Biteship::label()-\u003eresponse($label);\n```\n\n**Catatan:** `sender_name` dan `sender_phone` di label menggunakan data `shipper` (branding toko) jika tersedia, dengan fallback ke `origin`. `sender_address` selalu dari `origin`.\n\n---\n\n## Webhook \u0026 Events\n\nBiteship mengirim webhook saat status order berubah. Package ini menangani routing, verifikasi signature, dan dispatch Laravel Event secara otomatis.\n\n### Route\n\nWebhook URL sudah di-register otomatis:\n\n```\nPOST /biteship/webhook\n```\n\nDaftarkan URL ini di [Biteship Dashboard → Webhook Settings](https://beta.biteship.com/id/main/integration/api-key).\n\n### Signature Verification\n\nSet di Biteship Dashboard pada bagian **Custom Headers**:\n\n```env\nBITESHIP_WEBHOOK_SIGNATURE_KEY=X-Biteship-Signature\nBITESHIP_WEBHOOK_SIGNATURE_SECRET=rahasia-kamu\n```\n\nJika kedua nilai ini kosong, verifikasi dilewati (cocok untuk development).\n\n### Listen Events\n\nDaftarkan listener di `AppServiceProvider` atau `EventServiceProvider`:\n\n```php\nuse Aliziodev\\Biteship\\Events\\OrderStatusUpdated;\nuse Aliziodev\\Biteship\\Events\\OrderWaybillUpdated;\nuse Aliziodev\\Biteship\\Events\\OrderPriceUpdated;\n\nEvent::listen(OrderStatusUpdated::class, HandleBiteshipStatus::class);\nEvent::listen(OrderWaybillUpdated::class, HandleBiteshipWaybill::class);\nEvent::listen(OrderPriceUpdated::class, HandleBiteshipPrice::class);\n```\n\n### Event Payloads\n\n**`OrderStatusUpdated`** — dipicu saat status order berubah (`order.status`):\n```php\npublic function handle(OrderStatusUpdated $event): void\n{\n    $payload = $event-\u003epayload;\n\n    $payload-\u003eorder_id;            // string\n    $payload-\u003estatus;             // OrderStatus enum\n    $payload-\u003ewaybill_id;          // ?string\n    $payload-\u003ecourier_tracking_id;  // ?string\n    $payload-\u003eraw;                // array mentah dari webhook\n}\n```\n\n**`OrderWaybillUpdated`** — dipicu saat resi diterbitkan (`order.waybill_id`):\n```php\npublic function handle(OrderWaybillUpdated $event): void\n{\n    $payload = $event-\u003epayload;\n\n    $payload-\u003eorder_id;            // string\n    $payload-\u003ewaybill_id;          // string\n    $payload-\u003ecourier_tracking_id;  // ?string\n}\n```\n\n**`OrderPriceUpdated`** — dipicu saat harga final dikonfirmasi (`order.price`):\n```php\npublic function handle(OrderPriceUpdated $event): void\n{\n    $payload = $event-\u003epayload;\n\n    $payload-\u003eorder_id;            // string\n    $payload-\u003eprice;              // int (rupiah)\n    $payload-\u003einsurance_fee;       // int (rupiah)\n}\n```\n\nRespons **401** dikembalikan jika signature tidak valid. Respons **422** dikembalikan jika event tidak dikenal.\n\n---\n\n## HasBiteship Trait (Optional DB Layer)\n\nSimpan state pengiriman langsung di model Order kamu tanpa perlu menulis query manual.\n\n### Setup\n\nSaat `biteship:install`, pilih **Yes** untuk optional DB layer. Ini akan mempublish migration:\n\n```bash\nphp artisan migrate\n```\n\nTambahkan trait ke model Order:\n\n```php\nuse Aliziodev\\Biteship\\Support\\HasBiteship;\n\nclass Order extends Model\n{\n    use HasBiteship;\n}\n```\n\n### Methods\n\n```php\n// Simpan response Biteship setelah order dibuat\n$order-\u003ecreateBiteshipOrder($response);\n\n// Sync status terbaru dari Tracking API ke DB (idempoten — skip jika status sama)\n$order-\u003esyncBiteshipStatus();\n\n// Cancel order via API + update status di DB\n$order-\u003ecancelBiteship('Pembeli request cancel');\n\n// Generate label dari raw_response di DB (zero API call)\n$label = $order-\u003egenerateLabel();\nreturn Biteship::label()-\u003eresponse($label);\n\n// Relasi ke tabel biteship_orders\n$order-\u003ebiteshipOrder;          // BiteshipOrder model\n```\n\n### Integrasi Webhook + HasBiteship\n\nPattern umum: update status DB langsung dari webhook tanpa API call tambahan.\n\n```php\nclass HandleBiteshipStatus\n{\n    public function handle(OrderStatusUpdated $event): void\n    {\n        BiteshipOrder::where('biteship_order_id', $event-\u003epayload-\u003eorder_id)\n            -\u003eupdate(['biteship_status' =\u003e $event-\u003epayload-\u003estatus-\u003evalue]);\n    }\n}\n```\n\nAtau gunakan `syncBiteshipStatus()` jika ingin selalu pull dari Tracking API (lebih akurat tapi ada API call tambahan):\n\n```php\nclass HandleBiteshipStatus\n{\n    public function handle(OrderStatusUpdated $event): void\n    {\n        $order = Order::whereHas('biteshipOrder', fn ($q) =\u003e\n            $q-\u003ewhere('biteship_order_id', $event-\u003epayload-\u003eorder_id)\n        )-\u003efirst();\n\n        $order?-\u003esyncBiteshipStatus();\n    }\n}\n```\n\n---\n\n## Testing / Mock Mode\n\nGunakan `MockBiteshipClient` untuk testing tanpa hit API:\n\n```php\nuse Aliziodev\\Biteship\\Http\\MockBiteshipClient;\n\n// Bind di AppServiceProvider (untuk env testing) atau test setUp\n$this-\u003eapp-\u003ebind(\n    \\Aliziodev\\Biteship\\Contracts\\BiteshipClientInterface::class,\n    MockBiteshipClient::class,\n);\n```\n\nMock tersedia untuk semua endpoint: rates, orders, tracking, couriers, dan locations.\n\n---\n\n## Configuration\n\n```bash\nphp artisan vendor:publish --tag=biteship-config\n```\n\nKey konfigurasi di `config/biteship.php`:\n\n| Key | Default | Keterangan |\n|-----|---------|------------|\n| `api_key` | `env('BITESHIP_API_KEY')` | API key Biteship |\n| `cache.enabled` | `true` | Cache hasil ongkir |\n| `cache.ttl` | `900` | TTL dalam detik (15 menit) |\n| `cache.store` | `null` | Cache store (null = default) |\n| `cache.prefix` | `'biteship'` | Prefix cache key |\n| `webhook.path` | `'biteship/webhook'` | Path endpoint webhook |\n| `webhook.signature_key` | `null` | Nama custom header signature |\n| `webhook.signature_secret` | `null` | Nilai secret untuk verifikasi |\n| `default_origin` | `[...]` | Data origin default (dari env) |\n| `default_courier` | `[...]` | Kurir default untuk order \u0026 rates (dari env) |\n| `default_shipper` | `[...]` | Data shipper branding (dari env) |\n| `label.view` | `'biteship::label'` | Blade view untuk label print |\n\n---\n\n## Exceptions\n\n| Exception | Keterangan |\n|-----------|------------|\n| `AuthenticationException` | API key salah atau tidak aktif (401) |\n| `ValidationException` | Request tidak valid (422) |\n| `RateLimitException` | Rate limit tercapai (429) |\n| `ApiException` | Error lain dari Biteship API |\n| `WebhookSignatureException` | Signature header tidak cocok |\n| `InvalidWebhookEventException` | Event webhook tidak dikenal |\n\n---\n\n## License\n\nMIT — [Alizio](https://github.com/aliziodev)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliziodev%2Flaravel-biteship","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faliziodev%2Flaravel-biteship","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliziodev%2Flaravel-biteship/lists"}