Send verification SMS on the service line so carriers deliver the code.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-10-10 14:10:54 +03:30
co-authored by Cursor
parent 88f6a430d9
commit 0f80de1f05
5 changed files with 19 additions and 1 deletions
+2
View File
@@ -35,5 +35,7 @@ MEDIA_MAX_FILE_SIZE_MB=10
MESHKEE_SMS_URL=https://api.meshkee.com/api/v1/public/sms/send MESHKEE_SMS_URL=https://api.meshkee.com/api/v1/public/sms/send
MESHKEE_SMS_API_KEY= MESHKEE_SMS_API_KEY=
MESHKEE_SMS_DOMAIN=manacollections.ir MESHKEE_SMS_DOMAIN=manacollections.ir
# Service line. Omit and the gateway uses the advertising shortcode, which does not deliver OTP.
MESHKEE_SMS_SOURCE=5000110005
# Comma-separated admin mobiles for alerts # Comma-separated admin mobiles for alerts
SMS_NOTIFY_MOBILES= SMS_NOTIFY_MOBILES=
+5 -1
View File
@@ -24,6 +24,10 @@ async function main() {
'https://api.meshkee.com/api/v1/public/sms/send'; 'https://api.meshkee.com/api/v1/public/sms/send';
const apiKey = process.env.MESHKEE_SMS_API_KEY; const apiKey = process.env.MESHKEE_SMS_API_KEY;
const domain = process.env.MESHKEE_SMS_DOMAIN ?? 'manacollections.ir'; const domain = process.env.MESHKEE_SMS_DOMAIN ?? 'manacollections.ir';
const source =
process.argv.includes('--source')
? arg('source')
: (process.env.MESHKEE_SMS_SOURCE ?? '5000110005');
if (!apiKey) throw new Error('MESHKEE_SMS_API_KEY is not set in .env'); if (!apiKey) throw new Error('MESHKEE_SMS_API_KEY is not set in .env');
if (!/^09\d{9}$/.test(to)) throw new Error('to must match 09xxxxxxxxx'); if (!/^09\d{9}$/.test(to)) throw new Error('to must match 09xxxxxxxxx');
@@ -35,7 +39,7 @@ async function main() {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-Api-Key': apiKey, 'X-Api-Key': apiKey,
}, },
body: JSON.stringify({ domain, to, message }), body: JSON.stringify({ domain, to, message, source }),
}); });
const body = await response.json().catch(() => null); const body = await response.json().catch(() => null);
+1
View File
@@ -379,6 +379,7 @@ export class AuthService {
await this.sms.send({ await this.sms.send({
to: input.cellNumber, to: input.cellNumber,
message: input.message(code), message: input.message(code),
source: this.sms.otpSource(),
}); });
return { return {
+9
View File
@@ -20,6 +20,14 @@ export class SmsService {
this.domain = this.config.getOrThrow<string>('MESHKEE_SMS_DOMAIN'); this.domain = this.config.getOrThrow<string>('MESHKEE_SMS_DOMAIN');
} }
/**
* Service shortcode (خط خدماتی). The partner gateway otherwise sends from
* the advertising line, which operators drop for verification texts.
*/
otpSource(): string {
return this.config.get<string>('MESHKEE_SMS_SOURCE')?.trim() || '5000110005';
}
notifyMobiles(): string[] { notifyMobiles(): string[] {
const raw = this.config.get<string>('SMS_NOTIFY_MOBILES', ''); const raw = this.config.get<string>('SMS_NOTIFY_MOBILES', '');
return raw return raw
@@ -69,6 +77,7 @@ export class SmsService {
domain: this.domain, domain: this.domain,
to, to,
message, message,
...(input.source ? { source: input.source } : {}),
}), }),
}); });
} catch (err) { } catch (err) {
+2
View File
@@ -1,6 +1,8 @@
export type SendSmsInput = { export type SendSmsInput = {
to: string; to: string;
message: string; message: string;
/** Gama shortcode. OTP must use the service line; the partner default is advertising. */
source?: string;
}; };
export type SendSmsResult = { export type SendSmsResult = {