相亲网站建设策划方案个人网址怎么填写
相亲网站建设策划方案,个人网址怎么填写,网站建设项目及费用,怎么用ps做京东网站模板本文介绍在 React Node(Koa) 项目中接入阿里云号码认证服务#xff08;H5 一键登录#xff09;的完整流程#xff0c;包含前端网页端 SDK 与后端 OpenAPI 的对接#xff0c;以及常见坑点与解决方案。适合有一定前后端基础、希望为 H5 页面增加「本机号一键登录」能力的开发…本文介绍在React Node(Koa)项目中接入阿里云号码认证服务H5 一键登录的完整流程包含前端网页端 SDK 与后端 OpenAPI 的对接以及常见坑点与解决方案。适合有一定前后端基础、希望为 H5 页面增加「本机号一键登录」能力的开发者。一、什么是 H5 一键登录一键登录是指用户无需输入手机号和验证码在授权页确认本机号码并同意协议后由运营商移动/联通/电信返回该手机号完成登录或注册。在H5 网页里实现时需要用到阿里云号码认证服务提供 H5 能力与 OpenAPI。网页端 SDKaliyun_numberauthsdk_web负责鉴权、拉起授权页、获取spToken。服务端调用阿里云GetAuthToken、GetPhoneWithToken两个接口拿到鉴权 Token 和最终手机号并完成自家业务的登录/注册。整体流程可以概括为前端向自家后端要鉴权 TokenaccessToken、jwtToken。后端调用阿里云GetAuthToken把 Token 返回给前端。前端用 SDKcheckLoginAvailable鉴权通过后getLoginToken拉起授权页。用户输入手机号中间 4 位、勾选协议并点击登录SDK 返回spToken。前端把 spToken 交给后端后端调用GetPhoneWithToken拿到手机号再按业务做登录/注册返回登录态。下面按前置准备、后端、前端、注意事项四块说明并给出本项目中的核心代码。二、前置准备阿里云控制台开通 号码认证服务并创建H5 认证方案。在方案中配置页面地址协议 // 域名 /如http://yourdomain.com/请求来源源地址协议 // 域名如http://yourdomain.com末尾不要/记录方案 CodeSceneCode以及AccessKey ID / AccessKey SecretRAM 子账号即可需具备号码认证相关权限。注意中国移动侧能力需在创建方案后的第 2 个工作日才能使用若遇 105113「AppID 非法或为空」可先核对页面地址/源地址是否与控制台完全一致或等待生效后再试。三、后端实现Node.js Koa技术栈Koa alicloud/dypnsapi20170525。需要完成三件事加载环境变量、封装阿里云 GetAuthToken / GetPhoneWithToken、提供两个业务接口。3.1 依赖与环境变量npminstallalicloud/dypnsapi20170525 dotenv--save在项目根目录新建.env不要提交到 Git例如ALIYUN_ACCESS_KEY_ID你的AccessKeyId ALIYUN_ACCESS_KEY_SECRET你的AccessKeySecret PNVS_SCENE_CODEFC000000012345678 PNVS_PAGE_URLhttps://www.yourdomain.com/ PNVS_ORIGINhttps://www.yourdomain.com在入口最先加载 dotenv在bin/www或app.js最顶部// bin/www 最顶部require(dotenv).config({path:require(path).join(__dirname,..,.env)})3.2 封装阿里云接口numberAuth.js在services/numberAuth.js中封装两个方法getAuthToken、getPhoneWithToken。/** * 阿里云号码认证服务H5 一键登录 * 文档https://help.aliyun.com/zh/pnvs/developer-reference/h5-client-access */constDypnsapiClientrequire(alicloud/dypnsapi20170525).defaultconstGetAuthTokenRequestrequire(alicloud/dypnsapi20170525).GetAuthTokenRequestconstGetPhoneWithTokenRequestrequire(alicloud/dypnsapi20170525).GetPhoneWithTokenRequestconstaccessKeyIdprocess.env.ALIYUN_ACCESS_KEY_ID||constaccessKeySecretprocess.env.ALIYUN_ACCESS_KEY_SECRET||constsceneCodeprocess.env.PNVS_SCENE_CODE||constdefaultUrlprocess.env.PNVS_PAGE_URL||https://example.com/constdefaultOriginprocess.env.PNVS_ORIGIN||https://example.comfunctioncreateClient(){returnnewDypnsapiClient({accessKeyId,accessKeySecret,endpoint:dypnsapi.aliyuncs.com,})}/** 获取 H5 鉴权 Token供前端 checkLoginAvailable 使用 */asyncfunctiongetAuthToken(opts{}){if(!accessKeyId||!accessKeySecret||!sceneCode){thrownewError(请配置 ALIYUN_ACCESS_KEY_ID、ALIYUN_ACCESS_KEY_SECRET、PNVS_SCENE_CODE)}consturlopts.url||defaultUrlconstoriginopts.origin||defaultOriginconstclientcreateClient()constrequestnewGetAuthTokenRequest({url,origin,sceneCode,bizType:1,// 1一键登录})constresponseawaitclient.getAuthToken(request)constbodyresponse.bodyif(body.code!OK){thrownewError(body.message||GetAuthToken 失败)}consttokenInfobody.tokenInfo||{}return{accessToken:tokenInfo.accessToken||,jwtToken:tokenInfo.jwtToken||,}}/** 用 spToken 换取手机号H5 一键登录取号 */asyncfunctiongetPhoneWithToken(spToken){if(!accessKeyId||!accessKeySecret)thrownewError(请配置阿里云 AccessKey)if(!spToken)thrownewError(spToken 不能为空)constclientcreateClient()constrequestnewGetPhoneWithTokenRequest({spToken})constresponseawaitclient.getPhoneWithToken(request)constbodyresponse.bodyif(body.code!OK){thrownewError(body.message||GetPhoneWithToken 失败)}constmobilebody.databody.data.mobileif(!mobile)thrownewError(未获取到手机号)returnmobile}module.exports{getAuthToken,getPhoneWithToken}3.3 业务接口auth 路由在routes/auth.js中增加两个接口。1获取鉴权 Token给前端 SDK 用const{getAuthToken,getPhoneWithToken}require(../services/numberAuth)// POST /api/auth/number-auth-tokenrouter.post(/number-auth-token,async(ctx){const{url,origin}ctx.request.body||{}try{consttokenInfoawaitgetAuthToken({url,origin})ctx.body{code:0,message:ok,data:tokenInfo}}catch(e){console.error(number-auth-token error:,e.message)ctx.status500ctx.body{code:500,message:e.message||获取认证失败}}})2用 spToken 换手机号并登录/注册// POST /api/auth/number-loginrouter.post(/number-login,async(ctx){const{spToken}ctx.request.body||{}if(!spToken){ctx.status400ctx.body{code:400,message:缺少 spToken}return}try{constphoneawaitgetPhoneWithToken(spToken)// 查库已有用户则登录否则自动注册随机密码后续可改密const[rows]awaitdb.query(SELECT id, phone, name, password FROM users WHERE phone ? LIMIT 1,[String(phone).trim()])letuserrows[0]if(!user){constname用户${phone.slice(-4)}constrandomPasswordcrypto.randomBytes(24).toString(base64)consthashawaitbcrypt.hash(randomPassword,10)const[insertResult]awaitdb.query(INSERT INTO users (phone, password, name) VALUES (?, ?, ?),[String(phone).trim(),hash,name])user{id:insertResult.insertId,phone:String(phone).trim(),name,}}consttokensignToken(user.id)ctx.body{code:0,message:登录成功,data:{token,user:{id:user.id,phone:user.phone,name:user.name}},}}catch(e){console.error(number-login error:,e.message)ctx.status500ctx.body{code:500,message:e.message||一键登录失败}}})四、前端实现4.1 安装依赖npminstallaliyun_numberauthsdk_web--save4.2 登录页一键登录流程Login.jsx 核心逻辑import { PhoneNumberServer } from aliyun_numberauthsdk_web import { authApi } from ../api/request // 1. 在组件内创建 SDK 实例useRef避免重复创建 const phoneNumberServerRef useRef(null) useEffect(() { phoneNumberServerRef.current new PhoneNumberServer() return () { phoneNumberServerRef.current null } }, []) // 2. 一键登录点击处理 const handleOneClickLogin async () { const phoneNumberServer phoneNumberServerRef.current if (!phoneNumberServer) return // H5 一键登录要求走移动数据WiFi 下运营商无法可靠取号 const netType phoneNumberServer.getConnection?.() if (netType wifi) { Toast.show({ content: 一键登录需使用移动数据网络请关闭 Wi-Fi 后重试, icon: fail }) return } setOneClickLoading(true) try { // Step1向自家后端要 accessToken、jwtToken const res await authApi.getNumberAuthToken({ url: ${window.location.origin}/, origin: window.location.origin, }) const { accessToken, jwtToken } res.data || {} // Step2SDK 鉴权 phoneNumberServer.checkLoginAvailable({ accessToken, jwtToken, success: (res) { if (res.code ! 600000) { setOneClickLoading(false) Toast.show({ content: res.msg || 鉴权失败, icon: fail }) return } // Step3拉起授权页用户输入中间 4 位、勾选协议、点登录 phoneNumberServer.getLoginToken({ authPageOption: { navText: 本机号码登录, btnText: 立即登录, privacyBefore: 我已阅读并同意, privacyOne: [《用户协议》, /about], privacyTwo: [《隐私政策》, /about], isDialog: true, manualClose: true, }, success: async (tokenRes) { if (tokenRes.code ! 600000) { setOneClickLoading(false) Toast.show({ content: tokenRes.msg || 获取登录态失败, icon: fail }) return } // Step4把 spToken 交给后端完成登录/注册 try { const { data: loginData } await authApi.loginWithSpToken(tokenRes.spToken) phoneNumberServer.closeLoginPage?.() localStorage.setItem(app_token, loginData.token) localStorage.setItem(app_user, JSON.stringify(loginData.user)) setUser(loginData.user) setIsLoggedIn(true) Toast.show({ content: 登录成功, icon: success }) navigate(/) } catch (e) { Toast.show({ content: e.message || 登录失败, icon: fail }) } finally { setOneClickLoading(false) } }, error: () { setOneClickLoading(false) Toast.show({ content: 授权取消或失败, icon: fail }) }, }) }, error: (err) { setOneClickLoading(false) Toast.show({ content: err?.msg || 鉴权失败请关闭 Wi-Fi 使用移动数据或使用账号密码登录, icon: fail }) }, }) } catch (e) { setOneClickLoading(false) Toast.show({ content: 获取token失败${e.message}, icon: fail }) } } // 页面上增加按钮 Button block className{styles.btnOneClick} loading{oneClickLoading} onClick{handleOneClickLogin} 一键登录 /Button要点小结url/origin必须与阿里云控制台里配置的页面地址、请求来源完全一致含协议、域名、末尾斜杠。H5 场景下必须使用移动数据才能稳定取号WiFi 下会提示用户关闭 Wi-Fi 或改用账号密码登录。授权页的「登录」按钮文案需包含「登录」等字样符合运营商与阿里云规范。六、参考文档阿里云 H5 客户端接入GetAuthToken - 获取 H5 认证授权 TokenGetPhoneWithToken - 一键登录取号H5 能力专用错误码说明**