Bagikan melalui


API pengiriman Microsoft Store untuk aplikasi MSI atau EXE

Gunakan API pengiriman Microsoft Store untuk aplikasi MSI atau EXE untuk mengkueri dan membuat pengiriman secara terprogram untuk aplikasi MSI atau EXE untuk akun Pusat Mitra organisasi Anda. API ini berguna jika akun Anda mengelola banyak aplikasi, dan Anda ingin mengotomatiskan dan mengoptimalkan proses pengiriman untuk aset ini. API ini menggunakan Azure Active Directory (Azure AD) untuk mengautentikasi panggilan dari aplikasi atau layanan Anda.

Langkah-langkah berikut menjelaskan proses end-to-end menggunakan API pengiriman Microsoft Store:

  1. Pastikan Anda telah menyelesaikan semua prasyarat.
  2. Sebelum Anda memanggil metode di MICROSOFT Store submission API, dapatkan token akses Azure AD. Setelah mendapatkan token, Anda memiliki waktu 60 menit untuk menggunakan token ini dalam panggilan ke API pengiriman Microsoft Store sebelum token kedaluwarsa. Setelah token kedaluwarsa, Anda dapat menghasilkan token baru.
  3. Panggil API pengiriman Microsoft Store untuk aplikasi MSI atau EXE.

Langkah 1: Selesaikan prasyarat untuk menggunakan API pengiriman Microsoft Store

Sebelum Anda mulai menulis kode untuk memanggil API pengiriman Microsoft Store untuk aplikasi MSI atau EXE, pastikan Anda telah menyelesaikan prasyarat berikut.

  • Anda (atau organisasi Anda) harus memiliki direktori Azure Active Directory dan harus memiliki izin Administrator perusahaan untuk direktori tersebut. Jika sudah menggunakan Microsoft 365 atau layanan bisnis lainnya dari Microsoft, Anda sudah memiliki direktori Azure Active Directory. Jika tidak, Anda dapat membuat Azure AD baru di Pusat Mitra tanpa biaya tambahan.
  • Anda harus mengaitkan aplikasi Azure Active Directory dengan akun Pusat Mitra dan mendapatkan ID penyewa, ID klien, dan kunci. Anda memerlukan nilai-nilai ini untuk mendapatkan token akses Azure Active Directory, yang akan Anda gunakan dalam panggilan ke API pengiriman Microsoft Store.
  • Siapkan aplikasi Anda untuk digunakan dengan API pengiriman Microsoft Store:
    • Jika aplikasi Anda belum ada di Pusat Mitra, Anda harus membuat aplikasi dengan mengirimkan namanya di Pusat Mitra. Anda tidak dapat menggunakan API pengiriman Microsoft Store untuk membuat aplikasi di Pusat Mitra; Anda harus bekerja di Pusat Mitra untuk membuatnya, lalu setelah itu Anda dapat menggunakan API untuk mengakses aplikasi dan membuat pengiriman secara terprogram untuk itu.
    • Sebelum dapat membuat pengiriman untuk aplikasi tertentu menggunakan API ini, Anda harus terlebih dahulu membuat satu pengiriman untuk aplikasi di Pusat Mitra, termasuk menjawab kuesioner peringkat usia. Setelah melakukan ini, Anda akan dapat membuat pengiriman baru secara terprogram untuk aplikasi ini menggunakan API.
    • Jika Anda membuat atau memperbarui pengiriman aplikasi dan Anda perlu menyertakan paket baru, siapkan detail paket.
    • Jika Anda membuat atau memperbarui pengiriman aplikasi dan Perlu menyertakan cuplikan layar atau gambar untuk daftar Toko, siapkan cuplikan layar dan gambar aplikasi.

Cara mengaitkan aplikasi Azure Active Directory dengan akun Pusat Mitra Anda

Sebelum dapat menggunakan API pengiriman Microsoft Store untuk aplikasi MSI atau EXE, Anda harus mengaitkan aplikasi Microsoft Azure AD dengan akun Pusat Mitra Anda, mengambil ID penyewa dan ID klien untuk aplikasi dan membuat kunci. Aplikasi Azure ACTIVE Directory mewakili aplikasi atau layanan tempat Anda ingin memanggil API pengiriman Microsoft Store. Anda memerlukan ID penyewa, ID klien, dan kunci untuk mendapatkan token akses Azure Active Directory yang Anda berikan ke API.

Catatan

Anda hanya perlu melakukan tugas ini satu kali. Setelah memiliki ID penyewa, ID klien, dan kunci, Anda dapat menggunakannya kembali kapan saja Anda perlu untuk membuat token akses Azure Active Directory baru.

  1. Di Pusat Mitra, kaitkan akun Pusat Mitra organisasi dengan direktori Azure Active Directory organisasi Anda.
  2. Selanjutnya, dari halaman Pengguna di bagian Pengaturan akun di Pusat Mitra, tambahkan aplikasi Azure ACTIVE Directory yang mewakili aplikasi atau layanan yang akan Anda gunakan untuk mengakses pengiriman untuk akun Pusat Mitra Anda. Pastikan Anda menetapkan aplikasi ini sebagai peranManajer. Jika aplikasi belum ada di direktori Azure Active Directory, Anda dapat membuat aplikasi Azure Active Directory baru di Pusat Mitra.
  3. Kembali ke halaman Pengguna, klik nama aplikasi Azure Active Directory Anda untuk masuk ke pengaturan aplikasi, dan salin nilai ID Penyewa dan ID Klien.
  4. Untuk menambahkan kunci baru atau Rahasia klien, lihat instruksi berikut atau lihat instruksi untuk mendaftarkan aplikasi melalui Portal Microsoft Azure:

Untuk mendaftarkan aplikasi Anda:

  1. Masuk ke portal Azure.

  2. Jika Anda memiliki akses ke beberapa penyewa, gunakan filter Direktori + langganan di menu atas untuk memilih penyewa tempat Anda ingin mendaftarkan aplikasi.

  3. Cari dan pilih Microsoft Azure Active Directory.

  4. Di bawah Kelola, pilih Pendaftaran aplikasi > Pilih aplikasi Anda.

  5. Pilih Sertifikat & rahasia > Rahasia > klien Rahasia klien baru.

  6. Tambahkan deskripsi untuk rahasia klien Anda.

  7. Pilih kedaluwarsa untuk rahasia atau tentukan masa pakai kustom.

  8. Masa pakai rahasia klien dibatasi hingga dua tahun (24 bulan) atau kurang. Anda tidak dapat menentukan masa pakai kustom lebih dari 24 bulan.

    Catatan

    Microsoft menyarankan agar Anda menetapkan nilai kedaluwarsa kurang dari 12 bulan.

  9. Pilih Tambahkan.

  10. Catat nilai rahasia untuk digunakan dalam kode aplikasi klien Anda. Nilai rahasia ini tidak pernah ditampilkan lagi setelah Anda meninggalkan halaman ini.

Langkah 2: Mendapatkan token akses Azure Active Directory

Sebelum Anda memanggil salah satu metode di API pengiriman Microsoft Store untuk aplikasi MSI atau EXE, Anda harus terlebih dahulu mendapatkan token akses Microsoft Azure AD yang Anda teruskan ke header Otorisasi dari setiap metode di API. Setelah mendapatkan token akses, Anda memiliki waktu 60 menit untuk menggunakan token akses sebelum masa berlakunya habis. Setelah token kedaluwarsa, Anda dapat merefresh token sehingga Anda dapat terus menggunakannya dalam panggilan lebih lanjut ke API.

Untuk mendapatkan token akses, ikuti instruksi di [Service to Service Calls Using Client Credentials]/azure/active-directory/azuread-dev/v1-oauth2-client-creds-grant-flow) untuk mengirim HTTP POST ke https://login.microsoftonline.com/<titik akhir tenant_id>/oauth2/token. Berikut adalah contoh permintaan.

POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8

grant_type=client_credentials
&client_id=<your_client_id>
&client_secret=<your_client_secret>
&scope=https://api.store.microsoft.com/.default

tenant_id Untuk nilai di POST URI dan client_id parameter dan client_secret , tentukan ID penyewa, ID klien, dan kunci untuk aplikasi yang Anda ambil dari Pusat Mitra di bagian sebelumnya. Untuk parameter cakupan, Anda harus menentukan https://api.store.microsoft.com/.default.

Setelah token akses kedaluwarsa, Anda dapat merefreshnya dengan mengikuti instruksi di sini.

Untuk contoh yang menunjukkan cara mendapatkan token akses dengan menggunakan C# atau Node.js, lihat contoh kode untuk API pengiriman Microsoft Store untuk aplikasi MSI atau EXE.

Langkah 3: Menggunakan API pengiriman Microsoft Store

Setelah Anda memiliki token akses Azure ACTIVE Directory, Anda dapat memanggil metode di API pengiriman Microsoft Store untuk aplikasi MSI atau EXE. API mencakup banyak metode yang dikelompokkan ke dalam skenario untuk aplikasi. Untuk membuat atau memperbarui pengiriman, Anda biasanya memanggil beberapa metode dalam urutan tertentu. Untuk informasi tentang setiap skenario dan sintaks setiap metode, lihat bagian berikut:

Catatan

Setelah mendapatkan token akses, Anda memiliki waktu 60 menit untuk memanggil metode di API pengiriman Microsoft Store untuk aplikasi MSI atau EXE sebelum token kedaluwarsa.

URL Dasar

URL dasar untuk MICROSOFT Store Submission API untuk exe atau aplikasi MSI adalah: https://api.store.microsoft.com

Kontrak API

Dapatkan API Metadata Pengiriman Draf Saat Ini

Mengambil metadata di setiap modul (daftar, properti, atau ketersediaan) di bawah pengiriman draf saat ini.

Jalur [Semua Modul]: /submission/v1/product/{productId}/metadata?languages={languages}&includelanguagelist={true/false}
Jalur [Modul Tunggal]: /submission/v1/product/{productId}/metadata/{moduleName}?languages={languages}&includelanguagelist={true/false}
Metode: GET

Parameter Jalur

Pengaturan Deskripsi
ID produk ID Pusat Mitra produk
nama modul Modul Pusat Mitra – daftar, properti, atau ketersediaan

Parameter Kueri:

Pengaturan Deskripsi
bahasa Opsional Filter bahasa daftar sebagai string yang dipisahkan koma [batas hingga 200 Bahasa].

Jika tidak ada, 200 metadata bahasa daftar pertama yang tersedia akan diambil. [ misalnya, "en-us, en-gb"].
daftarBahasaDimasukkan Boolean opsional – jika true, mengembalikan daftar bahasa daftar tambahan dan status kelengkapannya.

Header yang Diperlukan

Kepala Halaman Nilai
Authorization: Bearer <Token> ID aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Header Respons

Kepala Halaman Nilai
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan Tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
dukungan aksesibilitas Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Ketentuan Lisensi Tambahan string
ketersediaan Objek Data modul ketersediaan
kategori string Lihat daftar kategori di bawah ini
catatan sertifikasi string
kode string Kode kesalahan Pesan
informasi kontak string
hak cipta string
bergantungPadaDriverAtauNT Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
deskripsi string
dikembangkan oleh string
kemampuan penemuan string [DAPAT DITEMUKAN, DEEPLINK_ONLY]
enableInFutureMarkets Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
freeTrial string [TIDAK_ADA_UJI_C
jenisItemPerangkatKeras string
Apakah Kebijakan Privasi Diperlukan Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
direkomendasikan Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
diharuskan Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
apakahFiturSistemDiperlukan Array objek
bahasa string Lihat daftar bahasa di bawah ini
Daftar Array objek Mencantumkan data modul untuk setiap bahasa
pasar Array string Lihat daftar pasar di bawah ini
pesan string Deskripsi kesalahan
perangkat keras minimal string
persyaratan minimum string
penAndInkSupport Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
harga string [GRATIS, FREEMIUM, LANGGANAN, BERBAYAR]
urlKebijakanPrivasi string
deklarasiProduk Objek
fiturProduk Array string
properti Objek Data modul properti
perangkat keras yang direkomendasikan string
persyaratan yang direkomendasikan string
responseData Objek Berisi Payload respons aktual untuk Permintaan
persyaratan Array objek
Istilah Pencarian Array string
Deskripsi Singkat string
subkategori string Lihat daftar sub-kategori di bawah ini
InformasiKontakDukungan string
rincianPersyaratanSistem Array objek
sasaran string Entitas tempat Kesalahan berasal
situs web string
Apa yang Baru string

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "availability":{
            "markets": ["US"],
            "discoverability": "DISCOVERABLE",
            "enableInFutureMarkets": true,
            "pricing": "PAID",
            "freeTrial": "NO_FREE_TRIAL"
        },
        "properties":{
            "isPrivacyPolicyRequired": true,
            "privacyPolicyUrl": "http://contoso.com",
            "website": "http://contoso.com",
            "supportContactInfo": "http://contoso.com",
            "certificationNotes": "Certification Notes",
            "category": "DeveloperTools",
            "subcategory": "Database",
            "productDeclarations": {
                "dependsOnDriversOrNT": false,
                "accessibilitySupport": false,
                "penAndInkSupport": false
            },
            "isSystemFeatureRequired": [
                {
                    "isRequired": true,
                    "isRecommended": false,
                    "hardwareItemType": "Touch"
                },
                {
                    "isRequired": true,
                    "isRecommended": false,
                    "hardwareItemType": "Keyboard"
                },
                {
                    "isRequired": false,
                    "isRecommended": false,
                    "hardwareItemType": "Mouse"
                },
                {
                    "isRequired": false,
                    "isRecommended": false,
                    "hardwareItemType": "Camera"
                },
                {
                    "isRequired": false,
                    "isRecommended": false,
                    "hardwareItemType": "NFC_HCE"
                },
                {
                    "isRequired": false,
                    "isRecommended": false,
                    "hardwareItemType": "NFC_Proximity"
                },
                {
                    "isRequired": false,
                    "isRecommended": false,
                    "hardwareItemType": "Bluetooth_LE"
                },
                {
                    "isRequired": false,
                    "isRecommended": false,
                    "hardwareItemType": "Telephony"
                },
                {
                    "isRequired": false,
                    "isRecommended": false,
                    "hardwareItemType": "Microphone"
                }
            ],
            "systemRequirementDetails": [
                {
                    "minimumRequirement": "1GB",
                    "recommendedRequirement": "4GB",
                    "hardwareItemType": "Memory"
                },
                {
                    "minimumRequirement": "",
                    "recommendedRequirement": "",
                    "hardwareItemType": "DirectX"
                },
                {
                    "minimumRequirement": "",
                    "recommendedRequirement": "",
                    "hardwareItemType": "Video_Memory"
                },
                {
                    "minimumRequirement": "",
                    "recommendedRequirement": "",
                    "hardwareItemType": "Processor"
                },
                {
                    "minimumRequirement": "",
                    "recommendedRequirement": "",
                    "hardwareItemType": "Graphics"
                }
            ]
        },
        "listings":[{
            "language": "en-us",
            "description": "Description",
            "whatsNew": "What's New",
            "productFeatures": ["Feature 1"],
            "shortDescription": "Short Description",
            "searchTerms": ["Search Ter 1"],
            "additionalLicenseTerms": "License Terms",
            "copyright": "Copyright Information",
            "developedBy": "Developer Details",
            "sortTitle": "Product 101",
            "requirements": [
                {
                    "minimumHardware": "Pentium4",
                    "recommendedHardware": "Corei9"
                }
            ],
            "contactInfo": "contactus@contoso.com"               
        }],      
        "listingLanguages": [{"language":"en-us", "isComplete": true}]
    }
}

Memperbarui API Metadata Pengiriman Draf Saat Ini

Memperbarui metadata di setiap Modul di bawah pengiriman draf. Pemeriksaan API

  • Untuk Pengiriman Aktif. Jika Ada, Gagal dengan Pesan Kesalahan.
  • Jika semua modul dalam status siap untuk mengizinkan operasi Simpan Draf.
  • Setiap bidang dalam pengiriman divalidasi sesuai persyaratan Penyimpanan
  • Aturan validasi Detail Persyaratan Sistem:
    • Nilai yang Diizinkan dalam hardwareItemType = Memori: 300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB
    • Nilai yang Diizinkan dalam hardwareItemType = DirectX: DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12
    • Nilai yang Diizinkan dalam hardwareItemType = Video_Memory: 1GB, 2GB, 4GB, 6GB

Jalur [Pembaruan Modul Lengkap]: /submission/v1/product/{productId}/metadata
Metode: PUT

Jalur [Module Patch Update]: /submission/v1/product/{productId}/metadata
Metode: PATCH

Perilaku API

Dalam kasus API Pembaruan Modul Lengkap – seluruh Data Modul perlu ada dalam Permintaan untuk pembaruan lengkap setiap bidang. Bidang apa pun yang tidak ada dalam Permintaan, nilai defaultnya digunakan untuk menimpa nilai saat ini untuk Modul tertentu tersebut.
Dalam kasus PATch Module Update API – hanya bidang yang akan diperbarui yang perlu ada dalam Permintaan. Nilai bidang dari Permintaan ini akan menimpa nilai yang ada, menjaga semua bidang lain yang tidak ada dalam Permintaan, sama seperti saat ini untuk Modul tertentu.

Parameter Jalur

Pengaturan Deskripsi
ID produk ID Pusat Mitra produk

Header yang Diperlukan

Kepala Halaman Nilai
Authorization: Bearer <Token> ID aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Parameter Permintaan

Nama Tipe Deskripsi
ketersediaan Objek Objek untuk menyimpan metadata Modul Ketersediaan
pasar Array string Diperlukan Lihat daftar pasar di bawah ini
kemampuan penemuan string Diperlukan [DAPAT DITEMUKAN, DEEPLINK_ONLY]
enableInFutureMarkets Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan
harga string Diperlukan [GRATIS, FREEMIUM, LANGGANAN, BERBAYAR]
freeTrial string Diperlukan jika Harga BERBAYAR atau LANGGANAN [NO_FREE_TRIAL, FREE_TRIAL]
properti Objek Objek untuk menyimpan metadata Modul Properti
Apakah Kebijakan Privasi Diperlukan Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan
urlKebijakanPrivasi string Diperlukan jika isPrivacyPolicyRequired = true Harus berupa URL yang valid
situs web string Harus berupa URL yang valid
InformasiKontakDukungan string Harus berupa URL atau alamat Email yang valid
catatan sertifikasi string Batas Karakter yang Direkomendasikan = 2000
kategori string Diperlukan Lihat daftar kategori di bawah ini
subkategori string Diperlukan Lihat daftar sub-kategori di bawah ini
deklarasiProduk Objek Diperlukan
apakahFiturSistemDiperlukan Array objek [Sentuh, Keyboard, Mouse, Kamera, NFC_HCE, NFC_Proximity, Bluetooth_LE, Telepon, Mikrofon]
diharuskan Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan
direkomendasikan Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan
jenisItemPerangkatKeras string Diperlukan
rincianPersyaratanSistem Array objek [Prosesor, Grafis, Memori, DirectX, Video_Memory]
persyaratan minimum string Diperlukan Untuk systemRequirementsText, MaxLength = 200

Nilai yang Diizinkan dalam hardwareItemType = Memori: [300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB]

Nilai yang Diizinkan dalam hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12]

Nilai yang Diizinkan dalam hardwareItemType = Video_Memory: [1GB, 2GB, 4GB, 6GB]
persyaratan yang direkomendasikan string Diperlukan Untuk systemRequirementsText, MaxLength = 200

Nilai yang Diizinkan dalam hardwareItemType = Memori: [300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB]

Nilai yang Diizinkan dalam hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12]

Nilai yang Diizinkan dalam hardwareItemType = Video_Memory: [1GB, 2GB, 4GB, 6GB]
bergantungPadaDriverAtauNT Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan
dukungan aksesibilitas Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan
penAndInkSupport Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan
Daftar Objek Objek untuk mencantumkan data modul untuk satu bahasa
bahasa string Diperlukan Lihat daftar bahasa di bawah ini
deskripsi string Batas Karakter yang Diperlukan = 10000
Apa yang Baru string Batas karakter = 1500
fiturProduk Array String 200 karakter per fitur; Hingga 20 fitur
Deskripsi Singkat string Batas karakter = 1000
Istilah Pencarian Array String 30 karakter per istilah pencarian; Hingga 7 istilah pencarian

21 kata unik TOTAL di semua istilah pencarian
Ketentuan Lisensi Tambahan string Batas Karakter yang Diperlukan = 10000
hak cipta string Batas karakter = 200
dikembangkan oleh string Batas karakter = 255
persyaratan Array objek 200 karakter per item; TOTAL hingga 11 item antara minimum dan disarankan]
minimumHardware string Batas karakter = 200
perangkat keras yang direkomendasikan string Batas karakter = 200
informasi kontak string Batas karakter = 200
daftar yang akan ditambahkan Array string Lihat daftar bahasa di bawah ini
daftarUntukDihapus Array string Lihat daftar bahasa di bawah ini

Pasar

Pasar Singkatan
Afganistan AF
Albania AL (Angkatan Laut)
Aljazair DZ
Samoa Amerika Amerika Serikat
Andorra IKLAN
Angola AO
Anguilla Kecerdasan Buatan (AI)
Antarktika AQ
Antigua dan Barbuda AG
Argentina AR (Augmented Reality)
Armenia pagi
Aruba AW
Australia AU
Austria PADA
Azerbaijan AZ
Bahama BS
Bahrain Bahrain
Bangladesh BD
Barbados BB
Belarus OLEH
Belgia ADA
Belize BZ
Benin BJ
Bermuda BM
Bhutan BT
Republik Bolivarian Venezuela VE
Bolivia BO
Bonaire BQ
Bosnia dan Herzegovina Bachelor of Arts
Botswana BW
Pulau Bouvet BV
Brasil Brasil
Wilayah Inggris di Samudra Hindia IO
Kepulauan Virgin Britania Raya VG
Brunei Darussalam BN
Bulgaria BG
Burkina Faso Pacar
Burundi Bank Indonesia
Kamboja KH
Kamerun cm
Kanada OS
Tanjung Verde Daftar Riwayat Hidup
Kepulauan Cayman KY
Republik Afrika Tengah CF
Cad TD
Cile CL
Tiongkok Cina
Pulau Christmas CX
Kepulauan Cocos (Keeling) CC
Kolombia Karbon Monoksida
Komoro KILOMETER
Kongo CG
Kongo (DRC) CD
Kepulauan Cook CK
Kosta Rika CR
Kroasia Sumber Daya Manusia
Curaçao CW
Siprus CY
Republik Ceko CZ
Pantai Gading Integrasi Berkelanjutan (CI)
Denmark DK
Jibuti DJ
Dominika DM
Republik Dominika MELAKUKAN
Ekuador Komisi Eropa
Mesir Misalnya
El Salvador SV
Guinea Ekuatorial GQ
Eritrea IGD
Estonia EE
Etiopia ET
Kepulauan Falkland FK
Kepulauan Faroe FO
Fiji FJ
Finlandia FI
Prancis FR
Guyana Prancis Pacar perempuan
Polinesia Prancis PF
Tanah Prancis Selatan dan Antartika TF
Gabon Majelis Umum
Gambia Manajer Umum
Georgia GE
Jerman Jerman
Ghana GH
Gibraltar Indeks Glikemik
Yunani GR
Grinlandia GL
Grenada GD
Guadeloupe dokter umum
Guam GU
Guatemala GT
Guernsey GG
Guinea GN
Guinea-Bissau GW
Guyana GY
Haiti HT
Pulau Heard dan Kepulauan McDonald HM
Vatikan VA
Honduras HN
Hong Kong, Kawasan Administratif Khusus (SAR) Hong Kong
Hungaria HU
Islandia Negara Islam
India DI
Indonesia Nomor Identitas
Irak IQ
Irlandia IE (Internet Explorer)
Israel Israel
Italia TI
Jamaika JM
Jepang JP
Jersey JE
Yordania JO
Kazakstan KZ
Kenya KE
Kiribati KI
Korea Selatan KR
Kuwait kW
Kirgistan kg
Laos LA
Latvia Latvia
Libanon LB
Lesotho LS
Liberia LR
Libya LY
Liechtenstein LI
Lituania LT
Luksemburg LU
Makau SAR MO
Makedonia Utara MK
Madagaskar MG
Malawi megawatt
Malaysia Milik saya
Maladewa MV
Mali ML
Malta MT
Pulau Man IM
Kepulauan Marshall MH
Martinik MQ
Mauritania Tuan
Mauritius MU
Mayotte YouTube
Meksiko MX
Mikronesia FM
Moldova MD
Monako Pembawa Acara (MC)
Mongolia MN
Montenegr - ME
Montserrat MS
Maroko Magister Seni
Mozambik MZ
Myanmar MM (milimeter)
Namibia NA
Nauru NR
Nepal NP
Belanda Belanda
Kaledonia Baru NC
Selandia Baru NZ
Nikaragua NI
Niger NE
Nigeria NG
Niue NU
Kepulauan Norfolk NF
Kepulauan Mariana Utara Anggota Parlemen
Norwegia TIDAK
Oman OM
Pakistan PK
Palau Tahanan perang
Otoritas Nasional Palestina P.S.
Panama PA
Papua Nugini PG
Paraguay PY
Peru PE
Filipina PH
Kepulauan Pitcairn PN
Polandia PL
Portugal PT
Qatar Penjaminan Kualitas (QA)
Reuni KEMBALI
Rumania RO
Rusia Rusia
Rwanda RW
Saint Barthélemy BL
Saint Helena, Ascension dan Tristan da Cunha SH
Saint Kitts dan Nevis KN
Saint Lucia LC
Saint Martin (Bagian Prancis) MF
Saint Pierre dan Miquelon Perdana Menteri
Saint Vincent dan Grenadines VC
Samoa WS
San Marino SM
Arab Saudi SA
Senegal SN
Serbia dan Montenegro RS
Seychelles SC
Sierra Leone SL
Singapura Singapura
Sint Maarten (Bagian Belanda) SX
Slovakia SK
Slovenia Sistem Internasional (SI)
Kepulauan Solomon SB
Somalia Jadi
Afrika Selatan Afrika Selatan
Georgia Selatan dan Kepulauan Sandwich Selatan GS
Spanyol ES
Sri Lanka LK
Suriname SR
Svalbard dan Jan Mayen SJ
Swaziland SZ
Swedia SE
Swiss CH
São Tomé dan Príncipe ST
Taiwan Taiwan
Tajikistan TJ
Tanzania TZ
Thailand TH
Timor-Leste TL
Tog - TG
Tokelau Taman Kanak-kanak
Tonga KE
Trinidad dan Tobag - TT
Tunisia TN
Türkiye TR
Turkmenistan TM
Kepulauan Turks dan Caicos TC
Tuvalu TELEVISI
Kepulauan Terluar Kecil A.S. UM
Kepulauan Virgin A.S. VI
Uganda UG
Ukraina UA
Uni Emirat Arab Æ
Inggris Raya GB
Amerika Serikat Amerika Serikat
Uruguay UY
Uzbekistan UZ
Vanuatu VU
Vietnam VN
Wallis dan Futuna WF
Yaman YA
Zambia ZM
Zimbabwe ZW
Kepulauan Åland Kapak

Kategori dan Sub-kategori

Kategori Subkategori
BooksAndReference EReader, Fiksi, Nonfiksi, Referensi
Bisnis AkuntansiDanKeuangan, Kolaborasi, CRM, DataDanAnalisis, ManajemenFile, InventarisDanLogistik, LegalDanHR, ManajemenProyek, DesktopJarakJauh, PenjualanDanPemasaran, WaktuDanPengeluaran
DeveloperTools Database, DesignTools, DevelopmentKits, Jaringan, ReferenceAndTraining, Server, Utilitas, WebHosting
Pendidikan BukuPendidikanDanReferensi, PembelajaranDini, AlatInstruksional, Bahasa, BantuanBelajar
Hiburan (Tidak Ada)
FoodAndDining (Tidak Ada)
Pemerintahan dan Politik (Tidak Ada)
Kesehatan dan Kebugaran (Tidak Ada)
KidsAndFamily BukuDanRujukanAnakDanKeluarga, HiburanAnakDanKeluarga, HobiDanMainan, OlahragaDanKegiatan, PerjalananAnakDanKeluarga
Gaya hidup Otomotif, DYI, HomeAndGarden, Hubungan, SpecialInterest, StyleAndFashion
Medis (Tidak Ada)
Desain Multimedia IlustrasiAndGraphicDesign, MusicProduction, PhotoAndVideoProduction
Musik (Tidak Ada)
NavigationAndMaps (Tidak Ada)
BeritaDanCuaca Berita, Cuaca
Keuangan Pribadi PerbankanDanInvestasi, AnggaranDanPajak
Personalisasi RingtonesAndSounds, tema, WallpaperAndLockScreens
PhotoAndVideo (Tidak Ada)
Produktivitas (Tidak Ada)
Keamanan PCProtection, PersonalSecurity
Berbelanja (Tidak Ada)
Sosial (Tidak Ada)
Olahraga (Tidak Ada)
Perjalanan KotaGuides, Hotel-hotel
UtilitasDanAlat BackupAndManage, FileManager

Bahasa

Nama bahasa Kode bahasa yang didukung
Afrika af, af-za
Albania sq, sq-al
Amharik pagi, am-et
Armenia hy, hy-am
Assam sebagai, as-in
Azerbaijan az-arab, az-arab-az, az-cyrl, az-cyrl-az, az-latn, az-latn-az
Basque (Bahasa Basque) Uni Eropa, eu-es
Belarusia menjadi, be-by
Bengali bn, bn-bd, bn-in
Bosnia bs, bs-cyrl, bs-cyrl-ba, bs-latn, bs-latn-ba
Bulgaria bg, bg-bg
Katalan ca, ca-es, ca-es-valensia
Cherokee chr-cher, chr-cher-us, chr-latn
Tionghoa (Aksara Sederhana) zh-Hans, zh-cn, zh-hans-cn, zh-sg, zh-hans-sg
Tionghoa (Aksara Tradisional) zh-Hant, zh-hk, zh-mo, zh-tw, zh-hant-hk, zh-hant-mo, zh-hant-tw, zh-mo, zh-tw, zh-hant-hk, zh-hant-mo, zh-hant-tw
Kroasia jam, jam-jam, hr-ba
Cheska cs, cs-cz
Dansk da, da-dk
Dari prs, prs-af, prs-arab
Belanda nl, nl-nl, nl-be
Inggris en, en-au, en-ca, en-gb, en-ie, en-in, en-nz, en-sg, en-us, en-za, en-bz, en-hk, en-id, en-jm, en-kz, en-mt, en-my, en-ph, en-pk, en-tt, en-vn, en-zw
Esti dan, et-ee
Filipina - fil, fil-latn, fil-ph
Suomi fi, fi-fi
Prancis fr, fr-be , fr-ca , fr-ch , fr-fr, fr-lu, fr-cd, fr-ci, fr-cm, fr-ht, fr-ma, fr-mc, fr-ml, fr-re, frc-latn, frp-latn
Galisia gl, gl-es
Georgia ka, ka-ge
Jerman de, de-at, de-ch, de-de, de-lu, de-li
Yunani el, el-gr
Gujarat gu, gu-in
Hausa ha, ha-latn, ha-latn-ng
Ibrani dia, he-il
Bahasa Hindi hai, hi-in
Hungaria hu, hu-hu
Islandia adalah, is-is
Igb - ig-latn, ig-ng
Indonesia id, id-id
Inuktitut (Latin) iu-cans, iu-latn, iu-latn-ca
Irlandia ga, ga-ie
isiXhosa xh, xh-za
isiZulu zu, zu-za
Italia itu, it-it, it-ch
Jepang ya , ja-jp
Kannada kn, kn-in
Bahasa Kazak kk, kk-kz
Khmer km, km-kh
K'iche' quc-latn, qut-gt, qut-latn
Kinyarwanda rw, rw-rw
Kiswahili sw, sw-ke
Konkani kok, kok-in
Korea ko, ko-kr
Kurdi ku-arab, ku-arab-iq
Kirgiz ky-kg, ky-cyrl
Laos Halo, lo-la
Latvi lv, lv-lv
Lituavi lt, lt-lt
Luksemburg lb, lb-lu
Makedonia mk, mk-mk
Melayu ms, ms-bn, ms-my
Malayalam ml, ml-in
Malta mt, mt-mt
Maori mi, mi-latn, mi-nz
Marathi mr, mr-in
Bahasa Mongolia (Sirilik) mn-cyrl, mn-mong, mn-mn, mn-phag
Nepal ne, ne-np
Norwegia nb, nb-no, nn, nn-no, tidak, no-no
Odia atau, atau
Farsi fa, fa-ir
Polski pl, pl-pl
Portugis (Brasil) pt-br
Portugis (Portugal) pt, pt-pt
Punjabi pa, pa-arab, pa-arab-pk, pa-deva, pa-in
Quechua quz, quz-bo, quz-ec, quz-pe
Rumania ro, ro-ro
Rusia ru , ru-ru
Gaelik Skotlandia gd-gb, gd-latn
Serbia (Latin) sr-Latn, sr-latn-cs, sr, sr-latn-ba, sr-latn-me, sr-latn-rs
Serbia (Sirilik) sr-cyrl, sr-cyrl-ba, sr-cyrl-cs, sr-cyrl-me, sr-cyrl-rs
Sesotho sa Leboa nso, nso-za
Setswana tn, tn-bw, tn-za
Sindhi sd-arab, sd-arab-pk, sd-deva
Sinhala si, si-lk
Bahasa Slowakia sk, sk-sk
Sloven sl, sl-si
Spanyol es, es-cl, es-co, es-es, es-mx, es-ar, es-bo, es-cr, es-do, es-ec, es-gt, es-hn, es-ni, es-pa, es-pe, es-pr, es-py, es-sv, es-us, es-uy, es-ve
Swedia sv, sv-se, sv-fi
Tajik (Sirilik) tg-arab, tg-cyrl, tg-cyrl-tj, tg-latn
Tamil Oke, ta-in
Tatar tt-arab, tt-cyrl, tt-latn, tt-ru
Telugu te, te-in
Thailand th, th-th
Tigrinya ti, ti-et
Turki tr, tr-tr
etnis Turkmen tk-cyrl, tk-latn, tk-tm, tk-latn-tr, tk-cyrl-tr
Ukraina Inggris, uk-ua
Bahasa Urdu Anda, your-pk
Suku Uighur ug-arab, ug-cn, ug-cyrl, ug-latn
Uzbekistan (Latin) uz, uz-cyrl, uz-latn, uz-latn-uz
Vietnam vi, vi-vn
Wales cy, cy-gb
Wolof wo, wo-sn
Yoruba yo-latn, yo-ng

Permintaan Sampel

{
    "availability":{
        "markets": ["US"],
        "discoverability": "DISCOVERABLE",
        "enableInFutureMarkets": true,
        "pricing": "PAID",
        "freeTrial": "NO_FREE_TRIAL"
    },
    "properties":{
        "isPrivacyPolicyRequired": true,
        "privacyPolicyUrl": "http://contoso.com",
        "website": "http://contoso.com",
        "supportContactInfo": "http://contoso.com",
        "certificationNotes": "Certification Notes",
        "category": "DeveloperTools",
        "subcategory": "Database",
        "productDeclarations": {
            "dependsOnDriversOrNT": false,
            "accessibilitySupport": false,
            "penAndInkSupport": false
        },
        "isSystemFeatureRequired": [
        {
            "isRequired": true,
                "isRecommended": false,
                "hardwareItemType": "Touch"
            },
            {
                "isRequired": true,
                "isRecommended": false,
                "hardwareItemType": "Keyboard"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Mouse"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Camera"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "NFC_HCE"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "NFC_Proximity"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Bluetooth_LE"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Telephony"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Microphone"
            }
        ],
        "systemRequirementDetails": [
            {
                "minimumRequirement": "1GB",
                "recommendedRequirement": "4GB",
                "hardwareItemType": "Memory"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "DirectX"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "Video_Memory"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "Processor"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "Graphics"
            }
        ]
    },
    "listings":{
        "language": "en-us",
        "description": "Description",
        "whatsNew": "What's New",
        "productFeatures": ["Feature 1"],
        "shortDescription": "Short Description",
        "searchTerms": ["Search Ter 1"],
        "additionalLicenseTerms": "License Terms",
        "copyright": "Copyright Information",
        "developedBy": "Developer Details",
        "sortTitle": "Product 101",
        "requirements": [
            {
                "minimumHardware": "Pentium4",
                "recommendedHardware": "Corei9"
            }
        ],
        "contactInfo": "contactus@contoso.com"               
    },      
    "listingsToAdd": ["en-au"],
    "listingsToRemove": ["en-gb"]
}

Header Respons

Kepala Halaman Nilai
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan Tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat Kesalahan berasal
responseData Objek Berisi Payload respons aktual untuk Permintaan
URL pemungutan suara string URL Polling untuk mendapatkan status Pengiriman Yang Sedang Berlangsung
IDPengajuanBerlangsung string Id Pengiriman dari Pengiriman yang Sudah Berlangsung

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    } 
}

Dapatkan API Paket Draf Saat Ini

Mengambil detail paket di bawah pengiriman draf saat ini.

Jalur [Semua Paket]: /submission/v1/product/{productId}/packages
Metode: GET

Jalur [Paket Tunggal]: /submission/v1/product/{productId}/packages/{packageId}
Metode: GET

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk
packageId ID unik paket yang akan diambil

Header yang Diperlukan

Kepala Halaman Nilai
Authorization: Bearer <Token> Menggunakan ID aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Header Respons

Kepala Halaman Nilai
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar kesalahan atau pesan peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
paket Array objek Objek untuk menyimpan data modul paket
packageId string
packageUrl string
bahasa Array string
Arsitektur Array string [Netral, X86, X64, Arm, Arm64]
isSilentInstall Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Ini harus ditandai sebagai true jika alat penginstal Anda berjalan dalam mode senyap tanpa memerlukan sakelar atau false lainnya
installerParameters string
genericDocUrl string
detailKesalahan Array objek
skenarioKesalahan string
errorScenarioDetails Array objek
nilaiKesalahan string
errorUrl string
jenis paket string

Respons Sampel

{   
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
    }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData":{
        "packages":[{
            "packageId": "pack0832",
            "packageUrl": "https://www.contoso.com/downloads/1.1/setup.exe",
            "languages": ["en-us"],
            "architectures": ["X86"],
            "isSilentInstall": true,
            "installerParameters": "/s",
            "genericDocUrl": "https://docs.contoso.com/doclink",
            "errorDetails": [{
                "errorScenario": "rebootRequired",
                "errorScenarioDetails": [{
                    "errorValue": "ERR001001",
                    "errorUrl": "https://errors.contoso.com/errors/ERR001001"
                }]
            }],
            "packageType": "exe",
        }]
    }
}

Perbarui API Paket Draf Saat Ini

Memperbarui detail paket di bawah pengiriman draf saat ini.

Jalur [Pembaruan Modul Lengkap]: /submission/v1/product/{productId}/packages
Metode: PUT

Jalur [Pembaruan Patch Paket Tunggal]: /submission/v1/product/{productId}/packages/{packageId}
Metode: PATCH

Perilaku API

Dalam kasus API Pembaruan Modul Penuh - seluruh data paket perlu ada dalam permintaan untuk pembaruan penuh dari setiap bidang. Bidang apa pun yang tidak ada dalam permintaan, nilai defaultnya digunakan untuk menimpa nilai saat ini untuk modul tertentu tersebut. Ini menghasilkan penimpaan semua paket yang ada dengan sekumpulan paket baru dari permintaan. Ini akan mengakibatkan regenerasi Id Paket dan pengguna harus memanggil GET Packages API untuk Id Paket terbaru.

Dalam kasus API Pembaruan Patch Paket Tunggal – hanya bidang yang akan diperbarui untuk paket tertentu yang perlu ada dalam permintaan. Nilai bidang dari permintaan ini akan menimpa nilai yang ada, menyimpan semua bidang lain yang tidak ada dalam permintaan, sama seperti saat ini untuk paket tertentu tersebut. Paket lain dalam set tetap apa adanya.

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk
packageId ID unik paket

Header yang Diperlukan

Kepala Halaman Nilai
Authorization: Bearer <Token> Menggunakan ID aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Parameter Permintaan

Nama Tipe Deskripsi
paket Array Objek Objek untuk menyimpan data Modul Paket [Hanya Diperlukan untuk Pembaruan Modul Penuh]
packageUrl string Diperlukan
bahasa Array string Diperlukan
Arsitektur Array string Diperlukan Harus berisi arsitektur tunggal - Netral, X86, X64, Arm, Arm64
isSilentInstall Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Diperlukan Ini harus ditandai sebagai true jika alat penginstal Anda berjalan dalam mode senyap tanpa memerlukan sakelar atau false lainnya
installerParameters string Diperlukan jika isSilentInstall salah
genericDocUrl string Diperlukan jika packageType adalah exe Link ke dokumen yang berisi detail kode kesalahan kustom untuk penginstal jenis EXE
detailKesalahan Array Objek Metadata untuk menyimpan kode kesalahan kustom dan detail untuk Penginstal jenis EXE.
skenarioKesalahan string Identifikasi skenario kesalahan tertentu. [instalasiDibatalkanOlehPengguna, aplikasiSudahAda, instalasiSedangBerlangsung, ruangDiskPenuh, perluRestart, kegagalanJaringan, paketDitolakSelamaInstalasi, instalasiBerhasil, lain-lain]
errorScenarioDetails Array Objek
nilaiKesalahan string Kode kesalahan yang dapat ada selama Penginstalan
URL kesalahan string URL untuk memiliki detail tentang kesalahan
jenis paket string Diperlukan [exe, msi]

Permintaan Sampel [Pembaruan Modul Lengkap]

{
    "packages":[{
        "packageUrl": "https://www.contoso.com/downloads/1.1/setup.exe",
        "languages": ["en-us"],
        "architectures": ["X86"],
        "isSilentInstall": true,
        "installerParameters": "/s",
        "genericDocUrl": "https://docs.contoso.com/doclink",
        "errorDetails": [{
            "errorScenario": "rebootRequired",
            "errorScenarioDetails": [{
                "errorValue": "ERR001001",
                "errorUrl": "https://errors.contoso.com/errors/ERR001001"
            }]
        }],
        "packageType": "exe",
    }]
}

Permintaan Sampel [Pembaruan Patch Paket Tunggal]

{
    "packageUrl": "https://www.contoso.com/downloads/1.1/setup.exe",
    "languages": ["en-us"],
    "architectures": ["X86"],
    "isSilentInstall": true,
    "installerParameters": "/s",
    "genericDocUrl": "https://docs.contoso.com/doclink",
    "errorDetails": [{
        "errorScenario": "rebootRequired",
        "errorScenarioDetails": [{
            "errorValue": "ERR001001",
            "errorUrl": "https://errors.contoso.com/errors/ERR001001"
        }]
    }],
    "packageType": "exe",
}

Header Respons

Kepala Halaman Nilai
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek [Daftar pesan kesalahan atau peringatan jika ada]
kode string Kode Kesalahan Pesan
pesan string Deskripsi Kesalahan
sasaran string Entitas tempat Kesalahan berasal
responseData Objek
URL pemungutan suara string [URL Polling untuk mendapatkan Status Pengiriman jika ada Pengiriman yang Sudah Berlangsung]
IDPengajuanBerlangsung string [ID Pengiriman dari Pengiriman yang Sudah Berlangsung]

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    } 
}

Commit Packages API

Menerapkan kumpulan Paket baru yang diperbarui menggunakan API Pembaruan Paket di bawah pengiriman draf saat ini. API ini mengembalikan URL Polling untuk melacak Unggahan Paket.

Jalur: /submission/v1/product/{productId}/packages/commit
Metode: POST

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk

Header yang Diperlukan

Kepala Halaman Nilai
Authorization: Bearer <Token> Menggunakan ID Aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Header Respons

Kepala Halaman Nilai
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek [Daftar pesan kesalahan atau peringatan jika ada]
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
URL pemungutan suara string [URL Polling untuk mendapatkan status Status Unggahan atau Pengiriman Paket jika ada Pengiriman yang Sudah Berlangsung]
IDPengajuanBerlangsung string [Id Pengiriman dari Pengiriman yang Sudah Berlangsung]

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/status",
        "ongoingSubmissionId": ""
    } 
}

Dapatkan API Aset Daftar Draf Saat Ini

Mengambil detail aset daftar di bawah pengiriman draf saat ini.

Jalur: /submission/v1/product/{productId}/listings/assets?languages={languages}
Metode: GET

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk

Parameter Kueri:

Nama Deskripsi
bahasa [Opsional] Bahasa daftar memfilter sebagai string yang dipisahkan koma [batas hingga 200 bahasa]. Jika tidak ada, 200 data aset bahasa daftar pertama yang tersedia akan diambil. (misalnya, "en-us, en-gb")

Header yang Diperlukan

Kepala Halaman Nilai
Authorization: Bearer <Token> Menggunakan ID Aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Header Respons

Kepala Halaman Nilai
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
daftarAset Array objek Mencantumkan detail aset untuk setiap bahasa
bahasa string
storeLogos Array objek
cuplikan layar Array objek
Id string
assetUrl string Harus berupa URL yang valid
ukuran gambar Objek
lebar Bilangan bulat
tinggi Bilangan bulat

Respons Sampel

{   
"isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData":{
        "listingAssets": [{
            "language": "en-us",
            "storeLogos": [
                {
                    "id": "1234567890abcdefgh",
                    "assetUrl": "https://contoso.com/blob=1234567890abcdefgh",
                    "imageSize": {
                        "width": 2160,
                        "height": 2160
                    }
                }
            ],
            "screenshots": [
                {
                    "id": "1234567891abcdefgh",
                    "assetUrl": "https://contoso.com/blob=1234567891abcdefgh",
                    "imageSize": {
                        "width": 2160,
                        "height": 2160
                    }
                }
            ]
        }]
    }
}

Membuat API Aset Daftar

Membuat Unggahan Aset Daftar baru di bawah pengiriman draf saat ini.

Pembaruan aset Daftar

MICROSOFT Store Submission API untuk EXE atau aplikasi MSI menggunakan URL SAS yang dihasilkan runtime ke Blob Stores untuk setiap unggahan aset gambar individu, bersama dengan panggilan Commit API setelah pengunggahan berhasil. Untuk memiliki kemampuan untuk memperbarui aset daftar, dan pada gilirannya, untuk dapat menambahkan/menghapus lokal dalam modul daftar, pendekatan berikut dapat digunakan:

  1. Gunakan API Buat Aset Daftar untuk mengirim permintaan mengenai pengunggahan aset bersama dengan bahasa, jenis, dan jumlah aset.
  2. Berdasarkan jumlah aset yang diminta, ID Aset dibuat sesuai permintaan dan akan membuat URL SAS jangka pendek dan mengirimkannya kembali di Isi Respons di bawah jenis aset. Anda dapat menggunakan URL ini untuk mengunggah aset Gambar dari jenis tertentu menggunakan Klien HTTP [Put Blob (REST API) - Azure Storage | Microsoft Docs].
  3. Setelah mengunggah, Anda dapat menggunakan COMmit Listing Assets API untuk juga mengirim informasi ID Aset baru yang diterima sebelumnya dari panggilan API sebelumnya. API tunggal akan secara internal menerapkan data aset daftar setelah validasi.
  4. Pendekatan ini akan secara efektif menimpa seluruh set Gambar Sebelumnya dari Jenis Aset di bawah Bahasa tertentu yang sedang dikirim dalam Permintaan. Oleh karena itu, Aset yang diunggah sebelumnya akan dihapus.

Jalur: /submission/v1/product/{productId}/listings/assets/create
Metode: POST

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk

Header yang Diperlukan

Kepala Halaman Deskripsi
Authorization: Bearer <Token> Menggunakan ID Aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Parameter Permintaan

Nama Tipe Deskripsi
bahasa string Diperlukan
buatPermintaanAset Objek Diperlukan
Cuplikan layar Bilangan bulat Diperlukan jika ISV perlu memperbarui cuplikan layar atau menambahkan bahasa daftar baru [1 - 10]
Logo Bilangan bulat Diperlukan jika ISV perlu memperbarui logo atau menambahkan bahasa daftar baru [1 atau 2]

Header Respons

Kepala Halaman Deskripsi
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
daftarAset Objek Objek yang berisi detail StoreLogos dan Cuplikan layar yang akan diunggah
bahasa string
storeLogos Array objek
cuplikan layar Array objek
Id string
URL Upload Aset Utama string URL utama untuk mengunggah aset daftar menggunakan Azure Blob REST API
URLUnggahAsetSekunder string URL sekunder untuk mengunggah aset daftar menggunakan Azure Blob REST API
Metode HTTP Metode HTTP Metode HTTP perlu digunakan untuk mengunggah Aset melalui URL Pengunggahan Aset – Primer atau Sekunder
httpHeader Objek Objek dengan kunci sebagai Header yang diperlukan untuk hadir dalam panggilan Unggah API ke URL Pengunggahan Aset. Jika nilainya tidak kosong, header harus memiliki nilai tertentu. Jika tidak, nilai dihitung selama panggilan API.

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "listingAssets": {
            "language": "en-us",
            "storeLogos":[{
                "id": "1234567890abcdefgh",
                "primaryAssetUploadUrl": "https://contoso.com/upload?blob=1234567890abcdefgh&sig=12345",
                "secondaryAssetUploadUrl": "https://contoso.com/upload?blob=0987654321abcdfger&sig=54326",
                "httpMethod": "PUT",
                "httpHeaders": {"Required Header Name": "Header Value"}
            }],
            "screenshots":[{
                "id": "0987654321abcdfger",
                "primaryAssetUploadUrl": "https://contoso.com/upload?blob=0987654321abcdfger&sig=54321",
                "secondaryAssetUploadUrl": "https://contoso.com/upload?blob=0987654321abcdfger&sig=54322",
                "httpMethod": "PUT",
                "httpHeaders": {"Required Header Name": "Header Value"}

            }]
        }
    } 
}

Terapkan API Aset Daftar

Menerapkan Aset Daftar baru yang Diunggah menggunakan detail dari Buat Aset API di bawah pengiriman draf saat ini.

Jalur: /submission/v1/product/{productId}/listings/assets/commit
Metode: PUT

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk

Header yang Diperlukan

Kepala Halaman Deskripsi
Authorization: Bearer <Token> Menggunakan ID Aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Parameter Permintaan

Nama Tipe Deskripsi
daftarAset Objek
bahasa string
logo toko Array Objek
cuplikan layar Array Objek
Id string Harus berupa ID yang sudah ada yang ingin dipertahankan pengguna dari Get Current Listing Assets API atau ID baru di mana Aset baru diunggah di Create Listing Assets API.
assetUrl string Harus berupa URL Aset yang ada yang ingin dipertahankan pengguna dari Get Current Listing Assets API atau URL Unggah – Primer atau Sekunder, yang menggunakan Aset baru yang diunggah di Api Buat Aset Daftar. Harus berupa URL yang valid

Permintaan Sampel

{
    "listingAssets": { 
        "language": "en-us",    
        "storeLogos": [
            {
                "id": "1234567890abcdefgh",
                "assetUrl": "https://contoso.com/blob=1234567890abcdefgh",
            }
        ],
        "screenshots": [
            {
                "id": "1234567891abcdefgh",
                "assetUrl": "https://contoso.com/blob=1234567891abcdefgh",
            }
        ]
    }
}

Header Respons

Kepala Halaman Deskripsi
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
URL pemungutan suara string URL polling untuk mendapatkan status pengiriman yang sedang berlangsung
IDPengajuanBerlangsung string ID pengiriman dari pengiriman yang sudah berlangsung

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    } 
}

API Polling Status Modul

API untuk memeriksa kesiapan modul sebelum pengiriman dapat dibuat. Juga memvalidasi status unggahan paket.

Jalur: /submission/v1/product/{productId}/status
Metode: GET

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk

Header yang Diperlukan

Kepala Halaman Deskripsi
Authorization: Bearer <Token> Menggunakan ID Aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Header Respons

Kepala Halaman Deskripsi
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
isReady Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Menunjukkan apakah semua Modul dalam status siap termasuk unggahan paket
IDPengajuanBerlangsung string ID pengiriman dari pengiriman yang sudah berlangsung

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "isReady": true,
        "ongoingSubmissionId": ""
    }
}

Membuat API Pengiriman

Membuat pengiriman dari draf saat ini untuk aplikasi MSI atau EXE. API memeriksa:

  • untuk pengiriman aktif dan gagal dengan pesan kesalahan jika pengiriman aktif ada.
  • jika semua modul dalam status siap untuk membuat pengiriman.
  • setiap bidang dalam pengiriman divalidasi sesuai persyaratan Penyimpanan

Jalur:/submission/v1/product/{productId}/submit
Metode: POST

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk

Header yang Diperlukan

Kepala Halaman Deskripsi
Authorization: Bearer <Token> Menggunakan ID Aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Header Respons

Kepala Halaman Deskripsi
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
URL pemungutan suara string URL polling untuk mendapatkan status kesiapan modul termasuk unggahan paket untuk pengiriman
ID pengajuan string ID untuk Pengiriman yang baru dibuat
IDPengajuanBerlangsung string ID pengiriman dari pengiriman yang sudah berlangsung

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "submissionId": "1234567890", 
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    }
}

API Polling Status Pengiriman

API untuk memeriksa Status Pengiriman.

Jalur: /submission/v1/product/{productId}/submission/{submissionId}/status
Metode: GET

Parameter Jalur

Nama Deskripsi
ID produk ID Pusat Mitra produk

Header yang Diperlukan

Kepala Halaman Deskripsi
Authorization: Bearer <Token> Menggunakan ID Aplikasi Azure ACTIVE Directory yang terdaftar di akun Pusat Mitra
X-Seller-Account-Id ID Penjual akun Pusat Mitra

Header Respons

Kepala Halaman Deskripsi
X-Correlation-ID ID unik jenis GUID untuk setiap permintaan. Ini dapat dibagikan dengan tim Dukungan untuk menganalisis masalah apa pun.
Retry-After Waktu dalam detik klien harus menunggu sebelum memanggil API lagi karena pembatasan tarif.

Parameter Respons

Nama Tipe Deskripsi
apakahBerhasil Boolean (tipe data yang hanya memiliki dua nilai: true atau false)
Kesalahan Array objek Daftar pesan kesalahan atau peringatan jika ada
kode string Kode kesalahan Pesan
pesan string Deskripsi kesalahan
sasaran string Entitas tempat kesalahan berasal
responseData Objek
status penerbitan string Status Penerbitan Pengiriman - [INPROGRESS, PUBLISHED, FAILED, UNKNOWN]
telah gagal Boolean (tipe data yang hanya memiliki dua nilai: true atau false) Menunjukkan apakah Penerbitan Gagal dan tidak akan dicoba kembali

Respons Sampel

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "publishingStatus": "INPROGRESS",
        "hasFailed": false
    }
}

Contoh kode

Artikel berikut ini menyediakan contoh kode terperinci yang menunjukkan cara menggunakan API pengiriman Microsoft Store dalam bahasa pemrograman yang berbeda:

Sampel C#: MICROSOFT Store Submission API untuk aplikasi MSI atau EXE

Artikel ini menyediakan contoh kode C# yang menunjukkan cara menggunakan API pengiriman Microsoft Store untuk aplikasi MSI atau EXE. Anda dapat meninjau setiap contoh untuk mempelajari lebih lanjut tentang tugas yang ditunjukkannya, atau Anda dapat membuat semua contoh kode dalam artikel ini ke dalam aplikasi konsol.

Prasyarat Contoh ini menggunakan pustaka berikut:

  • Paket Newtonsoft.Json NuGet dari Newtonsoft.

Program utama Contoh berikut mengimplementasikan program baris perintah yang memanggil metode contoh lain dalam artikel ini untuk menunjukkan berbagai cara untuk menggunakan API pengiriman Microsoft Store. Untuk menyesuaikan program ini untuk penggunaan Anda sendiri:

  • Tetapkan properti SellerId ke ID Penjual akun Pusat Mitra Anda.
  • Tetapkan properti ApplicationId ke ID aplikasi yang ingin Anda kelola.
  • Tetapkan properti ClientId dan ClientSecret ke ID klien dan kunci untuk aplikasi Anda, dan ganti string tenantid di URL TokenEndpoint dengan ID penyewa untuk aplikasi Anda. Untuk informasi selengkapnya, lihat Cara mengaitkan aplikasi Microsoft Azure Active Directory dengan akun Pusat Mitra Anda
using System;
using System.Threading.Tasks;

namespace Win32SubmissionApiCSharpSample
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            var config = new ClientConfiguration()
            {
                ApplicationId = "...",
                ClientId = "...",
                ClientSecret = "...",
                Scope = "https://api.store.microsoft.com/.default",
                ServiceUrl = "https://api.store.microsoft.com",
                TokenEndpoint = "...",
                SellerId = 0
            };

            await new AppSubmissionUpdateSample(config).RunAppSubmissionUpdateSample();

        }
    }
}

Kelas pembantu ClientConfiguration menggunakan C#

Aplikasi sampel menggunakan kelas pembantu ClientConfiguration untuk meneruskan data Azure Active Directory dan data aplikasi ke setiap metode contoh yang menggunakan API pengiriman Microsoft Store.

using System;
using System.Collections.Generic;
using System.Text;

namespace Win32SubmissionApiCSharpSample
{
    public class ClientConfiguration
    {
        /// <summary>
        /// Client Id of your Azure Active Directory app.
        /// Example" 00001111-aaaa-2222-bbbb-3333cccc4444
        /// </summary>
        public string ClientId { get; set; }

        /// <summary>
        /// Client secret of your Azure Active Directory app
        /// </summary>
        public string ClientSecret { get; set; }

        /// <summary>
        /// Service root endpoint.
        /// Example: "https://api.store.microsoft.com"
        /// </summary>
        public string ServiceUrl { get; set; }

        /// <summary>
        /// Token endpoint to which the request is to be made. Specific to your Azure Active Directory app
        /// Example: https://login.microsoftonline.com/d454d300-128e-2d81-334a-27d9b2baf002/oauth2/v2.0/token
        /// </summary>
        public string TokenEndpoint { get; set; }

        /// <summary>
        /// Resource scope. If not provided (set to null), default one is used for the production API
        /// endpoint ("https://api.store.microsoft.com/.default")
        /// </summary>
        public string Scope { get; set; }

        /// <summary>
        /// Partner Center Application ID.
        /// Example: 3e31a9f9-84e8-4d2d-9eba-487878d02ebf
        /// </summary>
        public string ApplicationId { get; set; }


        /// <summary>
        /// The Partner Center Seller Id
        /// Example: 123456892
        /// </summary>
        public int SellerId { get; set; }
    }
}

Membuat pengiriman aplikasi menggunakan C#

Contoh berikut mengimplementasikan kelas yang menggunakan beberapa metode di API pengiriman Microsoft Store untuk memperbarui pengiriman aplikasi.

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Win32SubmissionApiCSharpSample
{
    public class AppSubmissionUpdateSample
    {
        private ClientConfiguration ClientConfig;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="configuration">An instance of ClientConfiguration that contains all parameters populated</param>
        public AppSubmissionUpdateSample(ClientConfiguration configuration)
        {
            this.ClientConfig = configuration;
        }

        /// <summary>
        /// Main method to Run the Sample Application
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task RunAppSubmissionUpdateSample()
        {
            // **********************
            //       SETTINGS
            // **********************
            var appId = this.ClientConfig.ApplicationId;
            var clientId = this.ClientConfig.ClientId;
            var clientSecret = this.ClientConfig.ClientSecret;
            var serviceEndpoint = this.ClientConfig.ServiceUrl;
            var tokenEndpoint = this.ClientConfig.TokenEndpoint;
            var scope = this.ClientConfig.Scope;

            // Get authorization token.
            Console.WriteLine("Getting authorization token");
            var accessToken = await SubmissionClient.GetClientCredentialAccessToken(
                tokenEndpoint,
                clientId,
                clientSecret,
                scope);

            var client = new SubmissionClient(accessToken, serviceEndpoint);

            client.DefaultHeaders = new Dictionary<string, string>()
            {
                {"X-Seller-Account-Id", this.ClientConfig.SellerId.ToString() }
            };

            Console.WriteLine("Getting Current Application Draft Status");
            
            dynamic AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                SubmissionClient.Version, appId), null);
            
            Console.WriteLine(AppDraftStatus.ToString());

            Console.WriteLine("Getting Application Packages ");

            dynamic PackagesResponse = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.PackagesUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(PackagesResponse.ToString());

            Console.WriteLine("Getting Single Package");

            dynamic SinglePackageResponse = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.PackageByIdUrlTemplate,
                SubmissionClient.Version, appId, (string)PackagesResponse.responseData.packages[0].packageId), null);

            Console.WriteLine(SinglePackageResponse.ToString());

            Console.WriteLine("Updating Entire Package Set");

            // Update data in Packages list to have final set of updated Packages

            // Example - Updating Installer Parameters
            PackagesResponse.responseData.packages[0].installerParameters = "/s /r new-args";

            dynamic PackagesUpdateRequest = new
            {
                packages = PackagesResponse.responseData.packages
            };

            dynamic PackagesUpdateResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.PackagesUrlTemplate,
                SubmissionClient.Version, appId), PackagesUpdateRequest);

            Console.WriteLine(PackagesUpdateResponse.ToString());

            Console.WriteLine("Updating Single Package's Download Url");

            // Update data in the SinglePackage object

            var SinglePackageUpdateRequest = SinglePackageResponse.responseData.packages[0];

            // Example - Updating Installer Parameters
            SinglePackageUpdateRequest.installerParameters = "/s /r /t new-args";

            dynamic PackageUpdateResponse = await client.Invoke<dynamic>(HttpMethod.Patch, string.Format(SubmissionClient.PackageByIdUrlTemplate,
                SubmissionClient.Version, appId, SinglePackageUpdateRequest.packageId), SinglePackageUpdateRequest);

            Console.WriteLine("Committing Packages");

            dynamic PackageCommitResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.PackagesCommitUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(PackageCommitResponse.ToString());

            Console.WriteLine("Polling Package Upload Status");

            AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                SubmissionClient.Version, appId), null);

            while (!((bool)AppDraftStatus.responseData.isReady))
            {
                AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                    SubmissionClient.Version, appId), null);

                Console.WriteLine("Waiting for Upload to finish");

                await Task.Delay(TimeSpan.FromSeconds(2));

                if(AppDraftStatus.errors != null && AppDraftStatus.errors.Count > 0)
                {
                    for(var index = 0; index < AppDraftStatus.errors.Count; index++)
                    {
                        if(AppDraftStatus.errors[index].code == "packageuploaderror")
                        {
                            throw new InvalidOperationException("Package Upload Failed. Please try committing packages again.");
                        }
                    }
                }
            }

            Console.WriteLine("Getting Application Metadata - All Modules");

            dynamic AppMetadata = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.AppMetadataUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(AppMetadata.ToString());

            Console.WriteLine("Getting Application Metadata - Listings");

            dynamic AppListingsMetadata = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.AppListingsFetchMetadataUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(AppListingsMetadata.ToString());

            Console.WriteLine("Updating Listings Metadata - Description");

            // Update Required Fields in Listings Metadata Object - Per Language. For eg. AppListingsMetadata.responseData.listings[0]

            // Example - Updating Description
            AppListingsMetadata.responseData.listings[0].description = "New Description Updated By C# Sample Code";

            dynamic ListingsUpdateRequest = new
            {
                listings = AppListingsMetadata.responseData.listings[0]
            };

            dynamic UpdateListingsMetadataResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.AppMetadataUrlTemplate,
                SubmissionClient.Version, appId), ListingsUpdateRequest);

            Console.WriteLine(UpdateListingsMetadataResponse.ToString());

            Console.WriteLine("Getting All Listings Assets");

            dynamic ListingAssets = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ListingAssetsUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(ListingAssets.ToString());

            Console.WriteLine("Creating Listing Assets for 1 Screenshot");

            
            dynamic AssetCreateRequest = new
            {
                language = ListingAssets.responseData.listingAssets[0].language,
                createAssetRequest = new Dictionary<string, int>()
                {
                    {"Screenshot", 1 },
                    {"Logo", 0 }
                }
            };

            dynamic AssetCreateResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.ListingAssetsCreateUrlTemplate,
               SubmissionClient.Version, appId), AssetCreateRequest);

            Console.WriteLine(AssetCreateResponse.ToString());

            Console.WriteLine("Uploading Listing Assets");

            // Path to PNG File to be Uploaded as Screenshot / Logo
            var PathToFile = "./Image.png";
            var AssetToUpload = File.OpenRead(PathToFile);

            await client.UploadAsset(AssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl.Value as string, AssetToUpload);

            Console.WriteLine("Committing Listing Assets");

            dynamic AssetCommitRequest = new
            {
                listingAssets = new
                {
                    language = ListingAssets.responseData.listingAssets[0].language,
                    storeLogos = ListingAssets.responseData.listingAssets[0].storeLogos,
                    screenshots = JToken.FromObject(new List<dynamic>() { new
                {
                    id = AssetCreateResponse.responseData.listingAssets.screenshots[0].id.Value as string,
                    assetUrl = AssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl.Value as string
                }
                }.ToArray())
                }
            };

            dynamic AssetCommitResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.ListingAssetsCommitUrlTemplate,
               SubmissionClient.Version, appId), AssetCommitRequest);

            Console.WriteLine(AssetCommitResponse.ToString());

            Console.WriteLine("Getting Current Application Draft Status before Submission");

            AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(AppDraftStatus.ToString());

            if (AppDraftStatus == null || !((bool)AppDraftStatus.responseData.isReady))
            {
                throw new InvalidOperationException("Application Current Status is not in Ready Status for All Modules");
            }

            Console.WriteLine("Creating Submission");

            dynamic SubmissionCreationResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.CreateSubmissionUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(SubmissionCreationResponse.ToString());

            Console.WriteLine("Current Submission Status");

            dynamic SubmissionStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.SubmissionStatusPollingUrlTemplate,
                SubmissionClient.Version, appId, SubmissionCreationResponse.responseData.submissionId.Value as string), null);

            Console.Write(SubmissionStatus.ToString());

            // User can Poll on this API to know if Submission Status is INPROGRESS, PUBLISHED or FAILED.
            // This Process involves File Scanning, App Certification and Publishing and can take more than a day.
        }
    }
}

Kelas pembantu IngestionClient menggunakan C#

Kelas IngestionClient menyediakan metode pembantu yang digunakan oleh metode lain dalam aplikasi sampel untuk melakukan tugas-tugas berikut:

  • Dapatkan token akses Microsoft Azure ACTIVE Directory yang dapat digunakan untuk memanggil metode di API pengiriman Microsoft Store. Setelah mendapatkan token, Anda memiliki waktu 60 menit untuk menggunakan token ini dalam panggilan ke API pengiriman Microsoft Store sebelum token kedaluwarsa. Setelah token kedaluwarsa, Anda dapat menghasilkan token baru.
  • Proses permintaan HTTP untuk API pengiriman Microsoft Store.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Win32SubmissionApiCSharpSample
{
    /// <summary>
    /// This class is a proxy that abstracts the functionality of the API service
    /// </summary>
    public class SubmissionClient : IDisposable
    {
        public static readonly string Version = "1";
        private HttpClient httpClient;
        private HttpClient imageUploadClient;

        private readonly string accessToken;

        public static readonly string PackagesUrlTemplate = "/submission/v{0}/product/{1}/packages";
        public static readonly string PackageByIdUrlTemplate = "/submission/v{0}/product/{1}/packages/{2}";
        public static readonly string PackagesCommitUrlTemplate = "/submission/v{0}/product/{1}/packages/commit";
        public static readonly string AppMetadataUrlTemplate = "/submission/v{0}/product/{1}/metadata";
        public static readonly string AppListingsFetchMetadataUrlTemplate = "/submission/v{0}/product/{1}/metadata/listings";
        public static readonly string ListingAssetsUrlTemplate = "/submission/v{0}/product/{1}/listings/assets";
        public static readonly string ListingAssetsCreateUrlTemplate = "/submission/v{0}/product/{1}/listings/assets/create";
        public static readonly string ListingAssetsCommitUrlTemplate = "/submission/v{0}/product/{1}/listings/assets/commit";
        public static readonly string ProductDraftStatusPollingUrlTemplate = "/submission/v{0}/product/{1}/status";
        public static readonly string CreateSubmissionUrlTemplate = "/submission/v{0}/product/{1}/submit";
        public static readonly string SubmissionStatusPollingUrlTemplate = "/submission/v{0}/product/{1}/submission/{2}/status";

        public const string JsonContentType = "application/json";
        public const string PngContentType = "image/png";
        public const string BinaryStreamContentType = "application/octet-stream";

        /// <summary>
        /// Initializes a new instance of the <see cref="SubmissionClient" /> class.
        /// </summary>
        /// <param name="accessToken">
        /// The access token. This is JWT a token obtained from Azure Active Directory allowing the caller to invoke the API
        /// on behalf of a user
        /// </param>
        /// <param name="serviceUrl">The service URL.</param>
        public SubmissionClient(string accessToken, string serviceUrl)
        {
            if (string.IsNullOrEmpty(accessToken))
            {
                throw new ArgumentNullException("accessToken");
            }

            if (string.IsNullOrEmpty(serviceUrl))
            {
                throw new ArgumentNullException("serviceUrl");
            }

            this.accessToken = accessToken;
            this.httpClient = new HttpClient
            {
                BaseAddress = new Uri(serviceUrl)
            };
            this.imageUploadClient = new HttpClient();
            this.DefaultHeaders = new Dictionary<string, string>();
        }

        /// <summary>
        /// Gets or Sets the default headers.
        /// </summary>
        public Dictionary<string, string> DefaultHeaders { get; set; }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting
        /// unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (this.httpClient != null)
            {
                this.httpClient.Dispose();
                this.httpClient = null;
                GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// Gets the authorization token for the provided client id, client secret, and the scope.
        /// This token is usually valid for 1 hour, so if your submission takes longer than that to complete,
        /// make sure to get a new one periodically.
        /// </summary>
        /// <param name="tokenEndpoint">Token endpoint to which the request is to be made. Specific to your
        /// Azure Active Directory app. Example: https://login.microsoftonline.com/d454d300-128e-2d81-334a-27d9b2baf002/oauth2/v2.0/token </param>
        /// <param name="clientId">Client Id of your Azure Active Directory app. Example" 00001111-aaaa-2222-bbbb-3333cccc4444</param>
        /// <param name="clientSecret">Client secret of your Azure Active Directory app</param>
        /// <param name="scope">Scope. If not provided, default one is used for the production API endpoint.</param>
        /// <returns>Autorization token. Prepend it with "Bearer: " and pass it in the request header as the
        /// value for "Authorization: " header.</returns>
        public static async Task<string> GetClientCredentialAccessToken(
            string tokenEndpoint,
            string clientId,
            string clientSecret,
            string scope = null)
        {
            if (scope == null)
            {
                scope = "https://api.store.microsoft.com/.default";
            }

            dynamic result;
            using (HttpClient client = new HttpClient())
            {
                string tokenUrl = tokenEndpoint;
                using (
                    HttpRequestMessage request = new HttpRequestMessage(
                        HttpMethod.Post,
                        tokenUrl))
                {
                    string strContent =
                        string.Format(
                            "grant_type=client_credentials&client_id={0}&client_secret={1}&scope={2}",
                            clientId,
                            clientSecret,
                            scope);

                    request.Content = new StringContent(strContent, Encoding.UTF8,
                        "application/x-www-form-urlencoded");

                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        string responseContent = await response.Content.ReadAsStringAsync();
                        result = JsonConvert.DeserializeObject(responseContent);
                    }
                }
            }

            return result.access_token;
        }


        /// <summary>
        /// Invokes the specified HTTP method.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="httpMethod">The HTTP method.</param>
        /// <param name="relativeUrl">The relative URL.</param>
        /// <param name="requestContent">Content of the request.</param>
        /// <returns>instance of the type T</returns>
        /// <exception cref="ServiceException"></exception>
        public async Task<T> Invoke<T>(HttpMethod httpMethod,
            string relativeUrl,
            object requestContent)
        {
            using (var request = new HttpRequestMessage(httpMethod, relativeUrl))
            {
                this.SetRequest(request, requestContent);

                using (HttpResponseMessage response = await this.httpClient.SendAsync(request))
                {
                    T result;
                    if (this.TryHandleResponse(response, out result))
                    {
                        return result;
                    }

                    if (response.IsSuccessStatusCode)
                    {
                        var resource = JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync());
                        return resource;
                    }

                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
        }

        /// <summary>
        /// Uploads a given Image Asset file to Asset Storage
        /// </summary>
        /// <param name="assetUploadUrl">Asset Storage Url</param>
        /// <param name="fileStream">The Stream instance of file to be uploaded</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task UploadAsset(string assetUploadUrl, Stream fileStream)
        {
            using (var request = new HttpRequestMessage(HttpMethod.Put, assetUploadUrl))
            {
                request.Headers.Add("x-ms-blob-type", "BlockBlob");
                request.Content = new StreamContent(fileStream);
                request.Content.Headers.ContentType = new MediaTypeHeaderValue(PngContentType);
                using (HttpResponseMessage response = await this.imageUploadClient.SendAsync(request))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        return;
                    }
                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
        }

        /// <summary>
        /// Sets the request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="requestContent">Content of the request.</param>
        protected virtual void SetRequest(HttpRequestMessage request, object requestContent)
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", this.accessToken);

            foreach (var header in this.DefaultHeaders)
            {
                request.Headers.Add(header.Key, header.Value);
            }

            if (requestContent != null)
            {
                request.Content = new StringContent(JsonConvert.SerializeObject(requestContent),
                        Encoding.UTF8,
                        JsonContentType);
                
            }
        }


        /// <summary>
        /// Tries the handle response.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="response">The response.</param>
        /// <param name="result">The result.</param>
        /// <returns>true if the response was handled</returns>
        protected virtual bool TryHandleResponse<T>(HttpResponseMessage response, out T result)
        {
            result = default(T);
            return false;
        }
    }
}

sampel Node.js: MICROSOFT Store Submission API untuk aplikasi MSI atau EXE

Artikel ini menyediakan contoh kode Node.js yang menunjukkan cara menggunakan API pengiriman Microsoft Store untuk aplikasi MSI atau EXE. Anda dapat meninjau setiap contoh untuk mempelajari lebih lanjut tentang tugas yang ditunjukkannya, atau Anda dapat membuat semua contoh kode dalam artikel ini ke dalam aplikasi konsol.

Prasyarat Contoh ini menggunakan pustaka berikut:

  • Gunakan perintah berikut untuk menginstal versi 2 dari node-fetch: node-fetch v2 [npm install node-fetch@2]

Membuat pengiriman aplikasi menggunakan node.js

Contoh berikut memanggil contoh metode lain dalam artikel ini untuk menunjukkan berbagai cara untuk menggunakan API pengiriman Microsoft Store. Untuk menyesuaikan program ini untuk penggunaan Anda sendiri:

  • Tetapkan properti SellerId ke ID Penjual akun Pusat Mitra Anda.
  • Tetapkan properti ApplicationId ke ID aplikasi yang ingin Anda kelola.
  • Tetapkan properti ClientId dan ClientSecret ke ID klien dan kunci untuk aplikasi Anda, dan ganti string tenantid di URL TokenEndpoint dengan ID penyewa untuk aplikasi Anda. Untuk informasi selengkapnya, lihat Cara mengaitkan aplikasi Microsoft Azure Active Directory dengan akun Pusat Mitra Anda

Contoh berikut mengimplementasikan kelas yang menggunakan beberapa metode di API pengiriman Microsoft Store untuk memperbarui pengiriman aplikasi.

const config = require('./Configuration');
const submissionClient = require('./SubmissionClient');
const fs = require('fs');

var client = new submissionClient(config);

/**
 * Main entry method to Run the Store Submission API Node.js Sample
 */
async function RunNodeJsSample(){
    print('Getting Access Token');
    await client.getAccessToken();
    
    print('Getting Current Application Draft Status');
    var currentDraftStatus = await client.callStoreAPI(client.productDraftStatusPollingUrlTemplate, 'get');
    print(currentDraftStatus);

    print('Getting Application Packages');
    var currentPackages = await client.callStoreAPI(client.packagesUrlTemplate, 'get');
    print(currentPackages);

    print('Getting Single Package');
    var packageId = currentPackages.responseData.packages[0].packageId;
    var packageIdUrl = `${client.packageByIdUrlTemplate}`.replace('{packageId}', packageId);
    var singlePackage = await client.callStoreAPI(packageIdUrl, 'get');
    print(singlePackage);

    print('Updating Entire Package Set');
    // Update data in Packages list to have final set of updated Packages
    currentPackages.responseData.packages[0].installerParameters = "/s /r new-args";
    var packagesUpdateRequest = {
        'packages': currentPackages.responseData.packages
    };
    print(packagesUpdateRequest);
    var packagesUpdateResponse = await client.callStoreAPI(client.packagesUrlTemplate, 'put', packagesUpdateRequest);
    print(packagesUpdateResponse);

    print('Updating Single Package\'s Download Url');
    // Update data in the SinglePackage object
    singlePackage.responseData.packages[0].installerParameters = "/s /r /t new-args";
    var singlePackageUpdateResponse = await client.callStoreAPI(packageIdUrl, 'patch', singlePackage.responseData.packages[0]);
    print(singlePackageUpdateResponse);

    print('Committing Packages');
    var commitPackagesResponse = await client.callStoreAPI(client.packagesCommitUrlTemplate, 'post');
    print(commitPackagesResponse);

    await poll(async ()=>{
        print('Waiting for Upload to finish');
        return await client.callStoreAPI(client.productDraftStatusPollingUrlTemplate, 'get');
    }, 2);

    print('Getting Application Metadata - All Modules');
    var appMetadata = await client.callStoreAPI(client.appMetadataUrlTemplate, 'get');
    print(appMetadata);

    print('Getting Application Metadata - Listings');
    var appListingMetadata = await client.callStoreAPI(client.appListingsFetchMetadataUrlTemplate, 'get');
    print(appListingMetadata);

    print('Updating Listings Metadata - Description');   
    // Update Required Fields in Listings Metadata Object - Per Language. For eg. AppListingsMetadata.responseData.listings[0]
    // Example - Updating Description
    appListingMetadata.responseData.listings[0].description = 'New Description Updated By Node.js Sample Code';
    var listingsUpdateRequest = {
        'listings': appListingMetadata.responseData.listings[0]
    };
    var listingsMetadataUpdateResponse = await client.callStoreAPI(client.appMetadataUrlTemplate, 'put', listingsUpdateRequest);
    print(listingsMetadataUpdateResponse);

    print('Getting All Listings Assets');
    var listingAssets = await client.callStoreAPI(client.listingAssetsUrlTemplate, 'get');
    print(listingAssets);

    print('Creating Listing Assets for 1 Screenshot');
    var listingAssetCreateRequest = {
        'language': listingAssets.responseData.listingAssets[0].language,
        'createAssetRequest': {
            'Screenshot': 1,
            'Logo': 0
        }
    };
    var listingAssetCreateResponse = await client.callStoreAPI(client.listingAssetsCreateUrlTemplate, 'post', listingAssetCreateRequest);
    print(listingAssetCreateResponse);

    print('Uploading Listing Assets');
    const pathToFile = './Image.png';
    const stats = fs.statSync(pathToFile);
    const fileSize = stats.size;
    const fileStream = fs.createReadStream(pathToFile);
    await client.uploadAssets(listingAssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl, fileStream, fileSize);

    print('Committing Listing Assets');
    var assetCommitRequest = {
        'listingAssets': {
            'language': listingAssets.responseData.listingAssets[0].language,
            'storeLogos': listingAssets.responseData.listingAssets[0].storeLogos,
            'screenshots': [{
                'id': listingAssetCreateResponse.responseData.listingAssets.screenshots[0].id,
                'assetUrl': listingAssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl
            }]
        }
    };
    var assetCommitResponse = await client.callStoreAPI(client.listingAssetsCommitUrlTemplate, 'put', assetCommitRequest);
    print(assetCommitResponse);

    print('Getting Current Application Draft Status before Submission');
    currentDraftStatus = await client.callStoreAPI(client.productDraftStatusPollingUrlTemplate, 'get');
    print(currentDraftStatus);
    if(!currentDraftStatus.responseData.isReady){
        throw new Error('Application Current Status is not in Ready Status for All Modules');
    }

    print('Creating Submission');
    var submissionCreationResponse = await client.callStoreAPI(client.createSubmissionUrlTemplate, 'post');
    print(submissionCreationResponse);

    print('Current Submission Status');
    var submissionStatusUrl = `${client.submissionStatusPollingUrlTemplate}`.replace('{submissionId}', submissionCreationResponse.responseData.submissionId);
    var submissionStatusResponse = await client.callStoreAPI(submissionStatusUrl, 'get');
    print(submissionStatusResponse);

    // User can Poll on this API to know if Submission Status is INPROGRESS, PUBLISHED or FAILED.
    // This Process involves File Scanning, App Certification and Publishing and can take more than a day.
}

/**
 * Utility Method to Poll using a given function and time interval in seconds
 * @param {*} func 
 * @param {*} intervalInSeconds 
 * @returns 
 */
async function poll(func, intervalInSeconds){
var result = await func();
if(result.responseData.isReady){
    Promise.resolve(true);
}
else if(result.errors && result.errors.length > 0 && result.errors.find(element => element.code == 'packageuploaderror') != undefined){
throw new Error('Package Upload Failed');
}
else{
    await new Promise(resolve => setTimeout(resolve, intervalInSeconds*1000));
    return await poll(func, intervalInSeconds); 
}
}

/**
 * Utility function to Print a Json or normal string
 * @param {*} json 
 */
function print(json){
    if(typeof(json) == 'string'){
        console.log(json);
    }
    else{
        console.log(JSON.stringify(json));
    }
    console.log("\n");
}

/** Run the Node.js Sample Application */
RunNodeJsSample();

Pembantu ClientConfiguration

Aplikasi sampel menggunakan kelas pembantu ClientConfiguration untuk meneruskan data Azure Active Directory dan data aplikasi ke setiap metode contoh yang menggunakan API pengiriman Microsoft Store.

/** Configuration Object for Store Submission API */
var config = {
    version : "1",
    applicationId : "...",
    clientId : "...",
    clientSecret : "...",
    serviceEndpoint : "https://api.store.microsoft.com",
    tokenEndpoint : "...",
    scope : "https://api.store.microsoft.com/.default",
    sellerId : "...",
    jsonContentType : "application/json",
    pngContentType : "image/png",
    binaryStreamContentType : "application/octet-stream"
};

module.exports = config;

Pembantu IngestionClient menggunakan node.js

Kelas IngestionClient menyediakan metode pembantu yang digunakan oleh metode lain dalam aplikasi sampel untuk melakukan tugas-tugas berikut:

  • Dapatkan token akses Microsoft Azure ACTIVE Directory yang dapat digunakan untuk memanggil metode di API pengiriman Microsoft Store. Setelah mendapatkan token, Anda memiliki waktu 60 menit untuk menggunakan token ini dalam panggilan ke API pengiriman Microsoft Store sebelum token kedaluwarsa. Setelah token kedaluwarsa, Anda dapat menghasilkan token baru.
  • Proses permintaan HTTP untuk API pengiriman Microsoft Store.
const fetch = require('node-fetch');
/**
 * Submission Client to invoke all available Store Submission API and Asset Upload to Blob Store
 */
class SubmissionClient{

    constructor(config){
        this.configuration = config;
        this.accessToken = "";
        this.packagesUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages`;
        this.packageByIdUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages/{packageId}`;
        this.packagesCommitUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages/commit`;
        this.appMetadataUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/metadata`;
        this.appListingsFetchMetadataUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/metadata/listings`;
        this.listingAssetsUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets`;
        this.listingAssetsCreateUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets/create`;
        this.listingAssetsCommitUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets/commit`;
        this.productDraftStatusPollingUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/status`;
        this.createSubmissionUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/submit`;
        this.submissionStatusPollingUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/submission/{submissionId}/status`;
    }
    
    async getAccessToken(){
        var params = new URLSearchParams();
        params.append('grant_type','client_credentials');
        params.append('client_id',this.configuration.clientId);
        params.append('client_secret',this.configuration.clientSecret);
        params.append('scope',this.configuration.scope);
        var response = await fetch(this.configuration.tokenEndpoint,{
            method: "POST",
            body: params
        });    
        var data = await response.json();
        this.accessToken = data.access_token;
    }

    async callStoreAPI(url, method, data){
        var request = {
            method: method,
            headers:{
                'Authorization': `Bearer ${this.accessToken}`,
                'Content-Type': this.configuration.jsonContentType,
                'X-Seller-Account-Id': this.configuration.sellerId
            },            
        };
        if(data){
            request.body = JSON.stringify(data);
        }
        var response = await fetch(`${this.configuration.serviceEndpoint}${url}`,request);
        var jsonResponse = await response.json();
        return jsonResponse;
    }

    async uploadAssets(url, stream, size){
        var request = {
            method: 'put',
            headers:{
                'Content-Type': this.configuration.pngContentType,
                'x-ms-blob-type': 'BlockBlob',
                "Content-length": size
            },            
            body: stream
        };
        var response = await fetch(`${url}`,request);
        if(response.ok){
            return response;
        }
        else{
            throw new Error('Uploading of assets failed');
        }
    }
}
module.exports = SubmissionClient;

Bantuan tambahan

Jika Anda memiliki pertanyaan tentang API pengiriman Microsoft Store atau memerlukan bantuan dalam mengelola pengiriman Anda dengan API ini, gunakan sumber daya berikut:

  • Ajukan pertanyaan Anda di forum kami.
  • Kunjungi halaman dukungan kami dan minta salah satu opsi dukungan yang dibantu untuk Pusat Mitra. Jika Anda diminta untuk memilih jenis dan kategori masalah, pilih Pengiriman dan sertifikasi aplikasi dan Mengirimkan aplikasi.