React Native
...
Cloud Functions
เพิ่ม OTP Authentication ใน React Native ด้วย Parse Cloud
10 นาที
การตรวจสอบ otp สำหรับ react native โดยใช้ cloud functions บทนำ ในคู่มือนี้ คุณจะได้เรียนรู้วิธีการใช้ฟังก์ชัน parse cloud code เพื่อรวม api twilio verify ในแอป react native เพื่อเปิดใช้งานฟีเจอร์การเข้าสู่ระบบด้วย otp ฟังก์ชัน cloud code เป็นสถานที่ที่เหมาะสมสำหรับการดำเนินการประเภทนี้ เนื่องจากช่วยให้คุณจัดการข้อมูลที่ละเอียดอ่อนและใช้ api อื่น ๆ นอกเหนือจากแอปพลิเคชันของคุณ ในคู่มือนี้คุณยังจะได้ตรวจสอบวิธีการสร้างคอมโพเนนต์ react native โดยใช้การรวม otp ซึ่งจะช่วยปรับปรุงตัวอย่างการตรวจสอบอีเมลของผู้ใช้ในคู่มือก่อนหน้านี้ ในทุกช่วงเวลา คุณสามารถเข้าถึงโปรเจกต์ android ที่สร้างขึ้นจากบทเรียนนี้ได้ที่ที่เก็บ github ของเรา https //github com/templates back4app/android parse sdk kotlin https //github com/templates back4app/android parse sdk java ข้อกำหนดเบื้องต้น ในการทำตามบทแนะนำนี้ คุณจะต้องมี แอป react native ที่สร้างขึ้นและ https //www back4app com/docs/react native/parse sdk/react native sdk เข้าใจวิธีการ https //www back4app com/docs/get started/cloud functions บน back4app บัญชีที่ใช้งานอยู่ที่ twilio คุณสามารถสร้างบัญชีทดลองฟรี https //login twilio com/u/signup?state=hkfo2sbwngzlcuy5cjj3wgfzahqwcnizme5kqtvpvg51yjbzu6fur3vuaxzlcnnhbc1sb2dpbqn0awtzihg1lvrwtxpraupht3d4mghzwunxqm5wqi0xddm1wdhlo2npznkgtw05m1lttdvsclpmnzdobulkzfi3qktzyjzpoxv1cks บัญชีที่ใช้งานอยู่ที่ sendgrid คุณสามารถสร้างบัญชีทดลองฟรี https //login twilio com/u/signup?state=hkfo2sbfztlfrwntc2tflwrdqumtqujjc3pgnufnzfrgdlntdqfur3vuaxzlcnnhbc1sb2dpbqn0awtzihm3ek1jewjougvbn3dndljsc0dlytywlwtvbwppq0nno2npznkgr244uwmyz1foa2trz0llt2s4qljqrwz5ewnomtu2vuk เป้าหมาย รวม api twilio verify โดยใช้ฟังก์ชัน parse cloud code บน back4app และใช้ในแอป react native 1 การตั้งค่า twilio verify twilio เป็นผู้ให้บริการโทเค็น 2fa และ otp ที่มีชื่อเสียง ซึ่งถูกใช้โดยบริษัทต่างๆ ในปัจจุบัน api verify เป็นชุด api ที่เรียบง่ายเพื่อช่วยนักพัฒนาในการตรวจสอบโทรศัพท์ อีเมล และทำการเข้าสู่ระบบโดยไม่ใช้รหัสผ่านอย่างสะดวก ในคู่มือนี้ คุณจะใช้วิธีการตรวจสอบ sms และอีเมลเพื่อให้แอปพลิเคชันของคุณมีฟีเจอร์ otp เราจะติดตามเอกสาร verify อย่างเป็นทางการ https //www twilio com/docs/verify/api , ดังนั้นให้ดูอ้างอิงหากขั้นตอนใดขั้นตอนหนึ่งทำให้คุณสับสน หลังจากสร้างบัญชี twilio และ sendgrid ของคุณ (sendgrid จำเป็นสำหรับการส่งอีเมลอัตโนมัติที่มีโทเค็นผู้ใช้ของคุณ) ให้จดบันทึกตัวระบุต่อไปนี้ซึ่งสามารถดึงข้อมูลได้จากแดชบอร์ดของแต่ละบริการ sid บัญชี twilio และโทเค็นการรับรองตัวตน; id ของ sendgrid และ id ของเทมเพลตอีเมลที่ง่าย ตอนนี้ สร้างบริการ verify ใหม่ใน twilio verify https //www twilio com/console/verify/dashboard , ซึ่งเป็นชุดการตั้งค่าที่จะจัดการคำขอ otp และการตรวจสอบของเรา อย่าลืมจดบันทึก sid ของบริการของคุณที่นี่ หากคุณต้องการ คุณยังสามารถเปิดใช้งานการส่งรหัสทางอีเมลโดยการเพิ่มคีย์ sendgrid ของคุณโดยการสร้างการรวมอีเมลใหม่ภายในบริการ verify https //www twilio com/docs/verify/email แค่นั้นแหละ การตั้งค่าทั้งหมดเสร็จสิ้นแล้วและเราสามารถดำเนินการสร้างฟังก์ชัน cloud code ของเราได้แล้ว 2 การรวมเข้ากับฟังก์ชัน cloud code ตามที่ได้กล่าวไว้ก่อนหน้านี้ การใช้ฟังก์ชัน cloud code ในแอปพลิเคชันของคุณช่วยให้มีความยืดหยุ่นอย่างมากในโค้ดของคุณ ทำให้สามารถแยกวิธีการที่นำกลับมาใช้ใหม่จากแอปของคุณและควบคุมพฤติกรรมของพวกเขาได้ดีขึ้น คุณสามารถตรวจสอบหรือทบทวนวิธีการใช้งานได้ที่ https //www back4app com/docs/get started/cloud functions เรามาสร้างฟังก์ชันคลาวด์แรกของเราที่เรียกว่า requestotp requestotp , ซึ่งจะสร้าง otp และส่งไปยังผู้ใช้ผ่านวิธีที่เลือก ฟังก์ชันนี้ต้องรับพารามิเตอร์สองตัวคือ userdata userdata ซึ่งประกอบด้วยอีเมลหรือหมายเลขโทรศัพท์ และ erificationtype erificationtype , ซึ่งระบุวิธีการตรวจสอบที่ใช้ email email หรือ sms sms นี่คือรหัสฟังก์ชัน 1 // define twilio keys and require the library helper 2 const accountsid = 'your twilio account sid here'; 3 const authtoken = 'your twilio auth token here'; 4 const client = require('twilio')(accountsid, authtoken); 5	 6 // request otp 7 parse cloud define('requestotp', async (request) => { 8 const userdata = request params userdata; 9 const verificationtype = request params verificationtype; 10 let verification request = await client verify 11 services('your twilio verify service id here') 12 verifications create({ to userdata, channel verificationtype }); 13 return { status verification request status, error '' }; 14 }); โปรดทราบว่าในตอนต้นเราได้กำหนดคีย์ api ของ twilio และนำเข้าไลบรารีช่วยแล้ว การใช้งาน parse server ของ back4app ให้เราสามารถเข้าถึงไลบรารี twilio ได้จากค่าเริ่มต้น ดังนั้นคุณไม่จำเป็นต้องติดตั้งมันบนเซิร์ฟเวอร์ของคุณ ฟังก์ชันคลาวด์ที่สองและสุดท้ายเรียกว่า verifyotp verifyotp , มันจะตรวจสอบโทเค็นผู้ใช้ของคุณใน verify ของ twilio และเข้าสู่ระบบโดยอัตโนมัติ สร้างเซสชันและส่ง id กลับไปยังแอปพลิเคชันของคุณ เพื่อให้คุณสามารถเข้าสู่ระบบโดยไม่ต้องใช้รหัสผ่านจากที่นั่น มีพารามิเตอร์ที่จำเป็นสี่ตัว โดยสองตัวแรกเป็นพารามิเตอร์เดียวกันจากฟังก์ชันก่อนหน้า พร้อมกับการเพิ่ม usertoken usertoken , ซึ่งประกอบด้วยโทเค็นการตรวจสอบที่แจ้งไว้ และยังมี userinstallationid userinstallationid , ซึ่งจะอธิบายเพิ่มเติมในภายหลัง 1 // since we need in uuid v4 id for creating a new session, this function 2 // mocks the creation of one without the need to import the `uuidv4` module 3 // for a more robust solution, consider using the uuid module, which uses 4 // higher quality rng apis 5 // adapted from https //stackoverflow\ com/a/2117523 6 function uuidv4() { 7 return 'xxxxxxxx xxxx 4xxx yxxx xxxxxxxxxxxx' replace(/\[xy]/g, function (c) { 8 var r = (math random() 16) | 0, 9 v = c == 'x' ? r (r & 0x3) | 0x8; 10 return v tostring(16); 11 }); 12 } 13	 14 // verify otp 15 parse cloud define('verifyotp', async (request) => { 16 const { userdata, verificationtype, usertoken, userinstallationid } = 17 request params; 18 let verification check = await client verify 19 services('your twilio verify service id here') 20 verificationchecks create({ to userdata, code usertoken }); 21 // status can be 'approved' if correct or 'pending' if incorrect 22 if (verification check status === 'approved') { 23 try { 24 // get user to login 25 let user = null; 26 if (verificationtype === 'sms') { 27 user = await new parse query(parse user) 28 equalto('phonenumber', userdata) 29 first({ usemasterkey true }); 30 } else { 31 user = await new parse query(parse user) 32 equalto('email', userdata) 33 first({ usemasterkey true }); 34 } 35 // create new session for login use in 36 // manually create session (without using parse session because of it's update restrictions) 37 // adapted from https //stackoverflow\ com/a/67432715 38 let session = new parse object(' session', { 39 user user, 40 installationid userinstallationid, 41 sessiontoken `r ${uuidv4()}`, 42 }); 43 session = await session save(undefined, { usemasterkey true }); 44 return { sessionid session get('sessiontoken') }; 45 } catch (error) { 46 console log(error); 47 return { error `${error}` }; 48 } 49 } 50 return { error 'could not validate your token or account! try again!' }; 51 }); โปรดตรวจสอบให้แน่ใจว่าคุณได้ปรับใช้ฟังก์ชันเหล่านี้ใน parse server ของคุณก่อนที่จะไปยังขั้นตอนถัดไป 3 การสร้างฟีเจอร์ otp ใน react native ตอนนี้เรามาใช้ตัวอย่างโปรเจกต์เดียวกันจากการตรวจสอบอีเมลของผู้ใช้ https //www back4app com/docs/react native/parse sdk/working with users/react native email verification เป็นฐานและเพิ่มการเปลี่ยนแปลงบางอย่างเพื่อเปิดใช้งานฟีเจอร์ otp ใหม่ เราขอแนะนำให้ดาวน์โหลดตัวอย่างโปรเจกต์และตั้งค่าก่อนที่จะดำเนินการต่อกับคู่มือ ก่อนอื่น เพื่อให้ผู้ใช้สามารถเข้าสู่ระบบโดยใช้หมายเลขโทรศัพท์ของตนได้ ให้เพิ่มฟิลด์ข้อมูลใหม่และเพิ่มค่าไปยังวิธีการบันทึกการลงทะเบียนผู้ใช้ใน userregistration js userregistration js (หรือ userregistration tsx userregistration tsx ) ไฟล์ javascript 1 import react, {usestate} from 'react'; 2 import { 3 alert, 4 image, 5 text, 6 textinput, 7 touchableopacity, 8 view, 9 } from 'react native'; 10 import parse from 'parse/react native'; 11 import {usenavigation} from '@react navigation/native'; 12 import {stackactions} from '@react navigation/native'; 13 import styles from ' /styles'; 14	 15 export const userregistration = () => { 16 const navigation = usenavigation(); 17	 18 const \[username, setusername] = usestate(''); 19 const \[password, setpassword] = usestate(''); 20 const \[email, setemail] = usestate(''); 21 const \[phonenumber, setphonenumber] = usestate(''); 22	 23 const dousersignup = async function () { 24 // note that this values come from state variables that we've declared before 25 const usernamevalue = username; 26 const passwordvalue = password; 27 const emailvalue = email; 28 const phonenumbervalue = phonenumber; 29 try { 30 // since the signup method returns a promise, we need to call it using await 31 // note that now you are setting the user email value as well 32 let createduser = await parse user signup(usernamevalue, passwordvalue, { 33 email emailvalue, 34 phonenumber phonenumbervalue, 35 }); 36	 37 // parse user signup returns the already created parseuser object if successful 38 alert alert( 39 'success!', 40 `user ${createduser get( 41 'username', 42 )} was successfully created! verify your email to login`, 43 ); 44 // since email verification is now required, make sure to log out 45 // the new user, so any session created is cleared and the user can 46 // safely log in again after verifying 47 await parse user logout(); 48 // go back to the login page 49 navigation dispatch(stackactions poptotop()); 50 return true; 51 } catch (error) { 52 // signup can fail if any parameter is blank or failed an uniqueness check on the server 53 alert alert('error!', error message); 54 return false; 55 } 56 }; 57	 58 return ( 59 \<view style={styles login wrapper}> 60 \<view style={styles form}> 61 \<textinput 62 style={styles form input} 63 value={username} 64 placeholder={'username'} 65 onchangetext={(text) => setusername(text)} 66 autocapitalize={'none'} 67 keyboardtype={'email address'} 68 /> 69 \<textinput 70 style={styles form input} 71 value={email} 72 placeholder={'email'} 73 onchangetext={(text) => setemail(text)} 74 autocapitalize={'none'} 75 keyboardtype={'email address'} 76 /> 77 \<textinput 78 style={styles form input} 79 value={phonenumber} 80 placeholder={'phone (international format +15017122661)'} 81 onchangetext={(text) => setphonenumber(text)} 82 autocapitalize={'none'} 83 keyboardtype={'phone pad'} 84 /> 85 \<textinput 86 style={styles form input} 87 value={password} 88 placeholder={'password'} 89 securetextentry 90 onchangetext={(text) => setpassword(text)} 91 /> 92 \<touchableopacity onpress={() => dousersignup()}> 93 \<view style={styles button}> 94 \<text style={styles button label}>{'sign up'}\</text> 95 \</view> 96 \</touchableopacity> 97 \</view> 98 \<view style={styles login social}> 99 \<view style={styles login social separator}> 100 \<view style={styles login social separator line} /> 101 \<text style={styles login social separator text}>{'or'}\</text> 102 \<view style={styles login social separator line} /> 103 \</view> 104 \<view style={styles login social buttons}> 105 \<touchableopacity> 106 \<view 107 style={\[ 108 styles login social button, 109 styles login social facebook, 110 ]}> 111 \<image 112 style={styles login social icon} 113 source={require(' /assets/icon facebook png')} 114 /> 115 \</view> 116 \</touchableopacity> 117 \<touchableopacity> 118 \<view style={styles login social button}> 119 \<image 120 style={styles login social icon} 121 source={require(' /assets/icon google png')} 122 /> 123 \</view> 124 \</touchableopacity> 125 \<touchableopacity> 126 \<view style={styles login social button}> 127 \<image 128 style={styles login social icon} 129 source={require(' /assets/icon apple png')} 130 /> 131 \</view> 132 \</touchableopacity> 133 \</view> 134 \</view> 135 <> 136 \<touchableopacity onpress={() => navigation navigate('login')}> 137 \<text style={styles login footer text}> 138 {'already have an account? '} 139 \<text style={styles login footer link}>{'log in'}\</text> 140 \</text> 141 \</touchableopacity> 142 \</> 143 \</view> 144 ); 145 };1 import react, {fc, reactelement, usestate} from 'react'; 2 import { 3 alert, 4 image, 5 text, 6 textinput, 7 touchableopacity, 8 view, 9 } from 'react native'; 10 import parse from 'parse/react native'; 11 import {usenavigation} from '@react navigation/native'; 12 import {stackactions} from '@react navigation/native'; 13 import styles from ' /styles'; 14	 15 export const userregistration fc<{}> = ({}) reactelement => { 16 const navigation = usenavigation(); 17	 18 const \[username, setusername] = usestate(''); 19 const \[password, setpassword] = usestate(''); 20 const \[email, setemail] = usestate(''); 21 const \[phonenumber, setphonenumber] = usestate(''); 22	 23 const dousersignup = async function () promise\<boolean> { 24 // note that this values come from state variables that we've declared before 25 const usernamevalue string = username; 26 const passwordvalue string = password; 27 const emailvalue string = email; 28 const phonenumbervalue string = phonenumber; 29 try { 30 // since the signup method returns a promise, we need to call it using await 31 // note that now you are setting the user email value as well 32 let createduser = await parse user signup(usernamevalue, passwordvalue, { 33 email emailvalue, 34 phonenumber phonenumbervalue, 35 }); 36	 37 // parse user signup returns the already created parseuser object if successful 38 alert alert( 39 'success!', 40 `user ${createduser get( 41 'username', 42 )} was successfully created! verify your email to login`, 43 ); 44 // since email verification is now required, make sure to log out 45 // the new user, so any session created is cleared and the user can 46 // safely log in again after verifying 47 await parse user logout(); 48 // go back to the login page 49 navigation dispatch(stackactions poptotop()); 50 return true; 51 } catch (error object) { 52 // signup can fail if any parameter is blank or failed an uniqueness check on the server 53 alert alert('error!', error message); 54 return false; 55 } 56 }; 57	 58 return ( 59 \<view style={styles login wrapper}> 60 \<view style={styles form}> 61 \<textinput 62 style={styles form input} 63 value={username} 64 placeholder={'username'} 65 onchangetext={(text) => setusername(text)} 66 autocapitalize={'none'} 67 keyboardtype={'email address'} 68 /> 69 \<textinput 70 style={styles form input} 71 value={email} 72 placeholder={'email'} 73 onchangetext={(text) => setemail(text)} 74 autocapitalize={'none'} 75 keyboardtype={'email address'} 76 /> 77 \<textinput 78 style={styles form input} 79 value={phonenumber} 80 placeholder={'phone (international format +15017122661)'} 81 onchangetext={(text) => setphonenumber(text)} 82 autocapitalize={'none'} 83 keyboardtype={'phone pad'} 84 /> 85 \<textinput 86 style={styles form input} 87 value={password} 88 placeholder={'password'} 89 securetextentry 90 onchangetext={(text) => setpassword(text)} 91 /> 92 \<touchableopacity onpress={() => dousersignup()}> 93 \<view style={styles button}> 94 \<text style={styles button label}>{'sign up'}\</text> 95 \</view> 96 \</touchableopacity> 97 \</view> 98 \<view style={styles login social}> 99 \<view style={styles login social separator}> 100 \<view style={styles login social separator line} /> 101 \<text style={styles login social separator text}>{'or'}\</text> 102 \<view style={styles login social separator line} /> 103 \</view> 104 \<view style={styles login social buttons}> 105 \<touchableopacity> 106 \<view 107 style={\[ 108 styles login social button, 109 styles login social facebook, 110 ]}> 111 \<image 112 style={styles login social icon} 113 source={require(' /assets/icon facebook png')} 114 /> 115 \</view> 116 \</touchableopacity> 117 \<touchableopacity> 118 \<view style={styles login social button}> 119 \<image 120 style={styles login social icon} 121 source={require(' /assets/icon google png')} 122 /> 123 \</view> 124 \</touchableopacity> 125 \<touchableopacity> 126 \<view style={styles login social button}> 127 \<image 128 style={styles login social icon} 129 source={require(' /assets/icon apple png')} 130 /> 131 \</view> 132 \</touchableopacity> 133 \</view> 134 \</view> 135 <> 136 \<touchableopacity onpress={() => navigation navigate('login')}> 137 \<text style={styles login footer text}> 138 {'already have an account? '} 139 \<text style={styles login footer link}>{'log in'}\</text> 140 \</text> 141 \</touchableopacity> 142 \</> 143 \</view> 144 ); 145 }; ตอนนี้เรามาสร้างไฟล์ใหม่ที่มีหน้าจอใหม่ userotp userotp ซึ่งจะจัดการกับกระบวนการ otp ทั้งหมด หน้าจอจะมีช่องกรอกข้อมูลสองช่อง โดยช่องแรกให้ผู้ใช้กรอกวิธีการรับ otp (ที่อยู่อีเมลหรือหมายเลขโทรศัพท์) ช่องกรอกข้อมูลอีกช่องหนึ่ง ซึ่งจะซ่อนอยู่ก่อนที่จะส่งคำขอ otp จะมีโทเค็นที่ผู้ใช้ได้รับอยู่ที่นั่น นี่คือ userotp js userotp js (หรือ userotp tsx userotp tsx ) โค้ด javascript 1 import react, {usestate} from 'react'; 2 import {alert, text, textinput, touchableopacity, view} from 'react native'; 3 import parse from 'parse/react native'; 4 import {usenavigation} from '@react navigation/native'; 5 import styles from ' /styles'; 6	 7 export const userotp = () => { 8 const navigation = usenavigation(); 9	 10 const \[userdata, setuserdata] = usestate(''); 11 const \[usertoken, setusertoken] = usestate(''); 12 const \[tokenrequested, settokenrequested] = usestate(false); 13	 14 const requestotp = async function () { 15 // note that this values come from state variables that we've declared before 16 const userdatavalue = userdata; 17 // check if value is an email if it contains @ note that in a real 18 // app you need a much better validator for this field 19 const verificationtype = 20 userdatavalue includes('@') === true ? 'email' 'sms'; 21 // we need to call it using await 22 try { 23 await parse cloud run('requestotp', { 24 userdata userdatavalue, 25 verificationtype verificationtype, 26 }); 27 // show token input field 28 settokenrequested(true); 29 alert alert('success!', `token requested via ${verificationtype}!`); 30 return true; 31 } catch (error) { 32 alert alert('error!', error message); 33 return false; 34 } 35 }; 36	 37 const verifyotp = async function () { 38 // note that this values come from state variables that we've declared before 39 const userdatavalue = userdata; 40 const usertokenvalue = usertoken; 41 // check if value is an email if it contains @ note that in a real 42 // app you need a much better validator for this field 43 const verificationtype = 44 userdatavalue includes('@') === true ? 'email' 'sms'; 45 // we need the installation id to allow cloud code to create 46 // a new session and login user without password 47 const parseinstallationid = await parse getinstallationid(); 48 // we need to call it using await 49 try { 50 // verify otp, if successful, returns a sessionid 51 let response = await parse cloud run('verifyotp', { 52 userdata userdatavalue, 53 verificationtype verificationtype, 54 usertoken usertokenvalue, 55 parseinstallationid parseinstallationid, 56 }); 57 if (response sessionid !== undefined) { 58 // use generated sessionid to become a user, 59 // logging in without needing to inform password and username 60 await parse user become(response sessionid); 61 const loggedinuser= await parse user currentasync(); 62 alert alert( 63 'success!', 64 `user ${loggedinuser get('username')} has successfully signed in!`, 65 ); 66 // navigation navigate takes the user to the home screen 67 navigation navigate('home'); 68 return true; 69 } else { 70 throw response; 71 } 72 } catch (error) { 73 alert alert('error!', error message); 74 return false; 75 } 76 }; 77	 78 return ( 79 \<view style={styles login wrapper}> 80 {tokenrequested === false ? ( 81 \<view style={styles form}> 82 \<textinput 83 style={styles form input} 84 value={userdata} 85 placeholder={'email or mobile phone number'} 86 onchangetext={(text) => setuserdata(text)} 87 autocapitalize={'none'} 88 keyboardtype={'email address'} 89 /> 90 \<touchableopacity onpress={() => requestotp()}> 91 \<view style={styles button}> 92 \<text style={styles button label}>{'request otp'}\</text> 93 \</view> 94 \</touchableopacity> 95 \</view> 96 ) ( 97 \<view style={styles form}> 98 \<text>{'inform the received token to proceed'}\</text> 99 \<textinput 100 style={styles form input} 101 value={usertoken} 102 placeholder={'token (6 digits)'} 103 onchangetext={(text) => setusertoken(text)} 104 autocapitalize={'none'} 105 keyboardtype={'default'} 106 /> 107 \<touchableopacity onpress={() => verifyotp()}> 108 \<view style={styles button}> 109 \<text style={styles button label}>{'verify'}\</text> 110 \</view> 111 \</touchableopacity> 112 \<touchableopacity onpress={() => requestotp()}> 113 \<view style={styles button}> 114 \<text style={styles button label}>{'resend token'}\</text> 115 \</view> 116 \</touchableopacity> 117 \</view> 118 )} 119 \</view> 120 ); 121 };1 import react, {fc, reactelement, usestate} from 'react'; 2 import {alert, text, textinput, touchableopacity, view} from 'react native'; 3 import parse from 'parse/react native'; 4 import {usenavigation} from '@react navigation/native'; 5 import styles from ' /styles'; 6	 7 export const userotp fc<{}> = ({}) reactelement => { 8 const navigation = usenavigation(); 9	 10 const \[userdata, setuserdata] = usestate(''); 11 const \[usertoken, setusertoken] = usestate(''); 12 const \[tokenrequested, settokenrequested] = usestate(false); 13	 14 const requestotp = async function () promise\<boolean> { 15 // note that this values come from state variables that we've declared before 16 const userdatavalue string = userdata; 17 // check if value is an email if it contains @ note that in a real 18 // app you need a much better validator for this field 19 const verificationtype string = 20 userdatavalue includes('@') === true ? 'email' 'sms'; 21 // we need to call it using await 22 try { 23 await parse cloud run('requestotp', { 24 userdata userdatavalue, 25 verificationtype verificationtype, 26 }); 27 // show token input field 28 settokenrequested(true); 29 alert alert('success!', `token requested via ${verificationtype}!`); 30 return true; 31 } catch (error) { 32 alert alert('error!', error message); 33 return false; 34 } 35 }; 36	 37 const verifyotp = async function () promise\<boolean> { 38 // note that this values come from state variables that we've declared before 39 const userdatavalue string = userdata; 40 const usertokenvalue string = usertoken; 41 // check if value is an email if it contains @ note that in a real 42 // app you need a much better validator for this field 43 const verificationtype string = 44 userdatavalue includes('@') === true ? 'email' 'sms'; 45 // we need the installation id to allow cloud code to create 46 // a new session and login user without password; this is obtained 47 // using a static method from parse 48 const parseinstallationid string = await parse getinstallationid(); 49 // we need to call it using await 50 try { 51 // verify otp, if successful, returns a sessionid 52 let response object = await parse cloud run('verifyotp', { 53 userdata userdatavalue, 54 verificationtype verificationtype, 55 usertoken usertokenvalue, 56 parseinstallationid parseinstallationid, 57 }); 58 if (response sessionid !== undefined) { 59 // use generated sessionid to become a user, 60 // logging in without needing to inform password and username 61 await parse user become(response sessionid); 62 const loggedinuser parse user = await parse user currentasync(); 63 alert alert( 64 'success!', 65 `user ${loggedinuser get('username')} has successfully signed in!`, 66 ); 67 // navigation navigate takes the user to the home screen 68 navigation navigate('home'); 69 return true; 70 } else { 71 throw response; 72 } 73 } catch (error) { 74 alert alert('error!', error message); 75 return false; 76 } 77 }; 78	 79 return ( 80 \<view style={styles login wrapper}> 81 {tokenrequested === false ? ( 82 \<view style={styles form}> 83 \<textinput 84 style={styles form input} 85 value={userdata} 86 placeholder={'email or mobile phone number'} 87 onchangetext={(text) => setuserdata(text)} 88 autocapitalize={'none'} 89 keyboardtype={'email address'} 90 /> 91 \<touchableopacity onpress={() => requestotp()}> 92 \<view style={styles button}> 93 \<text style={styles button label}>{'request otp'}\</text> 94 \</view> 95 \</touchableopacity> 96 \</view> 97 ) ( 98 \<view style={styles form}> 99 \<text>{'inform the received token to proceed'}\</text> 100 \<textinput 101 style={styles form input} 102 value={usertoken} 103 placeholder={'token (6 digits)'} 104 onchangetext={(text) => setusertoken(text)} 105 autocapitalize={'none'} 106 keyboardtype={'default'} 107 /> 108 \<touchableopacity onpress={() => verifyotp()}> 109 \<view style={styles button}> 110 \<text style={styles button label}>{'verify'}\</text> 111 \</view> 112 \</touchableopacity> 113 \<touchableopacity onpress={() => requestotp()}> 114 \<view style={styles button}> 115 \<text style={styles button label}>{'resend token'}\</text> 116 \</view> 117 \</touchableopacity> 118 \</view> 119 )} 120 \</view> 121 ); 122 }; ดูใกล้ๆ ที่ requestotp requestotp และ verifyotp verifyotp ฟังก์ชัน ซึ่งมีหน้าที่ในการเรียกฟังก์ชัน cloud code ที่เกี่ยวข้องและตรวจสอบการตอบกลับของพวกเขา รายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงานสามารถตรวจสอบได้ในความคิดเห็นของโค้ด หลังจากสร้างหน้าจอใหม่แล้ว ให้นำเข้าและประกาศใน app js app js (หรือ app tsx app tsx ) หลังจากนั้น ให้เพิ่มปุ่มใหม่ใน userlogin js userlogin js (หรือ userlogin tsx userlogin tsx ) ไฟล์ เพื่อให้ผู้ใช้ของคุณสามารถนำทางไปยังหน้าจอ otp ได้ 4 การทดสอบฟีเจอร์ otp ใหม่ ตอนนี้เรามาทดสอบการเปลี่ยนแปลงในแอปกันเถอะ ก่อนอื่นให้ลงทะเบียนผู้ใช้ใหม่ที่มีอีเมลและหมายเลขโทรศัพท์ที่ถูกต้อง ตรวจสอบให้แน่ใจว่าใช้รูปแบบการเขียนหมายเลขโทรศัพท์ในรูปแบบสากล (e 164) (เช่น +14155552671) ตอนนี้ให้ไปที่หน้าจอ otp จากหน้าจอเข้าสู่ระบบและแจ้งอีเมลหรือหมายเลขโทรศัพท์เดียวกันตามที่กล่าวไว้ก่อนหน้านี้ คลิกที่ปุ่มขอและคุณควรได้รับข้อความเช่นนี้ โดยเปลี่ยนการป้อนข้อมูลที่ใช้งานอยู่บนหน้าจอของคุณ หากคุณแจ้งที่อยู่อีเมล คุณควรได้รับอีเมลที่มีโทเค็น otp; หากมีการส่งหมายเลขโทรศัพท์ คุณจะได้รับข้อความ sms บนโทรศัพท์มือถือของคุณ อีเมลควรมีข้อความเช่นนี้ ขึ้นอยู่กับว่าคุณตั้งค่าเทมเพลต sendgrid อย่างไร แจ้งโทเค็น otp และคลิกที่ตรวจสอบ หากทุกอย่างเป็นไปด้วยดี คุณควรอยู่ที่หน้าจอหลักพร้อมข้อความต่อไปนี้ บทสรุป ในตอนท้ายของคู่มือนี้ คุณได้เรียนรู้วิธีการใช้ฟังก์ชัน parse cloud code เพื่อรวมบริการของบุคคลที่สามในแอปพลิเคชัน react native ของคุณ ในคู่มือต่อไป คุณจะได้เรียนรู้วิธีการทำงานกับผู้ใช้ใน parse