1. Go to this page and download the library: Download glueful/payvia library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
return [
'default_gateway' => env('PAYVIA_DEFAULT_GATEWAY', 'paystack'),
// How long a PROVIDER-CONFIRMED "this hosted session is still live" answer is trusted
// before ensure-live asks the provider again. Only a confirmed-live probe refreshes the
// stamp; dead/unknown answers never do, and a brand-new attempt is never suppressed.
// Set to 0 to always probe.
'session_liveness_cooldown_seconds' => (int) env('PAYVIA_SESSION_LIVENESS_COOLDOWN_SECONDS', 30),
'intents' => [
// How long an `initializing`/`open` payment_intents row may sit UNTOUCHED before
// `payvia:intents:sweep-stale` retires it to `failed`, freeing its payable's active
// idempotency port. Age is the only criterion. Clamped to 1..365 days at read time.
'stale_after_days' => (int) env('PAYVIA_INTENTS_STALE_AFTER_DAYS', 30),
],
'gateways' => [
'paystack' => [
'enabled' => (bool) env('PAYVIA_PAYSTACK_ENABLED', true),
'driver' => 'paystack',
'secret_key' => env('PAYVIA_PAYSTACK_SECRET_KEY', env('PAYSTACK_SECRET_KEY', null)),
'webhook_secret' => env('PAYVIA_PAYSTACK_WEBHOOK_SECRET', env('PAYVIA_PAYSTACK_SECRET_KEY', env('PAYSTACK_SECRET_KEY', null))),
'base_url' => env('PAYVIA_PAYSTACK_BASE_URL', 'https://api.paystack.co'),
'timeout' => (int) env('PAYVIA_PAYSTACK_TIMEOUT', 15),
// Hosted-redirect trust boundary: the ONLY hosts a returned `authorization_url`
// may live on. File-config only -- not overridable via PayviaSettings.
'checkout_hosts' => ['checkout.paystack.com'],
],
'stripe' => [
'enabled' => (bool) env('PAYVIA_STRIPE_ENABLED', false),
'driver' => 'stripe',
'secret_key' => env('PAYVIA_STRIPE_SECRET_KEY', null),
'webhook_secret' => env('PAYVIA_STRIPE_WEBHOOK_SECRET', null),
'webhook_tolerance' => (int) env('PAYVIA_STRIPE_WEBHOOK_TOLERANCE', 300),
'base_url' => env('PAYVIA_STRIPE_BASE_URL', 'https://api.stripe.com'),
'timeout' => (int) env('PAYVIA_STRIPE_TIMEOUT', 15),
// Same trust boundary as paystack above, applied to the Checkout Session `url`
// for both one-time and subscription sessions.
'checkout_hosts' => ['checkout.stripe.com'],
],
],
'features' => [
'store_raw_payload' => (bool) env('PAYVIA_STORE_RAW_PAYLOAD', true),
],
'security' => [
// Three ordered profiles composed onto every /payvia/* route except the webhook
// route (which stays signature-authenticated/tenantless). See "Middleware profiles
// and tenancy" below.
'auth_middleware' => ['auth'],
'tenant_context_middleware' => [],
'manage_middleware' => ['admin'],
],
'webhooks' => [
'queue' => (bool) env('PAYVIA_WEBHOOKS_QUEUE', false),
'queue_name' => env('PAYVIA_WEBHOOKS_QUEUE_NAME', 'default'),
'relay_stale_seconds' => (int) env('PAYVIA_WEBHOOKS_RELAY_STALE_SECONDS', 300),
],
];
namespace Glueful\Extensions\Payvia\Contracts;
interface StrictPaymentEventListener
{
public const CONTAINER_TAG = 'payvia.strict_payment_event_listeners';
public function supports(PaymentProviderEventInterface $event): bool;
public function handle(PaymentProviderEventInterface $event): void;
}
use Glueful\Extensions\Payvia\Contracts\StrictPaymentEventListener;
public static function services(): array
{
return [
// ... other services ...
MyStrictEventListener::class => [
'class' => MyStrictEventListener::class,
'shared' => true,
'autowire' => true,
'tags' => [StrictPaymentEventListener::CONTAINER_TAG],
],
];
}
// config/payvia.php (application override — neutral defaults shown; single-store
// installs can leave this block out entirely)
return [
'security' => [
// Profile 1 — authentication.
'auth_middleware' => ['auth'],
// Profile 2 — tenant context. Empty by default; a tenancy-enabled host sets
// this to whatever establishes request-scoped tenant context before Payvia's
// repositories run (Payvia never names or hardcodes host-specific aliases here).
'tenant_context_middleware' => [],
// Profile 3 — authorization for the management (write) routes only.
'manage_middleware' => ['admin'],
],
];
use Glueful\Extensions\Payvia\Services\PaymentService;
/** @var PaymentService $payments */
$payments = container()->get(PaymentService::class);
$result = $payments->confirmAndRecord(
reference: 'PSK_tx_ref_123456',
gatewayName: 'paystack', // or null to use default
context: [
'user_uuid' => $userUuid,
'payable_type' => 'subscription',
'payable_id' => $subscriptionId,
'metadata' => [
'source' => 'web_checkout',
'campaign' => 'black_friday',
],
]
);
if (($result['payment_status'] ?? '') === 'success') {
// Start subscription, mark invoice paid, etc.
}
use Glueful\Extensions\Payvia\Services\BillingPlanService;
/** @var BillingPlanService $plans */
$plans = container()->get(BillingPlanService::class);
// Create a plan
$planUuid = $plans->create([
'name' => 'Pro Monthly',
'description' => 'Pro plan billed monthly',
'amount' => 9900, // minor units of `currency` (cents); $99.00 = 9900
'currency' => 'USD',
'interval' => 'monthly',
'trial_days' => 14,
'gateway' => 'stripe',
'gateway_product_id' => 'prod_123',
'gateway_price_id' => 'price_123',
]);
// List active monthly plans
$activePlans = $plans->list([
'status' => 'active',
'interval' => 'monthly',
]);
use Glueful\Extensions\Payvia\Services\InvoiceService;
/** @var InvoiceService $invoices */
$invoices = container()->get(InvoiceService::class);
// Create an invoice linked to a plan and payable entity
$invoiceUuid = $invoices->create([
'user_uuid' => $userUuid,
'billing_plan_uuid' => $planUuid,
'payable_type' => 'location_subscription',
'payable_id' => $locationUuid,
'amount' => 9900, // minor units of `currency` (cents); $99.00 = 9900
'currency' => 'USD',
'status' => 'pending',
'metadata' => [
'period' => '2025-01',
'source' => 'subscription_renewal',
],
]);
// After a successful payment, mark the invoice as paid
$invoices->markPaid($invoiceUuid);
// List paid invoices for a user for a given period
$userInvoices = $invoices->list([
'user_uuid' => $userUuid,
'status' => 'paid',
'metadata_contains' => [
'key' => 'period',
'value' => '2025-01',
],
]);