1/** 2 * Login por teléfono + OTP (SMS/WhatsApp). 3 * Requiere apiCall(action, data) en la página, o usa fetch a api/api.php. 4 * Ningún canal viene premarcado: el usuario debe elegir SMS o WhatsApp. 5 */ 6(function (w) { 7 function call(action, data) { 8 if (typeof w.apiCall === 'function') return w.apiCall(action, data); 9 if (typeof w.api === 'function') return w.api(action, data); 10 var fd = new FormData(); 11 fd.append('action', action); 12 Object.keys(data || {}).forEach(function (k) { 13 if (data[k] != null) fd.append(k, data[k]); 14 }); 15 return fetch('api/api.php', { method: 'POST', body: fd, credentials: 'same-origin' }).then(function (r) { 16 return r.json(); 17 }); 18 } 19 20 function channelOf(name) { 21 var el = document.querySelector('input[name="' + name + '"]:checked'); 22 if (!el) return ''; 23 return el.value === 'sms' || el.value === 'whatsapp' ? el.value : ''; 24 } 25 26 function channelRequiredMsg() { 27 return 'Elige cómo quieres recibir el código: SMS o WhatsApp.'; 28 } 29 30 function goAfterFlags(res, urls) { 31 urls = urls || {}; 32 if (res && res.pending_registration && typeof w.emsOnPendingRegistration === 'function') { 33 w.emsOnPendingRegistration(res); 34 return; 35 } 36 if (res && res.needs_basic_profile) { 37 if (urls.profile) { w.location.href = urls.profile; return; } 38 var box = document.getElementById('otpBasicWrap'); 39 if (box) box.style.display = 'block'; 40 return; 41 } 42 w.location.href = urls.home || 'cliente_panel.php'; 43 } 44 45 w.emsPhoneOtp = { 46 lastTicket: '', 47 request: function (role, phone, channel) { 48 var ch = (channel || '').toString().toLowerCase(); 49 if (ch !== 'sms' && ch !== 'whatsapp') { 50 return Promise.resolve({ 51 ok: false, 52 error: channelRequiredMsg(), 53 error_code: 'channel_required' 54 }); 55 } 56 return call('request_phone_otp', { role: role, phone: phone, otp_channel: ch }); 57 }, 58 verify: function (role, phone, code) { 59 return call('verify_phone_otp', { role: role, phone: phone, token: code }).then(function (res) { 60 if (res && res.otp_ticket) w.emsPhoneOtp.lastTicket = res.otp_ticket; 61 return res; 62 }); 63 }, 64 complete: function (payload) { 65 if (w.emsPhoneOtp.lastTicket && !payload.otp_ticket) payload.otp_ticket = w.emsPhoneOtp.lastTicket; 66 return call('complete_basic_profile', payload); 67 }, 68 changePassword: function (password) { 69 return call('otp_change_password', { password: password, password2: password }); 70 }, 71 channelOf: channelOf, 72 channelRequiredMsg: channelRequiredMsg, 73 goAfterFlags: goAfterFlags 74 }; 75})(window);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.