billing->balanceMinor($account->public_id); $ledger = $this->billing->serviceLedger($account->public_id, config('billing.service', 'mini')); } catch (Throwable $e) { Log::warning('Mini API wallet load failed', ['user' => $account->public_id, 'error' => $e->getMessage()]); } return response()->json([ 'data' => [ 'currency' => 'GHS', 'balance_minor' => $balanceMinor, 'spent_minor' => (int) ($ledger['spent_minor'] ?? 0), 'credited_minor' => (int) ($ledger['credited_minor'] ?? 0), ], ]); } public function topup(Request $request): JsonResponse { $account = ladill_account(); $data = $request->validate([ 'amount' => ['required', 'numeric', 'min:1', 'max:10000'], ]); $response = $this->identitySend('POST', '/api/identity/wallet-topup-account', [ 'user' => $account->public_id, 'amount' => (float) $data['amount'], // Paystack returns the customer here after payment; the app catches the deep link. 'return_url' => 'https://'.config('app.platform_domain').'/mini/wallet/topup-complete', ]); $this->rethrowValidation($response, 'amount'); $checkoutUrl = (string) $response->json('data.checkout_url', ''); if ($checkoutUrl === '') { return response()->json(['message' => 'Could not start top-up. Please try again.'], 422); } return response()->json(['data' => ['checkout_url' => $checkoutUrl]]); } public function banks(Request $request): JsonResponse { $type = $request->query('type') === 'mobile_money' ? 'mobile_money' : 'bank'; $response = $this->identitySend('GET', '/api/identity/banks?type='.urlencode($type), []); return response()->json(['data' => $response->json('data', [])]); } public function payoutAccount(): JsonResponse { $response = $this->identitySend('GET', '/api/identity/payout-account?user='.urlencode((string) ladill_account()->public_id), []); return response()->json(['data' => ['payout_account' => $response->json('data.payout_account')]]); } public function updatePayoutAccount(Request $request): JsonResponse { $data = $request->validate([ 'account_type' => ['required', 'in:mobile_money,bank_account'], 'account_name' => ['required', 'string', 'max:200'], 'account_number' => ['required', 'string', 'max:30'], 'bank_code' => ['required', 'string', 'max:30'], 'bank_name' => ['required', 'string', 'max:200'], 'currency' => ['sometimes', 'string', 'size:3'], ]); $data['currency'] = $data['currency'] ?? 'GHS'; $response = $this->identitySend('PUT', '/api/identity/payout-account', array_merge( ['user' => ladill_account()->public_id], $data, )); $this->rethrowValidation($response, 'account_number'); return response()->json(['data' => ['payout_account' => $response->json('data.payout_account')]]); } public function withdrawals(): JsonResponse { $response = $this->identitySend('GET', '/api/identity/wallet/withdrawals?user='.urlencode((string) ladill_account()->public_id), []); return response()->json(['data' => $response->json('data', [])]); } public function withdraw(Request $request): JsonResponse { $data = $request->validate([ 'amount' => ['required', 'numeric', 'min:1', 'max:50000'], ]); $response = $this->identitySend('POST', '/api/identity/wallet/withdraw', [ 'user' => ladill_account()->public_id, 'amount' => (float) $data['amount'], ]); $this->rethrowValidation($response, 'amount'); return response()->json(['data' => $response->json('data', [])]); } }