#android #kotlin #recaptcha #safetynet-api
Вопрос:
Я использую SafetyNet reCAPTCHA API в моем Activity
, и я разбил вызов API на следующее: Repository
класс, interface
который выполняет POST
вызов, data class
который хранит JSON
полученный ответ, ViewModel
а Success
также класс слушателя и класс Failure
слушателя в моем Activity
.
Repository
:
class RecaptchaRepository {
fun doRecaptchaValidation(
@NonNull baseUrl: String,
@NonNull response: String,
@NonNull key: String
): LiveData<RecaptchaVerifyResponse> {
val data: MutableLiveData<RecaptchaVerifyResponse> = MutableLiveData()
val params: MutableMap<String, String> = HashMap()
params["response"] = response
params["secret"] = key
getRecaptchaValidationService(baseUrl).verifyResponse(params)
.enqueue(object : Callback<RecaptchaVerifyResponse> {
override fun onResponse(
call: Call<RecaptchaVerifyResponse>,
response: Response<RecaptchaVerifyResponse>
) {
data.value = response.body()
}
override fun onFailure(call: Call<RecaptchaVerifyResponse>, t: Throwable) {
data.value = null
}
})
return data
}
private fun getRecaptchaValidationService(@NonNull baseUrl: String): RecaptchaVerificationService {
return getRetrofit(baseUrl).create(
RecaptchaVerificationService::class.java
)
}
private fun getRetrofit(@NonNull baseUrl: String): Retrofit {
val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
val client = OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build()
return Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(baseUrl)
.client(client)
.build()
}
}
Interface
чтобы вызвать POST
:
interface RecaptchaVerificationService {
@Headers("Content-Type: application/x-www-form-urlencoded; charset=utf-8")
@POST("/recaptcha/api/siteverify")
fun verifyResponse(@QueryMap params: Map<String, String>): Call<RecaptchaVerifyResponse>
}
data class
генерируется Moshi
:
@JsonClass(generateAdapter = true)
data class RecaptchaVerifyResponse(
@Json(name = "success")
val success: Boolean,
@Json(name = "challenge_ts")
val challenge_ts: String,
@Json(name = "apk_package_name")
val apk_package_name: String,
@Json(name = "error-codes")
val error_codes: List<String>
)
ViewModel
:
class RecaptchaResponseViewModel(application: Application) : AndroidViewModel(application) {
fun getmRecaptchaObservable(@NonNull baseUrl: String, @NonNull response: String, @NonNull key: String): LiveData<RecaptchaVerifyResponse> {
return RecaptchaRepository().doRecaptchaValidation(baseUrl, response, key)
}
}
The SafetyNet
API call in my activity’s onCreate
method:
SafetyNet.getClient(this).verifyWithRecaptcha(BuildConfig.RECAPTCHA_SITE_KEY)
.addOnSuccessListener(RecaptchaSuccessListener())
.addOnFailureListener(RecaptchaFailureListener())
And the Success
listener class and Failure
listener class, also in my Activity
:
private inner class RecaptchaSuccessListener : OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse> {
override fun onSuccess(recaptchaTokenResponse: SafetyNetApi.RecaptchaTokenResponse) {
val userResponseToken: String = recaptchaTokenResponse.tokenResult!!
if (userResponseToken.isNotEmpty()) {
recaptchaViewModel.getmRecaptchaObservable("https://www.google.com", userResponseToken, BuildConfig.RECAPTCHA_SECRET_KEY).observe(this@LoginActivity, object : Observer<RecaptchaVerifyResponse> {
override fun onChanged(@Nullable recaptchaVerifyResponse: RecaptchaVerifyResponse?) {
if (recaptchaVerifyResponse != null amp;amp; recaptchaVerifyResponse.success) {
// reCAPTCHA successfully worked and verified user is human
} else {
// reCAPTCHA response validation failed
}
}
})
}
}
}
private inner class RecaptchaFailureListener : OnFailureListener {
override fun onFailure(@NonNull e: Exception) {
// Device side validation resulted in no token. Failure
}
}
Now in the Success
listener class’s onChanged
method, when it checks to see if recaptchaVerifyResponse
is not null
and if recaptchaVerifyResponse.success
is true
, it fails because the success
, challenge_ts
, apk_package_name
, and error_codes
variables from the data class
are all set to null
.
Why is that the case? What am I doing wrong that’s causing all the fields to be set to null
?