Я определил https.onCall
Облачную функцию, в которой я вызываю request.post
(где request = require('request')
). В обратном вызове function(error, response, body)
я хочу обнаружить два варианта использования: а) есть ли ошибка? Если да, я должен отправить в приложение Android functions.https.HttpsError
; б) нет ошибки вообще? Если да, я должен отправить в приложение Android JSON объект, содержащий сообщение об успехе.
Код, который я написал, показан ниже. Это не работает: Android не выполняет блок ниже условия if(!task.isSuccessful())
(см. Часть "Android код стороны приложения")
/**
* Verifies a Recaptcha filled by the user in his Android app.
* 1. Success: returns the JSON response
* 2. Failure: throws the error
**/
exports.verifyRecaptcha = functions.https.onCall((data, context) => {
const user_response_token = data.userResponseToken;
if(user_response_token === null || user_response_token === '') {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with an adequat user response token.');
}
const remote_url = 'https://recaptcha.google.com/recaptcha/api/siteverify'; // Original value: 'https://www.google.com/recaptcha/api/siteverify'; # Moises' value: https://recaptcha.google.com/recaptcha/api/siteverify
const secret = '<Secret_Key>';
request2.post({url: remote_url, form:{secret: secret, response: user_response_token}}, function(error, response, body) {
if(error) {
console.log("error");
console.log(error);
throw new functions.https.HttpsError('unknown', error);
}
if(response.statusCode !== 200) {
console.log("error status code");
console.log(response.statusCode);
throw new functions.https.HttpsError('unknown', 'Something went wrong. Status code: ' + response.statusCode + '.');
}
body_in_json = JSON.parse(body);
if(!body_in_json.success) {
console.log("error body");
console.log(body);
throw new functions.https.HttpsError('unknown', 'Unable to verify this captcha.');
}
return {code: 'Success', message: 'You are actually a human (this msg is for test purposes).'};
});
});
Важное примечание: эти 4 строки работают
Четыре первые строки, переписанные ниже, на самом деле работают (если я добавлю условие 1 === 1
, исключение действительно будет брошено в приложение Android, которое фактически его ловит, оно работает отлично). Так что проблема напрямую связана с тем, как я реализовал обратный вызов request.post
.
const user_response_token = data.userResponseToken;
if(user_response_token === null || user_response_token === '') {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with an adequat user response token.');
}
То, что я пытался сделать
Возвращение обещания из request.post
, но я знаю, что это обещание не должно быть возвращено, потому что оно делает Cloud Function cra sh с чем-то вроде "максимальная глубина стека вызовов достигнута", нормально.
Возвращая functions.https.HttpsError
вместо того, чтобы бросать их, но это не решило проблему
Android код стороны приложения
final SafetyNetApi.RecaptchaTokenResponse response = task.getResult();
assert response != null;
final String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
final HashMap<String, String> the_data = new HashMap<>();
the_data.put("userResponseToken", userResponseToken);
FirebaseFunctions.getInstance()
.getHttpsCallable("verifyRecaptcha")
.call(the_data)
.continueWith(new Continuation<HttpsCallableResult, Void>() {
@Override
public Void then(@NonNull final Task<HttpsCallableResult> task) {
if(context.isDestroyed() || context.isFinishing()) {
return null;
}
if(!task.isSuccessful()) {
Exception e = task.getException();
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
System.out.println(ffe.getMessage());
}
return null;
}
callback.onAsking();
return null;
}
});
} else {
callback.onFailureUserResponseTokenIsEmpty();
}