我想通过中央游戏服务器上的Google API验证Android IAP。
有很多关于此的部分信息,这让我大吃一惊。 我还没有花25欧元成为谷歌开发者,因为我不确定我是否能够让它发挥作用。
创建IAP时,将返回JSON对象。此对象包含多个字段,例如purchaseToken
和productId
(source)。
我发现您可以通过以下GET请求请求有关已购买产品的信息:GET https://www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/products/productId/tokens/token
。
我可以对此进行编程没有问题,但您需要自行授权:"此请求需要具有以下范围的授权" (source)。 这是我开始感到困惑的地方。
互联网上有几个巨大的代码片段可能会或可能不会起作用,但它们都是部分的,并没有很好的记录。
我找到了适用于Java的Googles API库:link。此API似乎是为了解决OAuth和令牌的所有这些问题。但是,我无法弄清楚如何让这个API工作。
这可能不是那么难,但有很多不同的方法可以做到,我找不到任何明确的例子。
TL; DR:我需要验证Google Play IAP服务器端。为此,我想使用Googles Java API。
编辑:这可能是一种简单的解决方案。 将原始JSON和JSON传递到服务器可能会更容易,因为我只能验证非对称签名服务器端。
答案 0 :(得分:2)
我在Scala中完成了这项工作,但使用的是标准Java库。我认为将该代码转换为Java应该很简单。
首先,您需要一个服务帐户。您可以通过Google Dev控制台创建它。它基本上会返回一个生成的电子邮件帐户,您将用它来验证后端服务并生成令牌。
创建该帐户后,您将立即下载您的私钥。您需要这样才能签署JWT。
您必须以Google指定的格式生成JWT。 请参阅:https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatingjwt
然后,使用JWT,您可以请求访问令牌
使用访问令牌,您可以提出验证购买的请求
/** Generate JWT(JSON Web Token) to request access token
* How to generate JWT: https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatingjwt
*
* If we need to generate a new Service Account in the Google Developer Console,
* we are going to receive a .p12 file as the private key. We need to convert it to .der.
* That way the standard Java library can handle that.
*
* Covert the .p12 file to .pem with the following command:
* openssl pkcs12 -in <FILENAME>.p12 -out <FILENAME>.pem -nodes
*
* Convert the .pem file to .der with the following command:
* openssl pkcs8 -topk8 -inform PEM -outform DER -in <FILENAME>.pem -out <FILENAME>.der -nocrypt
*
* */
private def generateJWT(): String = {
// Generating the Header
val header = Json.obj("alg" -> "RS256", "typ" -> "JWT").toString()
// Generating the Claim Set
val currentDate = DateTime.now(DateTimeZone.UTC)
val claimSet =Json.obj(
"iss" -> "<YOUR_SERVICE_ACCOUNT_EMAIL>",
"scope" -> "https://www.googleapis.com/auth/androidpublisher",
"aud" -> "https://www.googleapis.com/oauth2/v4/token",
"exp" -> currentDate.plusMinutes(5).getMillis / 1000,
"iat" -> currentDate.getMillis / 1000
).toString()
// Base64URL encoded body
val encodedHeader = Base64.getEncoder.encodeToString(header.getBytes(StandardCharsets.UTF_8))
val encodedClaimSet = Base64.getEncoder.encodeToString(claimSet.getBytes(StandardCharsets.UTF_8))
// use header and claim set as input for signature in the following format:
// {Base64url encoded JSON header}.{Base64url encoded JSON claim set}
val jwtSignatureInput = s"$encodedHeader.$encodedClaimSet"
// use private key generated by Google Developer console to sign the content
val keyFile = Paths.get("<path_to_google_play_store_api.der>");
val keyBytes = Files.readAllBytes(keyFile);
val keyFactory = KeyFactory.getInstance("RSA")
val keySpec = new PKCS8EncodedKeySpec(keyBytes)
val privateKey = keyFactory.generatePrivate(keySpec)
// Sign payload using the private key
val sign = Signature.getInstance("SHA256withRSA")
sign.initSign(privateKey)
sign.update(jwtSignatureInput.getBytes(StandardCharsets.UTF_8))
val signatureByteArray = sign.sign()
val signature = Base64.getEncoder.encodeToString(signatureByteArray)
// Generate the JWT in the following format:
// {Base64url encoded JSON header}.{Base64url encoded JSON claim set}.{Base64url encoded signature}
s"$encodedHeader.$encodedClaimSet.$signature"
}
现在您已经生成了JWT,您可以像这样要求access token
:
/** Request the Google Play access token */
private def getAccessToken(): Future[String] = {
ws.url("https://www.googleapis.com/oauth2/v4/token")
.withHeaders("Content-Type" -> "application/x-www-form-urlencoded")
.post(
Map(
"grant_type" -> Seq("urn:ietf:params:oauth:grant-type:jwt-bearer"),
"assertion" -> Seq(generateJWT()))
).map {
response =>
try {
(response.json \ "access_token").as[String]
} catch {
case ex: Exception => throw new IllegalArgumentException("GooglePlayAPI - Invalid response: ", ex)
}
}
}
手上有访问令牌,您可以自由验证购买情况。
我希望有所帮助。
答案 1 :(得分:1)
继上述评论之后,Google API管理员的设计已经改变,但程序仍然相同。您想要创建服务帐户,创建后可以下载 JSON Web令牌,它是一个简单的JSON文件,其中包含您需要进行身份验证的凭据。该服务帐户应具有访问Google Play Developer API所需的所有权限。您需要在Google Play开发者控制台&gt;中授予对财务的访问权限。设置&gt; API访问页面。
您可以使用Google APIs Client Library for Java对Google Play Developer API进行身份验证和请求。按照OAuth2 Service accounts文档设置。 Data store上有一条说明,描述了如何处理刷新令牌。
还有关于如何使用Google Play Developer API Client Library for Java的文档。
对于验证购买JSON的签名,购买意图的响应有效负载中有INAPP_DATA_SIGNATURE
。有关如何获取该文档的详细信息,请参阅Purchasing an Item上的文档。您可以通过base64验证INAPP_PURCHASE_DATA
解码签名并使用您的许可密钥进行验证,该密钥可在Google Play开发者控制台&gt;中找到。所有应用程序&gt; [应用名称]&gt;服务与蜜蜂。确保INAPP_PURCHASE_DATA
完好无损,否则您最终会得到this problem。
希望这有帮助。