Email workspaceInvoice payment received — merchant notice
Source: App\Mail\paymentRecieved (retain spelling), app/Mail/paymentRecieved.php; resources/views/emails/invoice/paymentRecieved.blade.php. Distinct from the customer's invoice PDF receipt and the payer's payment-link receipt.
Subject: Payment Received (unchanged).
Suggested preheader: Payment received from {{customer_business_name}}: {{payment_amount}}.
Required portable values
| Token | Existing source / derivation | Handling |
|---|---|---|
| {{customer_business_name}} | constructor customer.business_name (invoice.customer at callers) | Escaped payer identity. Not wallet/business-owner name. |
| {{payment_amount}} | invoice.base_currency . number_format(constructor amount, 2) | Full formatted payment display. MOMO caller uses transaction.amount; card caller uses paymentTransaction.amount. Not cumulative invoice.amount_paid or invoice total. |
| {{payment_reference}} | constructor reference | MOMO transRef ?: ref; card reference. Preserve complete escaped string. |
| {{payment_description}} | constructor description | Escaped text, including empty/0; not trusted provider HTML. |
| {{transaction_charge}} | invoice.base_currency . ' ' . number_format(constructor charge, 2) | Final singular charge argument; wallet path supplies 0, otherwise charge_incedis. |
| {{net_amount}} | invoice.base_currency . ' ' . number_format(amount - charge, 2) | Preserve source arithmetic and rounding in Laravel. Do not calculate with formatted strings/JS or use plural charges. |
| {{app_name}} | config('app.name') | Original Thanks sign-off. |
| {{preheader}} | Suggested source-derived summary above | Escaped text, no settlement/bank-arrival promise. |
The first source sentence inserted a space between currency/amount while the Amount row did not. One canonical payment_amount retains the source row's complete display; no numeric/currency change. Required zero/negative values must not disappear. No optional business section is added. Default logo/optional {{logo_url}} and footer CID/HTTPS requirements: [shared-footer](../shared-footer.md).
Callers, recipient and charge distinction
app/Http/Controllers/Income/paymentsController.php::completeMomopayment (:386) and ::completeCardPayment (:753) queue this Mailable to the invoice business owner's user.email inside their successful collection/payment-application paths. Preserve the verification/idempotence/paid-status guards, existing ledger/wallet/payment updates and reminder handling. A redesigned email does not authorize changing any financial or provider behavior.
Both callers pass charge_incedis as plural charges, but the view prints singular charge. The last argument email_charges = has_wallet ? 0 : charge_incedis controls the displayed charge and amount-minus-charge. Plural charges is still bound but unused in this body. Do not map the wrong value or “fix” ledger/notification differences via the template.
Only subject is explicitly overridden; retain configured From/Reply-To and queue(), plus existing transport/outbox policy. No PDF, business attachment or transactional URL is configured. Keep original specialized payment-support contacts hello@builtgh.com and 030 397 4832 inside the body even though the common footer uses separate company contacts. These are fixed source contacts, not placeholder destinations or preview actions.
Integration and safety
Use the existing Mailable with a full HTML Blade view and text alternative; portable {{placeholder_name}} tokens are not automatically Blade. Escape every supplied text/attribute and use one pass for replacements. Validate logo/badge URLs/CIDs separately. No legacy duplicate action link, retry button, invoice link or invented settlement status exists. Keep recipient routing separate from printed customer name.
Five states cover charged payment, wallet zero charge, card caller, supplied zero values and long fields. Files: public/ready/invoice-payment-received.html/.txt, previews/invoice-payment-received-*.html/.txt. No separate project-owned plain-text source found; new text is proposed equivalent content. Previews keep the specialized contact text but substitute inert local links. Browser checks do not verify actual financial calculations, provider delivery, Gmail/Outlook/iOS Mail or current production delivery.