Windows Phone In-app purchase Error - c#

I used this wrapper for store functions to add to my Windows Phone 7 project condition to find out if user hase WP8 and enabled him in-apps and if not then just tell him.
I am using it like this:
if (Environment.OSVersion.Version.Major >= 8)
{
_store = StoreLauncher.GetStoreInterface("InAppPurchaseWrapper.Store, InAppPurchaseWrapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
}
if (_store != null)
{
var productListAsync = _store.LoadListingInformationAsync();
productListAsync.Completed = (async, status) =>
{
var listingInformation = async.GetResults();
var removeAdItem = listingInformation.ProductListings[Constants.RemoveAddKey];
PurchaseItem(removeAdItem.ProductId, Result);
};
}
else
{
MessageBox.Show(AppResources.remove_ads_notworking);
}
public void PurchaseItem(string id, Action<bool> result)
{
var purchaseAsync = _store.RequestProductPurchaseAsync(id, false);
purchaseAsync.Completed = (async, status) =>
{
try
{
if (status == StoreAsyncStatus.Completed)
{
var licenseInfo = _store.LicenseInformation;
if (licenseInfo.ProductLicenses[id].IsActive)
{
MessageBox.Show(AppResources.remove_ad_success);
appSettings.IsAdVisible = false;
}
else
{
MessageBox.Show(AppResources.remove_ads_something_goes_wrong);
}
}
else
{
if (status == StoreAsyncStatus.Error)
{
var forceException = async.GetResults();
}
result(false);
}
}
catch (Exception)
{
throw;
}
};
}
The problem is when I am calling RequestProductPurchaseAsync then I get: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)). But It was working. For one time I can buy that in-app and when I downloaded licenses I get it there. But not anymore. I was trying to restart emulator, OS but so far nothing helps. Anyone knows where could be problem? Thanks
Edit:
I find out that if I first run some sample application with same ProductId and that app is target for WP8. Then it's okay and I can buy in-app. If then I run original app (target for WP7) then I can buy in-apps too. So where could be problem? Is it posible to have working wrapper for Store functions for WP7 project? Should I send first WP8 app to Beta test and then use it's productId for WP7?

WP7 is not allowed to use Windows Phone Store in-app purchases
You should implement your own in-app purchases service

Related

StorePurchaseStatus.NotPurchased immediately after RequestPurchaseAsync()

The bounty expires in 23 hours. Answers to this question are eligible for a +100 reputation bounty.
JaSHin wants to draw more attention to this question.
In my WPF application which is packaged via Desktop Bridge I found a problem that some users can't buy addon via in-app purchase. It displays my "Canceled" alert which represents StorePurchaseStatus.NotPurchased where result.ExtendedError is null.
Target framework is:
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
Here is the simplified code that procures the purchase:
namespace MyApp {
public partial class MainWindow: Window {
private readonly StoreContext context;
public MainWindow(){
context = StoreContext.GetDefault();
}
private bool IsAdministrator()
{
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
private async void BuyButtonClick(object sender, RoutedEventArgs e) {
if (IsAdministrator())
{
ShowAlert("Cannot run under administrator rights");
return;
}
if (sender is Button button)
{
StoreProduct? storeProduct = ((Product)dataContext).storeProduct;
if (storeProduct != null)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(async delegate
{
var hwnd = new WindowInteropHelper(this).Handle;
WinRT.Interop.InitializeWithWindow.Initialize(context, hwnd);
var result = await context.RequestPurchaseAsync(storeProduct.StoreId);
switch (result.Status)
{
case StorePurchaseStatus.Succeeded:
ShowAlert("Succeeded");
break;
case StorePurchaseStatus.AlreadyPurchased:
ShowAlert("AlreadyPurchased");
break;
case StorePurchaseStatus.NotPurchased:
var extendedError = result.ExtendedError;
if (extendedError != null)
{
ShowAlert(extendedError.Message);
}
else
{
ShowAlert("Canceled");
}
break;
case StorePurchaseStatus.NetworkError:
ShowAlert("NetworkError");
break;
case StorePurchaseStatus.ServerError:
ShowAlert("ServerError");
break;
}
}
}
}
}
}
It works everywhere on my devices (Windows 11 and Windows 10). The user who cannot buy has Windows 11.
This might be caused by the account type that the customer is using.
First of all, the store purchase will fail if the app is running as administrator.
Normal “admin” accounts (people in the administrators group with a split token) will just run your desktop bridge app as a standard user, unless they right-click and launch something elevated explicitly.
But if the customer is using the system built-in account on their device, the purchase will be failed as the app will be running as administrator. This is not allowed for Microsoft Store purchase API.
It's possible that the issue is related to the user's Windows account or some settings on their device. Here are some steps you can take to troubleshoot the issue:
Check if the user has signed in to the Windows Store app with their Microsoft account. They may need to sign in or create an account if they haven't already done so.
Check if the user has a valid payment method associated with their Microsoft account. They may need to add or update their payment information if it's not valid or up-to-date.
Check if the user has disabled in-app purchases on their device. They can enable this feature in the Windows Settings app under "Apps & features" > "Microsoft Store" > "Advanced options" > "In-app purchases".
Try to reproduce the issue on a test device with the same configuration as the user's device. This can help you isolate the issue and identify any device-specific settings or configurations that may be causing the problem.
Contact Microsoft support for further assistance. They can help you troubleshoot the issue and provide guidance on how to resolve it.
Here's an updated version of your code that includes error handling and logging:
public partial class MainWindow : Window
{
private readonly StoreContext context;
public MainWindow()
{
context = StoreContext.GetDefault();
}
private async void BuyButtonClick(object sender, RoutedEventArgs e)
{
if (IsAdministrator())
{
ShowAlert("Cannot run under administrator rights");
return;
}
var product = (Product)dataContext;
if (product == null || product.storeProduct == null)
{
ShowAlert("Product is null or storeProduct is null");
return;
}
try
{
var hwnd = new WindowInteropHelper(this).Handle;
WinRT.Interop.InitializeWithWindow.Initialize(context, hwnd);
var result = await context.RequestPurchaseAsync(product.storeProduct.StoreId);
switch (result.Status)
{
case StorePurchaseStatus.Succeeded:
ShowAlert("Purchase succeeded");
break;
case StorePurchaseStatus.AlreadyPurchased:
ShowAlert("Already purchased");
break;
case StorePurchaseStatus.NotPurchased:
if (result.ExtendedError != null)
{
ShowAlert($"Purchase failed: {result.ExtendedError.Message}");
}
else
{
ShowAlert("Purchase cancelled");
}
break;
case StorePurchaseStatus.NetworkError:
ShowAlert("Network error");
break;
case StorePurchaseStatus.ServerError:
ShowAlert("Server error");
break;
default:
ShowAlert("Unknown error");
break;
}
}
catch (Exception ex)
{
// Log the exception
Debug.WriteLine(ex.Message);
ShowAlert($"Purchase failed: {ex.Message}");
}
}
private bool IsAdministrator()
{
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
private void ShowAlert(string message)
{
MessageBox.Show(message, "Purchase Status", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
This code logs any exceptions that occur during the purchase process and displays a message box with the error message. This can help you troubleshoot the issue and provide more detailed information to the user if the purchase fails.

Connect an already paired bluetooth headphone with .NET Core on Windows 11

I'm trying to write a small streamdeck plugin to connect my paired headphones after they have been paired to another device and haven't connected to my PC automatically. I basically want to kick off the same process as clicking Connect in the Windows 11 device list.
I'm able to enumerate my devices, find the correct device based on the device ID, and identify if it is already connected, but I'm not sure how to enable the music and chat connections if it's disconnected.
Here's basically what I have
string[] requestedProperties = {
"System.Devices.Aep.IsConnected",
};
var devices = await DeviceInformation.FindAllAsync(BluetoothDevice.GetDeviceSelector(), requestedProperties);
foreach (DeviceInformation di in devices) {
if (!di.Properties.ContainsKey("System.Devices.Aep.IsConnected")) {
continue;
}
if (di.Properties[ConnectedKey] is true) {
Debug.WriteLine($"Connected Device Name {di.Name}");
Debug.WriteLine($"Connected Device Id {di.Id}");
continue;
}
if ("<myHeadphonesBluetoothId>" == di.Id) {
// Not sure where to go at this point to initiate those connections
}
}
Been googling for hours without any success, and given some attempts at the AudioPlaybackConnection, BluetoothDevice, and RfcommDeviceService classes without success.
My big issue was a misunderstanding in the architecture involved in the way that devices, services, etc work.
I was able to get a small sample app working targeting net6.0-windows10.0.22000.0
const string targetDeviceId = "Bluetooth#Bluetooth00:00:00:00:00:00-00:00:00:0:0:00";
const int serialPortShortId = 0x1101;
using var streamSocket = new StreamSocket();
await EstablishConnection();
async ValueTask EstablishConnection() {
RfcommServiceId targetServiceId = RfcommServiceId.FromShortId(serialPortShortId);
BluetoothAdapter adapter = await BluetoothAdapter.GetDefaultAsync();
if (adapter is not null)
{
Radio btRadio = await adapter.GetRadioAsync();
if (btRadio.State == RadioState.Off)
{
await btRadio.SetStateAsync(RadioState.On);
Console.WriteLine("Bluetooth adapter was off. Turned it on.");
}
}
using BluetoothDevice btDevice = await BluetoothDevice.FromIdAsync(targetDeviceId);
btDevice.ConnectionStatusChanged += (sender, args) => Console.WriteLine("Bluetooth device connected");
RfcommDeviceServicesResult services = await btDevice.GetRfcommServicesForIdAsync(targetServiceId);
RfcommDeviceService service = services.Services.Single();
if (btDevice.ConnectionStatus != BluetoothConnectionStatus.Connected && service.DeviceAccessInformation.CurrentStatus == DeviceAccessStatus.Allowed) {
try {
await streamSocket.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName,
SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
}
catch (COMException e) when ((uint)e.HResult == 0x8007277C) {
Console.WriteLine("Bluetooth device is not on or in range.");
}
}
}
After running this the device would connect and windows would initialize the mic and speaker devices attached to it.

C# Xamarin Forms InAppBilling PurchaseAsync not returning after handle of playstore

I am using jamesmontenegro InAppBilling and I have a small issue regarding payments.
The code is working fine but after the payment is handled by Google Play Store, the app doesn't handle the procedure and doesn't return if the purchase was successfully leading to not being able to consume the purchased item.
Here is the simple code
public static async Task<bool> PurchaseItem(string productId, string payload)
{
var billing = CrossInAppBilling.Current;
try
{
var connected = await billing.ConnectAsync(ItemType.InAppPurchase);
if (!connected)
{
//we are offline or can't connect, don't try to purchase
return false;
}
//check purchases
var purchase = await billing.PurchaseAsync(productId, ItemType.InAppPurchase, payload);
//possibility that a null came through.
if (purchase == null)
{
//did not purchase
Debug.WriteLine("purchased but not consumed");
return true;
}
else if (purchase.State == PurchaseState.Purchased)
{
//purchased, we can now consume the item or do it later
//If we are on iOS we are done, else try to consume the purchase
//Device.RuntimePlatform comes from Xamarin.Forms, you can also use a conditional flag or the DeviceInfo plugin
if (Device.RuntimePlatform == Device.iOS)
return true;
var consumedItem = await CrossInAppBilling.Current.ConsumePurchaseAsync(purchase.ProductId, purchase.PurchaseToken);
if (consumedItem != null)
{
//Consumed!!
Debug.WriteLine("purchased and consumed");
return true;
}
}
return false;
}
Nothing is actually running after PurchaseAsync is called as the thread changes to Google Play Store.
Once the payment is finished and the thread goes back to the app it is not possible to handle anything.
Any ideas? There is a workaround for this but I am just wondering if I am doing something wrong here?

Media capture initializing error

I have a problem with UWP media capture initilization. My code is below,
private async Task StartPreviewAsync()
{
try
{
//set initilize settings
Settings oneSetting = null;
using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), sqlpath))
{
oneSetting = (from p in conn.Table<Settings>()
where p.id == 0
select p).FirstOrDefault();
}
if (oneSetting.camera != null)
{
var settings = new MediaCaptureInitializationSettings();
settings.StreamingCaptureMode = StreamingCaptureMode.Video;
settings.PhotoCaptureSource = PhotoCaptureSource.VideoPreview;
var devices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(Windows.Devices.Enumeration.DeviceClass.VideoCapture);
foreach (var device in devices)
{
if ((device.Id).Equals(oneSetting.cameraId))
{
settings.VideoDeviceId = device.Id;
break;
}
}
_mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync(settings);
//MediaCapture m = new MediaCapture();
//await m.InitializeAsync();
var focusSettings = new FocusSettings();
focusSettings.AutoFocusRange = AutoFocusRange.FullRange;
focusSettings.Mode = FocusMode.Auto;
focusSettings.WaitForFocus = true;
focusSettings.DisableDriverFallback = false;
_mediaCapture.VideoDeviceController.FocusControl.Configure(focusSettings);
await _mediaCapture.VideoDeviceController.ExposureControl.SetAutoAsync(true);
_mediaCapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
_mediaCapture.SetRecordRotation(VideoRotation.Clockwise90Degrees);
capturePreview.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
_isPreviewing = true;
_displayRequest.RequestActive();
DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape;
}
}
catch (UnauthorizedAccessException)
{
// This will be thrown if the user denied access to the camera in privacy settings
System.Diagnostics.Debug.WriteLine("The app was denied access to the camera");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("MediaCapture initialization failed. {0}", ex.Message);
}
}
It returns MediaCapture initialization failed. {0} error. Recently, it runs well. But since this morning it gives the error. Is there anybody who takes the same error?
The full error message is that;
The specified device interface level or feature is not supported on this system.
: Media Capture initialization failed. {0}
The thread 0x1924 has exited with code 0 (0x0).
Same issue here.
After many hours of retries and googling i realize that it was related to the windows 10 anniversary update.
I found the solution here:
https://www.macecraft.com/fix-webcam-issues-windows-10-anniversary-update/
I added the EnableFrameServerMode key in the registry and magically the webcam came back working.
But since this morning it gives the error.
Did you recently update your device OS? On which device did you meet this problem and what is the OS version?
I personally think this is more like a device problem or drive issue. You can try to restart your device and see if this helps. Or you can start the built-in camera app and check if this official app runs well.
I'm writing this answer here because there are too many details need to be confirmed, please leave a comment here to tell us the detail information about your device and your test result based on my suggestion, so can we keep look into this issue.

BackgroundTask geofence triggering

I am trying to showToast when the phone leaves or enter the geofenced location (which is set elsewhere and passed in). The issue is that when the app is in the background the trigger does not occur and I don't see the showToast message. I am changing the location manually using an emulator on my PC.
Background Tasks> Location is set under the app manifest.
This is the code I am using to build the Geofence and backgroundtask
//Creates Geofence and names it "PetsnikkerVacationFence"
public static async Task SetupGeofence(double lat, double lon)
{
await RegisterBackgroundTasks();
if (IsTaskRegistered())
{
BasicGeoposition position = new BasicGeoposition();
position.Latitude = lat;
position.Longitude = lon;
double radius = 8046.72; //5 miles in meters
Geocircle geocircle = new Geocircle(position, radius);
MonitoredGeofenceStates monitoredStates = MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited;
Geofence geofence = new Geofence("PetsnikkerVacationFence", geocircle, monitoredStates, false);
GeofenceMonitor monitor = GeofenceMonitor.Current;
var existingFence = monitor.Geofences.SingleOrDefault(f => f.Id == "PetsnikkerVacationFence");
if (existingFence != null)
monitor.Geofences.Remove(existingFence);
monitor.Geofences.Add(geofence);
}
}
//Registers the background task with a LocationTrigger
static async Task RegisterBackgroundTasks()
{
var access = await BackgroundExecutionManager.RequestAccessAsync();
if (access == BackgroundAccessStatus.Denied)
{
}
else
{
var taskBuilder = new BackgroundTaskBuilder();
taskBuilder.Name = "PetsnikkerVacationFence";
taskBuilder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable));
taskBuilder.SetTrigger(new LocationTrigger(LocationTriggerType.Geofence));
taskBuilder.TaskEntryPoint = typeof(Petsnikker.Windows.Background.GeofenceTask).FullName;
var registration = taskBuilder.Register();
registration.Completed += (sender, e) =>
{
try
{
e.CheckResult();
}
catch (Exception error)
{
Debug.WriteLine(error);
}
};
}
}
static bool IsTaskRegistered()
{
var Registered = false;
var entry = BackgroundTaskRegistration.AllTasks.FirstOrDefault(keyval => keyval.Value.Name == "PetsnikkerVacationFence");
if (entry.Value != null)
Registered = true;
return Registered;
}
}
}
This code is where I monitor the state of the geofence.
This is where the Entry point in the appxmanifest is pointing
public sealed class GeofenceTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
var monitor = GeofenceMonitor.Current;
if (monitor.Geofences.Any())
{
var reports = monitor.ReadReports();
foreach (var report in reports)
{
switch (report.NewState)
{
case GeofenceState.Entered:
{
ShowToast("Approaching Home",":-)");
break;
}
case GeofenceState.Exited:
{
ShowToast("Leaving Home", ":-)");
break;
}
}
}
}
//deferral.Complete();
}
private static void ShowToast(string firstLine, string secondLine)
{
var toastXmlContent =
ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var txtNodes = toastXmlContent.GetElementsByTagName("text");
txtNodes[0].AppendChild(toastXmlContent.CreateTextNode(firstLine));
txtNodes[1].AppendChild(toastXmlContent.CreateTextNode(secondLine));
var toast = new ToastNotification(toastXmlContent);
var toastNotifier = ToastNotificationManager.CreateToastNotifier();
toastNotifier.Show(toast);
Debug.WriteLine("Toast: {0} {1}", firstLine, secondLine);
}
}
After looking at your code, it seems that your code is correct.
In order to fire the Geofence Backgroundtask to show the toast information, please make sure the following things:
1) Please make sure that you have done all the necessary configuration in the Package.appxmanifest for registering the BackgroundTask, for example you have set the correct EntryPoint and added the “Location” capabilities.
For the detailed information, you can try to compare your Package.appxmanifest with the official sample Geolocation’s Package.appxmanifest.
Please also check: Create and register a background task and Declare background tasks in the application manifest.
2) Please make sure that you know how to set the location in the Emulator manually for simulating the phone leave or enter the geofenced location. For more information about how to set location in the emulator, please check the following article:
https://msdn.microsoft.com/library/windows/apps/dn629629.aspx#location_and_driving .
3) Please make sure that your second position in your emulator is not really far away from the geofences that you have defined in the first time, because the emulator behaves like a real device, and the device doesn’t expect to suddenly move from New York to Seattle. Or the BackgroundTask will not be fire immediately.
4) Background tasks for geofencing cannot launch more frequently than every 2 minutes. If you test geofences in the background, the emulator is capable of automatically starting background tasks. But for the next subsequent background tasks, you need to wait for more than 2 minutes.
Besides, I will recommend you refer to the following article about how to use the Windows Phone Emulator for testing apps with geofencing:
https://blogs.windows.com/buildingapps/2014/05/28/using-the-windows-phone-emulator-for-testing-apps-with-geofencing/ .
Thanks.

Categories