Menerapkan webhook pada layanan SaaS

Saat membuat penawaran SaaS yang dapat ditransaksikan di Pusat Mitra, mitra menyediakan URL Webhook Koneksi untuk digunakan sebagai titik akhir HTTP. Webhook ini dipanggil oleh Microsoft dengan menggunakan panggilan POST HTTP untuk memberi tahu sisi penerbit tentang peristiwa berikut yang terjadi di sisi Microsoft:

Peristiwa webhook 1. Ketika diterima 2. Jika diterima 3. Jika ditolak
ChangePlan Merespons dengan HTTP 200 PATCH dengan sukses (peristiwa ini opsional dan diterima secara otomatis dalam 10 detik) PATCH dengan kegagalan ATAU merespons dengan 4xx (dalam 10 detik)
ChangeQuantity Merespons dengan HTTP 200 PATCH dengan sukses (peristiwa ini opsional dan diterima secara otomatis dalam 10 detik) PATCH dengan kegagalan ATAU merespons dengan 4xx (dalam 10 detik)
Renew Merespons dengan HTTP 200 Tidak berlaku Tidak berlaku
Suspend Merespons dengan HTTP 200 Tidak berlaku Tidak berlaku
Unsubscribe Merespons dengan HTTP 200 Tidak berlaku Tidak berlaku
Reinstate Merespons dengan HTTP 200 Tidak berlaku Tidak berlaku (api penghapusan panggilan untuk memicu penghapusan jika pemulihan tidak dapat diterima)

Penerbit harus menerapkan webhook di layanan SaaS untuk menjaga status langganan SaaS tetap konsisten dengan sisi Microsoft. Layanan SaaS diperlukan untuk memanggil Get Operation API untuk memvalidasi dan mengotorisasi panggilan webhook dan data payload sebelum mengambil tindakan berdasarkan pemberitahuan webhook. Penerbit harus mengembalikan HTTP 200 ke Microsoft segera setelah panggilan webhook diproses. Nilai ini mengakui bahwa panggilan webhook telah berhasil diterima oleh penerbit.

Penting

Layanan URL webhook harus aktif dan berjalan 24 x 7, dan siap menerima panggilan baru dari Microsoft setiap saat. Microsoft memang memiliki kebijakan coba lagi untuk panggilan webhook (500 coba lagi selama delapan jam), tetapi jika penerbit tidak menerima panggilan dan mengembalikan respons, operasi yang diberitahukan webhook pada akhirnya akan gagal di sisi Microsoft.

Penting

ISV harus menghindari deserialisasi skema Webhook yang ketat. Microsoft berhak memperluas skema di masa mendatang.

Penting

ISV harus memvalidasi Microsoft Entra Token (JWT Token) di titik akhir webhook mereka dari header permintaan. Ini adalah token pembawa standar dan akan memberikan detail ISV tentang siapa pemanggilnya. Cari tahu selengkapnya tentang cara memvalidasi token dalam artikel ini. learn.microsoft.com/azure/active-directory/develop/access-tokens

Contoh payload webhook 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
}

Contoh payload webhook dari peristiwa 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
}

Contoh payload webhook dari peristiwa reinstate langganan:

// 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
}
 

Contoh payload webhook dari peristiwa perpanjangan:

// 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,
}

Contoh payload webhook dari peristiwa yang ditangguhkan:


{
    "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,
}

Contoh payload webhook dari peristiwa berhenti berlangganan:

Ini adalah peristiwa khusus pemberitahuan. Tidak ada pengiriman ke ACK untuk kejadian ini.


{
    "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,
}

Mengamankan Webhook Anda

Anda harus mengamankan Webhook Anda sehingga tidak ada selain titik akhir Microsoft yang melakukan panggilan Webhook tersebut. Anda dapat menggunakan teknologi apa pun untuk mengimplementasikan Webhook Anda, namun implementasi Webhook Anda harus mengikuti pedoman keamanan berikut.

  • Microsoft memanggil Webhook Anda dengan header Otorisasi yang berisi informasi yang diperlukan untuk memvalidasi panggilan. Anda harus mengaktifkan Webhook Agar dapat menerima header Otorisasi. (Jangan tambahkan detail otorisasi atau token keamanan seperti token SAS langsung di URL Webhook. Webhook tersebut mungkin gagal mengambil header Otorisasi yang dikirim Microsoft saat memanggil Webhook Anda).

  • Token Pembawa JWT yang diteruskan di header Otorisasi berisi data berikut dalam payload yang dapat Anda gunakan untuk mengamankan titik akhir Anda.

  • "aud": "ini adalah ID aplikasi Microsoft Entra Identity yang Anda tambahkan ke konfigurasi teknis penawaran Anda di Pusat Mitra Microsoft"

  • "appid" atau "azp": Ini adalah ID sumber daya yang Anda gunakan saat membuat token otorisasi penerbit untuk memanggil API pemenuhan SaaS. Dan tergantung pada pengaturan aplikasi, Anda mungkin melihat nilai ID sumber daya ini baik di "appid" atau "azp". Token memiliki salah satu dari dua klaim dan Anda harus bereaksi sesuai dalam kode Anda.

  • "tid": "ini adalah ID penyewa Microsoft Entra yang Anda tambahkan ke konfigurasi teknis penawaran Anda di Pusat Mitra Microsoft"

  • Anda dapat memeriksa bidang yang diteruskan di atas untuk memastikan panggilan Webhook valid.

Penting

Microsoft akan mulai mengharuskan ISV untuk membuat Webhook mereka dengan cara yang aman dan menerima header Otorisasi. Jika implementasi Webhook Anda saat ini tidak dapat menerima header Otorisasi, maka Anda harus memperbarui Webhook Anda dan mengamankan titik akhir tersebut (menggunakan panduan di atas) untuk menghindari gangguan.

Pengembangan dan pengujian

Untuk memulai proses pengembangan, kami sarankan untuk membuat respons API tiruan oleh penerbit. Tanggapan ini dapat didasarkan pada respons sampel yang disediakan dalam artikel ini.

Ketika penerbit siap untuk pengujian ujung ke ujung:

  • Publikasikan penawaran SaaS ke hadirin pratinjau terbatas dan simpan di tahap pratinjau.
  • Atur harga paket ke nol, untuk menghindari pemicu pengeluaran penagihan aktual saat pengujian. Opsi lain adalah menetapkan harga nonzero dan membatalkan semua pembelian pengujian dalam waktu 24 jam.
  • Pastikan semua alur dipanggil secara ujung ke ujung, untuk mensimulasikan skenario pelanggan yang sebenarnya.
  • Jika mitra ingin menguji alur pembelian dan penagihan penuh, lakukan dengan penawaran yang dihargai di atas $ 0. Pembelian ditagih, dan faktur akan dibuat.

Alur pembelian dapat dipicu dari portal Azure atau situs Microsoft AppSource, bergantung pada di mana penawaran diterbitkan.

TindakanUbah paket,ubahjumlah, dan berhenti berlangganandiuji dari sisi penerbit. Dari sisi Microsoft, berhenti berlangganan dapat dipicu dari portal Azure dan Pusat Admin (portal tempat pembelian Microsoft AppSource dikelola). Ubah jumlah dan paket hanya dapat dipicu dari Pusat Admin.

Dapatkan dukungan

Lihat Dukungan untuk program pasar komersial di Pusat Mitra untuk opsi dukungan penerbit.

Langkah berikutnya