Skip to content

Laravel SDK

Танилцуулга

Byl-ийн Laravel SDK нь нэхэмжлэх, checkout, харилцагч, багц (subscription), billing portal болон webhook-той ажиллах ажлыг Laravel-д зохицсон, илэрхийлэмжтэй (expressive) интерфэйсээр хангана. Хэрэв та Laravel Cashier ашиглаж байсан бол SDK-ийн Billable trait танд шууд танил санагдах болно.

  • Package: kitelab-dev/byl-laravel
  • Шаардлага: PHP 8.2+, Laravel 11 / 12 / 13

Суулгах

Эхлээд Composer ашиглан package-ээ суулгана:

bash
composer require kitelab-dev/byl-laravel

Тохиргоо

Дараа нь аппликейшнийхээ .env файлд Byl-ийн холболтын утгуудыг тодорхойлно:

dotenv
BYL_TOKEN=таны-api-token
BYL_PROJECT_ID=1
BYL_WEBHOOK_SECRET=таны-webhook-secret
  • BYL_TOKENAPI токен хуудсанд зааснаар үүсгэнэ.
  • BYL_PROJECT_ID — удирдлагын булангийн төслийн тохиргооноос харна.
  • BYL_WEBHOOK_SECRETwebhook-ийн дэлгэрэнгүй хуудсанд байх гарын үсгийн түлхүүр.

Шаардлагатай бол SDK-ийн тохиргооны файлыг publish хийж болно:

bash
php artisan vendor:publish --tag=byl-config

Нэхэмжлэх

Byl facade-ийн invoices method-оор нэхэмжлэх үүсгэж, удирдана:

php
use Byl\Laravel\Facades\Byl;

$invoice = Byl::invoices()->create([
    'amount' => 25000,
    'description' => 'Гишүүнчлэлийн төлбөр',
]);

$invoice->url;      // төлбөрийн хуудасны хаяг
$invoice->status;   // InvoiceStatus::Open
$invoice->isPaid(); // false

Мөн нэхэмжлэхийг лавлах, хүчингүй болгох, устгах боломжтой:

php
Byl::invoices()->find($invoice->id);
Byl::invoices()->void($invoice->id);
Byl::invoices()->delete($invoice->id);

Нэхэмжлэх, checkout, portal session объектыг route эсвэл controller-оос шууд буцаахад харилцагч тухайн төлбөрийн хуудас руу redirect хийгдэнэ:

php
public function pay(Order $order)
{
    return Byl::invoices()->createFor($order->total, "Багц #{$order->id}");
}

Checkout

Бүтээгдэхүүн, тоо хэмжээ, хөнгөлөлт бүхий худалдан авалтад checkout builder ашиглана. Builder нь Checkout API-ийн бүх параметрийг fluent method-уудаар илэрхийлнэ:

php
$checkout = Byl::checkouts()->builder()
    ->successUrl(route('purchase.success'))
    ->cancelUrl(route('cart'))
    ->addPrice('starter_monthly')            // lookup key
    ->addPriceId(3)                          // Byl дээрх үнийн ID
    ->addPriceData(15000, 'Гутал', quantity: 2)  // шууд үнэ
    ->collectPhoneNumber()
    ->collectDeliveryAddress()
    ->allowPromotionCodes()
    ->discount(5400, 'Хямдрал')
    ->clientReferenceId("order_{$order->id}")
    ->create();

return redirect()->away($checkout->url);

Checkout-ыг лавлахад item болон хэрэглэгдсэн хөнгөлөлтийн кодууд хамт ирнэ:

php
$checkout = Byl::checkouts()->find(13338);

$checkout->status;          // CheckoutStatus::Complete
$checkout->amountTotal;
$checkout->items;           // Collection<CheckoutItem>
$checkout->couponCodes;     // Collection<CouponCode>

Харилцагч

upsert method нь client_reference_id-гаар давхардал үүсгэлгүй ажилладаг тул checkout үүсгэхийн өмнө бүр удаа дуудаж болно:

php
$customer = Byl::customers()->upsert([
    'email' => $user->email,
    'name' => $user->name,
    'client_reference_id' => (string) $user->id,
]);

Өөрийн систем дэх хэрэглэгчийн ID-гаар харилцагчаа шууд лавлаж болно:

php
$customer = Byl::customers()->findByClientReferenceId((string) $user->id);
$customer = Byl::customers()->findByClientReferenceIdOrNull((string) $user->id); // олдоогүй бол null

Харилцагчийн объект дээр эрхийн шалгалтын туслах method-ууд бий:

php
$customer->isSubscribed();                                // эрхтэй багц байгаа эсэх
$customer->subscriptionForLookupKey('starter_monthly');

Багц

Давтагдах (recurring) үнэтэй checkout төлөгдөхөд багц автоматаар үүснэ. Ийм checkout-д customer_id заавал бөгөөд ганц item байна:

php
Byl::checkouts()->builder()
    ->customer($customer->id)
    ->addPrice('starter_monthly')
    ->successUrl(route('subscribe.success'))
    ->create();

Сунгалт эсвэл багц солилтын checkout үүсгэхдээ subscription method-оор багцаа заана:

php
Byl::checkouts()->builder()
    ->customer($customer->id)
    ->subscription($subscriptionId)
    ->addPrice('growth_monthly')
    ->create();

Багцыг лавлах, жагсаах, удирдах:

php
$subscription = Byl::subscriptions()->find(4);

$subscription->status;             // SubscriptionStatus::Active
$subscription->isEntitled();       // canceled-аас бусад бүх төлөв → true
$subscription->currentPeriodEnd;   // эрхийн дуусах хугацаа (Carbon)
$subscription->cancelRequested();  // цуцлалт хүссэн ч мөчлөг дуусаагүй

Byl::subscriptions()->list(['status' => 'active']);          // хуудаслалттай
Byl::subscriptions()->list(['price' => 'starter_monthly']);  // lookup key-ээр
Byl::subscriptions()->all(['status' => 'active']);           // бүх хуудас (lazy)
Byl::subscriptions()->startTrial(customerId: 12, price: 'starter_monthly', trialDays: 14);
Byl::subscriptions()->cancel(4);
Byl::subscriptions()->resume(4);

Billable trait

Laravel Cashier-тэй адилаар model дээрээ шууд ажиллахыг хүсвэл Billable trait ашиглана. Багцууд локал byl_subscriptions хүснэгтэд хадгалагдаж, webhook ирэх бүрд автоматаар шинэчлэгддэг тул $user->subscribed() шалгалт сүлжээнд гардаггүй.

Эхлээд SDK-ийн migration-уудыг publish хийж ажиллуулна:

bash
php artisan vendor:publish --tag=byl-migrations
php artisan migrate

Дараа нь billable model-оо .env-д зааж, trait-аа нэмнэ:

dotenv
BYL_BILLABLE_MODEL="App\Models\User"
php
use Byl\Laravel\Billing\Billable;

class User extends Authenticatable
{
    use Billable;
}

Эрхийн шалгалт

Хэрэглэгчийн багцын төлөвийг дараах method-уудаар шалгана:

php
$user->subscribed();                      // trialing / active / past_due
$user->subscribed('starter_monthly');     // тодорхой багц дээр
$user->subscribedToProduct(7);
$user->onTrial();
$user->onGracePeriod();                   // цуцлалт хүссэн ч мөчлөг дуусаагүй
$user->bylSubscription()->current_period_end;

Route хамгаалах

byl.subscribed middleware-ээр эрхтэй хэрэглэгчдэд л зориулсан route тодорхойлж болно:

php
Route::get('/dashboard', ...)->middleware('byl.subscribed');
Route::get('/pro', ...)->middleware('byl.subscribed:growth_monthly');

Багц эхлүүлэх

newSubscription method нь recurring checkout буцаадаг — төлөгдмөгц багц үүснэ:

php
return $user->newSubscription('starter_monthly')
    ->successUrl(route('subscribe.success'))
    ->checkout();

Мөн хэд хэдэн мөчлөгийг нэг дор худалдах эсвэл төлбөргүй туршилт эхлүүлж болно:

php
$user->newSubscription('starter_monthly')->cycles(3)->checkout();  // 3 мөчлөг нэг дор
$user->newSubscription('starter_monthly')->startTrial(14);         // төлбөргүй туршилт

Харилцагч Byl дээр байхгүй бол эдгээр method нь client_reference_id-гаар upsert хийж byl_customer_id-г автоматаар хадгална.

Багц удирдах

php
$subscription = $user->bylSubscription();

return $subscription->renewCheckout(3);                 // сунгах
return $subscription->swapCheckout('growth_monthly');   // багц солих

$subscription->cancel();
$subscription->resume();

Cashier-аас ялгаатай тал

Монголд автомат суутгал байдаггүй тул swap(), renew() шиг шууд суутгадаг method байхгүй — оронд нь checkout буцаадаг (swapCheckout(), renewCheckout()) бөгөөд хэрэглэгч төлбөрөө өөрөө төлнө.

Cashier-ийн танил method-уудын харгалзаа:

CashierByl SDK
$user->subscribed('default')$user->subscribed('starter_monthly')
$user->subscription()$user->bylSubscription()
$user->newSubscription(...)->checkout()$user->newSubscription('starter_monthly')->checkout()
->trialDays(14)->create()$user->newSubscription('starter_monthly')->startTrial(14)
$subscription->swap($price)$subscription->swapCheckout($price)
$subscription->renewCheckout($cycles)
$user->createAsStripeCustomer()$user->createOrGetBylCustomer()

Billable model тохируулах

Byl дээрх багцуудыг локал хүснэгтдээ гараар татах эсвэл харилцагчийн мэдээллийг API-аас авах бол:

php
$user->syncBylSubscriptions();   // Byl дээрх багцуудыг локал хүснэгтэд татах
$user->asBylCustomer();          // API-аас харилцагчийн мэдээлэл

client_reference_id нь өгөгдмөлөөр model-ийн primary key байна. Өөр багана эсвэл өөрийн resolve хийх логик хэрэглэхийг хүсвэл:

php
// config/byl.php
'billable' => ['client_reference_column' => 'uuid'],

// эсвэл AppServiceProvider::boot дотор
Byl::resolveBillableUsing(fn (string $reference) => Team::where('slug', $reference)->first());

Billing portal

Хэрэглэгчийг багцаа өөрөө удирдах billing portal руу чиглүүлэхдээ session үүсгээд шууд буцаана:

php
Route::get('/billing', function () {
    $customer = Byl::customers()->findByClientReferenceId((string) auth()->id());

    return Byl::billingPortal()->createSession($customer->id);   // portal руу redirect
});

Webhook

SDK нь POST /byl/webhook хаягийг автоматаар бүртгэж, Byl-Signature гарын үсгийг шалгаад Laravel event болгож илгээнэ. Удирдлагын буланд webhook нэмэхдээ энэ хаягийг бүртгэнэ.

Event-үүдийг ердийн Laravel listener-ээр барина:

php
use Byl\Laravel\Events\CheckoutCompleted;
use Byl\Laravel\Events\SubscriptionCanceled;
use Illuminate\Support\Facades\Event;

Event::listen(function (CheckoutCompleted $event) {
    Order::where('id', $event->checkout->clientReferenceId)->update(['paid_at' => now()]);
});

Event::listen(function (SubscriptionCanceled $event) {
    // Хэрэглэгчийн эрхийг ЗӨВХӨН энэ event дээр хаана
    User::where('id', $event->subscription->customer?->clientReferenceId)->update(['plan' => null]);
});

Event класс бүр Byl-ийн event төрөлтэй харгалзана: InvoicePaid, InvoiceVoided, CheckoutCompleted, CheckoutExpired, SubscriptionCreated, SubscriptionRenewed, SubscriptionUpdated, SubscriptionRenewalDue, SubscriptionPastDue, SubscriptionCanceled. Бүх event-ийг нэг дор барих бол WebhookReceived.

Webhook-ийн хаягийг өөрчлөх эсвэл өөрийн controller хэрэглэхийг хүсвэл:

php
// config/byl.php → webhook.route.path = 'integrations/byl/webhook'

// эсвэл өөрийн route дээр гарын үсгийн шалгалтыг залгах
Route::post('/my/byl-webhook', MyWebhookController::class)->middleware('byl-signature');

Алдааны боловсруулалт

SDK-ийн бүх алдаа Byl\Laravel\Exceptions\BylException interface-ийг хэрэгжүүлдэг:

php
use Byl\Laravel\Exceptions\BylException;
use Byl\Laravel\Exceptions\ValidationException;

try {
    Byl::invoices()->create(['amount' => 5]);
} catch (ValidationException $exception) {
    $exception->errorFor('amount');   // "The amount must be at least 10."
} catch (BylException $exception) {
    report($exception);
}
ExceptionСтатус
AuthenticationException401 — токен буруу/хүчингүй
AuthorizationException403 — эрхгүй
NotFoundException404 — олдсонгүй
ConflictException409 — жш: цуцлагдсан багцыг дахин цуцлах
ValidationException422 — параметер буруу
RateLimitException429 — retryAfter()
ServerException5xx
ConnectionExceptionсүлжээ / timeout

TIP

Холболтын алдаа, 429 болон 5xx хариу дээр SDK автоматаар дахин хүсэлт илгээдэг тул та retry логик бичих шаардлагагүй.

Олон төсөл

Өгөгдмөл төслөөс өөр төсөлтэй ажиллахдаа project method ашиглана:

php
Byl::project(7)->invoices()->createFor(1000);
Byl::project(7, 'other-token')->customers()->find(12);

Тест бичих

Byl::fake() нь сүлжээнд гарахгүйгээр бодит бүтэцтэй хариу буцааж, илгээгдсэн хүсэлтүүд дээр assertion хийх боломж олгоно:

php
$byl = Byl::fake();

$this->post('/orders', ['product' => 'starter'])->assertRedirect();

$byl->assertCheckoutCreated(fn (array $payload) => $payload['items'][0]['price'] === 'starter_monthly');

Webhook-ийг зөв гарын үсэгтэйгээр турших бол FakeWebhook ашиглана:

php
use Byl\Laravel\Testing\FakeWebhook;

$webhook = FakeWebhook::checkoutCompleted(['id' => 13338]);

$this->postJson(route('byl.webhook'), $webhook->payload(), $webhook->headers())->assertOk();