So, i want to get my products list from my Huawei developer account, i integrate the sdk and all it's fine. the issue here in this code :
Future<List<ProductInfo>> getConsumableProducts() async {
try {
ProductInfoReq req = ProductInfoReq(); // The named parameter 'skuIds' is required, but there's no corresponding argument.Try adding the required argument.dartmissing_required_argumentThe named parameter 'priceType' is required, but there's no corresponding argument.Try adding the required argument.dartmissing_required_argument
req.priceType = IapClient.IN_APP_CONSUMABLE;
req.skuIds = ["prod_01", "prod_02"];
ProductInfoResult res = await IapClient.obtainProductInfo(req);
return res.productInfoList; // A value of type 'List<ProductInfo>?' can't be returned from the method 'getConsumableProducts' because it has a return type of 'Future<List<ProductInfo>>'
} on PlatformException catch (e) {
log(e.toString());
return null;
}
}
i mention the issues in the code. P.S : i made a search and verify that this code is the same code which public
If you want to obtain purchase information, you could follow the code below:
List<String> productIdList = new ArrayList<>();
// Only those products already configured in AppGallery Connect can be queried.
productIdList.add("ConsumeProduct1001");
ProductInfoReq req = new ProductInfoReq();
// priceType: 0: consumable; 1: non-consumable; 2: subscription
req.setPriceType(0);
req.setProductIds(productIdList);
// Obtain the Activity object that calls the API.
final Activity activity = getActivity();
// Call the obtainProductInfo API to obtain the details of the product configured in AppGallery Connect.
Task<ProductInfoResult> task = Iap.getIapClient(activity).obtainProductInfo(req);
Check here for more info.
Related
I'm trying to implement unity iap and I need to send PaymentSucceed event to my analytics in order to track purchases!
I'm Calling PaymentSucceed event in my
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
function, but the issue is that when user re-installs application the ProcessPurchase event is called again on android to restore purchases, and sents event for my analytics, but that's not a revenue event, so that's not correct to count it as Payment, can you share please some thoughts how I can understand is it restore or actual payment in the correct way?
here is my ProcessPurchase script
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
// A consumable product has been purchased by this user.
if (String.Equals(args.purchasedProduct.definition.id, kProductIDNoAds, StringComparison.Ordinal))
{
Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
PlayerPrefs.SetInt("noads",1);
BannerAdManager.Instance.HideBanner();
CheckNoAds();
var prodID = args.purchasedProduct.definition.id;
var price = ReplaceCommas(args.purchasedProduct.metadata.localizedPrice.ToString());
var currency = args.purchasedProduct.metadata.isoCurrencyCode;
var receipt = args.purchasedProduct.receipt;
var param = new Dictionary<string, string>();
param["af_quantity"] = "1";
param["af_content_type"] = "general";
var recptToJSON = (Dictionary<string, object>)AFMiniJSON.Json.Deserialize(receipt);
var receiptPayload = (Dictionary<string, object>)AFMiniJSON.Json.Deserialize((string)recptToJSON["Payload"]);
var purchaseData = (string)receiptPayload["json"];
var signature = (string)receiptPayload["signature"];
Debug.LogError("Purchase Event Sent Start");
AppsFlyerAndroid appsFlyerAndroid = new AppsFlyerAndroid();
appsFlyerAndroid.validateAndSendInAppPurchase(
"111",
signature,
purchaseData,
price,
currency,
param,
this);
Debug.LogError("Purchase Event Sent Finish");
PaymentSucceed(args.purchasedProduct.definition.id,args.purchasedProduct.metadata.isoCurrencyCode,(float)args.purchasedProduct.metadata.localizedPrice,"noads");
}
// Or ... an unknown product has been purchased by this user. Fill in additional products here....
else
{
Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
}
// Return a flag indicating whether this product has completely been received, or if the application needs
// to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still
// saving purchased products to the cloud, and when that save is delayed.
return PurchaseProcessingResult.Complete;
}
Goal : To save user ID and their properties, as he/she interacts with the flutter application.
Problem : Events are getting logged but i cant see user id and properties. I noticed it initially (that user id and properties arre not being logged) while working in debug mode, and then I also waited for 24-48 hours to check in the dashboard but no details for userId.
Documentation link : https://firebase.google.com/docs/analytics/userid#dart
and Yes the properties that I am trying to save in analytics, I have defined them in Custom definitions under User scope.
Code :
import 'package:firebase_analytics/firebase_analytics.dart';
class AnalyticsClass {
static final AnalyticsClass _singleton = AnalyticsClass._internal();
late FirebaseAnalytics fa = FirebaseAnalytics.instance;
factory AnalyticsClass() {
return _singleton;
}
AnalyticsClass._internal();
buttonTap(id, name) async {
await fa.logEvent(name: 'button_tap');
}
setUser(String id, name) async {
await fa.setUserId(id: id);
await fa.setUserProperty(name: 'referral', value: "test new : $name");
}
resetUser() async {
await fa.setUserId(id: null);
await fa.setUserProperty(name: 'referral', value: null);
}
}
If you're using the setUserId() in Firebase, this does not show up in the Analytics reports due to privacy concerns. What you can do is to export your data to BigQuery. This will allow you to query your raw data as well as build custom reports via Data Studio. You may also consider using the User explorer in Google Analytics Dashboard which will help you gain more insight on the behavior of your individual users.
I am trying to use appwrite server sdk list users to get userid from an email.
The documentation says there is a search: option that can be used but no where does it say what the format of that String? is.
What is the format of the search: String? to only get a list of users whose email matches?
void main() { // Init SDK
Client client = Client();
Users users = Users(client);
client
.setEndpoint(endPoint) // Your API Endpoint
.setProject(projectID) // Your project ID
.setKey(apiKey) // Your secret API key
;
Future result = users.list(search: '<<<WHAT GOES HERE>>>');
}
:wave: Hello!
Thanks for bringing this question up, this is definitely not well documented, I'll note this down and try to make it clearer in the docs, but here's how you'd approach this in Dart:
final res = users.list(search: Query.equal('email',
'email#example.com'));
res.then((response) {
print(response.users[0].toMap());
}).catchError((error) {
print(error);
});
The Query object generates a query string, and works similar to how listDocument would work. The difference here is that it only takes a single query string instead of a list.
My company is looking into reporting on Azure. We only want our customers to give us read only credentials for us to use. I did some research and it looks like Azure Active Directory does just that. So I'm looking to authenticate using a read only Azure Directory Application.
To get me started I was following this blog on using the Management API via Azure Active Directory.
https://msdn.microsoft.com/en-us/library/azure/dn722415.aspx
Aside from the approach show being very unfriendly, it doesn't work =(
I get this error after logging in as a global administrator:
"AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'."
Did some research and found this style of authentication was for native app and NOT web apps (despite what the blog post saying other wise..). So I made a tweak. My GetAuthorizationHeader now looks like this:
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
I am able to get the Access Token (yay). But now when I try to use this with the Azure Management library client I get this error:
"ForbiddenError: The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription."
I double checked my permissions in my application. It looked good. I tried giving full access to everything to see if that would have made a difference.
I double checked my tenantId, clientId, and subscriptionId, all looked good.
I made sure the subscription I'm using is pointed to the AD my application is in.
I tried making a new secret key.
My guess is this is the issue:
However in this UI I am unable to select any values for that property. I'm unsure if this is the result of a bug or an unfinished feature.
Am I missing something here?
Thanks
Here's my full code for reference:
class Program
{
static void Main(string[] args)
{
var token = GetAuthorizationHeader();
var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);
using (var computeClient = new ComputeManagementClient(credential))
{
var images = computeClient.VirtualMachineOSImages.List();
}
}
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
}
EDIT:
Progress has been made. As I discussed with Gaurav, I needed to ditch the Azure Management Library because as of right now it does not seem to support Azure Resource Manager (ARM) API! So instead I did raw web requests. And it works as intended. If I remove role access off my AD Application I get access denied. When I have it I get back data.
One thing I'm not sure about is making it so my application is auto-adding to new resources.
Also, Is there a way to list Resource Groups that are accessible for my AD Application?
New code:
class Program
{
static void Main(string[] args)
{
var token = GetAuthorizationHeader();
string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"];
string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"];
var uriListMachines = string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/virtualmachines?api-version=2015-05-01-preview", subscriptionId, resourceGroupName);
var t = WebRequest.Create(uriListMachines);
t.ContentType = "application/json";
t.Headers.Add("Authorization", "Bearer " + token);
var response = (HttpWebResponse)t.GetResponse();
string result = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
//Original Attempt:
//var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);
//using (var client = CloudContext.Clients.CreateComputeManagementClient(credential))
//{
// var images = client.VirtualMachineVMImages.List();
//}
}
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
}
EDIT EDIT:
I figured out my hung up. Resources created in the OLD portal will get it's own distinct resource group.
From what I can tell you can not add a resource made in the old portal existing resource group (boooo). Resources created in the new portal will be able to assign the resource to an existing group (aka one that gives a role access to my AD Application).
This is such a mess! But at least I know what is going on now.
I believe you're on the right track as to why you're running into this problem.
Here's what's happening:
Essentially permission to execute Service Management API is a delegated permission and not an application permission. In other words, the API is executed in context of the user for which the token is acquired. Now you are getting this token for your application (specified by client id/secret). However your application doesn't have access to your Azure Subscription because the user record created for this application in your Azure AD is of type Service Principal. Since this Service Principal doesn't have access to your Azure Subscription, you're getting this Forbidden Error (I must say that the error is misleading because you're not using certificate at all).
There are a few things you could do:
Switch to Azure Resource Manager (ARM) API - ARM API is the next generation of Service Management API (SM API) and Azure is moving towards this direction only. It exclusively works off of Azure AD token. If possible, make use of that to manage your Azure resources (though you need to keep in mind that as of today not all Azure resources can be managed through ARM API). They way you do it is take your Service Principal and assign it to a particular role using new Azure Portal. Please see this link for more details on this: https://azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/.
Use X509 Certificate - You can always use X509 Certificate based authorization to authorize your SM API requests. Please see this link for more details on that: https://msdn.microsoft.com/en-us/library/azure/ee460782.aspx#bk_cert. The downside of this approach is that the application (or whosoever has access to this certificate) will get full access to your Azure Subscription and can do everything there (including deleting resources).
Acquire token for a user instead of an application - This is another approach you can take. Essentially ask your users to login into Azure AD through your console application and acquire token for that user. Again, please keep in mind that this user must be a Co-Admin in your Azure Subscription and will have full access to your Azure Subscription as with SM API there's no concept of Role-based access control.
I am currently trying to convert the phone sample app from the official ADAL github repo to a caliburn.micro MVVM app. But there are so many moving parts backed into the code-behind to get along with WebAuthenticationBroker that I don't now how to push that into viewmodels and handle navigation correctly when the app is activated again after the broker did the sign-on. Since I am totally clueless at the moment there is no code to share yet.
I've been using MvvmLight along with ADAL in my Windows Phone 8.1 App. What you need to do is as soon as you get a token, you need to send the message using the Messenger pattern. All of those view models which require the token and have already subscribed to it will receive it. Here is something I've done in my app using MvvmLight. Remember that you need to have a ContinuationManager class and IWebContinuable interface to make the app work.
private async void Login()
{
AuthenticationResult result = null;
context = AuthenticationContext.CreateAsync("https://login.windows.net/<tenant-id>").GetResults();
try
{
//try to check if you can get the token without showing pop-up
result = await context.AcquireTokenSilentAsync("https://management.core.windows.net/", "<clientid>");
if(result.Status==AuthenticationStatus.ClientError)
{
bool exists = CheckInVault();
if(exists)
{
PasswordVault vault = new PasswordVault();
var tokenvault = vault.FindAllByResource("Token");
string RefreshToken = tokenvault[0].Password;
var refresh=await context.AcquireTokenByRefreshTokenAsync(RefreshToken, clientid);
vault.Remove(tokenvault[0]);
StoreToken(refresh);
}
else
{
context.AcquireTokenAndContinue("https://management.core.windows.net/", clientid, WebAuthenticationBroker.GetCurrentApplicationCallbackUri(), StoreToken);
}
}
else if(result != null && result.Status == AuthenticationStatus.Success)
{
// A token was successfully retrieved. Post the new To Do item
bool exists = CheckInVault();
if (exists)
{
PasswordVault vault = new PasswordVault();
var tokenvault = vault.FindAllByResource("Token");
vault.Remove(tokenvault[0]);
}
StoreToken(result);
}
//this method will be called when app is opened first time and pop-up appears
result=await context.AcquireTokenSilentAsync("https://management.core.windows.net/", "<client-id>");
}
catch(Exception e)
{
MessageDialog dialog = new MessageDialog("Error");
}
}
What I am doing here is - after acquiring the access token and reference token when the user signs up first, I store the refresh token in the PasswordVault, so as to get it in the future to enable single sign-on. ADAL actually does using its caching feature, but sometimes the single sign-on failed for me, hence using the PasswordVault to store the refresh token. After the authentication completes, I have a delegate to StoreToken function, where I actually store the new refresh token and send the access token to all the subscribers using the Messenger class in MvvmLight.
private void StoreToken(AuthenticationResult result)
{
try
{
var token = result.AccessToken;
Messenger.Default.Send<string>(token); //send the access token.
PasswordVault vault = new PasswordVault();
PasswordCredential credential = new PasswordCredential();
credential.UserName = result.AccessToken;
credential.Password = result.RefreshToken;
credential.Resource = "Token";
vault.Add(credential);
}
catch(Exception e)
{
}
}
I would recommend handling the navigation in the view models. Define a helper class like NavigationService:
public class NavigationService:INavigationService
{
private Frame _frame;
public Frame Frame
{
get
{
return _frame;
}
set
{
_frame = value;
_frame.Navigated+= OnFrameNavigated;
}
}
public void NavigateTo(string type)
{
Frame.Navigate(Type.GetType(type));
}
public void GoForward()
{
if (Frame.CanGoForward)
Frame.GoForward();
}
public void GoBack()
{
if (Frame.CanGoBack)
Frame.GoBack();
}
}
To navigate to a page from the view models, you use the NavigateTo(string) method as
NavigateTo("<fully qualified class name of the page you want to navigate to>,<assembly name>")
I would also suggest using a IoC container (MvvmLight gives you a ViewModelLocator class) so that you can maintain singleton instances of your view models and helpers like NavigationService. I haven't used the CaliburnMicro framework but I would assume there would be similar features for Messaging and Dependency Injection.