Use an AppReceiptId to verify a user's identity in a Windows Store App? - windows-8

I want to be able to use the AppReceiptId from the result of CurrentApp.GetAppReceiptAsync() and tie it to a username in my backend service, to verify that the user has actually purchased the app.
I know I'm supposed to use CurrentAppSimulator in place of CurrentApp, but CurrentAppSimulator.GetAppReceiptAsync() always returns a different, random value for AppReceiptId. This makes it difficult to test with my service.
Is there a way to make it always return the same value, other than just using a hardcoded one? I'm worried that when I replace CurrentAppSimulator with CurrentApp and submit it to the store, it won't behave the way I expect it to. In the real world, the AppReceiptId won't ever change, right?
The Code I use to get AppReceiptId:
var receiptString = await CurrentAppSimulator.GetAppReceiptAsync();
XmlDocument doc = new XmlDocument();
doc.LoadXml(receiptString);
var ReceiptNode = (from s in doc.ChildNodes
where s.NodeName == "Receipt"
select s).Single();
var AppReceiptNode = (from s in ReceiptNode.ChildNodes
where s.NodeName == "AppReceipt"
select s).Single();
var idNode = (from s in AppReceiptNode.Attributes
where s.NodeName == "Id"
select s).Single();
string id = idNode.NodeValue.ToString();
id will always be some random Guid.

CurrentApp.GetAppReceiptAsync().Id is a unique ID for the actual purchase. Although it does technically represent a unique purchase made by a single Windows ID, it doesn't represent the user themselves and I don't think there's any guarantee on the durability of that ID.
Would you be better suited using the Windows Live SDK to track the actual user identity across devices?
At any rate, to answer your original question, no I don't believe there's any way to make it return the same ID all the time. The only logical place for that functionality would be in the WindowsStoreProxy.xml file, and I don't see anything in the schema that would allow you to specify this information.

Related

How to use numeric chat IDs to avoid expensive `get_entity(channel_name)` calls?

As per this comment, I'm trying to use numeric channel IDs in my telethon code, so that I don't end up spamming the Telegram API with expensive name lookup calls and getting throttled, but I'm having some difficulty.
e.g. assuming I've already instantiated and connected client:
messages = client.get_messages(numeric_channel_id)
...fails with this error:
ValueError: Could not find the input entity for PeerUser(user_id=[numeric_channel_id]) (PeerUser)
I think there's some cacheing going on, because if I do a get_entity call using the account name first, then the get_messages call works. i.e. something like this:
client.get_entity(channel_name_which_belongs_to_numeric_channel_id)
messages = client.get_messages(numeric_channel_id)
That works just fine, but now I'm doing the expensive get_entity(name) call which is what I'm trying to avoid (because it will result in FloodWaitError problems).
Is there any way I can use the numeric ID of a channel to avoid the expensive get_entity call, in this scenario?
I've also tried forcing the entity type to Channel, like this:
channel = Channel(id=numeric_channel_id, title=None, photo=None, date=None)
messages = client.get_messages(channel)
...but the results are the same, except that the error mentions PeerChannel rather than PeerUser
ID usage is not going to work unless you cached the target as you stated, that's the only way to use the integer id.
you must have met the entity from events or manual requests (say, username fetching).
you should be using client.get_input_entity('username')
it will try to search the local cache first for the saved id + hash that equals the passed username, if found it won't do ResolveUsername (heavy one) and use the local access_hash + id and return you an inputPeer. you pass that to any request you want.
you mustn't use id alone unless you're certain you have met its holder, in other words, id you use has to be something you found out from within the library and within the same session, not something you knew/found out externally.
There is no magical way to fetch something with id you claim you know, if you actually know it, the lib has to create (when the access_hash is present) an InputPeer
As the other answer states, fetching by username will always work but is expensive. However note that such a call will fill the cache so it can later be fetched again much more cheaply by ID.
If you really need a stable reference to some entity and cannot rely on the session cache, and want to avoid usernames, the documentation for Entities vs. Input Entities may be helpful.
What it boils down to is, you can do this:
print(await client.get_input_entity('username'))
...which will show something like:
InputPeerChannel(channel_id=1066197625, access_hash=-6302373944955169144)
...and then, the account that made the get_input_entity call will always be able to use the printed result, without the need for it to be in cache:
from telethon.tl.types import InputPeerChannel
USERNAME = InputPeerChannel(channel_id=1066197625, access_hash=-6302373944955169144)
# ...
await client.send_message(USERNAME, 'Hi') # works without cache

How to create several new records in another SQL table from one button-click

I'm new here. Thanks in advance for your advice.
I’m working on an app which will ask the user how many items they made.
The user will enter a number. My app should then create that many new records in a table called 'Items_Made'.
E.g. The app asks “How many items did you make?”, the user enters “19”, the app then creates 19 new records in the 'Items_Made' table.
I've managed to pull together some code (shown below) that creates ONE new record, but I would like it to create several. I probably need some kind of loop or 'while' function but am unsure how to do so.
var ceateDatasource = app.datasources.Items_Made.modes.create;
var newItem = ceateDatasource.item;
ceateDatasource.createItem();
This code successfully creates 1 record. I would like it to be able to create several.
Creating a lot of records via client script is not recommended, especially if you loose connection or the app gets closed by mistake. In my opinion, the best way to handle this would be via server script for two things: First, It's more reliable and second, it's faster. As in the example from the official documentation, to create a record you need to do something like this:
// Assume a model called "Fruits" with a string field called "Name".
var newRecord = app.models.Fruits.newRecord();
newRecord.Name = "Kiwi"; // properties/fields can be read and written.
app.saveRecords([newRecord]); // save changes to database.
The example above is a clear example on how to create only one record. To create several records at once, you can use a for statement like this:
function createRecordsInBulk(){
var newRecords = [];
for(var i=0; i<19; i++){
var newRecord = app.models.Fruits.newRecord();
newRecord.Name = "Kiwi " + i;
newRecords.push(newRecord);
}
app.saveRecords(newRecords);
}
In the example above, you initiate newRecords, an empty array that will be responsible for holding all the new records to create at once. Then using a for statement, you generate 19 new records and push them into the newRecords. Finally, once the loop is finished, you save all the records at once by using app.saveRecords and passing the newRecords array as an argument.
Now, all this is happening on the server side. Obviously you need a way to call this from the client side. For that, you need to use the google.script.run method. So from the client side you need to do the following:
google.script.run.withSuccessHandler(function(result) {
app.datasources.Fruits.load();
}).createRecordsInBulk();
All this information is clearly documented on the app maker official documentation site. I strongly suggest you to always check there first as I believe you can get a faster resolution by reading the documentation.
I'd suggest making a dropdown or textbox where the user can select/enter the number of items they want to create and then attach the following code to your 'Create' button:
var createDatasource = app.datasources.Items_Made.modes.create;
var userinput = Number(widget.root.descendants.YourTextboxOrDropdown.value);
for (var i = 0; i <= userinput; i++) {
var newItem = createDatasource.item;
createDatasource.createItem();
}
Simple loop with your user input should get this accomplished.

Can we extract all Visitor ID's from Adobe Analytics using API

I'm looking to determine whether it's possible via visitor API to be able to find out all visitor ID's.
In the code examples below, [your mcorgid here] is your company's marketing cloud organization id. If you do not know this then you need to contact Adobe Client Care to get it.
getMarketingCloudVisitorID - Get the Marketing Cloud Visitor ID (mid= param)
var visitor = Visitor.getInstance("[your mcorgid here]#AdobeOrg")
var mcvid = visitor.getMarketingCloudVisitorID();
getAnalytcisVisitorID - get legacy visitor id (aid= if applicable)
var visitor = Visitor.getInstance("[your mcorgid here]#AdobeOrg")
var aid = visitor.getAnalyticsVisitorID();
getCustomerIDs - get all customer IDs
var visitor = Visitor.getInstance("[your mcorgid here]#AdobeOrg");
var customerIDs = visitor.getCustomerIDs();
s_fid - Fallback ID
There is no built-in method for retrieving this, but you can use AA's s.c_r() cookie reading utility function, or any other cookie reading method you have to look for the s_fid cookie. (sidenote: I do not recommend using DTM's _satellite.readCookie()method. It only looks for cookies on the current page's full (not root) domain, and there is no way to change that. Since AA and most other things usually set on root domain, it makes _satellite.readCookie() unreliable in practice).
var fid = s.c_r('s_fid');
Use Adobe datawarehouse and extract Experience Cloud ID. Assuming you know how to use the API already, here is an easy report to try
report_definition = ReportDefinition(
dimensions="marketingcloudvisitorid",
metrics="visits",
date_from=insertdate,
date_to=insertdate,
source="warehouse"
)

RESTful API - How do I return different results for the same resource?

Question
How do I return different results for the same resource?
Details
I have been searching for some time now about the proper way to build a RESTful API. Tons of great information out there. Now I am actually trying to apply this to my website and have run into a few snags. I found a few suggestions that said to base the resources on your database as a starting point, considering your database should be structured decently. Here is my scenario:
My Site:
Here is a little information about my website and the purpose of the API
We are creating a site that allows people to play games. The API is supposed to allow other developers to build their own games and use our backend to collect user information and store it.
Scenario 1:
We have a players database that stores all player data. A developer needs to select this data based on either a user_id (person who owns the player data) or a game_id (the game that collected the data).
Resource
http://site.com/api/players
Issue:
If the developer calls my resource using GET they will receive a list of players. Since there are multiple developers using this system they must specify some ID by which to select all the players. This is where I find a problem. I want the developer to be able to specify two kinds of ID's. They can select all players by user_id or by game_id.
How do you handle this?
Do I need two separate resources?
Lets say you have a controller name 'Players', then you'll have 2 methods:
function user_get(){
//get id from request and do something
}
function game_get(){
//get id from request and do something
}
now the url will look like: http://site.com/api/players/user/333, http://site.com/api/players/game/333
player is the controller.
user/game are the action
If you use phil sturgeon's framework, you'll do that but the url will look like:
http://site.com/api/players/user/id/333, http://site.com/api/players/game/id/333
and then you get the id using : $this->get('id');
You can limit the results by specifying querystring parameters, i.e:
http://site.com/api/players?id=123
http://site.com/api/players?name=Paolo
use phil's REST Server library: https://github.com/philsturgeon/codeigniter-restserver
I use this library in a product environment using oauth, and api key generation. You would create a api controller, and define methods for each of the requests you want. In my case i created an entirely seperate codeigniter instance and just wrote my models as i needed them.
You can also use this REST library to insert data, its all in his documentation..
Here is a video Phil threw together on the basics back in 2011..
http://philsturgeon.co.uk/blog/2011/03/video-set-up-a-rest-api-with-codeigniter
It should go noted, that RESTful URLs mean using plural/singular wording e.g; player = singular, players = all or more than one, games|game etc..
this will allow you to do things like this in your controller
//users method_get is the http req type.. you could use post, or put as well.
public function players_get(){
//query db for players, pass back data
}
Your API Request URL would be something like:
http://api.example.com/players/format/[csv|json|xml|html|php]
this would return a json object of all the users based on your query in your model.
OR
public function player_get($id = false, $game = false){
//if $game_id isset, search by game_id
//query db for a specific player, pass back data
}
Your API Request URL would be something like:
http://api.example.com/player/game/1/format/[csv|json|xml|html|php]
OR
public function playerGames_get($id){
//query db for a specific players games based on $userid
}
Your API Request URL would be something like:
http://api.example.com/playerGames/1/format/[csv|json|xml|html|php]

Advice on polling for new documents in RavenDB

I want to poll for new documents in my Raven DB. What is the recommended way of doing this? Can I use the IndexTimestamp or can I rely on the order of the documents?
I guess I want to either do it in two steps:
1. Check if there is anything new, if so:
1.1. Get the latest X documents.
Or in one step: Get the latest X documents and have it return those or tell me that there's nothing new according some argument I sent.
FYI: I have no corresponding CLR objects to the documents.
I would not poll for it, but I would use the Changes API included with RavenDB to just get the continuous stream of documents from RavenDB.
Check out the Changes API here http://ravendb.net/docs/2.0/client-api/changes-api
I personally would use the Changes API with some kind of Message Bus (RabbitMQ) to make sure every change is processed and resilient.
If you still want to poll, just create an index with your date time and sort in descending order.
var result = session.Query<Orders>()
.OrderByDescending(x => x.Created)
.Take(10)
.ToList();
If you need to process every document, you might want to create marker documents that include the id of the document you get and make sure they have not been processed.
To do that:
marker id : polling/processed/order/1
Index:
from o in orders
let processed = LoadDocument("polling/processed/" + o.Id)
select new {
WasProcessed = processed != null,
Created = o.Created
}
A few options for you, hope that helps :)