Skip to content

Laravel SDK

Laravel аппликэйшнаас Byl-ийг ашиглах албан ёсны SDK. Нэхэмжлэх, checkout, харилцагч, захиалга, billing portal болон webhook-ийг Laravel-д зохицсон байдлаар хэрэглэнэ.

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

Суулгах

bash
composer require kitelab-dev/byl-laravel

.env файлд дараах гурван утгыг нэмнэ:

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

Тохиргооны файл хэрэгтэй бол:

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

Нэхэмжлэх

php
use Byl\Laravel\Facades\Byl;

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

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

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

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

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

Checkout

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);

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

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

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

Харилцагч

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

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

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

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

Захиалга

Recurring үнэтэй checkout төлөгдөхөд subscription автоматаар үүснэ (customer_id заавал, ганц item):

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

// Сунгалт / багц солилт
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 шиг модель дээрээ шууд ажиллах хувилбар. Захиалга нь локал byl_subscriptions хүснэгтэд тусаж, webhook ирэх бүрд автоматаар шинэчлэгддэг тул $user->subscribed() шалгалт сүлжээнд гарахгүй.

bash
php artisan vendor:publish --tag=byl-migrations
php artisan migrate
dotenv
BYL_BILLABLE_MODEL="App\Models\User"
php
use Byl\Laravel\Billing\Billable;

class User extends Authenticatable
{
    use Billable;
}

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

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

Route хамгаалах:

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

Захиалга эхлүүлэх, удирдах

php
// Recurring checkout — төлөгдмөгц subscription үүснэ
return $user->newSubscription('starter_monthly')
    ->successUrl(route('subscribe.success'))
    ->checkout();

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

$subscription = $user->bylSubscription();

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

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

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

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

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()

Өгөгдлөө нөхөх

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

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

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

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

Billing portal

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 болгож илгээнэ. Byl веб хуудсанд webhook нэмэхдээ энэ хаягийг бүртгэнэ.

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.

Хаягийг өөрчлөх, эсвэл өөрийн controller хэрэглэх:

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

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

Алдаа

Бүх алдаа 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

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

Хэд хэдэн төсөл

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

Тест бичих

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

php
$byl = Byl::fake();

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

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

Webhook-ийг гарын үсэгтэйгээр турших:

php
use Byl\Laravel\Testing\FakeWebhook;

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

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