BuiltEmail workspace

Bank top-up authorization — internal finance

Source: App\Mail\BankTopupCode, app/Mail/BankTopupCode.php, resources/views/emails/BankTopupCode.blade.php using mail::message. Subject: Built:No-reply (retain exact native string). Suggested preheader: Bank top-up {{topup_reference}} for {{business_name}}. Never include the code in a preheader or subject.

Required portable values

TokenExisting source / derivationHandling
{{business_name}}wallet.business_nameEscaped wallet-labelled business, not an unrelated Business.name.
{{wallet_number}}wallet.numberExact string, including leading zeros.
{{topup_reference}}transaction.reference (BankTopupTransaction)Complete original bank-top-up reference.
{{topup_amount}}wallet.currency . number_format(transaction.amount, 2)Full supplied formatted display, preserving currency, sign and zero. Not a charge/net/ledger value.
{{authorization_code}}transaction.secreteExact original code, including case/zeros. Preserve legacy secrete field spelling in the adapter; do not read it from serialized API JSON.
{{bank_name}}bank.bank_name (TopupBank)Original destination-bank label.
{{bank_account_name}}bank.account_nameExact escaped original account name.
{{bank_account_number}}bank.account_numberExact string; never numeric coercion or a wallet/account ID.
{{bank_branch}}bank.branchOriginal row, including supplied empty value. No invented fallback.
{{app_name}}config('app.name')Original Thanks sign-off.
{{preheader}}Suggested existing reference/business summary aboveEscaped text; no code or approval claim.

All business rows remain required even if a source value is supplied empty; no optional body blocks or legacy duplicate link fields exist. Missing required data needs an explicit target-project decision. The default Built logo/optional {{logo_url}} and common badge CID/HTTPS requirements follow [shared-footer](../shared-footer.md).

Trigger, recipient and data lifetime

WalletController::bankTopTup, app/Http/Controllers/Wallet/WalletController.php:130–200, is registered at POST topup/bank (routes/api.php:1634). It validates amount/account/bank, checks account ownership and suspended wallet state, finds the destination bank and creates MobileMoneyCollections with the existing pending collection context. It generates Str::random(8), saves BankTopupTransaction and calls Mail::to(the fixed internal finance recipient)->send(new BankTopupCode(transaction, wallet, bank)) at :184. It then invokes separate internal SMS messages, clears the in-memory code and returns the response. Preserve this ordering and all source recipient/validation/error policy.

BankTopupTransaction hides secrete from serialization and the caller sets its in-memory value to null after the send. Read transaction.secrete explicitly in the existing Mailable view/data adapter before that clearing step; API response JSON/toArray is not equivalent. Never retrieve a live code or banking record to fill previews, reports or screenshots. All codes/bank identifiers here are fictional.

The Mailable overrides only subject. Keep configured From/Reply-To, native send() and underlying transport/outbox. Queueable alone is not queue() usage. No business PDF, attachment, approval URL, expiry or single-use rule is configured. Do not add those claims or a confirmation/credit badge. Source creation is not proof that the bank received payment or the wallet was approved/credited. Destination bank account replaces the original paid-to label to avoid asserting verified receipt.

Integration and safety

Prefer the existing Mailable with a full HTML Blade view and proposed plain-text alternative; portable {{placeholder_name}} tokens are not automatically Blade. Escape all text/attributes, preserve the code as a string, validate logo/image URLs or real CID attachments separately, and use one pass for replacement. No new framework or send/authorization behavior is needed. Keep this internal audience distinct from a customer top-up receipt.

Four states cover standard, leading zeros/mixed case, supplied zero and long fields/code as rendering checks. The source generator normally emits eight characters; unusual fixture lengths do not establish real code validity. Files: public/ready/bank-topup-authorization.html/.txt and previews/bank-topup-authorization-*.html/.txt. No separate project-owned plain-text source found. Browser checks do not verify actual authorization, bank receipt, code validity, Gmail/Outlook/iOS Mail, embedded-image delivery or production sending.