In a previous post, I've shown how to publish your Delphi app to the Windows Store. If it is a paid app, you can start getting money with it as soon as it starts to sell. But sometimes, you don't want to make it a paid app, but you still want to earn money with it.
One way to do it is to do the same that many games do: to use In-app purchases. You can offer a free basic version and put some paid add-ins in the app, so the user must pay to get the premium features. Even if it's a paid app, you can also give the user a trial period, so, the user can use the premium version for some time and then, if he doesn't want to pay for the app, he can still use the basic features.
Delphi 10.3 introduced a new component, TWindowsStore, that allows you to control the store features (add-ins, trial version) and enable or disable features depending on what the user pays. In this article, I will show how to use the TWindowsStore component to control the features and set the In-app purchases.
We will use the same Financial Calculator we've used in the previous article, but we'll do some changes:
- The basic calculator will be able to calculate only the Present Value of the investment. The other calculators won't be available.
- The user will have a trial period where all the calculators are available. Once the trial period is expired, the app will revert to the basic version
- The user will be able to buy calculators as add-in purchases. He won't need to buy all, he will be able to buy just the ones he needs as add-in purchases.
Developing the trial and in-app purchases
The first step in the development of the trial version is to add a TWindowsStore component in the main window of the calculator. Then, we will change the app to show the basic features for the app. To do this, change the PageIndex of the calculators:
- Present Value - 0
- Future Value - 1
- Payments - 2
- Return Rate - 3
Put a panel with a button over each calculator, except the first one, with this text: "To open this calculator, click on the button". Change the ParentBackground property to false. Add another TabSheet, with a label with a caption with text "Trial version - % days remaining". If you run the app, you should have something like this:
Now, let's program the trial version. When the user is in trial period, he will be able to use all calculators. To do that, we'll do something like this:
procedure TForm1.CheckIfTrial;
begin
if WindowsStore1.AppLicense.IsActive then begin
if WindowsStore1.AppLicense.IsTrial then begin
var RemainingDays := WindowsStore1.AppLicense.TrialTimeRemaining.Days;
Label21.Caption := Format(Label21.Caption, [RemainingDays]);
EnableFullVersion;
end
end
else begin
CheckBoughtCalculators;
end;
end;
The CheckIfTrial procedure will be called in the OnCreate handler of the form, thus setting the UI accordingly at start. The EnableFullVersion procedure will hide all trial panels:
procedure TForm1.EnableFullVersion;
begin
Panel1.Visible := False;
Panel2.Visible := False;
Panel3.Visible := False;
end;
The CheckBoughtCalculators will only hide the panels for the add-ons that had been bought:
procedure TForm1.CheckBoughtCalculators;
begin
Panel1.Visible := not WindowsStore1.UserHasBought('FutureCalc');
Panel2.Visible := not WindowsStore1.UserHasBought('PaymentCalc');
Panel3.Visible := not WindowsStore1.UserHasBought('RateCalc');
end;
The code to buy the add-ons is:
function TForm1.PurchaseItem(Item: string) : string;
begin
LogMessage('Will purchase item: ' +Item);
for var i := 0 to WindowsStore1.AppProducts.Count - 1 do
if TWindowsString.HStringToString(WindowsStore1.AppProducts[i].InAppOfferToken) = Item then begin
BuyProduct(WindowsStore1.AppProducts[i]);
exit;
end;
LogMessage('Item not found: ' +Item);
end;
procedure TForm1.BuyProduct(Product: IStoreProduct);
begin
try
var status := WindowsStore1.PurchaseProduct(Product);
LogMessage('Got status: '+Integer(status).ToString);
if status = StorePurchaseStatus.Succeeded then begin
LogMessage('Item ' +TWindowsString.HStringToString(Product.Title)+' bought');
CheckBoughtCalculators();
end
else begin
ShowMessage('Item could not be purchased. Error: '+Integer(status).ToString);
end;
except
On e : Exception do
LogMessage('Exception while buying item.'+Chr(13)+
E.ClassName+', with message : '+E.Message);
end;
end;
The code for the buttons is:
procedure TForm1.Button1Click(Sender: TObject);
begin
PurchaseItem('FutureCalc');
end;
While developing the app, I found that this code generates an exception, there is something in the code that doesn't like the Delphi Window handle and crashes the app when the code is run. Not a good experience for a paid app. So, I searched the web for an alternative and found this article that shows how to create a dll in C# that can be used in Delphi, to allow buying add-in purchases in the Windows Store. If you follow the instructions there and compile the dll, you will have the IAPWrapper.dll that can be used in our Delphi program.
This dll exposes a function, Purchase, that makes the purchase of an add-in. It's different than the TWindowsStore's PurchaseProduct, because it receives the item id as a parameter and not the item itself. That way, we must add the dll to the project, declare the Purchase function and change the BuyProduct method:
function Purchase(StoreId : PAnsiChar) : PAnsiChar; stdcall; external 'IAPWrapper.dll';
procedure TForm1.BuyProduct(Product: IStoreProduct);
begin
try
var status := Purchase(PAnsiChar(AnsiString(TWindowsString.HStringToString(Product.StoreId))));
LogMessage('Got status: '+status);
if status = 'Succeeded' then begin
LogMessage('Item ' +TWindowsString.HStringToString(Product.Title)+' bought');
CheckBoughtCalculators();
end
else begin
ShowMessage('Item could not be purchased. Error: '+Integer(status).ToString);
end;
except
On e : Exception do
LogMessage('Exception while buying item.'+Chr(13)+
E.ClassName+', with message : '+E.Message);
end;
end;
With this code, you can put your app in the store and monetize with it. When the user wants a calculator, he can buy the item and it will be available forever. You could also make it consumable, so it can be bought again at anytime, but for our purposes, that's fine.
Creating the add-ins in the store
Once you have the program developed, you must create your add-ins in the store. Go to the Windows Development Center, select the app you have developed for the store and click on the "Create a new add-on" button.
There you can create many types of add-ons:
- Developer-managed consumable - this kind of add-on is managed by your app, like some kind of strength. If this consumable is used on your app, the user can buy it again.
- Store-managed consumable - this kind of add-on is managed by the store, like some kind of gun. You can query the store to know how many guns the user has bought
- Durable - this kind of add-on is bought once and it is available until its lifetime
- Subscription - this kind of add-on needs periodic payment to keep using it
Our add-ons will all be durable, once the user buys a calculator, he won't need to buy it again. Create a new durable add-on and name it FutureCalc. Then start the submission for it:
Set the properties for the add-on, with a product lifetime Forever and Content type as Software as service:
Then, set the price and availability of the add-on:
We won't change anything here - we will leave the add-in for free, so you just need to click the Save button.
The next step is to add the store listings. Add a new language and select English (United States) and edit it:
Set the title and description and click on the Save button. When you have everything set, just click on the Submit to the store to submit it. Do the same thing with the PaymentCalc and RateCalc add-ons.
The next step is to create a new flight for the package. Just change the version to 1.1 and compile the app for the store (don't forget to change the Provisioning data to Store). Then, create a new flight for the submission and send the package there. It will be available to download as soon as it passes certification. It will show that it has in-app purchases:
Once you've installed it, it will show you the new version, and you can unlock the calculator you want:
Conclusions
As you can see you can send your Delphi apps to the Windows store and get some money with them The TWindowsStore component allows you to interact with the add-ins you've set in the store, so you can earn money by creating a paid version or even by adding purchases in the app. While developing the app, I've shown that you can also create a dll in C# that interacts with your Delphi program in the same way that a Win32 dll does. You can use this dll in the store to buy add-ins and monetize your app.
The full source code for this article is in https://github.com/bsonnino/FinCalcAddIn
Hi Sir,
I tried with delphi 10.3.1 Rio, error shows up when adding TWindowsStore component to form, the error is ‘delphi can not get factory class Windows.Services.store.storecontext’.
What to do ?. Kindly help.
Regards
Fajrin
Which version of Windows are you running? This component only works with the October 2018 Windows 10 version
The sample application is compilable but not executable, at the time of starting the application an initiation error message is displayed and the application must be terminated. No information is shown as to why or in which unit the error is located.
I think there is an incompatibility of initiation (a circular reference, perhaps) between the windowsstore reference units and the TWindowsStore component reference unit.
I will check it, it was running fine, maybe some change in the Delphi version. Let me check it and I’ll return to you
Sorry, I found the problem. The problem of execution was in the use of the library that was not attached to the project.
According to what I could read on Microsoft sites, some problems still prevail to obtain the correct information, such as the remaining time of the Trial period, the return value is incorrect even in applications made in C #!
Hi Bruno,
The sample application is compilable but it is not executable!
There is an incompatibility between the units referred to WindowsStore. The following units are declared in Uses:
Vcl.WindowsStore, required for the component
System.Win.WinRt, unit needed for HStringToString
WinApi.WinRt,
WinApi.Foundation,
WinApi.WindowsStore,
WinApi.CommonTypes,
Winapi.Storage,
WinApi.ServicesRt.Store,
WinApi.WinRt.Utils,
I have tried all the combinations that have occurred to me and I have not been able to make the application run, regardless of the combination between referenced units, the application compiles but does not run. Immediately upon executing the application, the message that the application could not be started correctly and must be closed is displayed. The problem is that it does not indicate why the error is due or in which unit it is hosted.
Any ideas????
Sorry, I found the problem. The problem of execution was in the use of the library that was not attached to the project.
According to what I could read on Microsoft sites, some problems still prevail to obtain the correct information, such as the remaining time of the Trial period, the return value is incorrect even in applications made in C #!