Реализация веб-перехватчика в службе SaaS
При создании предложения SaaS для транзакций в Центре партнеров партнер предоставляет URL-адрес веб-перехватчика подключения, который будет использоваться в качестве конечной точки HTTP. Этот веб-перехватчик вызывается Майкрософт с помощью HTTP-вызова POST, чтобы уведомить сторону издателя о следующих событиях, происходящих на стороне Майкрософт:
Событие веб-перехватчика | 1. При получении | 2. Если принято | 3. Если отклонено |
---|---|---|---|
ChangePlan |
Ответ с помощью HTTP 200 | PATCH с успехом (это событие является необязательным и автоматически настроено в 10 с) | PATCH с ошибкой OR отвечает 4xx (в течение 10 секунд) |
ChangeQuantity |
Ответ с помощью HTTP 200 | PATCH с успехом (это событие является необязательным и автоматически настроено в 10 с) | PATCH с ошибкой OR отвечает 4xx (в течение 10 секунд) |
Renew |
Ответ с помощью HTTP 200 | Неприменимо | Неприменимо |
Suspend |
Ответ с помощью HTTP 200 | Неприменимо | Неприменимо |
Unsubscribe |
Ответ с помощью HTTP 200 | Неприменимо | Неприменимо |
Reinstate |
Ответ с помощью HTTP 200 | Нет данных | Неприменимо (вызов API удаления для активации удаления, если восстановление не может быть принято) |
Издатель должен реализовать веб-перехватчик в службе SaaS, чтобы обеспечить согласованный статус подписки SaaS на стороне Майкрософт. Служба SaaS требуется для вызова API-интерфейса операции Get для проверки и авторизации вызова веб-перехватчика и полезных данных перед выполнением действия с учетом данных в уведомлении веб-перехватчика. Издатель должен возвращать код HTTP 200 в Майкрософт непосредственно после обработки вызова веб-перехватчика. Это значение подтверждает, что вызов веб-перехватчика был успешно получен издателем.
Внимание
Служба URL-адреса веб-перехватчика должна быть запущена и запущена 24 x 7 и готова получать новые вызовы от Корпорации Майкрософт в любое время. Корпорация Майкрософт имеет политику повторных попыток для вызова веб-перехватчика (500 повторных попыток в течение восьми часов), но если издатель не принимает вызов и возвращает ответ, операция, о которую веб-перехватчик уведомляет о том, что в конечном итоге завершится сбоем на стороне Майкрософт.
Внимание
Поставщики программного обеспечения должны избегать строгой десериализации схемы веб-перехватчика. Корпорация Майкрософт оставляет за собой право расширить схему в будущем.
Внимание
Поставщики программного обеспечения должны проверить токен Microsoft Entra (токен JWT) в конечной точке веб-перехватчика из заголовка запроса. Это стандартный маркер носителя и предоставит поставщику программного обеспечения сведения о том, кто вызывается. Узнайте больше о том, как проверить маркер в этой статье. learn.microsoft.com/azure/active-directory/develop/access-tokens
Пример полезных данных веб-перехватчика в 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
}
Пример полезных данных веб-перехватчика события ChangeQuantity:
{
"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
}
Пример полезных данных веб-перехватчика события восстановления подписки:
// 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
}
Пример полезных данных веб-перехватчика события продления:
// 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,
}
Пример полезных данных веб-перехватчика события приостановки:
{
"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,
}
Пример полезных данных веб-перехватчика события отмены подписки:
Это событие только для уведомления. Для этого события нет отправки в ACK.
{
"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,
}
Защита веб-перехватчиков
Необходимо защитить веб-перехватчики, чтобы никто другой, кроме конечных точек Майкрософт, не делал таких вызовов веб-перехватчика. Вы можете использовать любую технологию для реализации веб-перехватчиков, однако реализация веб-перехватчика должна соответствовать следующим рекомендациям по безопасности (см. руководство).
Корпорация Майкрософт вызывает веб-перехватчики с заголовками авторизации, содержащими необходимые сведения для проверки вызовов. Чтобы веб-перехватчики могли получать заголовки авторизации, необходимо включить веб-перехватчики. (Не добавляйте сведения о авторизации или маркеры безопасности, такие как маркеры SAS непосредственно в URL-адресах веб-перехватчика. Такие веб-перехватчики могут не получить заголовки авторизации, которые корпорация Майкрософт отправляет при вызове веб-перехватчиков.
Маркер носителя JWT, переданный в заголовке авторизации, содержит следующие данные в полезных данных, которые можно использовать для защиты конечных точек.
"aud": "Это идентификатор приложения удостоверений Майкрософт, который вы добавляете в техническую конфигурацию вашего предложения в Центре партнеров Майкрософт"
Appid или azp: это идентификатор ресурса, используемый при создании маркера авторизации издателя для вызова API выполнения SaaS. И в зависимости от настройки приложения вы можете увидеть это значение идентификатора ресурса в "appid" или "azp". Маркер имеет одно из двух утверждений, и вы должны реагировать соответствующим образом в коде.
"tid": "это идентификатор клиента Microsoft Entra, который вы добавляете в техническую конфигурацию вашего предложения в Центре партнеров Майкрософт"
Вы можете проверить наличие указанных выше полей, чтобы убедиться, что вызов веб-перехватчика действителен.
Внимание
Корпорация Майкрософт начнет требовать от поставщиков программного обеспечения создавать веб-перехватчики безопасным образом и принимать заголовки авторизации. Если текущая реализация веб-перехватчика не может принимать заголовки авторизации, необходимо обновить веб-перехватчики и защитить такие конечные точки (используя приведенные выше рекомендации), чтобы избежать каких-либо нарушений.
Разработка и тестирование
Чтобы приступить к процессу разработки, рекомендуется создать фиктивные отклики API на стороне издателя. Эти отклики могут быть созданы на основе примеров откликов, приведенных в этой статье.
Если издатель готов к сквозному тестированию:
- Опубликуйте предложение SaaS для ограниченной аудитории предварительной версии и сохраните его предварительную версию.
- Задайте для плана нулю, чтобы избежать активации фактических расходов на выставление счетов во время тестирования. Другим вариантом является установка ненулевой цены и отмена всех тестовых покупок в течение 24 часов.
- Убедитесь, что вызываются все этапы процесса, чтобы сымитировать реальный сценарий с участием клиента.
- Если партнер хочет протестировать полный процесс покупки и выставления счетов, для этого можно использовать предложение с ценой выше 0 долларов США. Счет за покупку выставляется, и будет создан счет.
Процесс покупки можно запустить на портале Azure или на сайтах Microsoft AppSource в зависимости от места публикации предложения.
Действия Изменить план, Изменить количество рабочих мест и Отменить подписку тестируются на стороне издателя. На стороне Майкрософт действие Отменить подписку может запускаться как на портале Azure, так и в Центре администрирования (портал, где осуществляется управление покупками в Microsoft AppSource). Действия "Изменить количество рабочих мест" и "Изменить план" можно выполнить только в Центре администрирования.
Поддержка
Возможности поддержки для издателя см. в разделе Поддержка коммерческой платформы в Центре партнеров.
Связанный контент
- Дополнительные варианты предложений SaaS на коммерческой платформе см. в разделе API-интерфейсы службы оценки показателей коммерческой платформы.
- Ознакомьтесь с разделом Клиенты для различных языков программирования и примеры.
- Ознакомьтесь со следующими видеороликами: