fix(sms): every SMS says منتزر instead of هنزا گلد

The SMS texts were ported verbatim from henza and still carried its brand:
the login code, the welcome message (with the app.henzagold.com link), the
two complete-profile messages and the financial-document confirm/reject.
All now say منتزر, and the welcome link is https://bnk.montzar.ir.

The login code keeps its first line ("<#> code is <CODE>") and the trailing
SMS Retriever hash unchanged, so Android autofill still works. «اپلیکشن» is
corrected to «اپلیکیشن» in the same line.

Tests: sms.service.spec OTP template. All 263 API tests pass.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
s.esmaeili
2026-10-10 17:10:45 +03:30
co-authored by Cursor
parent 48da4cb4c7
commit 4d635cb89a
5 changed files with 21 additions and 21 deletions
@@ -141,8 +141,8 @@ export class AdminCustomersService {
/** /**
* The welcome SMS the reference sends after every new customer is created * The welcome SMS the reference sends after every new customer is created
* (AdminController.php:378-387). Byte-identical, including the line order and * (AdminController.php:378-387), with the brand and the PWA link changed to
* the trailing PWA link; the commented-out Android/iOS lines are not sent * منتزر; same line order. The commented-out Android/iOS lines are not sent
* there and are not sent here. * there and are not sent here.
* *
* D20 — awaiting it would let a slow or unconfigured gateway hold up the * D20 — awaiting it would let a slow or unconfigured gateway hold up the
@@ -153,11 +153,11 @@ export class AdminCustomersService {
*/ */
private sendWelcomeSms(mobile: string, firstName: string, lastName: string) { private sendWelcomeSms(mobile: string, firstName: string, lastName: string) {
const body = const body =
'هنزا گلد\n' + 'منتزر\n' +
`همکار گرامی ${firstName} ${lastName}\n` + `همکار گرامی ${firstName} ${lastName}\n` +
`نام کاربری : ${mobile}\n` + `نام کاربری : ${mobile}\n` +
'لینک pwa \n' + 'لینک pwa \n' +
'https://app.henzagold.com'; 'https://bnk.montzar.ir';
void this.sms.send(mobile, body).catch((e: unknown) => { void this.sms.send(mobile, body).catch((e: unknown) => {
// send() is documented never to throw; this is belt-and-braces so an // send() is documented never to throw; this is belt-and-braces so an
@@ -345,8 +345,8 @@ export class AdminDocumentsService {
// Legacy CashController::toggleConfiremCash sent an SMS on both outcomes. // Legacy CashController::toggleConfiremCash sent an SMS on both outcomes.
private notifyDocumentConfirm(customerId: string, confirmed: boolean) { private notifyDocumentConfirm(customerId: string, confirmed: boolean) {
const text = confirmed const text = confirmed
? 'هنزا گلد\nسند مالی شما توسط مدیر سیستم تایید شد.' ? 'منتزر\nسند مالی شما توسط مدیر سیستم تایید شد.'
: 'هنزا گلد\nسند مالی شما توسط مدیر سیستم رد شد.'; : 'منتزر\nسند مالی شما توسط مدیر سیستم رد شد.';
this.prisma.customer this.prisma.customer
.findUnique({ where: { id: customerId }, select: { mobile: true } }) .findUnique({ where: { id: customerId }, select: { mobile: true } })
@@ -728,13 +728,13 @@ export class CustomerAuthService {
* simply retries, and the throttle in assertSendAllowed still applies. * simply retries, and the throttle in assertSendAllowed still applies.
*/ */
private async deliver(mobile: string, code: string) { private async deliver(mobile: string, code: string) {
// BYTE-IDENTICAL to the reference (ApiMobileController.php:47). The // The reference's text (ApiMobileController.php:47) with the brand changed
// leading "<#> code is <CODE>" line and the trailing "aMo6iFyUQaY" are the // to منتزر. The leading "<#> code is <CODE>" line and the trailing
// Android SMS Retriever app hash — change either and autofill stops // "aMo6iFyUQaY" are the Android SMS Retriever app hash — change either and
// working on every installed client. Do not "tidy" this string. // autofill stops working on every installed client. Do not "tidy" them.
const smsText = const smsText =
`<#> code is ${code}\n` + `<#> code is ${code}\n` +
`رمز عبور یکبار مصرف شما جهت ورود به اپلیکشن هنزا گلد ${code} می باشد\n` + `رمز عبور یکبار مصرف شما جهت ورود به اپلیکیشن منتزر ${code} می باشد\n` +
`aMo6iFyUQaY`; `aMo6iFyUQaY`;
// persist:false — the real text carries the live code, and the admin SMS // persist:false — the real text carries the live code, and the admin SMS
@@ -104,15 +104,15 @@ export class CustomerProfileService {
* reference likewise queued them (SendSmsAfterCreate::dispatch, :100). * reference likewise queued them (SendSmsAfterCreate::dispatch, :100).
*/ */
private notify(mobile: string, firstName: string, lastName: string) { private notify(mobile: string, firstName: string, lastName: string) {
// Byte-identical to Major/CustomerController::complete:97-99. // Major/CustomerController::complete:97-99, brand changed to منتزر.
const message = const message =
'هنزا گلد\n' + 'منتزر\n' +
`همکار گرامی ${firstName} ${lastName}\n` + `همکار گرامی ${firstName} ${lastName}\n` +
'تکمیل پروفایل شما با موفقیت انجام شد.'; 'تکمیل پروفایل شما با موفقیت انجام شد.';
// Byte-identical to :103-105. // :103-105, brand changed to منتزر.
const adminMessage = const adminMessage =
'هنزا گلد\n' + `مشتری با نام ${firstName} ${lastName}` + ' مدارک خود را بارگذاری کرد.'; 'منتزر\n' + `مشتری با نام ${firstName} ${lastName}` + ' مدارک خود را بارگذاری کرد.';
const fire = (to: string, body: string) => { const fire = (to: string, body: string) => {
void this.sms.send(to, body).catch((e: unknown) => { void this.sms.send(to, body).catch((e: unknown) => {
+6 -6
View File
@@ -309,19 +309,19 @@ describe('SmsService.send', () => {
}); });
/** /**
* The OTP text must stay byte-identical to the reference * The OTP text keeps the reference's shape (ApiMobileController.php:47) with
* (ApiMobileController.php:47) — the first line and the trailing token are the * the brand منتزر — the first line and the trailing token are the Android SMS
* Android SMS Retriever hash, and autofill breaks if either changes. * Retriever hash, and autofill breaks if either changes.
*/ */
describe('OTP message template', () => { describe('OTP message template', () => {
const build = (code: string) => const build = (code: string) =>
`<#> code is ${code}\n` + `<#> code is ${code}\n` +
`رمز عبور یکبار مصرف شما جهت ورود به اپلیکشن هنزا گلد ${code} می باشد\n` + `رمز عبور یکبار مصرف شما جهت ورود به اپلیکیشن منتزر ${code} می باشد\n` +
`aMo6iFyUQaY`; `aMo6iFyUQaY`;
it('matches the reference byte for byte', () => { it('matches the expected text byte for byte', () => {
expect(build('1234')).toBe( expect(build('1234')).toBe(
'<#> code is 1234\nرمز عبور یکبار مصرف شما جهت ورود به اپلیکشن هنزا گلد 1234 می باشد\naMo6iFyUQaY', '<#> code is 1234\nرمز عبور یکبار مصرف شما جهت ورود به اپلیکیشن منتزر 1234 می باشد\naMo6iFyUQaY',
); );
}); });