Your Session Has Expired. Please Sign in Again by Clicking on the Amazon Pay Button

Server-side validation tin help you validate purchase authenticity. The device will brand a request to Google servers to find out whether the buy has actually taken place and whether it is valid.

In this guide, we'll discuss how to configure server-side validation for Android apps.

This is the fifth article in our series about implementing in-app purchases for Android apps. I recommend yous look through the others as well:

  1. Android in-app purchases, part i: configuration and adding to the projection
  2. Android in-app purchases, part 2: processing purchases with the Google Play Billing Library
  3. Android in-app purchases, part three: retrieving active purchases and subscription modify
  4. Android in-app purchases, part 4: billing Library Error Codes and how not to screw up with testing
  5. Android in-app purchases, part 5: server-side purchase validation

Why validate purchases

It should be noted that server-side validation isn't mandatory — in-app purchases will all the same piece of work without it. There are some pregnant benefits to it, though:

  1. Advanced payment analytics, which is especially important for subscriptions since everything that happens afterwards the activation isn't processed by the device. With no server-side purchase processing, you won't be able to retrieve the electric current subscription status and know whether the user has renewed the subscription or canceled it, whether at that place are whatsoever payment issues, and and so on.
  2. Beingness able to verify the purchase's authenticity. You lot'll be sure that the transaction isn't fraudulent, and the user has really paid for your product.
  3. Cross platform subscriptions. If yous can check the user'southward subscription condition in real time, you can synchronize it with other platforms. For example, the user who purchased the subscription from an iOS device will exist able to use it on Android, the Spider web, and other platforms.
  4. Being able to control content access from the server side, which protects you from users trying to access the data with no subscription past merely executing requests to the server.

Speaking from our feel, the start advantage lonely is enough to set up server-side purchase processing.

⭐️ Download our guide on in-app techniques which will make in-app purchases in your app perfect

Payment validation

We can summarize Android payment validation with this scheme:

Authentication for Google Play Developer API requests

To piece of work with Google Play Developer API, you lot'll first demand to generate a central to sign requests. Showtime, you'll have to link your Google Play Panel business relationship (where you manage your app) to your Google Deject account (where y'all'll generate a key for request signing). Once everything's configured, you'll have to grant the user purchase management rights. It'd take a dedicated commodity to describe this process. Luckily, we've already covered information technology in a step-by-step guide found in Adapty documentation.

Note that usually, you'll take to wait for 24 hours or more after generating a key for it to start working. To avoid that, just update the description for any  in-app product or subscription, which volition instantly activate the fundamental.

We use the official google-api-python-client library to piece of work with Google Play Programmer API. This library is bachelor for the majority of popular languages, and I recommend using it as it supports all the methods you might need.

Validation for subscription transactions

Unlike iOS server-side validation, in Android, both subscription and other product validation are implemented using a diversity of methods. Therefore, when validating a transaction, you demand to know whether you're dealing with a production or a subscription. In practice, this ways y'all'll need to transfer this data from the mobile app, as well as continue the flag in the database in example token re-validation volition be necessary.

The 2d important difference is that while each transaction has its ain token in Android, all iOS transactions utilise an app-specific shared hole-and-corner to store the entire transaction history. This means that if you want to be able to restore the user's purchases at any moment, you'll need to store all buy tokens, as opposed to picking out an arbitrary single one.

To validate the subscription, you'll need to invoke the purchases.subscriptions.get method.  Basically, it's a Become request call

            https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}          

All parameters are required:

  • packageName: App identifier, e.g., com.adapty.sample_app.
  • subscriptionId: Subscription identifier for the subscription that'due south to be validated, east.yard., com.adapty.sample_app.weekly_sub.
  • token: Unique transaction token. It appears one time the purchase is processed on the mobile app side.

First, allow'due south look at the error letters you lot need to take care of to make certain everything works every bit intended:

  • 400, Invalid grant: account not found: This error message ways that the request authentication fundamental was generated incorrectly. Make sure that your accounts are linked, you're using the right one that has enough permissions, and all the required APIs are activated. See the section below for a guide on how to configure everything. Note the tip on product clarification update.
  • 400, The purchase token does not match the package name: This error message is usually encountered in fraudulent transactions. If you lot see it while testing, brand sure you aren't using an app buy token that belongs to a different app.
  • 403, Quota exceeded for quota metric 'Queries' and limit 'Queries per day' of service 'androidpublisher.googleapis.com': This means the Google API requests daily quota was exceeded. Past default, you tin execute up to 200,000 requests per day. This quota tin exist increased, only information technology should suffice for about apps. If you come up up against this limit, yous should probably double-check your app's logic and make sure everything's right.
  • 410, The subscription purchase is no longer available for query because it has been expired for also long: This mistake bulletin appears in transactions where the subscription has expired more than than threescore days ago. It's non an actual error message and shouldn't be processed as such.

Subscription transaction

If the validation was successful, you'll receive transaction data equally your response.

Transaction data (for a subscription):

            {     "expiryTimeMillis": "1631116261362",     "paymentState": ane,     "acknowledgementState": 1,     "kind": "androidpublisher#subscriptionPurchase",     "orderId": "GPA.3382-9215-9042-70164",     "startTimeMillis": "1630504367892",     "autoRenewing": true,     "priceCurrencyCode": "USD",     "priceAmountMicros": "1990000",     "countryCode": "US",     "developerPayload": "" }          

To empathize whether the user tin admission the premium options offered by the app — that is, whether they have an active subscription — y'all need to:

  1. Cheque the startTimeMillis and expiryTimeMillis parameters. The current time should be between these.
  2. What's more, you have to make sure the paymentState parameter doesn't have the '1' value. This would mean the subscription purchase'southward nevertheless pending, therefore, there's no need to grant the user premium function access just nevertheless.
  3. If the transaction has the autoResumeTimeMillis holding, and so the subscription is paused. This ways that the user shouldn't be granted premium function access before the specified engagement.

Let'south encounter the key backdrop of a subscription transaction:

  • kind: Transaction type. For subscription, it always has the androidpublisher#subscriptionPurchase value. With this parameter, y'all can understand whether you're dealing with a subscription or a product, and choose the processing logic accordingly.
  • paymentState: Payment status. This belongings isn't present for expired transactions. The possible values are:
    0: This purchase hasn't been candy withal. In some countries, the user can pay for the subscription onsite. That is, the user will initiate the subscription purchase from their device and pay for it at a nearby terminal. Overall, it'southward a quite rare case, merely it should notwithstanding exist kept in mind.
    ane: Subscription was purchased.
    2: Subscription is in the trial menstruum.
    three: Subscription volition be up- or downgraded in the adjacent menstruation. This means the subscription plan is to change.
  • acknowledgementState: Purchase confirmation status. It'southward an of import parameter that acknowledges whether the user has received the access to what they paid for. The '0' value means they haven't, and '1' ways they have. The developer is responsible for defining this status, which tin be done on both the mobile app and the server sides. If you don't admit the buy inside 3 days later on it's been made, it'll be automatically exist refunded. I recommend implementing this logic: once you receive a transaction containing acknowledgementState=0, the parameter gets inverse by the server. I'll talk over how to do that beneath.
  • orderId: Unique transaction identifier. Each subscription purchase or renewal will have its own identifier, which can be used to learn whether this transaction has already been processed earlier. Each renewal identifier will have a constant commencement half, to which two dots and the subscription renewal count (which starts with 0) are appended. If the subscription had the GPA.3382-9215-9042-70164 identifier when activated, and so the first renewal volition be identified by GPA.3382-9215-9042-70164..0, the 2d 1 by GPA.3382-9215-9042-70164..1, etc. This way, you lot can build transaction bondage and continue rail of renewal count.
  • startTimeMillis: Subscription get-go date.
  • expiryTimeMillis: Subscription expiration date.
  • autoRenewing: Flag showing whether or not the subscription is to be renewed into the next period.
  • priceCurrencyCode: Buy currency in a three-letter format, east.g., USD.
  • priceAmountMicros: Buy toll. To go the normal price value, divide this value by 1000000. That is, 1990000 actually ways 1,99.
  • countryCode: Purchase country in two-letter format, eastward.grand., US.
  • purchaseType: Buy blazon. This key won't exist present in almost cases. Information technology'due south nonetheless important to account for, because it helps y'all understand whether the purchase was made in Sandbox environment. The possible values are:
    0: The purchase was made in Sandbox environment, therefore, it shouldn't be included in the analytics data.
    1: The purchase was made with a promo code.
  • autoResumeTimeMillis: Subscription renewal appointment. It's only present for subscriptions that take previously been paused. If this parameter is nowadays, you lot don't need to grant the user premium function admission before the given engagement.
  • cancelReason: The reason why the subscription won't be renewed. The possible values are:
    0: The user canceled the subscription car-renewal.
    1: Subscription was canceled by the system. This is most oftentimes caused by a billing issue.
    2: The user switched to a different subscription plan.
    iii: The developer canceled the subscription.
  • userCancellationTimeMillis: Subscription renewal counterfoil data. Information technology's only present if cancelReason is 0. The subscription can still exist active — to make sure, run into the expiryTimeMillis parameter'due south value.
  • cancelSurveyResult: Object that stores the reason behind subscription cancellation, which will be present if the user has left any feedback on this matter.
  • introductoryPriceInfo: Object that stores introductory cost data. For case, this can be a special offer of 1 month with 50% off.
  • promotionType: Promo code blazon that was used to actuate the subscription. The possible values are:
    0: One-time promo lawmaking.
    1: Custom promo code that can be applied by multiple customers. Such codes are commonly used for blogger partnerships.
  • promotionCode: Custom promo code that was used to activate the subscription. This parameter isn't present for one-fourth dimension promo codes.
  • priceChange: Object that stores future price change information, every bit well equally whether the user has agreed to information technology.

Subscription acknowledgement

As it was already mentioned above, in case the subscription isn't acknowledged within iii days after the buy is made, information technology'll get canceled and refunded automatically. To be honest, I don't really understand the logic backside it, and I've never encountered information technology in any other payment processing systems, the iOS ane included. Still, if you receive a transaction containing acknowledgementState=0, you are to admit the subscription.

To do and then, you'll demand to invoke the purchases.subscriptions.acknowledge method. This method executes a Mail service asking

            https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}:acknowledge          

The parameters are the aforementioned as for request validation. If the request is successfully executed, the subscription will get best-selling, which means you won't lose your coin.

If the subscription hasn't been fully purchased nevertheless, at that place's no need to acknowledge it.

Subscription renewal cancellation, revocation, refund, and deferral

Apart from subscription validation and acknowledgement, Google Play Developer API tin can also be used for other subscription operations. It should be noted that these are quite rare and, with the exception of renewal, are supported past Google Play Console. I'll still list them to give you a full general understanding of API solutions scope. All these requests accept the same parameters required as the previously mentioned methods, namely, packageName, subscriptionId, and token.

  • Renewal counterfoil. The purchases.subscriptions.abolish method. It cancels auto-renewal for the selected subscription. However, the subscription will still exist bachelor throughout the electric current billing period.
  • Subscription refund. The purchases.subscriptions.refund method. Information technology refunds the subscription. Yet, the user will still retain subscription access, and it will be automatically renewed in the next period. In about cases, you should also revoke the subscription when issuing a refund.
  • Subscription revocation. The purchases.subscriptions.revoke method. Information technology immediately revokes the subscription, which means the user will be unable to admission the premium functions. The subscription won't exist renewed. This method is usually invoked along with issuing a refund.
  • Subscription purchase deferral. The purchases.subscriptions.defer method. Information technology extends the subscription up to the specified date. In the asking, specify the subscription decease date, also every bit the engagement you lot want to supervene upon it with. The latter must result in a longer subscription period than the former.

Production (not subscription) validation

Product validation is similar to subscription validation. You lot need to invoke the purchases.products.go method to execute the GET request.

            https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}          

Nosotros're already familiar with all these parameters from looking at the examples outlined to a higher place.

Transaction data (for a product):

            {   "purchaseTimeMillis": "1630529397125",   "purchaseState": 0,   "consumptionState": 0,   "developerPayload": "",   "orderId": "GPA.3374-2691-3583-90384",   "acknowledgementState": 1,   "kind": "androidpublisher#productPurchase",   "regionCode": "RU" }          

Product transactions include much fewer properties than subscription transactions. Allow's have a look at some of import ones:

  • kind: Transaction type. In products, it always has the androidpublisher#productPurchase value. With this parameter, you tin understand whether you're dealing with a subscription or a product, and choose the processing logic accordingly.
  • purchaseState: Payment condition. Annotation that the cardinal values here are different from the paymentState parameter for subscriptions. The possible values are:
    0: Purchase was completed.
    1: Purchase was canceled. This ways that the purchase was pending, simply the user never paid for it.
    two: Purchase is pending. In some countries, the user can pay for the subscription onsite. That is, the user will initiate the subscription purchase from their device and pay for it at a nearby last. Overall, it's a quite rare case, but it should nevertheless be kept in mind.
  • acknowledgementState: Purchase confirmation status. Information technology's an of import parameter that acknowledges whether the user has received the access to what they paid for. The '0' value means they haven't, and '1' means they have. The programmer is responsible for defining this status, which tin can be done on both the mobile app and the server sides. If y'all don't acknowledge the purchase within iii days afterward it'due south been made, information technology'll automatically be refunded. I recommend implementing this logic: once you lot receive a transaction containing acknowledgementState=0, the parameter gets changed by the server. I'll discuss how to exercise that below.
  • consumptionState: Production consumption status. That'due south what iOS calls a 'consumable'. Information technology'due south defined on the mobile app side. If it has the '0' value, it ways the product wasn't consumed; if it's 'one', then it was. If you lot're selling lifetime access to your app or some specific premium feature, and so such a product shouldn't exist consumed, that is, they should have the 0 status. If you're selling coins the user can buy time and time again, such products should be consumed, that is, they should have the one condition. consumptionState=0 means the product tin can only be purchased once, whereas consumptionState=ane means it tin be purchased many times.
  • orderId: Unique transaction identifier. Each subscription buy or renewal will take its own identifier, which tin can be used to learn whether this transaction has already been candy earlier.
  • purchaseTimeMillis: Buy date.
  • regionCode: Purchase country in two-letter format, e.grand., US. Note that this parameter's name is unlike from the one in subscriptions, where it'due south named countryCode.
  • purchaseType: Purchase blazon. This fundamental won't be present in about cases. It'south still important to business relationship for, because it helps you understand whether the purchase was fabricated in Sandbox surroundings. The possible values are:
    0: The buy was fabricated in Sandbox environment, therefore, it shouldn't be included in the analytics data.
    1: The purchase was made with a promo code.
    2: The purchase was granted for a target action, due east.k., watching an in-app ad in identify of payment.

As you can see, product validation is quite similar to subscription validation. There are some points to have notation of, though:

  • The price doesn't get returned, although that would be quite handy for analytics.
  • The purchaseState parameter's values are significantly different from the values of the paymentState parameter found in subscriptions. Information technology will crusade bugs if not accounted for.
  • regionCode gets returned, even though information technology'southward named countryCode for subscriptions.

Just as subscription purchases, product purchases need to be acknowledged. To do so, invoke the purchases.products.acknowledge method which will execute a POST request

            https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}:acknowledge          

If the purchase hasn't notwithstanding been completed, in that location'southward no need to acknowledge information technology.

Refund tracking for subscriptions and products

Loftier-quality analytics is incommunicable without accounting for refunds. Unfortunately, refund information is neither present in the transaction nor gets prompted every bit a separate upshot, equally information technology works in iOS. To receive the list of refunded transactions, you lot'll need to invoke the purchases.voidedpurchases.list on a regular basis — for example, one time per solar day. This method will execute a GET request:

            https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/voidedpurchases          

In response to the request, you'll receive the list of all refunded transactions. I recommend searching for transactions in the database by the orderId parameter, as opposed to the purchaseToken one. First, this will accept less time. Second, all subscription renewals volition share the same token, and you'll but need to fetch the most recent one.

Server notifications for transactions

Server notifications (Real-time programmer notifications) help y'all learn of events that occurred on Google's side, on your server, and almost live. Once these are configured, you'll exist notified about new purchases, renewals, payment bug, etc. This can assistance you lot collect better analytics, as well as brand subscriber status management much easier.

To showtime receiving server notifications, you need to create a Google Cloud Pub/Sub topic, which will send notifications to your desired address. This topic should then be indicated in the Monetization setup section of the Google Play Console. For a detailed guide with screenshots included, see Adapty docs.

Server notification:

            {   "bulletin": {     "data": "eyJ2ZXJzaW9uIjoiMS4wIiwicGFja2FnZU5hbWUiOiJjb20uYWRhcHR5LnNhbXBsZV9hcHAiLCJldmVudFRpbWVNaWxsaXMiOiIxNjMwNTI5Mzk3MTI1Iiwic3Vic2NyaXB0aW9uTm90aWZpY2F0aW9uIjp7InZlcnNpb24iOiIxLjAiLCJub3RpZmljYXRpb25UeXBlIjo2LCJwdXJjaGFzZVRva2VuIjoiY2o3anAuQU8tSjFPelIxMjMiLCJzdWJzY3JpcHRpb25JZCI6ImNvbS5hZGFwdHkuc2FtcGxlX2FwcC53ZWVrbHlfc3ViIn19",     "messageId": "2829603729517390",     "message_id": "2829603729517390",     "publishTime": "2021-09-01T20:49:59.124Z",     "publish_time": "2021-08-04T20:49:59.124Z"   },   "subscription": "projects/935083/subscriptions/adapty-rtdn" }          

Nosotros're mostly concerned with the information key that contains transaction data encoded with base64. The messageId key tin be used for message deduplication, and so that you don't need to process duplicate letters.

Here's a transaction in a server notification:

            {   "version": "1.0",   "packageName": "com.adapty.sample_app",   "eventTimeMillis": "1630529397125",   "subscriptionNotification": {     "version": "1.0",     "notificationType": 6,     "purchaseToken": "cj7jp.AO-J1OzR123",     "subscriptionId": "com.adapty.sample_app.weekly_sub"   } }          

The packageName cardinal helps y'all understand which app this event belongs to. The subscriptionId key tells you which subscription is involved, and purchaseToken helps you find the specific transaction. With subscriptions, you'll always be looking for the last transaction in the renewal chain, every bit information technology'south the one this upshot will belong to. The notificationType fundamental contains the event type. In my stance, these are the almost handy ones for subscriptions:

  • (2) SUBSCRIPTION_RENEWED: The subscription has successfully been renewed.
  • (3) SUBSCRIPTION_CANCELED: The user has disabled subscription car-renewal. If auto-renewal is disabled, y'all'll demand to try to go the user back as an active subscriber.
  • (five) SUBSCRIPTION_ON_HOLD, (half-dozen) SUBSCRIPTION_IN_GRACE_PERIOD: The subscription couldn't take been renewed considering of payment issues. You should notify the user nigh it then that their subscription doesn't get canceled automatically.
  • (12) SUBSCRIPTION_REVOKED: the subscription has been revoked. This means the user should lose access to the premium functions previously granted by the subscription.

In products (not subscriptions), yous'll receive oneTimeProductNotification in place of the subscriptionNotification cardinal. It will likewise contain the sku central instead of the subscriptionId central. Moreover, you'll simply always receive 2 types of events for products:

  • (1) ONE_TIME_PRODUCT_PURCHASED: Successful product purchase.
  • (ii) ONE_TIME_PRODUCT_CANCELED: Product buy was canceled, as the user hadn't paid for it.

Conclusion

Server-side validation supercharges the analytics y'all'll exist able to collect for your app. It makes it harder for fraudsters to access the premium content and can be used to implement cross-platform subscriptions. However, server-side validation tin take quite a while to implement, especially if loftier information accurateness is a must. To provide high-quality data, you'd need to account for a multitude of side cases, such equally subscription upgrade, subscription crossgrade, trial periods, promo and introductory offers, grace menstruum, refunds, etc. You lot'd as well have to know of and account for all the policy minutiae, such as Google only charging a 15% (every bit opposed to thirty%) commission on subscriptions that get renewed for more than than a yr.

rodriguezconem1977.blogspot.com

Source: https://adapty.io/blog/android-in-app-purchases-part-5-server-side-purchase-validation

0 Response to "Your Session Has Expired. Please Sign in Again by Clicking on the Amazon Pay Button"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel