云函数(第 2 代)(当我允许未经身份验证的调用时,该函数被正确调用,并且结果也正确。但是,当我将函数配置为需要身份验证时,会出现问题。)
import functions_framework
from google.auth import default
from googleapiclient.discovery import build
from flask import jsonify
@functions_framework.http
def verify_purchase_http(request):
"""HTTP Cloud Function to verify Android subscription purchases."""
try:
# Use Application Default Credentials (ADC)
credentials, project = default(scopes=['https://www.googleapis.com/auth/androidpublisher'])
androidpublisher = build('androidpublisher', 'v3', credentials=credentials)
except Exception as e:
print("Failed to initialize credentials or service: ", str(e))
return jsonify({"error": "Failed to initialize credentials or service"}), 500
request_json = request.get_json(silent=True)
if request_json:
# Extract the token depending on the structure
if 'data' in request_json:
purchase_token = request_json['data'].get('token')
else:
purchase_token = request_json.get('token')
else:
return jsonify({"error": "Invalid request format"}), 400
package_name = "" #Already added
subscription_id = "premium"
if not purchase_token:
print("no token found")
return jsonify({"error": "Token is required"}), 400
try:
subscription = androidpublisher.purchases().subscriptions().get(
packageName=package_name,
subscriptionId=subscription_id,
token=purchase_token
).execute()
return jsonify({"data": subscription}), 200
except Exception as e:
print("Error calling Google Play API: ", str(e))
return jsonify({"error": str(e)}), 500
调用函数(Android Kotlin)
private fun testVerifyPurchase() {
// Hardcoded test purchase token
val testPurchaseToken = "" #Added test purchase token
Log.d("PremiumFragment", "Testing verify purchase with token: $testPurchaseToken")
// Call Firebase function
verifyPurchaseWithFirebase(testPurchaseToken)
}
private fun verifyPurchaseWithFirebase(purchaseToken: String) {
// Get the currently signed-in user
val user = FirebaseAuth.getInstance().currentUser
user?.getIdToken(true)?.addOnCompleteListener { idTokenTask ->
if (idTokenTask.isSuccessful) {
val idToken = idTokenTask.result?.token
Log.d("PremiumFragment", "ID Token: $idToken")
// Ensure the ID token is not null
if (idToken != null) {
val data = hashMapOf(
"token" to purchaseToken
)
Log.d("PremiumFragment", "Verifying purchase with token: $purchaseToken")
Log.d("PremiumFragment", "Data to send to Firebase: $data")
functions
.getHttpsCallable("verify_purchase")
.call(data)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d(
"PremiumFragment",
"Purchase verified successfully with Firebase"
)
val result = task.result?.data as? Map<String, Any>
if (result != null) {
Log.d("PremiumFragment", "Result from Firebase: $result")
// Update the UI or take necessary actions based on the result
} else {
Log.e(
"PremiumFragment",
"No data received from Firebase function"
)
}
} else {
Log.d("PremiumFragment", task.result.toString())
Log.e(
"PremiumFragment",
"Failed to verify purchase with Firebase",
task.exception
)
}
}
}
}
}
}
错误
com.google.android.gms.tasks.RuntimeExecutionException:com.google.firebase.functions.FirebaseFunctionsException:未经身份验证
我不明白,我该怎么办?我已经检查了有关此事的文档,如果我使用 firebase,似乎应该自动处理身份验证。
对于可调用对象,Firebase 身份验证令牌、FCM 令牌和应用程序检查令牌(如果可用)会自动包含在请求中。 触发器自动反序列化请求正文并验证身份验证令牌。我已将云运行调用者角色添加到默认计算服务帐户(即构建服务帐户)。
有人可以解释一下为什么这没有自动验证吗?此外,如果没有解决这个问题,有人可以建议一个替代方案吗?我对功能部署和Android开发总体来说是新手,所以我可能误解了一些东西,请耐心等待,谢谢!
可调用函数 - 您编写了一个普通的HTTP 函数。 我建议查看链接的文档,以更好地理解它们的编写方式之间的差异。 如果您想要可调用函数,则可以使用 @https_fn.on_call
而不是
@https_fn.on_request
(以及其他差异)来注释该函数。