I'm trying to implement in-app subscriptions in my app. So ,first I set upped the real time notifications. But the problem is that I can't test them for in-app subscriptions. Can anyone help me with this? Let me describe what I have.
I created the topic
Created the subscription in that topic
Added the endpoint in the subscription
Added topic name in the play.google.com in the Services and APIs section
Added the endpoint on my server, so I can receive the requests
When I hit the SEND TEST NOTIFICATION button, I can successfully receive the request, but the problem is that the request has no any values, as described here.
https://developer.android.com/google/play/billing/realtime_developer_notifications
According to link,
Each publish made to a Pub/Sub topic contains a single base64-encoded DeveloperNotification with the following fields:
{
"version": string,
"packageName": string
"eventTimeMillis": long
"oneTimeProductNotification": OneTimeProductNotification
"subscriptionNotification": SubscriptionNotification
"testNotification": TestNotification
}
and
A TestNotification contains the following fields:
{
"version": string
}
So my question is , how can test this Json? I mean why the request has no values ?
Thanks.
Sorry Guys.
I found the problem.
I was trying to get the fields in the wrong way. As my server technology is PHP,I was trying to get from $_POST array, but the right way is
$result = file_get_contents("php://input");
Related
After setting up Android real-time developer notifications (RTDN) as a way to receive IAP subscription state changes to my web server, I only actually receive a certain push from Google's RTDN webhook that never includes the subscription details. Below is the payload structure that gets delivered to my server every time a purchase subscription event happens from my app:
"message": {
"data": "longstringofcharacters",
"messageId": "604411111111111",
"message_Id": "60442222222222",
"publishTime": "2019-07-03T11:03:34.076Z",
"publish_time": "2019-07-03T11:03:34.076Z",
},
"subscription": "projects/api-keyname/subscriptions/my-project-name"
According to Google's RTDN setup guide (https://developer.android.com/google/play/billing/realtime_developer_notifications.html), the below format is what I should expect to receive anytime a new subscription is purchased, cancelled, restored, or undergoes any other related state change from a user in my app:
{
"version": string,
"packageName": string
"eventTimeMillis": long
"subscriptionNotification": SubscriptionNotification
"testNotification": TestNotification
}
I have gone through Google's RTDN setup guide a number of times, and made sure my topic has granted publisher permissions for "Pub/Sub Publisher" using "google-play-developer-notifications#system.gserviceaccount.com" which Google says is a necessary step; doing this I believe is the reason why I'm able to receive webhook transmissions, but for some reason I don't understand why subscriptions events aren't getting transmitted.
Ultimately, my goal is to receive the correct payload which contains IAP state change details so that automatically syncs with my user database on my server.
Has anyone experienced this with RTDN when attempting to receive IAP push notifications?
I figured it out: I missed in Google's guide that the payload I was expecting was base64 encoded in the "data": "longstringofcharacters" portion I pasted above. Once I realized that, I decoded one from my logs, and found the IAP subscription details I was expecting.
We have an Android education app and we use FCM Topic Messaging for sending specific notifications to each user. We categorized each user according to academic year.
Now, we have one problem for topic messaging, in the specified time, these students goes to one level higher and if we don't change the topic in Firebase for new academic year, it gives the last year notification.
How can we do this? Does Firebase have a solution for this problem? Thanks <3
This can be done through your App Server by using the InstanceID API.
You can batchAdd the corresponding tokens to the new topic (i.e. academicy year) you need, then batchRemove them from the old topic (i.e. last year).
From the link above:
Manage relationship maps for multiple app instances
Using the Instance ID service's batch methods, you can perform batch management of app instances. For example, you can perform bulk addition or removal of app instances to an FCM or GCM topic. To manage app instances, call the Instance ID service at this endpoint, providing the app instance tokens in the JSON body:
https://iid.googleapis.com/iid/v1:batchAdd
https://iid.googleapis.com/iid/v1:batchRemove
Parameters
Authorization: key=YOUR_API_KEY. Set this parameter in the header.
to : The topic name.
registration_tokens : The array of IID tokens for the app instances you want to add or remove.
Results
On success the call returns HTTP status 200. Empty results indicate successful subscription for the token. For failed subscriptions, the result contains one of these error codes:
NOT_FOUND — The registration token has been deleted or the app has been uninstalled.
INVALID_ARGUMENT — The registration token provided is not valid for the Sender ID.
INTERNAL — The backend server failed for unknown reasons. Retry the request.
TOO_MANY_TOPICS — Excessive number of topics per app instance.
Example POST request
https://iid.googleapis.com/iid/v1:batchAdd
Content-Type:application/json
Authorization:key=API_KEY
{
"to": "/topics/movies",
"registration_tokens": ["nKctODamlM4:CKrh_PC8kIb7O...", "1uoasi24:9jsjwuw...", "798aywu:cba420..."],
}
Example result
HTTP 200 OK
{
"results":[
{},
{"error":"NOT_FOUND"},
{},
]
}
We want to be able to associate app users with real transactions done.The problem is that we have the user’s email address on application back end side, and we track user purchase amounts, but when we go into the Google Wallet transactions we have no way of knowing which transaction/s belong to that user. We need a solution for this, because even if we have the user's email, we cannot search transactions by email address.
Is it possible to update the receipt numbers we are sending in the API to include the Google Wallet Receipt number instead of the time stamp ?
Please, provide us your suggestions.
I thought the answer would lie in the postback facility. That gives google's user ID and order number. However, I didn't see how to convert either of those to an email address for sending the digital good just purchased.
BTW. I rejected doing the fulfilment client side as that seemed insecure. If I'm wrong about that then why would they offer the postback facility?
... then I realised, we could do part of it client and part server side.
I guessed that something comes back from the client-side success callback.
success: function(result) {
console.log('success',result.response.orderId);
complete(result.response.orderId);
},
So, I now have the google's orderId on the client side and there I know the user's ID. So my complete() function can send the orderId and our userId to the server which can then match this with successful payment orderId from the postback (which happens first) and fulfil the order.
Yes, this is inelegant, but I believe it to be a secure solution.
Maybe slightly more elegant is to use the [sellerData] property in the submission payload to contain our user ID and order ref. We then have more items to match after the success callback has happened. I think I'll hold off delivering the digital good until all those checks have been completed.
What I do not understand is why cannot this kind of suggestion (or a better one) be found in the wallet tutorial?
Paul
My answer here refers to the previous answer provided:
Totally agree on "why cannot this kind of suggestion (or a better one) be found in the wallet tutorial?".
Your suggested solution does not seem to be very secured (to say the least). You want the client to send you their username/email/client-id in the Success callback... This means that anyone will be able to send you their ID, even if they did not make a purchase. They can add a random order-ID and hope to get a match (and then repeat the process many times in order to increase the chances).
My guess is that the username/email/client-id lies somewhere in the request object sent from Google to the postback URL (your server's doPost routine). But I have the feeling that you need to add something in the JWT generated in your Purchase function before it is passed to the google.payments.inapp.buy routine.
Looking for an answer myself...
Here is a possible solution, although I have not yet tested it myself:
Download the 'zip' file from: https://code.google.com/p/wallet-online-quickstart-java/downloads/list
Take the entire 'com' folder and add it to your project source folder (sorry, I have not been able to find a JAR for this package). Then, add the following code to your servlet:
...
import com.google.wallet.online.jwt.JwtResponseContainer;
import com.google.wallet.online.jwt.util.JwtGenerator;
import com.google.wallet.online.jwt.JwtResponse;
...
public void doPost(HttpServletRequest request, HttpServletResponse response) ...
{
try
{
String maskedWalletJwt = request.getParameter("maskedWalletJwt");
JwtResponseContainer jwtResponseContainer = JwtGenerator.jwtToJava(JwtResponseContainer.class, maskedWalletJwt, SellerSecret);
JwtResponse jwtResponse = jwtResponseContainer.getResponse();
String email = jwtResponse.getEmail();
...
}
}
One thing I'm not so sure about, is request.getParameter("maskedWalletJwt").
You might have to add this parameter when calling the google.payments.inapp.buy routine.
I have followed some tutorials in using in-app purchasing and I got this all to work. But is it possible to use it securely for this example case:
The app is free to download and has some chat functionality. It can
send 100 messages per day. The app can send extra messages for x per
year.
The problem here is: how does the server know the user bought something? Is there a Google service to use and check this? Because by allowing the app to send a message to to server "hey, I just bought this" seems to be wrong.
As part of IAP, you need a BroadcastReceiver to get notifications from Google. One of the notifications is com.android.vending.billing.PURCHASE_STATE_CHANGED. That notification includes a data block and a signature. Transmit both, exactly, to your server. Google Play will supply you with a public key that you can then use to validate the signature of the data block on the server (in php, openssl_verify works). Once you have verified the data on the server, you can then parse the data block (json) to get the list of orders including their product identifiers which tell you what the user has purchased. From there, your own protocols will have to include a device/user/contract identifier to validate against the server. Hard to make recommendations on that part without knowing more about your plans.
on this method you will get the response of transaction.
#Override
public void onRequestPurchaseResponse(RequestPurchase request,
ResponseCode responseCode) {
if responseCode is RESULT_OK means successful transaction.
you can refer this link.
You can relay the information about purchase to your server after receiving from the service.
You can use openssl_verify ($data, $signature, $key)
Data and signature are in your result you get from the service. Key is your public RSA key that you can find in your Developer Console.
I am Trying to fetch and push A notification (To inform the device to connect to the data source because it has been changed/Updated)
I read A lot of tutorials about it , and tried to apply it to help me in my case , but really i faced some problem understanding the GCM HOW IT Works
I've register at https://code.google.com/apis/console and take the SENDER ID AND APIKEY
Now I've Some Questions :
do you register the device to the service every time we start the application or only for the first time ?
do we use GCM for (only notify the device something happens) or to (notify and get the information about whats is changes) ?
why this operation need (Client And Server)
I mean (Client) it's OK Because he'll receive the push notification ,, but (Server What it Means Here) :( ,, because i think the server here will be the Google it self to notify the device
In this Case When We Use A APIKEY
the Idea Is :
I've SQL Server Database on my web-site and have small android application (Dealing With it) with two users
need when any user Add A record to the database notify the other user
Thanks In Advance ,,
Regards :)
1) You register with GCM only when you need to. E.g. When you call
GCMRegistrar.getRegistrationId(appContext);
And it returns a blank string. Typically this happens the first time you launch your app.
2) It depends on what the data you are trying to is and whether or not it will fit within the 4K payload limit. Take a look at the Send-to-Sync vs. Messages with Payload Google Help topic.
3) Your server is the server that sends the message to the GCM servers. The GCM servers then send the message down to the apps. Take a look at this blog post I wrote for a service that I helped create: http://blog.andromo.com/2012/how-does-airbop-push-messaging-work/ It should help explain how this works. In the explanation you can just substitute our servers with your own.
4) You send your API key as part of your message to the GCM servers as detailed here: http://developer.android.com/google/gcm/gcm.html#request
So in the following request:
Content-Type:application/json
Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA
{
"registration_ids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."],
"data" : {
...
},
}
Authorization: key=YOUR_API_KEY