以下是我正在使用的代码,简化了此示例:
Public PackageName As String = "com.yourdomain.app"
Public InAppPurchaseProductID As String = "com.yourdomain.app.subscriptionXYZ"
Public PublicLicenseKey As String = "YOUR_LONG_ENCODED_LICENSE_KEY"
Public ConsolePrivateKeyCertificateData As Byte() 'method for reading p12 file contents left out for simplicity
Public ConsoleCertificate As X509Certificate2 = New X509Certificate2(ConsolePrivateKeyCertificateData, "notasecret", X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.Exportable)
Public ConsoleServiceAccountEmail As String = "console-generated-account-here@developer.gserviceaccount.com"
Public ConsoleApplicationName As String = "I just realized this may be my issue. Not sure what this value should be!"
Public Function VerifySubscriptionReceipt(ByRef expirationDate As DateTime,
ByRef purchaseDate As DateTime,
token As String,
purchasedProductID As String,
signature As String,
rawJSONData As String) As Boolean?
'First: basic check to verify the receipt matches the product you will deliver
If Not purchasedProductID = InAppPurchaseProductID Then
Return Nothing
End If
'Second: verify receipt signature
Dim rkp As RsaKeyParameters = CType(PublicKeyFactory.CreateKey(Convert.FromBase64String(PublicLicenseKey)), RsaKeyParameters)
Dim rsaParams As New RSAParameters
rsaParams.Modulus = rkp.Modulus.ToByteArrayUnsigned
rsaParams.Exponent = rkp.Exponent.ToByteArrayUnsigned
Dim rsaProvider As New RSACryptoServiceProvider
rsaProvider.ImportParameters(rsaParams)
If Not rsaProvider.VerifyData(Encoding.UTF8.GetBytes(rawJSONData), CryptoConfig.MapNameToOID("SHA1"), Convert.FromBase64String(signature)) Then
Return Nothing
End If
'Third: check subscription status
Dim result As SubscriptionPurchase
Dim serviceInitializer As New AndroidPublisherService.Initializer With
{
.HttpClientInitializer = New ServiceAccountCredential(New ServiceAccountCredential.Initializer(ConsoleServiceAccountEmail) With
{
.Scopes = New String() {"https://www.googleapis.com/auth/androidpublisher"}
}.FromCertificate(ConsoleCertificate)),
.ApplicationName = ConsoleApplicationName
}
Using service As New AndroidPublisherService(serviceInitializer)
'*** Error thrown on this line. Google returning 403 Forbidden ***
result = service.Purchases.Get(PackageName, InAppPurchaseProductID, token).Execute
End Using
If Not result.AutoRenewing.HasValue And
result.ValidUntilTimestampMsec.HasValue And
result.InitiationTimestampMsec.HasValue Then
Throw New KeyNotFoundException("The subscription does not appear to be valid. (token: " & token & ")")
End If
expirationDate = New DateTime(result.ValidUntilTimestampMsec.Value)
purchaseDate = New DateTime(result.InitiationTimestampMsec.Value)
Return result.AutoRenewing.Value
End Function
所以在回顾这个例子的代码时,我意识到可能的问题是我真的不知道ConsoleApplicationName
应该是什么。我尝试过使用Google Developer Console中的“项目名称”和“项目ID”,但两者都没有区别。
代码一直运行,直到Google返回403异常。
答案 0 :(得分:1)
此相关帖子解决了我的403错误问题:https://stackoverflow.com/a/23029201/2092250
现在正在运作。就ConsoleApplicationName而言 - 我甚至不确定它是否是必填字段。可能会被完全忽略。这个价值似乎并不重要。
我必须说,谷歌不可能让这更令人困惑或更难记录。但它最终是功能性的!