当前位置: 首页 > article >正文

todo: 使用融云imserve做登录(android)

使用融云做登录注册思路

  • 注册界面需要name, email, password
  • 考虑到融云注册用户的post格式
POST http://api.rong-api.com/user/getToken.json?userId=1690544550qqcom&name=Ironman
  • 这里的userId可以使用用户的email,但是要截断@. 符号,即1690544550@qq.com -> 1690544550qqcom, 融云不让我传完整的邮箱地址,这里可能要考虑到奇怪的邮箱地址,如fuckerfucker@fucker.edu.cn,我不确定截断后的是fuckerfuckerfuckereducn能不能还原成邮箱地址
  • 注册的name传入post 参数的name
  • 融云注册返回格式
{
  "code": 200,
  "userId": "1690544550qqcom",
  "token": "测试"
}
  • 那android注册界面需要检查返回的response的code==200token!=null, 如果ok,注册用户成功
  • 登录界面需要email和password, 这里可能还要考虑到自己搭建服务后端来存取用户基本信息(email, password)
  • 但是查到融云一条api是关于查询用户信息的
POST http://api.rong-api.com/user/info.json?userId=1690544550qqcom

接口返回

{
  "code": 200,
  "userName": "Ironman",
  "userPortrait": "http://abc.com/myportrait.jpg",
  "createTime": "2025-03-05 11:46:49"
}
  • 现在考虑怎么校验密码那一块, 校验密码能不能本地校验,就是注册的时候拿到email和password存到手机本地数据库,到登录时,需要用userId请求融云用户信息,检查code==200, 密码就比对本地数据库的email, password一对,好像相对繁琐了
  • 登录成功后跳转界面
  • 完啦,注册的页面还要考虑到验证邮箱地址正确,就是发邮箱验证码,这不知道怎么入手

todo实现以上思路

1. 使用go语言简单搭建一个邮箱验证码服务,邮箱服务来自qq邮箱

  • 后端地址: https://gitee.com/EEPPEE_admin/dont-want-to-write-code-anymore/tree/master/send_code_to_mail
  • 配置自己的qqmail 授权码还有自己的发送邮箱地址
  • 提供接口
### 发送验证码,这里的email是从adnroid客户端注册用户获取
POST http://localhost:8080/send-code?email=1876056356@qq.com
### 验证验证码, 738702 是验证码,有发送验证码获取,随机的,这里的email是从adnroid客户端注册用户获取
POST http://localhost:8080/verify-code?email=1876056356@qq.com&code=6271

2. 搭建data层调式邮箱验证码

  • 先启动后端go run main.go
  • 创建data/network/EmailVerifyCodeApiService.kt

// Base url:https://7f498cbc.r7.cpolar.top
interface EmailVerifyCodeApiService {
    @POST("send-code")
    fun sendVerificationCode(
        @Query("email") email: String
    ): Call<VerifyCodeResponse>

    @POST("verify-code")
    fun verifyEmailCode(
        @Query("email") email: String,
        @Query("code") code: String
    ): Call<VerifyCodeResponse>

}

// 邮箱验证码的返回
data class VerifyCodeResponse(
    val message: String
)

object EmailVerifyCodeApiClient {
    // todo: 这个base url随时变动,根据你的cpolar地址来
    private const val BASE_URL = "https://7f498cbc.r7.cpolar.top"
    private var apiService: EmailVerifyCodeApiService? = null

    val emailVerifyCodeApiService: EmailVerifyCodeApiService?
        get() {
            if (apiService == null) {
                val client: OkHttpClient = OkHttpClient.Builder()
                    .build()

                val retrofit = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()

                apiService = retrofit.create(EmailVerifyCodeApiService::class.java)
            }

            return apiService
        }
}
  • 测试点击发送邮件事件(这个简单界面代码就不给出了,就一个按钮,一个EditText,使用viewbinding)
 binding.sendBtn.setOnClickListener {
            val email = binding.emailEt.text.toString().trim()
            // todo: 处理发送邮箱验证码
            val apiService = EmailVerifyCodeApiClient.emailVerifyCodeApiService

           
            val call = apiService?.sendVerificationCode(
                email
            )

            call!!.enqueue(object : retrofit2.Callback<VerifyCodeResponse> {
                override fun onResponse(
                    call: Call<VerifyCodeResponse>,
                    response: Response<VerifyCodeResponse>
                ) {
                    Log.d("注册", response.body().toString())
                    Log.d("注册", "发送邮箱验证码成功")
                }

                override fun onFailure(call: Call<VerifyCodeResponse>, t: Throwable) {
                    Log.d("注册", "发送验证码失败")
                }
            })
        }
  • 测试邮箱验证码发送通过

3. 调试融云api

  • 创建data/network/RongCloudApiService.kt
// todo: 构建融云api服务, 接口里面的方法可以是suspend和普通函数
/*
普通函数 vs. suspend 函数
普通函数:
使用回调(Callback)或 Call 对象来处理异步请求。
适用于传统的异步编程模型。
代码相对复杂,需要处理回调和线程切换。
suspend 函数:
使用 Kotlin 协程来处理异步请求。
代码更简洁,更接近同步编程风格。
需要结合 CoroutineScope 或其他协程工具来调用。
示例代码
 */
interface RongCloudApiService {
    @FormUrlEncoded
    @POST("user/getToken.json")
    fun getToken(
        // 这是x-form形式
        @Field("userId") userId: String, // todo: required
        @Field("name") name: String = "",
        @Field("portraitUri") portraitUri: String = ""
    ): Call<GetTokenResponse>

//    @POST("user/info.json")
//     fun getRongCloudUserInfo(
//        @Query("userId") userId: String
//    ): Response<RongCloudUserInfo>

    @FormUrlEncoded
    @POST("user/info.json")
    fun getUserInfo(
        @Field("userId") userId: String,
    ): Call<UserInfoResponse>

}

// user/getToken.json接口的返回
data class GetTokenResponse(
    val code: Int,
    val userId: String,
    val token: String?
)

// user/info.json接口的返回
data class UserInfoResponse(
    val code: Int,
    val userName: String,
    val userPortrait: String?,
    val createTime: String
)

object RongCloudApiClient {
    // 要求不能明文传输,改成https
    private const val BASE_URL = "https://api.rong-api.com/"
    private const val APP_KEY = "你自己的"
    private const val NONCE = "1442907399"
    private const val TIMESTAMP = "1741092643"
    private const val SIGNATURE = "你自己的"

    private var apiService: RongCloudApiService? = null

    // todo: 获取实例方法
    val rongIMApiService: RongCloudApiService?
        get() {
            if (apiService == null) {
                val client: OkHttpClient = OkHttpClient.Builder()
                    .addInterceptor(Interceptor { chain ->
                        val originalRequest: Request = chain.request()
                        val newRequest: Request = originalRequest.newBuilder()
                            .header("App-Key", APP_KEY)
                            .header("Nonce", NONCE)
                            .header("Timestamp", TIMESTAMP)
                            .header("Signature", SIGNATURE)
                            .header("Content-Type", "application/x-www-form-urlencoded")
                            .build()
                        chain.proceed(newRequest)
                    })
                    .build()

                val retrofit = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()

                apiService = retrofit.create(RongCloudApiService::class.java)
            }
            return apiService
        }
}
  • 调试代码,点击一个注册按钮,观察Logcat
  binding.registerBtn.setOnClickListener {
            val email = binding.emailEt.text.toString().trim()
            Log.d("注册", email)


            val name = binding.nameEt.text.toString().trim()
            Log.d("注册", name)

            val password = binding.passwordEt.text.toString().trim()
            Log.d("注册", password)

            val mailVerifyCode = binding.mailVerifycodeEt.text.toString().trim()
            Log.d("注册", mailVerifyCode)

            if (name.isEmpty() || email.isEmpty() || password.isEmpty() || mailVerifyCode.isEmpty()) {
                Toast.makeText(this, "请填充完整信息", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            // email 处理成 userId
            val processedEmailAsUserId = EmailUtil.convertEmailToRongCloudId(email)
            Log.d("注册", processedEmailAsUserId)

            // todo 取到接口实例
            val apiService = RongCloudApiClient.rongIMApiService

            // todo 调用api service
            val call = apiService?.getToken(
                processedEmailAsUserId,
                name
            )
            // todo call 进入队列
            call!!.enqueue(object : retrofit2.Callback<GetTokenResponse> {
                override fun onResponse(
                    call: Call<GetTokenResponse>,
                    response: retrofit2.Response<GetTokenResponse>
                ) {
                    Log.d("注册", response.body().toString())
                    //RongCloudTokenResponse(code=200, userId=13266263124qqcom, token=Seq1kNg6Uft4UOBPzi2gGqh30okEsnM0kPAf6ohCvgf1vll6L9v54A==@ptfq.cn.rongnav.com;ptfq.cn.rongcfg.com)
                }

                override fun onFailure(call: Call<GetTokenResponse>, t: Throwable) {
                    Log.d("注册", "获取token失败")
                }

            })
            // todo new call 进入队列

            val newcall = apiService?.getUserInfo(
                processedEmailAsUserId
            )
            newcall!!.enqueue(object : retrofit2.Callback<UserInfoResponse> {
                override fun onResponse(
                    call: Call<UserInfoResponse>,
                    response: Response<UserInfoResponse>
                ) {
                    Log.d("注册", response.body().toString())
                    // UserInfoResponse(code=200, userName=好, userPortrait=http://abc.com/myportrait.jpg, createTime=2025-03-05 16:51:19)
                }

                override fun onFailure(call: Call<UserInfoResponse>, t: Throwable) {
                    Log.d("注册", "获取用户信息失败")
                }
            })
        }

todo还要考虑谷歌和facebook登录情况


http://www.kler.cn/a/573684.html

相关文章:

  • xshell中bashdb 调试器的详细使用方法
  • 【全栈开发】---- 一文掌握 Websocket 原理,并用 Django 框架实现
  • 飞机大战lua迷你世界脚本
  • 软件工程与实践(第4版 新形态) 练习与实践1
  • kettle插件-高性能插入更新插件Upsert
  • ZT26 小球投盒
  • 网络安全需要掌握哪些技能?
  • 解决java-jar报错:xxx.jar 中没有主清单属性的方法
  • Linux断电重启后,硬盘挂载失败问题。
  • 解决新建小程序页面文字顶在顶部问题
  • Android开发Android调web的方法
  • 获取Kernel32基地址
  • Docker小游戏 | 使用Docker部署DOS游戏合集
  • SQL命令详解之常用函数
  • 虚拟网络IP设置
  • Python 面向对象编程-继承与多态
  • C#-泛型
  • 二、Redis 安装与基本配置:全平台安装指南 服务器配置详解
  • c++ cin输入流的使用总结
  • (YOLOv11)基于Vue Flask YOLOv11的水稻病害检测系统【含有数据大屏展示】