mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 17:29:45 +00:00
fix(whatsapp): allow connecting Meta test numbers without a PIN
The WhatsApp config POST handler hard-failed with a 400 whenever a number needed registration (first save or number change) and no 6-digit two-step-verification PIN was supplied. Meta test numbers (Developer Console) are pre-registered by Meta and expose no PIN to set, so test-number users could never complete setup (issue #242). The PIN-based /{phone_number_id}/register call only governs inbound webhook routing for production numbers under a shared WABA (issue #136) — it has nothing to do with credential validity or outbound sends. So treat it as best-effort: when no PIN is supplied, skip /register, save the (already Meta-verified) credentials as connected, and leave registered_at null. The response now reports `registered` accurately and adds `registration_skipped` so the UI can react. UI: the save handler no longer falsely claims the number is "Live" on a skipped registration — it points at the existing "Not registered" banner, which already offers a PIN-retry path. The PIN field is relabelled (optional) with copy explaining it's only for production inbound routing and that test numbers have no PIN. Fixes #242 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5b6fe3d677
commit
3b924c85bc
@ -284,26 +284,32 @@ export async function POST(request: Request) {
|
||||
|
||||
// Step 1: register the phone number for inbound webhooks.
|
||||
//
|
||||
// Required on first save AND whenever the user supplies a fresh
|
||||
// Attempted on first save AND whenever the user supplies a fresh
|
||||
// PIN (e.g. they rotated the 2FA PIN in Meta Manager). Skipped
|
||||
// when the same number is already registered and no PIN was
|
||||
// supplied — re-registering an already-active number with a
|
||||
// stale PIN would actually fail and undo the active subscription.
|
||||
let registeredAt: string | null = existing?.registered_at ?? null
|
||||
let registrationError: string | null = null
|
||||
// True when registration was deliberately skipped because no PIN
|
||||
// was supplied (see below). Distinct from registrationError — this
|
||||
// is not a failure, just an incomplete-but-valid save.
|
||||
let registrationSkipped = false
|
||||
|
||||
const needsRegistration = !sameNumber || (typeof pin === 'string' && pin.length > 0)
|
||||
if (needsRegistration) {
|
||||
if (!pin) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
'Two-step verification PIN is required to subscribe this number to wacrm. ' +
|
||||
'Set a 6-digit PIN in Meta WhatsApp Manager → Phone Numbers → Two-step verification, then paste it below.',
|
||||
},
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
// No PIN provided. Meta TEST numbers (Developer Console) are
|
||||
// pre-registered by Meta and expose no two-step verification
|
||||
// PIN to set, so requiring one made them impossible to connect
|
||||
// (issue #242). The /register + PIN step only matters for
|
||||
// production numbers under a shared WABA (issue #136), so treat
|
||||
// it as best-effort: skip it, save the (already Meta-verified)
|
||||
// credentials as connected, and leave registered_at null. The
|
||||
// UI surfaces a separate "Not registered" banner with a path to
|
||||
// add a PIN later for users who do need inbound webhook routing.
|
||||
registrationSkipped = true
|
||||
} else {
|
||||
try {
|
||||
await registerPhoneNumber({
|
||||
phoneNumberId: phone_number_id,
|
||||
@ -321,6 +327,7 @@ export async function POST(request: Request) {
|
||||
// not actually live yet.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: subscribe the WABA to this app. Idempotent on Meta's
|
||||
// side, so we call on every save and persist the timestamp.
|
||||
@ -410,7 +417,12 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
saved: true,
|
||||
registered: true,
|
||||
registered: registeredAt != null,
|
||||
// Credentials are valid and saved, but inbound webhook
|
||||
// registration was skipped because no PIN was supplied (e.g. a
|
||||
// Meta test number). The UI shows the "Not registered" banner
|
||||
// rather than claiming the number is fully live.
|
||||
registration_skipped: registrationSkipped,
|
||||
phone_info: phoneInfo,
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
@ -233,6 +233,16 @@ export function WhatsAppConfig() {
|
||||
`Saved, but Meta couldn't register the number: ${data.registration_error}`,
|
||||
{ duration: 12000 },
|
||||
);
|
||||
} else if (data.registration_skipped) {
|
||||
// Credentials saved + verified, but /register was skipped
|
||||
// because no PIN was supplied (e.g. a Meta test number).
|
||||
// Don't claim the number is "Live" — point at the
|
||||
// Registration status banner instead.
|
||||
toast.success(
|
||||
'Credentials saved and verified. Inbound registration was skipped (no PIN) — see Registration status below.',
|
||||
{ duration: 10000 },
|
||||
);
|
||||
setPin('');
|
||||
} else {
|
||||
toast.success(
|
||||
data.phone_info?.verified_name
|
||||
@ -604,9 +614,7 @@ export function WhatsAppConfig() {
|
||||
<div className="space-y-2">
|
||||
<Label className="text-slate-300">
|
||||
Two-step verification PIN
|
||||
{!isRegistered && (
|
||||
<span className="ml-1 text-red-400">*</span>
|
||||
)}
|
||||
<span className="ml-1 text-slate-500">(optional)</span>
|
||||
</Label>
|
||||
<Input
|
||||
type="text"
|
||||
@ -620,16 +628,19 @@ export function WhatsAppConfig() {
|
||||
className="bg-slate-800 border-slate-700 text-white placeholder:text-slate-500 tracking-widest"
|
||||
/>
|
||||
<p className="text-xs text-slate-500 leading-relaxed">
|
||||
Required the first time you connect a number, and any
|
||||
time you swap to a different number. Set it in{' '}
|
||||
Needed only to wire <strong className="text-slate-300">inbound</strong> messages
|
||||
for a <strong className="text-slate-300">production</strong> number. Set it in{' '}
|
||||
<strong className="text-slate-300">
|
||||
Meta Business Manager → WhatsApp Accounts → Phone
|
||||
Numbers → Two-step verification
|
||||
</strong>
|
||||
. Without this PIN, Meta saves your credentials but
|
||||
won't actually route inbound messages to wacrm —
|
||||
the symptom that hits second numbers under a shared
|
||||
WABA. Leave blank to keep an existing registration
|
||||
, then paste it here so wacrm can subscribe the number —
|
||||
otherwise Meta routes inbound events to whichever app
|
||||
last claimed it (the symptom that hits second numbers
|
||||
under a shared WABA).{' '}
|
||||
<strong className="text-slate-300">Meta test numbers</strong> have no
|
||||
PIN and are pre-registered — leave this blank for them.
|
||||
Leaving it blank also keeps an existing registration
|
||||
untouched.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user