Een webhook implementeren in de SaaS-service

Bij het maken van een transactable SaaS-aanbieding in partnercentrum biedt de partner de Verbinding maken ion webhook-URL die moet worden gebruikt als een HTTP-eindpunt. Deze webhook wordt door Microsoft aangeroepen met behulp van de POST HTTP-aanroep om de uitgever op de hoogte te stellen van de volgende gebeurtenissen die aan de Zijde van Microsoft plaatsvinden:

Webhook-gebeurtenis 1. Wanneer ontvangen 2. Indien geaccepteerd 3. Indien afgewezen
ChangePlan Reageren met HTTP 200 PATCH met succes (deze gebeurtenis is optioneel en autoaccepted in 10 sec. PATCH met fout OF reageer met 4xx (binnen 10 seconden)
ChangeQuantity Reageren met HTTP 200 PATCH met succes (deze gebeurtenis is optioneel en autoaccepted in 10 sec. PATCH met fout OF reageer met 4xx (binnen 10 seconden)
Renew Reageren met HTTP 200 Niet van toepassing Niet van toepassing
Suspend Reageren met HTTP 200 Niet van toepassing Niet van toepassing
Unsubscribe Reageren met HTTP 200 Niet van toepassing Niet van toepassing
Reinstate Reageren met HTTP 200 Niet van toepassing Niet van toepassing (aanroepen van verwijder-API om verwijdering te activeren als de herstelbewerking niet kan worden geaccepteerd)

De uitgever moet een webhook implementeren in de SaaS-service om de status van het SaaS-abonnement consistent te houden met de Microsoft-zijde. De SaaS-service is vereist om de Get Operation-API aan te roepen om de webhook-aanroep- en nettoladinggegevens te valideren en autoriseren voordat actie wordt ondernomen op basis van de webhookmelding. De uitgever moet HTTP 200 retourneren aan Microsoft zodra de webhook-aanroep wordt verwerkt. Deze waarde bevestigt dat de webhook-aanroep is ontvangen door de uitgever.

Belangrijk

De webhook-URL-service moet 24 x 7 actief zijn en kan altijd nieuwe oproepen van Microsoft ontvangen. Microsoft heeft een beleid voor opnieuw proberen voor de webhook-aanroep (500 nieuwe pogingen van meer dan acht uur), maar als de uitgever de oproep niet accepteert en een antwoord retourneert, mislukt de bewerking waarover de webhook op de hoogte brengt uiteindelijk aan de Zijde van Microsoft.

Belangrijk

ISV's moeten strikte deserialisatie van het Webhook-schema voorkomen. Microsoft behoudt zich het recht voor om het schema in de toekomst uit te breiden.

Belangrijk

ISV's moeten het Microsoft Entra-token (JWT-token) op hun webhookeindpunt valideren vanuit de aanvraagheader. Dit is een standaard bearer-token en geeft ISV details over wie de beller is. Meer informatie over het valideren van het token in dit artikel. learn.microsoft.com/azure/active-directory/develop/access-tokens

Voorbeeld van Webhook-nettolading van ChangePlan:

{
    "id": "<guid>",
    "activityId": "<guid>",
    "publisherId": "XXX",
    "offerId": "YYY",
    "planId": "plan2",
    "quantity": 10,
    "subscriptionId": "<guid>",
    "timeStamp": "2023-02-10T18:48:58.4449937Z",
    "action": "ChangePlan",
    "status": "InProgress",
    "operationRequestSource": "Azure",
    "subscription":
    {
      "id": "<guid>",
      "name": "Test",
      "publisherId": "XXX",
      "offerId": "YYY",
      "planId": "plan1",
      "quantity": 10,
      "beneficiary":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "purchaser":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "allowedCustomerOperations": ["Delete", "Update", "Read"],
      "sessionMode": "None",
      "isFreeTrial": false,
      "isTest": false,
      "sandboxType": "None",
      "saasSubscriptionStatus": "Subscribed",
      "term":
        {
          "startDate": "2022-02-10T00:00:00Z",
          "endDate": "2022-03-12T00:00:00Z",
          "termUnit": "P1M",
          "chargeDuration": null,
        },
      "autoRenew": true,
      "created": "2022-01-10T23:15:03.365988Z",
      "lastModified": "2022-02-14T20:26:04.5632549Z",
    },
    "purchaseToken": null
}

Voorbeeld van webhookpayload van changeQuantity-gebeurtenis:


{
    "id": "<guid>",
    "activityId": "<guid>",
    "publisherId": "XXX",
    "offerId": "YYY",
    "planId": "plan1",
    "quantity": 20,
    "subscriptionId": "<guid>",
    "timeStamp": "2023-02-10T18:54:00.6158973Z",
    "action": "ChangeQuantity",
    "status": "InProgress",
    "operationRequestSource": "Azure",
    "subscription": {
        "id": "<guid>",
        "name": "Test",
        "publisherId": "XXX",
        "offerId": "YYY",
        "planId": "plan1",
        "quantity": 10,
        "beneficiary":
            {
            "emailId": XX@outlook.com,
            "objectId": "<guid>",
            "tenantId": "<guid>",
            "puid": "1234567890",
            },
        "purchaser":
            {
            "emailId": XX@outlook.com,
            "objectId": "<guid>",
            "tenantId": "<guid>",
            "puid": "1234567890",
            },
        "allowedCustomerOperations": ["Delete", "Update", "Read"],
        "sessionMode": "None",
        "isFreeTrial": false,
        "isTest": false,
        "sandboxType": "None",
        "saasSubscriptionStatus": "Subscribed",
        "term":
            {
            "startDate": "2022-02-10T00:00:00Z",
            "endDate": "2022-03-12T00:00:00Z",
            "termUnit": "P1M",
            "chargeDuration": null,
            },
        "autoRenew": true,
        "created": "2022-01-10T23:15:03.365988Z",
        "lastModified": "2022-02-14T20:26:04.5632549Z",
    },
    "purchaseToken": null
}

Voorbeeld van een webhook-nettolading van een gebeurtenis voor het opnieuw activeren van een abonnement:

// end user's payment instrument became valid again, after being suspended, and the SaaS subscription is being reinstated


{
    "id": "<guid>",
    "activityId": "<guid>",
    "publisherId": "XXX",
    "offerId": "YYY",
    "planId": "plan1",
    "quantity": 100,
    "subscriptionId": "<guid>",
    "timeStamp": "2023-02-11T11:38:10.3508619Z",
    "action": "Reinstate",
    "status": "InProgress",
    "operationRequestSource": "Azure",
    "subscription":
    {
      "id": "<guid>",
      "name": "Test",
      "publisherId": "XXX",
      "offerId": "YYY",
      "planId": "plan1",
      "quantity": 100,
      "beneficiary":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "purchaser":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "allowedCustomerOperations": ["Delete", "Update", "Read"],
      "sessionMode": "None",
      "isFreeTrial": false,
      "isTest": false,
      "sandboxType": "None",
      "saasSubscriptionStatus": "Suspended",
      "term":
        {
          "startDate": "2022-02-10T00:00:00Z",
          "endDate": "2022-03-12T00:00:00Z",
          "termUnit": "P1M",
          "chargeDuration": null,
        },
      "autoRenew": true,
      "created": "2022-01-10T23:15:03.365988Z",
      "lastModified": "2022-02-14T20:26:04.5632549Z",
    },
    "purchaseToken": null
}
 

Voorbeeld van een webhook-nettolading van een vernieuwingsevenement:

// end user's subscription renewal
 
{
    "id": "<guid>",
    "activityId": "<guid>",
    "publisherId": "XXX",
    "offerId": "YYY",
    "planId": "plan1",
    "quantity": 100,
    "subscriptionId": "<guid>",
    "timeStamp": "2023-02-10T08:49:01.8613208Z",
    "action": "Renew",
    "status": "Succeeded",
    "operationRequestSource": "Azure",
    "subscription":
    {
      "id": "<guid>",
      "name": "Test",
      "publisherId": "XXX",
      "offerId": "YYY",
      "planId": "plan1",
      "quantity": 100,
      "beneficiary":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "purchaser":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "allowedCustomerOperations": ["Delete", "Update", "Read"],
      "sessionMode": "None",
      "isFreeTrial": false,
      "isTest": false,
      "sandboxType": "None",
      "saasSubscriptionStatus": "Subscribed",
      "term":
        {
          "startDate": "2022-02-10T00:00:00Z",
          "endDate": "2022-03-12T00:00:00Z",
          "termUnit": "P1M",
          "chargeDuration": null,
        },
      "autoRenew": true,
      "created": "2022-01-10T23:15:03.365988Z",
      "lastModified": "2022-02-14T20:26:04.5632549Z",
    },
  "purchaseToken": null,
}

Voorbeeld van webhookpayload van een onderbrekings gebeurtenis:


{
    "id": "<guid>",
    "activityId": "<guid>",
    "publisherId": "XXX",
    "offerId": "YYY",
    "planId": "plan1",
    "quantity": 100,
    "subscriptionId": "<guid>",
    "timeStamp": "2023-02-10T08:49:01.8613208Z",
    "action": "Suspend",
    "status": "Succeeded",
    "operationRequestSource": "Azure",
    "subscription":
    {
      "id": "<guid>",
      "name": "Test",
      "publisherId": "XXX",
      "offerId": "YYY",
      "planId": "plan1",
      "quantity": 100,
      "beneficiary":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "purchaser":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "allowedCustomerOperations": ["Delete", "Update", "Read"],
      "sessionMode": "None",
      "isFreeTrial": false,
      "isTest": false,
      "sandboxType": "None",
      "saasSubscriptionStatus": "Suspended",
      "term":
        {
          "startDate": "2022-02-10T00:00:00Z",
          "endDate": "2022-03-12T00:00:00Z",
          "termUnit": "P1M",
          "chargeDuration": null,
        },
      "autoRenew": true,
      "created": "2022-01-10T23:15:03.365988Z",
      "lastModified": "2022-02-14T20:26:04.5632549Z",
    },
  "purchaseToken": null,
}

Voorbeeld van een webhookpayload van een afmeldingsevenement:

Dit is een gebeurtenis die alleen op de hoogte is. Er is geen verzendbericht naar ACK voor deze gebeurtenis.


{
    "id": "<guid>",
    "activityId": "<guid>",
    "publisherId": "XXX",
    "offerId": "YYY",
    "planId": "plan1",
    "quantity": 100,
    "subscriptionId": "<guid>",
    "timeStamp": "2023-02-10T08:49:01.8613208Z",
    "action": "Unsubscribe",
    "status": "Succeeded",
    "operationRequestSource": "Azure",
    "subscription":
    {
      "id": "<guid>",
      "name": "Test",
      "publisherId": "XXX",
      "offerId": "YYY",
      "planId": "plan1",
      "quantity": 100,
      "beneficiary":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "purchaser":
        {
          "emailId": XX@outlook.com,
          "objectId": "<guid>",
          "tenantId": "<guid>",
          "puid": "1234567890",
        },
      "allowedCustomerOperations": ["Delete", "Update", "Read"],
      "sessionMode": "None",
      "isFreeTrial": false,
      "isTest": false,
      "sandboxType": "None",
      "saasSubscriptionStatus": "Unsubscribed",
      "term":
        {
          "startDate": "2022-02-10T00:00:00Z",
          "endDate": "2022-03-12T00:00:00Z",
          "termUnit": "P1M",
          "chargeDuration": null,
        },
      "autoRenew": true,
      "created": "2022-01-10T23:15:03.365988Z",
      "lastModified": "2022-02-14T20:26:04.5632549Z",
    },
  "purchaseToken": null,
}

Uw webhooks beveiligen

U moet uw webhooks beveiligen, zodat niemand anders dan Microsoft-eindpunten dergelijke Webhook-aanroepen uitvoert. U kunt elke technologie gebruiken om uw webhooks te implementeren, maar uw webhook-implementatie moet voldoen aan de volgende beveiligingsrichtlijnen.

  • Microsoft roept uw webhooks aan met autorisatieheaders die de benodigde informatie bevatten om de aanroepen te valideren. U moet uw webhooks inschakelen om de autorisatieheaders te kunnen ontvangen. (Voeg geen autorisatiedetails of beveiligingstokens zoals SAS-tokens rechtstreeks toe in de URL's van de webhook. Dergelijke webhooks kunnen de autorisatieheaders die Door Microsoft worden verzonden, niet ophalen bij het aanroepen van uw webhooks).

  • Het JWT Bearer-token dat is doorgegeven in de autorisatieheader bevat de volgende gegevens in de nettolading die u kunt gebruiken om uw eindpunten te beveiligen.

  • "aud": "dit is de id van de Microsoft Entra Identity-toepassing die u toevoegt aan de technische configuratie van uw aanbieding in het Microsoft Partnercentrum"

  • 'appid' of 'azp': dit is de resource-id die u gebruikt wanneer u een autorisatietoken voor uitgevers maakt om SaaS-fulfillment-API's aan te roepen. Afhankelijk van de installatie van de toepassing ziet u mogelijk deze resource-id-waarde in 'appid' of 'azp'. Het token heeft een van de twee claims en u moet dienovereenkomstig reageren in uw code.

  • "tid": "this is the Microsoft Entra tenant ID you add to your offer's technical configuration in Microsoft Partner Center"

  • U kunt controleren op de bovenstaande doorgegeven velden om ervoor te zorgen dat de webhook-aanroep geldig is.

Belangrijk

Microsoft vereist dat ISV's hun webhooks op een veilige manier maken en autorisatieheaders accepteren. Als uw huidige webhook-implementatie geen autorisatieheaders kan accepteren, moet u uw Webhooks bijwerken en dergelijke eindpunten beveiligen (met behulp van bovenstaande richtlijnen) om onderbrekingen te voorkomen.

Ontwikkelen en testen

Als u het ontwikkelingsproces wilt starten, raden we u aan dummy-API-antwoorden te maken aan de kant van de uitgever. Deze antwoorden kunnen worden gebaseerd op voorbeeldantwoorden in dit artikel.

Wanneer de uitgever klaar is voor het end-to-end testen:

  • Publiceer een SaaS-aanbieding voor een beperkte preview-doelgroep en houd deze in de preview-fase.
  • Stel de planprijs in op nul om te voorkomen dat de werkelijke factureringskosten worden geactiveerd tijdens het testen. Een andere optie is om een niet-nulprijs in te stellen en alle testaankopen binnen 24 uur te annuleren.
  • Zorg ervoor dat alle stromen end-to-end worden aangeroepen om een echt klantscenario te simuleren.
  • Als de partner de volledige aankoop- en factureringsstroom wil testen, doet u dit met een aanbieding die hoger is dan $ 0. De aankoop wordt gefactureerd en er wordt een factuur gegenereerd.

Een aankoopstroom kan worden geactiveerd vanuit Azure Portal of Microsoft AppSource-sites, afhankelijk van waar de aanbieding wordt gepubliceerd.

Wijzigingsplan, wijzigingshoeveelheid en afmeldingsacties worden getest aan de zijde van de uitgever. Aan de kant van Microsoft kunt u zich afmelden via zowel Azure Portal als Beheer Center (de portal waar Microsoft AppSource-aankopen worden beheerd). Het aantal en het abonnement kunnen alleen worden geactiveerd vanuit Beheer Center.

Ondersteuning krijgen

Zie Ondersteuning voor het commerciële marketplace-programma in Partnercentrum voor ondersteuningsopties voor uitgevers.

Volgende stappen