Extract Ladill QR Plus as standalone app at qr.ladill.com.
Deploy Ladill QR Plus / deploy (push) Failing after 1s

Utility QR types only (URL, WiFi, link list, business, app download) with
SSO, Billing API integration, public /q resolver, and qr-plus:import for
platform migration. vCard and commerce types stay on the platform.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-06-06 21:31:24 +00:00
co-authored by Cursor
commit cd6571f199
208 changed files with 30931 additions and 0 deletions
@@ -0,0 +1,74 @@
<?php
namespace App\Services\Qr;
use App\Models\QrCode;
use App\Models\QrTransaction;
use App\Models\QrWallet;
use App\Models\User;
use App\Services\Billing\BillingClient;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use RuntimeException;
/**
* QR Plus billing consumes the platform UserWallet via the Billing API.
*/
class QrWalletBillingService
{
public function __construct(
private BillingClient $billing,
) {}
public function balanceCedis(User $user): float
{
return $this->billing->balanceMinor($user->public_id) / 100;
}
public function canCreate(User $user): bool
{
$priceMinor = (int) round(QrWallet::pricePerQr() * 100);
return $this->billing->canAfford($user->public_id, $priceMinor);
}
public function debitForQrCreation(QrWallet $wallet, QrCode $qrCode): QrTransaction
{
$price = QrWallet::pricePerQr();
$priceMinor = (int) round($price * 100);
$user = $wallet->user;
$reference = 'QR-DEBIT-'.strtoupper(Str::random(12));
return DB::transaction(function () use ($wallet, $user, $qrCode, $price, $priceMinor, $reference) {
$ok = $this->billing->debit(
$user->public_id,
$priceMinor,
'qr',
'qr_create',
$reference,
$qrCode->id,
sprintf('Created QR code: %s', $qrCode->label),
);
if (! $ok) {
throw new RuntimeException('Insufficient wallet balance.');
}
$wallet->increment('qr_codes_total');
$balanceAfter = $this->billing->balanceMinor($user->public_id) / 100;
return QrTransaction::create([
'user_id' => $wallet->user_id,
'qr_wallet_id' => $wallet->id,
'qr_code_id' => $qrCode->id,
'type' => QrTransaction::TYPE_DEBIT,
'amount_ghs' => round($price, 4),
'balance_after_ghs' => $balanceAfter,
'reference' => $reference,
'status' => 'completed',
'description' => sprintf('Created QR code: %s', $qrCode->label),
'metadata' => ['qr_code_id' => $qrCode->id],
]);
});
}
}