How to sell your SaaS offer through Microsoft

Stefan Riedmann
10 min readOct 6, 2020

--

Sell your SaaS offer in Microsoft Marketplace or AppSource

Perhaps you already published your service in the Microsoft Marketplace or AppSource. Now you want to implement the Transact option — so people can purchase your service directly.

First, let’s go back one step. If you start working in the Partner Center, you’ll find quite a number of options and types of offers that you can choose from, and which the marketplaces support. In our case, we have a SaaS platform for the storage and management of design files, all hosted in Azure, and we offer subscriptions for individuals, teams, and companies, like in many other platforms.

So when we started working with the Microsoft Partner Center, the first thing we did was to publish a so-called ‘Contact Me’ offer which is the simplest form, because it doesn’t require any integrations and functionalities on your side. It’s meant for using the marketplace as a showroom, and if people are interested, they have to get in contact with you or register on your platform.

Then, we wanted to make it a bit easier for visitors to register on our platform and to try it out in a demo. So this kind of publication is called ‘Free Trial’ in the marketplace. After the trial, people will still have to contact you or purchase the offer on your side. But this is already much better than the first option because it helps you creating leads and getting more users, and the “only” requirement is that you implement SSO (Single Sign-On) with Microsoft Azure Directory — meaning people can use their existing Microsoft account to login to your service. This implementation is basically an OAuth implementation. There is also tons of materials on the web, as well as a very good documentation from Microsoft covering the specifics to set up your application in Azure Active Directory. The newest article I found is this one, I can really recommend it. So I will try not to get into too many details of SSO right now, and focus on the topic.

So now, we want to close the whole circle on the marketplace and allow users to purchase a plan for our service in the marketplace.

Subscription handling between Marketplace, ActiveDirectory, and the SaaS offering

Basically, there are 2 different flows, at least those are the basic flows that I’m going to cover in this article. Be aware of the colors. Light green for example is what happens on the SaaS side, the dark is Active Directory, and blue is Marketplace/AppSource.

One flow is the purchase, where the user is being redirected to your landing page. In that case, you’ll have to perform the SSO login, so the user authorizes your platform to access her/his account. Then your platform has to apply the purchase (configure your service) and activate the subscription on Microsoft side. Part of the redirects is a marketplaceToken that allows you to identify the purchase and the user.

The other flow is a change of plan, in which case you get notified by a webhook call. In that call, you have to apply the changes to the user’s account and tell Microsoft that the operation succeeded.

When setting up such a transact offer in the partner center, you have to answer the first question as follows.

Setting up a transact offer in Microsoft Marketplace

Then you will have to fill in a lot of details, properties, and product information as in any other publication, but the key elements for Transact are

  • the technical configuration (marketplace)
  • the definition of plans that can be purchased (marketplace)
  • implementation of the Billing API (your platform)

Before going into details, I’d like to share a link to the documentation of the SaaS fulfillment API which explains the lifecycle and the different states of a subscription.

Lifecycle and states of a SaaS subscription

Now, I will go step-by-step through what I did to implement the (almost) complete flow, considering the following pieces of the solution. When I say ‘publisher side’ I mean our, respectively your, side of the implementation.

  • Azure Active Directory App Registration
  • Partner Center offer configuration
  • Landing page (publisher side)
  • Webhook (publisher side)

Azure Active Directory

The Azure Active Directory must already be configured for the Single Sign On (SSO) solution that you need for a ‘Free Trial’ offer. As for the transact offer, it must be a multi-tenant Azure AD application, allowing both work and school accounts or personal Microsoft accounts. You should avoid requesting Admin permissions during login, if not you’ll have to declare it in the offering.

Under ‘Authentication’ you have to configure the callback URLs that are allowed during the OAuth login, where the user will be redirected after successfully logging in, providing you with an OAuth code and state.

Configuration for your Active Directory application

As you can see, I also added the localhost URLs so I can debug the login process locally. Also, I have two different callbacks. One for simple sign in with Microsoft (for a free account), the other one for the subscription activation process. Everything being stateless, that comes in handy — so in your application, you know that when this login finishes, you still have to activate the purchased subscription.

To be able to access the user’s basic information, you should also have configured some permissions to access Microsoft Graph.

So the user allows your app to access his/her Graph info

For a complete understatement of the AD application, please see the official documentation.

Supplement
I was recently told that ActiveDirectory SSO integration now became a strictly enforced requirement for SaaS app. It also requires you to only request minimum User.Read permission: Link

Also, as a best practice in production scenarios, there is new guidance to use two separate AAD app registrations:
1) multi-tenanted for SSO via OAuth2 code-flow
2) single-tenant for SaaS Fulfillment API (and metered billing, if used, same one for all offers of one publisher) for OAuth2 client_credential grant
Link

Partner Center configuration

You will have to provide the technical configuration and the definition of plans that can be purchased, and the preview users — this should be your account and those of your team and testers, so they can purchase your offer while the listing is still in preview.

Anyway, it is recommended to create a Marketplace listing that will never be published (leave it in preview), where you can point against your test environment, and where you can keep the prices at zero, so testing doesn’t get too expensive ;-). Once everything is working, you configure your real listing with the real prizes, against your production environment.

The technical configuration is pretty straight forward, just configure the Azure Active directory app from above, and the two endpoints for landing and the webhook. The landing page is where the user is being sent after purchasing (with the marketplaceToken), the webhook is where Microsoft will inform you about changes — when you’ll have to reconfigure your user’s account on plan changes, and to disable it when the subscription ends, or payment fails.

Technical configuration for the Transact integration of your SaaS offer

The plan configuration is something that completely depends on your application. I won’t have to explain more details, since it’s all well documented and easy to understand.

Landing page

After the client purchased an offer of yours, he will be sent to this URL. On that page, you’ll have to make sure that the user is being identified (Single Sign-On), an account is being set up (if the user doesn’t have one already), and that you configure the account on your side according to the plan the user bought just before.

When the user gets directed to your subscription landing page with a billing token, you have to keep this token until after the login/registration with Microsoft. But first, you should use the marketplaceToken to know the email of the ‘beneficiary’ — the person that bought your offer or to whom it was assigned. This is being done with the following API, but we’ll see this later in detail.

https://marketplaceapi.microsoft.com/api/saas/subscriptions/resolve

I add the email address from the purchase (the ‘beneficiary’)to the Microsoft sign-in URL, so it gets preselected — and the user can’t make a mistake, using the wrong account, in case he or she has several ones like me.

As for the marketplaceToken itself, I send it as a state parameter for the login process, so when the user comes back to my

https://saasdomain/completeoauth/mssubscription?code=abc&state=def

endpoint, I know that I can use the state parameter as marketplaceToken for completing the subscription activation.

This is how I generate the URL for sending the user to log in.

Activate the Purchase

So the user is on your landing page — if the SSO just finished, you have the OAuth code (to get an OAuth token, used to ask the GraphAPI for the user’s details), and the marketplaceToken (which we’ve smuggled in through the state parameter). These two parameters are being given to you as query parameters in your redirect URL.

Now it’s time to setup up the user’s account according to the purchase, and let Microsoft know that the subscription has been activated.

In our case, the user can have several workspaces, in that case the plan that was purchased has to be assigned to one workspace. We have to ask the user about that, in case that there’s already more than one.

For that, you have to use the following APIs:

Resolve subscription (purchase)
Activate subscription

Now comes the coding part. I published implementations for the Billing Api with UnitTests, as well as a simple WebApi with basic endpoints on GitHub:

The BillingApiService is implemented in a way that you can use it against Microsoft’s mocking API, as well as against the production API. Not all endpoints are available for mocking, and for the production API, tokens from Active Directory have to be generated. For this, you’ll have to complete the appsettings.json with your

TenantId
ClientId
ClientSecret

BillingApi interface with basic methods

If you pull my solution, you should first run the tests to make sure the mock API endpoints work.

Please have a look at the controller class, where I implemented some basic interactions for the landing page and the webhook.

Example Controller for Billing API interactions

Then, you can add your configuration to the BillingApiExample, run it, and call the endpoint

http://localhost:5000/api/billing/getallsubscriptions

This should give you an empty array if you have no purchases yet. This is also the moment to confirm if your setup in AzureDirectory and in this application is correct. If you call

http://localhost:5000/api/billing/getallsubscriptions?mock=true

…you should get an array of subscriptions from the mocking API, without the need of your setup. The next endpoint is

http://localhost:5000/api/billing/resolvepurchase?mktplaceToken=mock

… which is actually the first endpoint you should call from your landing page (with the given token from Microsoft). Like this, you can figure out who is the buyer, and what was bought.

Once the user is authenticated with Single Sign-On, and registered to your platform, you can call

http://localhost:5000/api/billing/activatesubscription?mktplaceToken=mock

… to apply the purchase on your user’s account and to activate the subscription on the Microsoft side. Until that moment, Microsoft won’t charge your client.

In BillingController.cs there are two ToDo’s explaining that this is the moment to actually apply changes to your user’s account.

Connection webhook

In the folder of BillingController.cs, there’s a file

WebhookPayloadExample.json

…which you can use to send a POST call to the endpoint, which simulates an actual event from Microsoft. It will be called from Marketplace on any change of the subscription — for example, change of plan by the user, end of demo, suspend, or cancel the subscription.

Actually, there’s not much more to say about this webhook. It has to be available 24/7, and Microsoft will keep trying to call it a lot of times until you return 200. Still, you have to call the endpoint

UpdateOperationStatus

…to confirm that the change of plan was applied to your user’s account. The FAQ’s can be pretty helpful to understand the mechanisms in more detail.

What is missing?

Earlier, I mentioned that this is an almost complete solution. First of all, my example doesn’t include a frontend solution with OAuth and landing page, since there are so many possible ways for doing that. If you need help with that, please contact me.

But there are also some Billing API’s that I don’t use yet:

Change the plan on the subscription
Change the quantity of seats on the SaaS subscription
Cancel a subscription

Those are not that important in a first solution, since the buyer can do these operations in the marketplace, where the subscription was originally purchased. You’ll be notified through the webhook. Once the basic flow is implemented and working, you can check that out. For a start, the activation as well as the webhook are more important.

Also, there’s an API to list all your plans. I didn’t look into this yet, since we’re just publishing 2 plans for direct sales, and I can hard code our side.

List the available plans

Once you have a more complex solution, with different offers and prices for different countries or tenants, that’s another story — and you’ll need more logic on your side to apply purchases to your user’s account, and to show your user just those plans that are actually available in his or her country or tenant.

Please let me know if this was helpful. Also, feel free to contribute to the GitHub solution, to implement the missing API’s and to improve the example.

HAPPY PLANTING

Postscript
After finishing this article, I was told that there are preview source-codes for .NET available now, partially auto generated from the OpenAPI spec. So for a more complete and up-to-date SDK, you can also check this out
https://github.com/Azure/commercial-marketplace-sdk-dotnet
https://github.com/Azure/commercial-marketplace-openapi

--

--

Stefan Riedmann
Stefan Riedmann

No responses yet