Reputation: 877
Here is the code I am using, simplified for this example:
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 = "[email protected]"
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
So in reviewing the code for the example, I realized the likely problem is that I don't really know what the ConsoleApplicationName
should be. I have tried using the "Project Name" and the "Project ID" from the Google Developer Console, but neither made a difference.
The code runs until Google returns the 403 exception.
Upvotes: 2
Views: 1591
Reputation: 877
This related post solved my 403 error issue: https://stackoverflow.com/a/23029201/2092250
It is working now. As far as the ConsoleApplicationName - I'm not even sure it is a required field. Might be completely ignored. That value doesn't seem to matter.
I must say, Google could not have possibly made this more confusing or more poorly documented. But it is functional finally!
Upvotes: 1