How to manage Google Billing subscription with free trial period? - google-play-services

This is the current test setup in Google Play console:
Test product 1
Subscription base plan 1: duration 1 month
Subscription base plan 2: duration 6 months
Offer 1: 1 week free trial period
The result of queryProductDetailsAsync are 3 offers:
Offer 1
Pricing phase 1: P1M
Offer 2
Pricing phase 1: P1W (free)
Pricing phase 2: P6M
Offer 3
Pricing phase 1: P6M
The app dynamically presents all available offers to the user, so that offers can be managed remotely via the Google Play console.
The issue is that the offer 2 appears in addition to offer 3. If a base plan has an offer and the user is eligible for it, I want to hide the base plan (offer 3), as it's kind of redundant because less attractive than P1W (free) + P6M (offer 2).
On the other hand, if a user already subscribed to P1W (free) + P6M and cancelled within the free trial period, they should not get the P1W (free) + P6M but only the base plan P6M. I assume that is already managed by the Google Billing, as queryProductDetailsAsync should only return offers that are available to the user.
In the queryProductDetailsAsync response I see no way to know that offer 2 is using offer 3 as a base plan. They appear as two unrelated offers, which makes it difficult to add any logic in the app to hide the base offer. The only solution I can think of is using offerTags, add a unique ID to the base plan to be able to associate then with one another.
What is the best approach to hide offer 3 if offer 2 is also available?

It seems that tags is what Google intended to be used, according to docs:
A tag is an optional label of up to 20 characters that you can use to mark or group base plans and offers and identify them in the API. Tags can be used to determine which offer to show when the user is eligible for more than one. You can add up to 20 tags. Users cannot see tags.
Tip: We recommend using tags to identify the offers created with developer-determined eligibility to help differentiate between them when showing the collection of offers available to the user.
It seems to be the only way to identify an offer as part of a base plan. That is surprising because Google Billing already knows that the offer is part of a base plan, why do we have to mess around with custom tags to get that information? Even more surprisingly, the Google Billing API 5.0 has only recently (May 2022) been redesigned but is lacking such a basic feature.

I see two solutions:
Use the Tags to identify offers provided by the billing API as mentioned in the currently accepted answer and documented here (search for "Tags").
Use the Offer ID, the one set in Google Play Console for any discounted offer. Base plans don't have it as documented here:
Note: This field is only set for a discounted offer. Returns null for a regular base plan.
Example implementation (based on Billing Client 5.1.0):
Obtain a list of subscription offers (SubscriptionOfferDetails) via ProductDetails.getSubscriptionOfferDetails()
One of these offers represents the subscription base plan, that instance of SubscriptionOfferDetails contains the null value under the offerId/getOfferId() method.
TLDR: To filter out the base plan, I recommend to check if the list of returned subscription offers is larger than one, and if yes, remove the base plan offer from it (remove the one where offerId == null).
The answer refers to the redesigned subscriptions, introduced by Google in May 2022, more details here.

I don't see why tags should be needed in your case.
basePlanId and offerId in the subscriptionOfferDetails objects returned by queryProductDetails completely identify each base plan / base plan with offer (as Jarosław said, offerId is null for base plans without offer).
In your example, you see that "offer 2 is using offer 3 as a base plan" as it has the same basePlanId.
So just check for each basePlanId if a subscriptionOfferDetails object with offerId != null is present, and in this case, hide the one with offerId = null
As indicated in the docs, tags should only be needed for offers with developer-determined eligibility.

Related

Amadeus Web Services - Fair Quote API

I am trying to find the equivalent of FQP/FQD/FQN queries in the Amadeus SOAP service (Flight) API, but couldn't find one. I checked the API documents as well with no luck. There is command cryptic API to call the GDS commands, but the response is raw data as in the terminal, not a structured one. I need structured data response to precess data in the system.
Is there any SOAP APIs available to get the fare details and the rules?
Thanks
This is a question best sent to Amadeus directly! It's hard to know exactly what you are after without more information. Also Amadeus offer a wide variety of doing basically the same thing and your business can be better off using one or the other - its really impossible to tell without background information.
Check out these webservice calls:
Fare_PricePNRWithBookingClass
The function Fare_PricePNRWithBookingClass is used to price itineraries.
It can return one or several fare recommendations for the passenger(s) and for the itinerary of the active PNR. Only booking classes present in the flight segment of the PNR are considered.
After calling Fare_PricePNRWithBookingClass function, the system keeps the recommendations stored internally for three minutes in a dedicated context. This context can be used to create a TST by using Ticket_CreateTSTFromPricing.
Fare_PricePNRWithLowerFares
The function Fare_PricePNRWithLowerFares is used to display the lowest available fare for a given itinerary.
"Lowest available" means that this fare is applicable in a booking class where there are still enough seats available for the passengers of the PNR. This class might not be the one currently present in the flight segment of the PNR. In this case, rebooking might be necessary.
It can return one or several fare recommendations for the passenger(s) and for the itinerary of the active PNR.
After calling Fare_PricePNRWithLowerFares function, the system keeps the recommendations stored internally for three minutes in a dedicated context. This context can be used to create a TST by using Ticket_CreateTSTFromPricing. Please not that in case rebooking is required, it must be done (for example, using Air_RebookAirSegment) before TST creation.
Fare_InformativeBestPricingWithoutPNR
The InformativeBestPricingWithoutPNR function provided in the Fare interface is used to price informatively an itinerary without any PNR. If a PNR exists, it is neither taken into account nor updated. No pricing record (TST) is created to store the results.
Fare_QuoteItinerary
The QuoteItinary transaction (FQP) quotes fares for passenger types without existing reservations (PNR). Pricing is executed according to the principles of IATA resolutions as well as according to specific user requirements, if industry conform or individual.
Most likely there are more options available (that I don't know about).
Documentation available at https://webservices.amadeus.com/ - login required.

Google Custom Search Engine pricing

The pricing regarding CSE is a little bit vague:
For CSE users, the API provides 100 search queries per day for free. If you need more, you may sign up for billing in the API Console. Additional requests cost $5 per 1000 queries, up to 10k queries per day
Does one query equal one keyword regardless of pagination used, or one request? (in this sense XML is more efficient than JSON, as it allows 20 in num parameter, as opposed to JSONs 10)
Are the queries counted per API key, or per cx key?
It is vague and you are not the first to be puzzled. When I did my research I found this blog post helpful.
Assume you are talking about Custom Search Engine (terms you noted in your Q) and NOT Google Site Search (paid from the start). The reason I ask is that the XML function is only for Google Site Search customers. There is the JSON/Atom API and Custom Search API available for CSE.
For Q1, one Query = one request. You can use as many keywords or other parameters in your request (see comments in the blog post I referenced), but you will always be limited to 100 results.
For Q2, the billing is enabled through the API console. Once enabled (and in order to allow the 101st query) your code must include both your cx and API key. So in theory you could set up multiple search engines within your API and stay under the 100 request limit, but I have not seen a way to allow an API to support multiple cx keys.

VirtoCommerce API getting item prices

I am using VirtoCommerce 2.9 and have some questions regarding the API and what would be the best way to get all the information I need, while keeping the number of API requests down.
Right now I am using the endpoint /api/catalog/search to find items that matches a number of attributes. But the response does not include prices and product texts. Both I would like to present to the end user. What would be the correct or best way to retrieve this information?
Thanks!
Cheers!
Currently search service does not return the description and price for the products.
To get this details you need to use separate queries
api/catalog/product/ids?respGroup='ItemSmall'
to get product detail with description and
api/pricing/evaluate
to retrieve actual products prices. You can call them in parallel for better performance.
Be aware to use WithProperties response group because it may cause
perfomance problem. Anyway product returned with all properties values
and this 'response group' is only responsible for retrieving properties meta-information
(as possible dictionary values, multilingual, required or optional flag etc) this information often used in admin area and in storefront almost not used.
Indexed search module will be serious changed in future versions, and you will be able to have more control over the product details in the search index.

REST API - Reduce number of POSTS operations

I have designed some API which have some nested resources and I am wondering how to reduce the number of POSTS when I am creating some records.
for example, I have the following resources:
/orders/
and
/orders/{order_id}/products/
at the moment I need to run two POST separately if I need to create a new order or a new order's product but I would like to reduce the time for this and run only one POST.
Is this possible? is there any documentation I can read about this?
Thank you
Although you might have found your answer in an other thread there is still some issue regarding your endpoint design.
The first intuition that your endpoint give is that product resource could exist in several place.
./orders/{order_id}/products/{prod_id}
./products/{prod_id}
The question you should ask yourself is: Do you really want to refer to product?
Can product be leaving outside of any orders?
Having a resource sitting in 2 different place might not be that great as you are managing 2 different endpoint with similar behavior. Keeping consistency between both endpoint is not that easy.
My 2 cent is to avoid the term product as it can be confused with a single instance of a product. For example if you sell a toothbrush branded AAA, sku 1234 an order is not compose by this product but by one off the item that you have in stock. The item is "instance" of the toothbrush branded AAA, sku 1234.
As I understand your question you are not really referring to a product but more to a stock-item which should be a unique id.
The resource stock-item if you decide to have one should exist prior to the order. I guess the customer is not adding item to your stock and at the same time purchasing this item.
In conclusion I think that you are not creating the stock-item resource at all when creating orders but just making a reference to it.

Commission Junction API for Local (Daily) Deals

Has anyone used Commission Junction's Product Catalog Search API for searching/fetching local deals? (BuyWithMe and KGBDeals post their deals to CJ)
There is a Yipit clone out there which uses this API. This clone was unable to categorize deals properly based on location. I was supposed to fix this issue. The problem I saw is: API's response does not contain location/city info. Therefore, deals cannot be categorized based on cities. This basically kills the purpose of local deals.
I am looking for advice from anyone who has done similar work using CJ API. May be I am missing something.
OneBigPlanet has an All-In-One API filled with all affiliate networks and daily deal providers for U.S & Canada
If you are going to use a deal aggregator API for your site/blog, you may want to take a look at this one as well.
SideBuy has recently released its version 1 API which lets the user (like yourself) connect to its comprehensive set of daily deals using several parameters to fully customize the listings. I suggest you check it out and get in touch in SideBuy's site if you need further assistance.
Disclaimer: I work for sidebuy.com.