Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Użyj interfejsu API przesyłania ze sklepu Microsoft Store dla aplikacji MSI lub EXE, aby programowo wykonywać zapytania i tworzyć zgłoszenia dla aplikacji MSI lub EXE dla konta Centrum partnerskiego organizacji. Ten interfejs API jest przydatny, jeśli twoje konto zarządza wieloma aplikacjami i chcesz zautomatyzować i zoptymalizować proces przesyłania dla tych zasobów. Ten interfejs API używa usługi Azure Active Directory (Azure AD) do uwierzytelniania wywołań z aplikacji lub usługi.
W poniższych krokach opisano proces od początku do końca korzystania z interfejsu API do przesyłania w Microsoft Store.
- Upewnij się, że zostały spełnione wszystkie wymagania wstępne.
- Przed wywołaniem metody w interfejsie API przesyłania sklepu Microsoft Store uzyskaj token dostępu usługi Azure AD. Po uzyskaniu tokenu masz 60 minut na użycie tego tokenu w wywołaniach interfejsu API przesyłania do Microsoft Store, zanim token wygaśnie. Po wygaśnięciu tokenu możesz wygenerować nowy token.
- Uruchom interfejs API przesyłania aplikacji MSI lub EXE do sklepu Microsoft Store.
Krok 1. Pełne wymagania wstępne dotyczące korzystania z interfejsu API przesyłania do sklepu Microsoft Store
Przed rozpoczęciem pisania kodu w celu wywołania interfejsu API przesyłania aplikacji do sklepu Microsoft Store dla aplikacji MSI lub EXE, upewnij się, że spełniono następujące wymagania wstępne.
- Ty (lub Twoja organizacja) musisz mieć katalog usługi Azure AD i musisz mieć uprawnienia administratora globalnego dla katalogu. Jeśli korzystasz już z platformy Microsoft 365 lub innych usług biznesowych, masz już katalog usługi Azure AD. W przeciwnym razie możesz utworzyć nową usługę Azure AD w Centrum partnerskim bez dodatkowych opłat.
- Musisz skojarzyć aplikację usługi Azure AD z kontem Centrum partnerskiego i uzyskać identyfikator dzierżawy, identyfikator klienta i klucz. Te wartości są niezbędne do uzyskania tokenu dostępu Azure AD, który zostanie użyty w wywołaniach do interfejsu API Microsoft Store Submission.
- Przygotuj swoją aplikację do użycia z interfejsem API przesyłania do sklepu Microsoft Store.
- Jeśli Twoja aplikacja nie istnieje jeszcze w Centrum Partnerskiego, musisz utworzyć aplikację, rezerwując jej nazwę w Centrum Partnerskiego. Nie można użyć interfejsu API przesyłania Microsoft Store do utworzenia aplikacji w Centrum partnerskim; musisz pracować w Centrum partnerskim, aby ją utworzyć, a następnie za pomocą interfejsu API można uzyskać dostęp do aplikacji i programowo tworzyć dla niej przesyłki.
- Przed utworzeniem zgłoszenia dla danej aplikacji przez ten interfejs API, należy najpierw utworzyć zgłoszenie dla aplikacji w Centrum partnerskim, które obejmuje wypełnienie kwestionariusza dotyczącego oceny wieku. Po wykonaniu tej czynności będzie można programowo utworzyć nowe przesłania dla tej aplikacji przy użyciu interfejsu API.
- Jeśli tworzysz lub aktualizujesz zgłoszenie aplikacji i musisz dołączyć nowy pakiet, przygotuj szczegóły pakietu.
- Jeśli tworzysz lub aktualizujesz zgłoszenie aplikacji i musisz uwzględnić zrzuty ekranu lub obrazy do listingu w Sklepie, przygotuj zrzuty ekranu i obrazy aplikacji.
Jak skojarzyć aplikację usługi Azure AD z kontem Centrum partnerskiego
Aby skorzystać z interfejsu API przesyłania do Microsoft Store dla aplikacji MSI lub EXE, należy skojarzyć aplikację Azure AD z kontem w Centrum partnerskim, pobrać dla tej aplikacji identyfikatory dzierżawy i klienta oraz wygenerować klucz. Aplikacja Azure AD reprezentuje aplikację lub usługę, z której chcesz wywołać API przesyłania do Microsoft Store. Potrzebujesz identyfikatora dzierżawcy, identyfikatora klienta i klucza, aby uzyskać token dostępu Azure AD, który następnie przekazujesz do interfejsu API.
Uwaga / Notatka
To zadanie trzeba wykonać tylko raz. Po utworzeniu identyfikatora dzierżawy, identyfikatora klienta i klucza możesz użyć ich ponownie w dowolnym momencie, gdy musisz utworzyć nowy token dostępu usługi Azure AD.
- W Partner Center skojarz konto Partner Center swojej organizacji z katalogiem Azure AD Twojej organizacji.
- Następnie na stronie Użytkownicy w sekcji Ustawienia konta Centrum partnerskiego dodać aplikację usługi Azure AD reprezentującą aplikację lub usługę, której będziesz używać do uzyskiwania dostępu do przesyłania dla konta Centrum partnerskiego. Upewnij się, że przypiszesz tej aplikacji rolę Menedżera. Jeśli aplikacja jeszcze nie istnieje w katalogu usługi Azure AD, możesz utworzyć nową aplikację usługi Azure AD w Centrum partnerskim.
- Wróć do strony Użytkownicy, kliknij nazwę aplikacji usługi Azure AD, aby przejść do ustawień aplikacji, a następnie skopiuj wartości Identyfikatora dzierżawcy i Identyfikatora klienta.
- Aby dodać nowy klucz lub klucz tajny klienta, zobacz następujące instrukcje lub zapoznaj się z instrukcjami dotyczącymi rejestrowania aplikacji za pośrednictwem witryny Azure Portal:
Aby zarejestrować aplikację:
Zaloguj się do witryny Azure Portal.
Jeśli masz dostęp do wielu dzierżaw, użyj filtru Katalogów i subskrypcji w górnym menu, aby przełączyć się do dzierżawy, w której chcesz zarejestrować aplikację.
Wyszukaj pozycję Azure Active Directory i wybierz ją.
W obszarze Zarządzanie wybierz pozycję Rejestracje aplikacji, a następnie wybierz swoją aplikację.
Wybierz Certyfikaty i sekrety > Sekrety klienta > Nowy sekret klienta.
Dodaj opis tajemnicy klienta.
Wybierz datę wygaśnięcia klucza tajnego lub określ niestandardowy okres ważności.
Czas ważności tajemnicy klienta jest ograniczony do dwóch lat (24 miesięcy) lub mniej. Nie można określić niestandardowego okresu ważności dłuższego niż 24 miesiące.
Uwaga / Notatka
Firma Microsoft zaleca ustawienie wartości wygaśnięcia mniejszej niż 12 miesięcy.
Wybierz Dodaj.
Zapisz wartość sekretu do użycia w kodzie aplikacji klienckiej. Ta wartość tajna nigdy nie jest wyświetlana ponownie po opuszczeniu strony.
Krok 2. Uzyskiwanie tokenu dostępu usługi Azure AD
Przed wywołaniem dowolnej metody w interfejsie API dla aplikacji MSI lub EXE w sklepie Microsoft Store, należy najpierw uzyskać token dostępu Azure AD, który należy przekazać do nagłówka Autoryzacja każdej metody w tym interfejsie API. Po uzyskaniu tokenu dostępu należy 60 minut używać go przed jego wygaśnięciem. Po wygaśnięciu tokenu możesz odświeżyć token, aby móc nadal używać go w kolejnych wywołaniach interfejsu API.
Aby uzyskać token dostępu, postępuj zgodnie z instrukcjami w temacie [Service to Service Calls Using Client Credentials]/azure/active-directory/azuread-dev/v1-oauth2-client-creds-grant-flow) w celu wysłania żądania HTTP POST do punktu końcowego https://login.microsoftonline.com/
<tenant_id>/oauth2/token. Oto przykładowe żądanie.
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
Dla wartości tenant_id
w URI POST oraz parametrów client_id
i client_secret
określ identyfikator dzierżawy, identyfikator klienta oraz klucz aplikacji, które uzyskałeś z Centrum partnerskiego w poprzedniej sekcji. Dla parametru zakresu należy określić wartość https://api.store.microsoft.com/.default
.
Po wygaśnięciu tokenu dostępu możesz go odświeżyć, postępując zgodnie z instrukcjami podanymi tutaj.
Aby zapoznać się z przykładami ilustrującymi sposób uzyskania tokenu dostępu przy użyciu języka C# lub Node.js, zobacz przykłady kodu dla interfejsu API przesyłania aplikacji MSI lub EXE do Microsoft Store.
Krok 3: Użyj API wysyłania w sklepie Microsoft Store
Po uzyskaniu tokenu dostępu Azure AD można wywołać metody w interfejsie API do przesyłania Microsoft Store dla aplikacji MSI lub EXE. Interfejs API zawiera wiele metod, które są pogrupowane w scenariusze dla aplikacji. Aby utworzyć lub zaktualizować zgłoszenia, zazwyczaj wywołujesz wiele metod w określonej kolejności. Aby uzyskać informacje o poszczególnych scenariuszach i składni każdej metody, zobacz następujące sekcje:
Uwaga / Notatka
Po uzyskaniu tokenu dostępu masz 60 minut na wywołanie metod w interfejsie Microsoft Store submission API dla aplikacji MSI lub EXE przed wygaśnięciem tokenu.
Podstawowy adres URL
Podstawowy adres URL interfejsu API przesyłania sklepu Microsoft Store dla aplikacji EXE lub MSI to: https://api.store.microsoft.com
Kontrakty API
Pobieranie bieżącego interfejsu API metadanych przesyłania wersji roboczej
Pobiera metadane w każdym module (listy, właściwości lub dostępność) w bieżącej wersji roboczej przesyłania.
Ścieżka [Wszystkie moduły]: /submission/v1/product/{productId}/metadata?languages={languages}&includelanguagelist={true/false}
Ścieżka [pojedynczy moduł]: /submission/v1/product/{productId}/metadata/{moduleName}?languages={languages}&includelanguagelist={true/false}
, metoda: GET
Parametry ścieżki
Parametr | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
nazwa modułu | Moduł Centrum Partnera — oferty, zasoby lub dostępność |
Parametry zapytania
Parametr | Opis |
---|---|
Języki |
Opcjonalne Filtr języków listy jako ciąg znaków rozdzielony przecinkami [limit do 200 języków]. Jeśli jest nieobecny, zostaną pobrane metadane dla pierwszych 200 dostępnych języków listy. [ np. "en-us, en-gb"]. |
dodajlistęjęzyków | opcjonalne typ logiczny — jeśli jest to prawda, zwraca listę dodanych języków ofert i ich status kompletności. |
Wymagane nagłówki
Nagłówek | Wartość |
---|---|
Authorization: Bearer <Token> |
Identyfikator aplikacji usługi Azure AD zarejestrowany w koncie Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
nagłówki odpowiedzi
Nagłówek | Wartość |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Można to udostępnić zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
wsparcie dostępności | Boolowski | |
dodatkowe warunki licencji | Sznurek | |
dostępność | Przedmiot | Dane modułu dostępności |
kategoria | Sznurek | Zobacz listę kategorii poniżej |
notatki certyfikacyjne | Sznurek | |
kod | Sznurek | Kod błędu komunikatu |
informacje kontaktowe | Sznurek | |
prawo autorskie | Sznurek | |
ZależyOdSterownikówLubNT | Boolowski | |
opis | Sznurek | |
opracowany przez | Sznurek | |
Łatwość odnalezienia | Sznurek | [ODNAJDYWANIE, DEEPLINK_ONLY] |
enableInFutureMarkets | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
freeTrial | Sznurek | [BRAK_DARMOWEJ_WERSJI_PRÓBNEJ, DARMOWA_WERSJA_PRÓBNA] |
typElementuSprzętowego | Sznurek | |
isPrivacyPolicyRequired (ZasadyPrywatnościWymagane) This includes both the original and a translated version in parentheses for clarity if needed in documentation or user-facing text. | Boolowski | |
jestZalecane | Boolowski | |
wymagane | Boolowski | |
czySukces | Boolowski | |
czySystemowaFunkcjaJestWymagana | Tablica obiektów | |
Język | Sznurek | Zobacz listę języków poniżej |
Ogłoszenia | Tablica obiektów | Wyświetlanie listy danych modułu dla każdego języka |
Rynki | Tablica ciągów znaków | Zobacz listę rynków poniżej |
Komunikat | Sznurek | Opis błędu |
minimalne wymagania sprzętowe | Sznurek | |
minimalne wymagania | Sznurek | |
wsparcie dla pióra i tuszu | Boolowski | |
cennik | Sznurek | [DARMOWY, FREEMIUM, ABONAMENTOWY, PŁATNY] |
URLPolitykiPrywatności | Sznurek | |
deklaracje produktów | Przedmiot | |
cechy produktu | Tablica ciągów znaków | |
właściwości | Przedmiot | Dane modułu właściwości |
zalecany sprzęt | Sznurek | |
zalecane wymaganie | Sznurek | |
dane odpowiedzi | Przedmiot | Zawiera rzeczywisty ładunek odpowiedzi dla żądania |
wymagania | Tablica obiektów | |
terminy wyszukiwania | Tablica ciągów znaków | |
krótki opis | Sznurek | |
Podkategorii | Sznurek | Zobacz listę podkategorii poniżej |
supportContactInfo | Sznurek | |
szczegóły wymagań systemowych | Tablica obiektów | |
cel | Sznurek | Jednostka, z której pochodzi błąd |
witryna sieci Web | Sznurek | |
Co nowego | Sznurek |
Przykładowa odpowiedź
{
"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}]
}
}
Aktualizowanie bieżącego interfejsu API metadanych przesyłania wersji roboczej
Aktualizuje metadane w każdym module w wersji roboczej przesyłania. Sprawdzanie interfejsu API
- W przypadku aktywnego przesyłania. Jeśli istnieje, niepowodzenie z komunikatem o błędzie.
- Jeśli wszystkie moduły są w stanie gotowości, aby umożliwić operację Zapisu wersji roboczej.
- Każde pole w zgłoszeniu jest weryfikowane zgodnie z wymaganiami Sklepu
- Reguły sprawdzania poprawności szczegółów wymagań systemowych:
- Dozwolone wartości w hardwareItemType = Pamięć: 300 MB, 750 MB, 1 GB, 2 GB, 4 GB, 6 GB, 8 GB, 12 GB, 16 GB, 20 GB
- Dozwolone wartości w hardwareItemType = DirectX: DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12
- Dozwolone wartości w hardwareItemType = Video_Memory: 1 GB, 2 GB, 4 GB, 6 GB
ścieżka [pełna aktualizacja modułu]: /submission/v1/product/{productId}/metadata
, metoda: PUT
ścieżka [aktualizacja poprawki modułu]: /submission/v1/product/{productId}/metadata
: metoda: PATCH
zachowania interfejsu API
W przypadku interfejsu API pełnej aktualizacji modułu — wszystkie dane modułu muszą być uwzględnione w żądaniu, aby dokonać pełnej aktualizacji każdego pola. Jeśli jakieś pole nie jest obecne w żądaniu, jego wartość domyślna zostanie użyta do nadpisania bieżącej wartości dla danego modułu.
W przypadku interfejsu API aktualizacji modułu poprawek — w żądaniu muszą znajdować się tylko pola, które mają zostać zaktualizowane. Te dane z pól z żądania zastąpią istniejące wartości, zachowując niezmienione wszystkie inne pola, które nie znajdują się w żądaniu, tak jak obecnie dla tego konkretnego modułu.
Parametry ścieżki
Parametr | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Wymagane nagłówki
Nagłówek | Wartość |
---|---|
Authorization: Bearer <Token> |
Identyfikator aplikacji usługi Azure AD zarejestrowany w koncie Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
Parametry żądania
Nazwa | Typ | Opis |
---|---|---|
dostępność | Przedmiot | Obiekt do przechowywania metadanych modułu dostępności |
Rynki | Tablica ciągów znaków | Wymagane Zobacz listę rynków poniżej |
Łatwość odnalezienia | Sznurek | wymagane [ODNAJDYWANIE, DEEPLINK_ONLY] |
enableInFutureMarkets | Boolowski | Wymagane |
cennik | Sznurek | Wymagane [BEZPŁATNA, FREEMIUM, SUBSKRYPCJA, PŁATNA] |
freeTrial | Sznurek | wymagane, jeśli cennik jest płatny lub subskrypcja [NO_FREE_TRIAL, FREE_TRIAL] |
właściwości | Przedmiot | Obiekt do przechowywania metadanych modułu właściwości |
isPrivacyPolicyRequired (ZasadyPrywatnościWymagane) This includes both the original and a translated version in parentheses for clarity if needed in documentation or user-facing text. | Boolowski | Wymagane |
URLPolitykiPrywatności | Sznurek | Wymagane, jeśli parametr isPrivacyPolicyRequired = true Musi być prawidłowym adresem URL |
witryna sieci Web | Sznurek | Musi być prawidłowym adresem URL |
supportContactInfo | Sznurek | Musi być prawidłowym adresem URL lub adresem e-mail |
notatki certyfikacyjne | Sznurek | Zalecane Limit znaków = 2000 |
kategoria | Sznurek | Wymagane Zobacz listę kategorii poniżej |
Podkategorii | Sznurek | Wymagane Zobacz listę podkategorii poniżej |
deklaracje produktów | Przedmiot | Wymagane |
czySystemowaFunkcjaJestWymagana | Tablica obiektów | [Touch, Klawiatura, Mysz, Kamera, NFC_HCE, NFC_Proximity, Bluetooth_LE, Telefonia, Mikrofon] |
wymagane | Boolowski | Wymagane |
jestZalecane | Boolowski | Wymagane |
typElementuSprzętowego | Sznurek | Wymagane |
szczegóły wymagań systemowych | Tablica obiektów | [Procesor, grafika, pamięć, DirectX, Video_Memory] |
minimalne wymagania | Sznurek |
wymagane dla elementu systemRequirementsText, MaxLength = 200 Dozwolone wartości w hardwareItemType = Pamięć: [300 MB, 750 MB, 1 GB, 2 GB, 4 GB, 6 GB, 8 GB, 12 GB, 16 GB, 20 GB] Dozwolone wartości w hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12] Dozwolone wartości w hardwareItemType = Video_Memory: [1 GB, 2 GB, 4 GB, 6 GB] |
zalecane wymaganie | Sznurek |
wymagane dla elementu systemRequirementsText, MaxLength = 200 Dozwolone wartości w hardwareItemType = Pamięć: [300 MB, 750 MB, 1 GB, 2 GB, 4 GB, 6 GB, 8 GB, 12 GB, 16 GB, 20 GB] Dozwolone wartości w hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12] Dozwolone wartości w hardwareItemType = Video_Memory: [1 GB, 2 GB, 4 GB, 6 GB] |
ZależyOdSterownikówLubNT | Boolowski | Wymagane |
wsparcie dostępności | Boolowski | Wymagane |
wsparcie dla pióra i tuszu | Boolowski | Wymagane |
Ogłoszenia | Przedmiot | Obiekt wyświetlania listy danych modułu dla pojedynczego języka |
Język | Sznurek | Wymagane Zobacz listę języków poniżej |
opis | Sznurek | Limit znaków wymagany to 10000 |
Co nowego | Sznurek | Limit znaków = 1500 |
cechy produktu | Tablica ciągów | 200 znaków na funkcję; Maksymalnie 20 funkcji |
krótki opis | Sznurek | Limit znaków = 1000 |
terminy wyszukiwania | Tablica ciągów | 30 znaków na termin wyszukiwania; Do 7 terminów wyszukiwania 21 unikatowych wyrazów ŁĄCZNIE we wszystkich terminach wyszukiwania |
dodatkowe warunki licencji | Sznurek | Limit znaków wymagany to 10000 |
prawo autorskie | Sznurek | Limit znaków = 200 |
opracowany przez | Sznurek | Limit znaków = 255 |
wymagania | Tablica obiektów | 200 znaków na element; Maksymalnie 11 elementów łącznie między minimalną a zalecaną ilością] |
minimalne wymagania sprzętowe | Sznurek | Limit znaków = 200 |
zalecany sprzęt | Sznurek | Limit znaków = 200 |
informacje kontaktowe | Sznurek | Limit znaków = 200 |
listyDoDodania | Tablica ciągów znaków | Zobacz listę języków poniżej |
listyDoUsunięcia | Tablica ciągów znaków | Zobacz listę języków poniżej |
Rynki
Rynek | Skrót |
---|---|
Afganistan | AF |
Albania | AL |
Algieria | DZ |
Samoa Amerykańskie | JAKO |
Andora | REKLAMA |
Angola | AO |
Anguilla | Sztuczna inteligencja |
Antarktyda | AQ |
Antigua i Barbuda | AG |
Argentyna | Rzeczywistość rozszerzona |
Armenia | rano |
Aruba | AW |
Australia | AU |
Austria | PRZY |
Azerbejdżan | AZ |
Bahamy | Licencjat nauk ścisłych |
Bahrajn | BH |
Bangladesz | BD |
Barbados | BB |
Białoruś | PRZEZ |
Belgia | BYĆ |
Belize | BZ |
Benin | BJ |
Bermudy | BM |
Bhutan | BT |
Boliwizańska Republika Wenezueli | VE |
Boliwia | Bo |
Bonaire | BQ |
Bośnia i Hercegowina | BA |
Botswana | BW |
Wyspa Bouvet | BV |
Brazylia | BR |
Terytorium Brytyjskiego Oceanu Indyjskiego | IO |
Brytyjskie Wyspy Dziewicze | VG |
Brunei | BN |
Bułgaria | BG |
Burkina Faso | BF |
Burundi | Analityka Biznesowa (BI) |
Kambodża | KH |
Kamerun | CENTYMETR |
Kanada | CA |
Cabo Verde | Życiorys zawodowy |
Wyspy Kajamańskie | KY |
Republika Środkowoafrykańska | POR |
Czad | TD |
Chile | CL |
Chiny | CN |
Wyspa Bożego Narodzenia | CX |
Wyspy Kokosowe (Keeling) | DW |
Kolumbia | Kobalt |
Komory | km |
Kongo | Grafika komputerowa |
Kongo (DRC) | Płyta CD |
Wyspy Cooka | CK |
Kostaryka | CR |
Chorwacja | Zasoby Ludzkie |
Curaçao | CW |
Cypr | CY |
Republika Czeska | CZ |
Côte d'Ivoire | Ciągła integracja |
Dania | DK |
Dżibuti | DJ |
Dominika | dm |
Dominikana | ZRÓB |
Ekwador | Komisja Europejska |
Egipt | NP |
Salwador | SV |
Gwinea Równikowa | GQ |
Erytrea | ER |
Estonia | EE |
Etiopia | ET |
Wyspy Falklandzkie | FK |
Wyspy Owcze | FO |
Fidżi | FJ |
Finlandia | Fi |
Francja | Francja |
Gujana Francuska | bezglutenowy (assuming "GF" stands for "gluten-free") |
Polinezja Francuska | PF |
Francuskie Lądy Południowe i Antarktydy | TF |
Gabon | Zgromadzenie Ogólne |
Gambia | General Motors |
Gruzja | GE |
Niemcy | Niemcy |
Ghana | GH |
Gibraltar | Indeks glikemiczny |
Grecja | GR |
Grenlandia | GL |
Grenada | GD |
Gwadelupa | Lekarz rodzinny |
Guam | GU |
Gwatemala | GT |
Guernsey | GG |
Gwinea | GN |
Gwinea Bissau | GW |
Gujana | GY |
Haiti | HT |
Wyspy Heard i McDonald | HM |
Watykan | VA |
Honduras | HN |
Specjalny Region Administracyjny Hongkong | HK |
Węgry | HU |
Islandia | JEST |
Indie | W |
Indonezja | Identyfikator |
Irak | IQ |
Irlandia | IE (Internet Explorer) |
Izrael | Illinois |
Włochy | Dział IT |
Jamajka | JM |
Japonia | JP |
Jersey | JE |
Jordania | JO |
Kazachstan | Kazachstan |
Kenia | Komisja Europejska |
Kiribati | KI |
Korea | KR |
Kuwejt | KW |
Kirgistan | kg |
Laos | LA |
Łotwa | Łotwa |
Liban | FUNT |
Lesotho | LS |
Liberia | LR |
Libia | LY |
Liechtenstein | LI |
Litwa | LT |
Luksemburg | LU |
Makau SAR | MO |
Macedonia Północna | MK |
Madagaskar | MG |
Malawi | MW |
Malezja | moje |
Malediwy | MV |
Mali | ML (uczenie maszynowe) |
Malta | MT |
Wyspa Mana | Komunikator internetowy |
Wyspy Marshalla | MH |
Martynika | MQ |
Mauretania | PAN |
Mauritius | MU |
Majotta | YouTube |
Meksyk | MX |
Mikronezja | FM |
Mołdawia | Lekarz medycyny |
Monako | MC |
Mongolia | MN |
Montenegr - ME | |
Montserrat | MS |
Maroko | mgr |
Mozambik | MZ |
Myanmar | MM |
Namibia | NIE |
Nauru | NR |
Nepal | NP |
Holandia | Holandia |
Nowa Kaledonia | NC |
Nowa Zelandia | NZ |
Nikaragua | NI |
Niger | NE |
Nigeria | NG |
Niue | NU |
Wyspa Norfolk | NF |
Mariany Północne | poseł |
Norwegia | NIE |
Oman | OM |
Pakistan | PK |
Palau | PW |
Autonomia Palestyńska | Postscriptum |
Panama | TATUŚ |
Papua-Nowa Gwinea | PG |
Paragwaj | PY |
Peru | PE |
Filipiny | PH |
Wyspy Pitcairn | PN |
Polska | Polska |
Portugalia | PT |
Katar | Zapewnienie Jakości |
Spotkanie | ODP |
Rumunia | RO |
Rosja | Rosja |
Rwanda | RW |
Saint-Barthélemy | BL |
Święte Helena, Wniebowstąpienie i Tristan da Cunha | SH |
Saint Kitts i Nevis | KN |
Saint Lucia | LC |
Saint Martin (część francuska) | Ministerstwo Finansów |
Saint Pierre i Miquelon | po południu |
Saint Vincent i Grenadyny | Kapitał podwyższonego ryzyka (VC) |
Samoa | WS |
San Marino | SM |
Arabia Saudyjska | S.A. |
Senegal | SN |
Serbia | RS |
Seszele | SC |
Sierra Leone | SL |
Singapur | SG |
Sint Maarten (część holenderska) | SX |
Słowacja | SK |
Słowenia | Międzynarodowy Układ Jednostek SI |
Wyspy Salomona | SB |
Somalia | WIĘC |
Republika Południowej Afryki | ZA |
Georgia Południowa i Południowe Wyspy Sandwich | GS |
Hiszpania | ES |
Sri Lanka | LK |
Surinam | SR |
Svalbard i Jan Mayen | SJ |
Eswatini | SZ |
Szwecja | SE |
Szwajcaria | CH |
São Tomé i Príncipe | ST |
Tajwan | TW |
Tadżykistan | TJ |
Tanzania | TZ |
Tajlandia | TH |
Timor-Leste | TL |
Tog — TG | |
Tokelau | TK |
Tonga | DO |
Trynidad i Tobag - TT | |
Tunezja | TN |
Turcja | Turcja |
Turkmenistan | TM |
Wyspy Turks i Caicos | TC |
Tuvalu | TELEWIZJA |
Niewielkie wyspy zewnętrzne USA | Uniwersytet Michigan |
Wyspy Dziewicze Stanów Zjednoczonych | VI |
Uganda | UG |
Ukraina | UA |
Zjednoczone Emiraty Arabskie | AE |
Wielka Brytania | GB |
Stany Zjednoczone | USA |
Urugwaj | UY |
Uzbekistan | UZ |
Vanuatu | VU |
Wietnam | VN |
Wallis i Futuna | WF |
Jemen | Jemen |
Zambia | ZM |
Zimbabwe | ZW |
Wyspy Alandzkie | SIEKIERA |
Kategorie i podkategorie
Kategoria | Podkategorie |
---|---|
Książki i Odniesienia | Czytnik e-booków, Fikcja, Literatura faktu, Literatura naukowa |
Biznes | Księgowość i finanse, Współpraca, CRM, Dane i analityka, Zarządzanie plikami, Inwentaryzacja i logistyka, Prawo i HR, Zarządzanie projektami, Pulpit zdalny, Sprzedaż i marketing, Czas i wydatki |
DeveloperTools | Bazy danych, Narzędzia projektowe, Zestawy deweloperskie, Sieć komputerowa, Materiały referencyjne i szkoleniowe, Serwery, Narzędzia administracyjne, Hosting stron WWW |
Edukacja | KsiążkiEdukacyjneIReferencyjne, WczesnaNauka, NarzędziaInstruktażowe, Język, PomocNaukowa |
Rozrywka | (N/A) |
FoodAndDining | (N/A) |
Rząd i polityka | (N/A) |
Zdrowie i Fitness | (N/A) |
Dzieci i Rodzina | KsiążkiIDokumentyDlaDzieciIRodziny, RozrywkaDlaDzieciIRodziny, HobbyIZabawki, SportIAktywności, PodróżeDlaDzieciIRodziny |
Styl życia | Automotive, DIY, Dom i Ogród, Relacje, Zainteresowania Specjalne, Styl i Moda |
Medyczny | (N/A) |
Projektowanie multimedialne | Ilustracja i projektowanie graficzne, Produkcja muzyczna, Produkcja fotograficzna i wideo |
Muzyka | (N/A) |
NavigationAndMaps | (N/A) |
WiadomościIPogoda | Wiadomości, pogoda |
Finanse osobiste | Bankowość I Inwestycje, Budżetowanie I Podatki |
Personalizacja | Dzwonki i Dźwięki, motywy, Tapety i Ekrany Blokady |
Zdjęcie i Video | (N/A) |
Produktywność | (N/A) |
Bezpieczeństwo | PCProtection, PersonalSecurity |
Zakupy | (N/A) |
Społeczny | (N/A) |
Sport | (N/A) |
Podróż | CityGuides, Hotele |
Narzędzia i narzędzia pomocnicze | BackupAndManage, FileManager |
Języki
Nazwa języka | Obsługiwane kody języków |
---|---|
Afrikaans | af, af-za |
Albański | sq, sq-al |
Amharski | rano, am-et |
Armeński | Cześć, hy-am |
język assamski | as, as-in |
Azerbejdżańcy | az-arab, az-arab-az, az-cyrl, az-cyrl-az, az-latn, az-latn-az |
Baskijski (baskijski) | ja, eu-es |
Białoruski | bądź, be-by |
język bengalski | bn, bn-bd, bn-in |
Bośniacki | bs, bs-cyrl, bs-cyrl-ba, bs-latn, bs-latn-ba |
Bułgarski | bg, bg-bg |
Kataloński | ca, ca-es, ca-es-valencia |
Cherokee | chr-cher, chr-cher-us, chr-latn |
Chiński (uproszczony) | zh-Hans, zh-cn, zh-hans-cn, zh-sg, zh-hans-sg |
Chiński (tradycyjny) | zh-Hant, zh-hk, zh-mo, zh-tw, zh-hant-hk, zh-potent-mo, zh-potent-tw, zh-mo, zh-tw, zh-tweet-hk, zh-tweet-mo, zh-hant-tw |
Chorwacki | hr, hr-hr, hr-ba |
Czeski | cs, cs-cz |
Duński | tak, da-dk |
Dari | prs, prs-af, prs-arab |
Niderlandzki | nl, nl-nl, nl-be |
angielski | 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-phen-pk, en-tt, en-vn, en-zw |
Estoński | oraz, et-ee |
Filipin - fil, fil-latn, fil-ph | |
Fiński | fi, fi-fi |
Francuski | 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 |
Galicyjski | gl, gl-es |
Gruziński | ka, ka-ge |
Niemiecki | de, de-at, de-ch, de-de, de-lu, de-li |
Grecki | el, el-gr |
Gudżarati | gu, gu-in |
Hausa | ha, ha-latn, ha-latn-ng |
Hebrajski | on, he-il |
Język hindi | cześć, hi-in |
Węgierski | hu, hu-hu |
Islandzki | jest, is-is |
Igb — ig-latn, ig-ng | |
Indonezyjski | id, id-id |
Inuktitut (łaciński) | iu-cans, iu-latn, iu-latn-ca |
Irlandzki | ga, ga-ie |
isiXhosa | xh, xh-za |
isiZulu | zu, zu-za |
Włoski | to, it-it, it-ch |
Japoński | tak , ja-jp |
Kannada | kn, kn-in |
język kazachski | kk, kk-kz |
język khmerski | km, km-kh |
K'iche' | quc-latn, qut-gt, qut-latn |
Kinyarwanda | rw, rw-rw |
Suahili | sw, sw-ke |
Konkani | kok, kok-in |
Koreański | ko, ko-kr |
Kurdyjski | ku-arab, ku-arab-iq |
Kirgiski | ky-kg, ky-cyrl |
Laotański | lo, lo-la |
Łotewski | lv, lv-lv |
Litewski | lt, lt-lt |
Luksemburski | lb, lb-lu |
Macedoński | mk, mk-mk |
Malajski | ms, ms-bn, ms-my |
Malayalam | ml, ml-in |
Maltański | mt, mt-mt |
Māori | mi, mi-latn, mi-nz |
Marathi | pan, mr-in |
Mongolski (cyrylica) | mn-cyrl, mn-mong, mn-mn, mn-phag |
Nepalski | nie, ne-np |
Norweski | nb, nb-no, nn, nn-no, nie, no-no |
Orija | lub, or-in |
Perski | fa, fa-ir |
Polski | pl, pl-pl |
portugalski (Brazylia) | pt-br |
Język portugalski (Portugalia) | pt, pt-pt |
Pendżabski | pa, pa-arab, pa-arab-pk, pa-deva, pa-in |
Keczua | quz, quz-bo, quz-ec, quz-pe |
Rumuński | ro, ro-ro |
Rosyjski | ru , ru-ru |
Szkocki gaelicki | gd-gb, gd-latn |
Serbski (łaciński) | sr-Latn, sr-latn-cs, sr-latn-ba, sr-latn-me, sr-latn-rs |
Serbski (cyrylica) | 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 | tak, si-lk |
Słowacki | sk, sk-sk |
Słoweński | sl, sl-si |
Hiszpański | 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-uses-uy, es-ve |
Szwedzki | sv, sv-se, sv-fi |
język tadżycki (cyrylica) | tg-arab, tg-cyrl, tg-cyrl-tj, tg-latn |
język tamilski | ta, ta-in |
Tatarski | tt-arab, tt-cyrl, tt-latn, tt-ru |
Telugu | te, te-in |
Tajska | th, th-th |
Tigrinia | ti, ti-et |
Turecki | tr, tr-tr |
Turkmeński | tk-cyrl, tk-latn, tk-tm, tk-latn-tr, tk-cyrl-tr |
Ukraiński | uk, uk-ua |
urdu | twój, ur-pk |
Ujgur | ug-arab, ug-cn, ug-cyrl, ug-latn |
Uzbek (łaciński) | uz, uz-cyrl, uz-latn, uz-latn-uz |
Wietnamski | vi, vi-vn |
Walijski | cy, cy-gb |
Wolof | wo, wo-sn |
Joruba | yo-latn, yo-ng |
Przykładowe żądanie
{
"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"]
}
nagłówki odpowiedzi
Nagłówek | Wartość |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Można to udostępnić zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, przez który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | Zawiera rzeczywisty ładunek odpowiedzi dla żądania |
adres ankiety | Sznurek | Adres URL do sondowania w celu sprawdzenia statusu każdego przesłania In-Progress |
identyfikatorTrwającegoZgłoszenia | Sznurek | Identyfikator zgłoszenia jakiegokolwiek już przesłanego In-Progress |
Przykładowa odpowiedź
{
"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": ""
}
}
Pozyskaj bieżące wersje robocze pakietów interfejsu API
Pobiera szczegóły pakietu w bieżącej wersji roboczej przesyłania.
ścieżka [Wszystkie pakiety]: /submission/v1/product/{productId}/packages
, metoda: GET
ścieżka [pojedynczy pakiet]: /submission/v1/product/{product/{productId}/packages/{packageId}
, metoda: GET
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
packageId (identyfikator pakietu) | Unikatowy identyfikator pakietu do pobrania |
Wymagane nagłówki
Nagłówek | Wartość |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
nagłówki odpowiedzi
Nagłówek | Wartość |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista błędów lub komunikatów ostrzegawczych, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
pakiety | Tablica obiektów | Obiekt do przechowywania danych modułu pakietu |
packageId (identyfikator pakietu) | Sznurek | |
adresPakietu | Sznurek | |
Języki | Tablica ciągów znaków | |
Architektury | Tablica ciągów znaków | [Neutral, X86, X64, Arm, Arm64] |
isSilentInstall | Boolowski | Należy oznaczyć jako prawda, jeśli instalator działa w trybie dyskretnym bez potrzeby użycia przełączników, w przeciwnym razie nieprawda. |
parametry instalatora | Sznurek | |
genericDocUrl | Sznurek | |
szczegóły błędu | Tablica obiektów | |
scenariusz błędu | Sznurek | |
SzczegółyScenariuszaBłędu | Tablica obiektów | |
wartość błędu | Sznurek | |
adresURLbłąd | Sznurek | |
typ pakietu | Sznurek |
Przykładowa odpowiedź
{
"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",
}]
}
}
Zaktualizuj interfejs API bieżących pakietów roboczych
Uzupełnia szczegóły pakietu w ramach bieżącej wersji roboczej zgłoszenia.
Ścieżka [pełna aktualizacja modułu]: /submission/v1/product/{productId}/packages
, metoda: PUT
ścieżka [aktualizacja poprawki pojedynczego pakietu]: /submission/v1/product/{productId}/packages/{packageId}
: metoda: PATCH
zachowania interfejsu API
W przypadku interfejsu API aktualizacji pełnego modułu — kompletne dane pakietów muszą być zawarte w żądaniu, aby zaktualizować wszystkie pola. Każde pole, które nie jest obecne w żądaniu, jej wartość domyślna zostaje użyta do zastąpienia bieżącej wartości dla danego modułu. Spowoduje to zastąpienie wszystkich istniejących pakietów nowym zestawem pakietów wynikających z żądania. Spowoduje to ponowne generowanie identyfikatorów pakietów, a użytkownik powinien wywołać interfejs API GET Packages dla najnowszych identyfikatorów pakietów.
W przypadku interfejsu API aktualizacji pojedynczego pakietu — w żądaniu muszą znajdować się tylko pola, które mają zostać zaktualizowane dla danego pakietu. Te wartości pól z żądania zastąpią ich istniejące wartości, zachowując wszystkie inne pola, które nie są obecne w żądaniu, takie jak bieżące dla tego konkretnego pakietu. Inne pakiety w zestawie pozostają w niezmienionej postaci.
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
packageId (identyfikator pakietu) | Unikatowy identyfikator pakietu |
Wymagane nagłówki
Nagłówek | Wartość |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
Parametry żądania
Nazwa | Typ | Opis |
---|---|---|
pakiety | Tablica obiektów | Obiekt do przechowywania danych modułu pakietu [Wymagane tylko do pełnej aktualizacji modułu] |
adresPakietu | Sznurek | Wymagane |
Języki | Tablica ciągów znaków | Wymagane |
Architektury | Tablica ciągów znaków | wymagane powinna zawierać jedną architekturę — Neutral, X86, X64, Arm, Arm64 |
isSilentInstall | Boolowski | Wymagane Powinno być ustawione jako prawda, jeśli instalator działa w trybie dyskretnym bez konieczności użycia przełączników, w przeciwnym razie jako fałsz. |
parametry instalatora | Sznurek | Wymagane, jeśli isSilentInstall ma wartość false |
genericDocUrl | Sznurek | Wymagane, jeśli parametr packageType jest exe Link do dokumentu zawierającego szczegóły niestandardowych kodów błędów instalatora typu EXE |
szczegóły błędu | Tablica obiektów | Metadane przeznaczone do przechowywania niestandardowych kodów błędów i szczegółów dla instalatorów typu EXE. |
scenariusz błędu | Sznurek | Zidentyfikuj konkretny scenariusz błędu. [instalacjaAnulowanaPrzezUżytkownika, aplikacjaJużIstnieje, instalacjaJużWTrakcie, brakMiejscaNaDysku, wymaganePonowneUruchomienie, awariaSieci, pakietOdrzuconyPodczasInstalacji, instalacjaZakończonaSukcesem, różne] |
SzczegółyScenariuszaBłędu | Tablica obiektów | |
wartość błędu | Sznurek | Kod błędu, który może być obecny podczas instalacji |
adresURLbłąd | Sznurek | Adres URL, aby uzyskać szczegółowe informacje o błędzie |
typ pakietu | Sznurek | wymagane [exe, msi] |
Przykładowe żądanie [pełna aktualizacja modułu]
{
"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",
}]
}
przykładowe żądanie [aktualizacja poprawki pojedynczego pakietu]
{
"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",
}
nagłówki odpowiedzi
Nagłówek | Wartość |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | [Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieje] |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
adres ankiety | Sznurek | [Adres URL do odpytywania, aby uzyskać stan przesłania w razie już przesłania In-Progress] |
identyfikatorTrwającegoZgłoszenia | Sznurek | [Identyfikator dowolnego już istniejącego przesłania In-Progress] |
Przykładowa odpowiedź
{
"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": ""
}
}
Interfejs API zatwierdzania pakietów
Zatwierdza nowy zestaw pakietów zaktualizowanych przy użyciu interfejsów API aktualizacji pakietów w ramach bieżącej wersji roboczej. Ten interfejs API zwraca adres URL sondowania do śledzenia przesyłania pakietu.
ścieżka: /submission/v1/product/{productId}/packages/commit
, metoda: POST
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Wymagane nagłówki
Nagłówek | Wartość |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
nagłówki odpowiedzi
Nagłówek | Wartość |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | [Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieje] |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
adres ankiety | Sznurek | [Adres URL sondowania, aby uzyskać stan przekazywania lub przesyłania pakietu w przypadku dowolnego już In-Progress przesyłania] |
identyfikatorTrwającegoZgłoszenia | Sznurek | [Identyfikator przesyłania dowolnego już In-Progress przesłania] |
Przykładowa odpowiedź
{
"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": ""
}
}
Pobierz bieżący interfejs API zasobów listy roboczej
Pobiera szczegóły elementów zawartości w bieżącej wersji roboczej przesyłania.
ścieżka: /submission/v1/product/{productId}/listings/assets?languages={languages}
, metoda: GET
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Parametry zapytania
Nazwa | Opis |
---|---|
Języki | [Opcjonalnie] Lista języków filtruje jako ciąg rozdzielony przecinkami [limit do 200 języków]. W przypadku nieobecności, zostaną pobrane dane pierwszych 200 dostępnych zasobów w języku ogłoszenia. (np. "en-us, en-gb") |
Wymagane nagłówki
Nagłówek | Wartość |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
nagłówki odpowiedzi
Nagłówek | Wartość |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
wyświetlanie zasobów | Tablica obiektów | Wyświetlanie szczegółów zasobów dla każdego języka |
Język | Sznurek | |
logotypySklepów | Tablica obiektów | |
zrzuty ekranu | Tablica obiektów | |
id | Sznurek | |
assetUrl | Sznurek | Musi być prawidłowym adresem URL |
rozmiarObrazu | Przedmiot | |
Szerokość | Liczba całkowita | |
wysokość | Liczba całkowita |
Przykładowa odpowiedź
{
"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
}
}
]
}]
}
}
Interfejs API do tworzenia zasobów listingu
Tworzy nowe przesyłanie zasobów listingu w ramach bieżącej wersji roboczej zgłoszenia.
Aktualizacja zasobów listy
Interfejs API przesyłania ze sklepu Microsoft Store dla pliku EXE lub aplikacji MSI używa adresów SAS generowanych przez środowisko uruchomieniowe do magazynów Blob dla każdego przekazywania poszczególnych zasobów obrazu oraz wywołania interfejsu API zatwierdzania po pomyślnym przekazaniu. Aby mieć możliwość aktualizowania zasobów listy i z kolei, aby można było dodawać/usuwać ustawienia regionalne w module listy, można użyć następującego podejścia:
- Użyj interfejsu API Create Listing Asset, aby wysłać żądanie dotyczące przesyłania zasobów wraz z językiem, typem i ilością zasobów.
- Na podstawie liczby żądanych zasobów identyfikatory zasobów są tworzone na żądanie i mogłyby utworzyć krótkoterminowy adres URL sygnatury dostępu współdzielonego i wysłać go z powrotem w treści odpowiedzi pod typem zasobów. Za pomocą tego adresu URL można przekazać zasoby obrazów określonego typu przy użyciu klientów HTTP [Put Blob (interfejs API REST) — Azure Storage | Microsoft Docs].
- Po przekazaniu możesz skorzystać z interfejsu API zatwierdzania zasobów na liście, aby również wysłać nowe informacje o identyfikatorze zasobu, które otrzymano wcześniej z poprzedniego wywołania interfejsu API. Pojedynczy interfejs API wewnętrznie zatwierdzi dane zasobów listy po weryfikacji.
- Takie podejście skutecznie zastąpi cały zestaw poprzednich obrazów typu zasobu w określonym języku, który jest wysyłany w żądaniu. W związku z tym wcześniej przesłane zasoby zostaną usunięte.
ścieżka: /submission/v1/product/{productId}/listings/assets/create
, metoda: POST
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Wymagane nagłówki
Nagłówek | Opis |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
Parametry żądania
Nazwa | Typ | Opis |
---|---|---|
Język | Sznurek | Wymagane |
utwórzŻądanieUtworzeniaZasobu | Przedmiot | Wymagane |
Zrzut ekranu | Liczba całkowita | Wymagane, jeśli niezależny dostawca oprogramowania musi zaktualizować zrzuty ekranu lub dodać nowy język opisu [1–10] |
Logo | Liczba całkowita | Wymagane, jeśli niezależny dostawca oprogramowania musi zaktualizować logo lub dodać nowy język ogłoszenia [1 lub 2] |
nagłówki odpowiedzi
Nagłówek | Opis |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
wyświetlanie zasobów | Przedmiot | Obiekt zawierający szczegółowe informacje o StoreLogos i Zrzutach ekranu do przesłania |
Język | Sznurek | |
logotypySklepów | Tablica obiektów | |
zrzuty ekranu | Tablica obiektów | |
id | Sznurek | |
primaryAssetUploadUrl | Sznurek | Podstawowy adres URL do przekazywania elementu zawartości listy przy użyciu interfejsu API REST obiektu blob platformy Azure |
adres przesyłania dodatkowych zasobów | Sznurek | Pomocniczy adres URL do przekazywania elementu zawartości listy przy użyciu interfejsu API REST usługi Azure Blob |
HTTPMetoda | Metoda HTTP | Metoda HTTP musi służyć do przekazywania zasobów za pośrednictwem adresów URL przekazywania zasobów — podstawowy lub pomocniczy |
Nagłówki HTTP | Przedmiot | Obiekt, w którym kluczami są wymagane nagłówki do umieszczenia w wywołaniu API do przekazywania na adresy URL przesyłania zasobów. Jeśli wartość jest niepusta, nagłówki muszą mieć określone wartości. W przeciwnym razie wartości są obliczane podczas wywoływania interfejsu API. |
Przykładowa odpowiedź
{
"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"}
}]
}
}
}
Interfejs API zarządzania listą zasobów
Zatwierdza nowy przesłany zasób listingu, korzystając ze szczegółów z interfejsu API tworzenia aktywów, w ramach bieżącej wersji roboczej zgłoszenia.
ścieżka: /submission/v1/product/{productId}/listings/assets/commit
, metoda: PUT
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Wymagane nagłówki
Nagłówek | Opis |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
Parametry żądania
Nazwa | Typ | Opis |
---|---|---|
wyświetlanie zasobów | Przedmiot | |
Język | Sznurek | |
logotypySklepów | Tablica obiektów | |
zrzuty ekranu | Tablica obiektów | |
id | Sznurek | Powinien być albo istniejącym identyfikatorem, który użytkownik chce zachować z interfejsu API Pobierz Bieżące Zasoby Listy, albo nowym identyfikatorem, pod którym nowy zasób został przekazany w interfejsie API Utwórz Zasoby Listy. |
assetUrl | Sznurek | Powinien być adresem URL istniejącego zasobu, który użytkownik chce zachować z interfejsu API Pobierz bieżące zasoby listy, lub adresem URL przesyłania — podstawowym lub pomocniczym, za pomocą którego nowy zasób został przesłany w interfejsie API Tworzenie zasobów listy. Musi być prawidłowym adresem URL |
Przykładowe żądanie
{
"listingAssets": {
"language": "en-us",
"storeLogos": [
{
"id": "1234567890abcdefgh",
"assetUrl": "https://contoso.com/blob=1234567890abcdefgh",
}
],
"screenshots": [
{
"id": "1234567891abcdefgh",
"assetUrl": "https://contoso.com/blob=1234567891abcdefgh",
}
]
}
}
nagłówki odpowiedzi
Nagłówek | Opis |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
adres ankiety | Sznurek | Adres URL do regularnego sprawdzania statusu przesyłania w toku |
identyfikatorTrwającegoZgłoszenia | Sznurek | Identyfikator zgłoszenia jakiegokolwiek w trakcie przesłania |
Przykładowa odpowiedź
{
"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": ""
}
}
Interfejs API odpytywania stanu modułu
Interfejs API do sprawdzenia gotowości modułu przed przesłaniem może być utworzony. Sprawdza również stan przesyłania pakietu.
ścieżka: /submission/v1/product/{productId}/status
, metoda: GET
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Wymagane nagłówki
Nagłówek | Opis |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
nagłówki odpowiedzi
Nagłówek | Opis |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
gotowy | Boolowski | Wskazuje, czy wszystkie moduły są w gotowym stanie, w tym przesyłanie pakietu. |
identyfikatorTrwającegoZgłoszenia | Sznurek | Identyfikator zgłoszenia jakiegokolwiek w trakcie przesłania |
Przykładowa odpowiedź
{
"isSuccess": true,
"errors": [{
"code": "badrequest",
"message": "Error Message 1",
"target": "listings"
}, {
"code": "warning",
"message": "Warning Message 1",
"target": "properties"
}],
"responseData": {
"isReady": true,
"ongoingSubmissionId": ""
}
}
Utwórz interfejs API przesyłania
Tworzy zgłoszenie z bieżącej wersji roboczej aplikacji typu MSI lub EXE. Interfejs API sprawdza:
- Jeśli istnieje aktywne przesyłanie, próba zakończy się niepowodzeniem i pojawi się komunikat o błędzie.
- jeśli wszystkie moduły są w stanie gotowości, aby utworzyć zgłoszenie.
- każde pole w zgłoszeniu jest weryfikowane zgodnie z wymaganiami sklepu
ścieżka:/submit/v1/product/{productId}/submit
, metoda: POST
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Wymagane nagłówki
Nagłówek | Opis |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
nagłówki odpowiedzi
Nagłówek | Opis |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
adres ankiety | Sznurek | Adres URL odpytywania w celu uzyskania statusu gotowości modułu, w tym przesyłania pakietu do zgłoszenia. |
ID zgłoszenia | Sznurek | Identyfikator nowo utworzonego zgłoszenia |
identyfikatorTrwającegoZgłoszenia | Sznurek | Identyfikator zgłoszenia jakiegokolwiek w trakcie przesłania |
Przykładowa odpowiedź
{
"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": ""
}
}
Interfejs API sondowania statusu przesyłki
Interfejs API do sprawdzenia statusu przesyłania.
ścieżka: /submission/v1/product/{productId}/submission/{submissionId}/status
, metoda: GET
Parametry ścieżki
Nazwa | Opis |
---|---|
ID produktu | Identyfikator Partner Center produktu |
Wymagane nagłówki
Nagłówek | Opis |
---|---|
Authorization: Bearer <Token> |
Używanie identyfikatora aplikacji usługi Azure AD zarejestrowanego przy użyciu konta Centrum partnerskiego |
X-Seller-Account-Id |
Identyfikator konta sprzedawcy w Centrum partnerskim |
nagłówki odpowiedzi
Nagłówek | Opis |
---|---|
X-Correlation-ID |
Unikatowy identyfikator typu GUID dla każdego żądania. Może to być udostępniane zespołowi pomocy technicznej w celu analizowania dowolnego problemu. |
Retry-After |
Czas w sekundach, który klient musi czekać przed ponownym wywołaniem interfejsów API z powodu ograniczania szybkości. |
Parametry odpowiedzi
Nazwa | Typ | Opis |
---|---|---|
czySukces | Boolowski | |
Błędy | Tablica obiektów | Lista komunikatów o błędach lub ostrzeżeniach, jeśli istnieją |
kod | Sznurek | Kod błędu komunikatu |
Komunikat | Sznurek | Opis błędu |
cel | Sznurek | Jednostka, z której pochodzi błąd |
dane odpowiedzi | Przedmiot | |
status publikacji | Sznurek | Status publikacji zgłoszenia — [W TRAKCIE, OPUBLIKOWANO, NIE POWIODŁO SIĘ, NIEZNANY] |
niepowodzenie nastąpiło | Boolowski | Wskazuje, czy publikowanie nie powiodło się i nie zostanie ponowione |
Przykładowa odpowiedź
{
"isSuccess": true,
"errors": [{
"code": "badrequest",
"message": "Error Message 1",
"target": "listings"
}, {
"code": "warning",
"message": "Warning Message 1",
"target": "properties"
}],
"responseData": {
"publishingStatus": "INPROGRESS",
"hasFailed": false
}
}
Przykłady kodu
Poniższe artykuły zawierają szczegółowe przykłady kodu, które pokazują, jak używać interfejsu API przesyłania ze sklepu Microsoft Store w różnych językach programowania:
Przykład w języku C#: API przesyłania do sklepu Microsoft Store dla aplikacji MSI lub EXE
Ten artykuł zawiera przykłady kodu w języku C#, pokazujące, jak używać API przesyłania Microsoft Store dla aplikacji MSI lub EXE. Możesz przejrzeć każdy przykład, aby dowiedzieć się więcej o przedstawionym zadaniu lub utworzyć wszystkie przykłady kodu w tym artykule w aplikacji konsolowej.
Warunki wstępne W poniższych przykładach użyto następującej biblioteki:
- Pakiet NuGet Newtonsoft.Json firmy Newtonsoft.
Program główny Poniższy przykład implementuje przykładowy program wiersza polecenia, który wywołuje inne przykładowe metody w tym artykule, aby zademonstrować różne sposoby korzystania z interfejsu API przesyłania do sklepu Microsoft Store. Aby dostosować ten program do własnego użycia:
- Przypisz właściwość SellerId do identyfikatora sprzedawcy konta Centrum partnerskiego.
- Przypisz właściwość ApplicationId do identyfikatora aplikacji, którą chcesz zarządzać.
- Przypisz właściwości ClientId i ClientSecret do identyfikatora klienta i klucza dla swojej aplikacji, a następnie zastąp ciąg tenantid w adresie URL TokenEndpoint identyfikatorem dzierżawy dla Twojej aplikacji. Aby uzyskać więcej informacji, zobacz Jak skojarzyć aplikację usługi Azure AD z kontem Centrum partnerskiego
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();
}
}
}
ClientConfiguration, klasa pomocnika używająca języka C#
Przykładowa aplikacja używa klasy pomocniczej ClientConfiguration do przekazywania danych Azure Active Directory oraz danych aplikacji do metod przykładowych korzystających z API przesyłania 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; }
}
}
Utwórz zgłoszenie aplikacji przy użyciu języka C#
Poniższy przykład implementuje klasę, która używa kilku metod w interfejsie API przesyłania aplikacji do sklepu Microsoft Store do aktualizacji przesyłania aplikacji.
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.
}
}
}
IngestionClient, klasa pomocnika używająca języka C#
Klasa IngestionClient udostępnia metody pomocnicze, które są używane przez inne metody w przykładowej aplikacji do wykonywania następujących zadań:
- Uzyskaj token dostępu do Azure AD, który może służyć do wywoływania metod w interfejsie API zgłoszeń do sklepu Microsoft Store. Po uzyskaniu tokenu masz 60 minut na użycie tego tokenu w wywołaniach interfejsu API przesyłania do Microsoft Store, zanim token wygaśnie. Po wygaśnięciu tokenu możesz wygenerować nowy token.
- Przetwarzanie żądań HTTP dla interfejsu API przesyłania sklepu 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;
}
}
}
przykład Node.js: API Microsoft Store do przesyłania aplikacji MSI lub EXE
Ten artykuł zawiera przykłady kodu Node.js, które pokazują, jak używać interfejsu API przesyłania do Microsoft Store zarówno dla aplikacji MSI, jak i EXE. Możesz przejrzeć każdy przykład, aby dowiedzieć się więcej o przedstawionym zadaniu lub utworzyć wszystkie przykłady kodu w tym artykule w aplikacji konsolowej.
Warunki wstępne W poniższych przykładach użyto następującej biblioteki:
- Biblioteka node-fetch w wersji 2 [npm install node-fetch@2]
Przesyłanie aplikacji przy użyciu node.js
Poniższy przykład wywołuje inne przykładowe metody w tym artykule, aby zademonstrować różne sposoby korzystania z API przesyłania do Microsoft Store. Aby dostosować ten program do własnego użycia:
- Przypisz właściwość SellerId do identyfikatora sprzedawcy konta Centrum partnerskiego.
- Przypisz właściwość ApplicationId do identyfikatora aplikacji, którą chcesz zarządzać.
- Przypisz właściwości ClientId i ClientSecret do identyfikatora klienta i klucza dla swojej aplikacji, a następnie zastąp ciąg tenantid w adresie URL TokenEndpoint identyfikatorem dzierżawy dla Twojej aplikacji. Aby uzyskać więcej informacji, zobacz Jak skojarzyć aplikację usługi Azure AD z kontem Centrum partnerskiego
Poniższy przykład implementuje klasę, która używa kilku metod w interfejsie API przesyłania aplikacji do sklepu Microsoft Store do aktualizacji przesyłania aplikacji.
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();
Narzędzie wspomagające KonfiguracjęKlienta
Przykładowa aplikacja używa klasy pomocniczej ClientConfiguration do przekazywania danych Azure Active Directory oraz danych aplikacji do metod przykładowych korzystających z API przesyłania 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;
Klient IngestionClient wykorzystujący node.js
Klasa IngestionClient udostępnia metody pomocnicze, które są używane przez inne metody w przykładowej aplikacji do wykonywania następujących zadań:
- Uzyskaj token dostępu do Azure AD, który może służyć do wywoływania metod w interfejsie API zgłoszeń do sklepu Microsoft Store. Po uzyskaniu tokenu masz 60 minut na użycie tego tokenu w wywołaniach interfejsu API przesyłania do Microsoft Store, zanim token wygaśnie. Po wygaśnięciu tokenu możesz wygenerować nowy token.
- Przetwarzanie żądań HTTP dla interfejsu API przesyłania sklepu 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;
Dodatkowa pomoc
Jeśli masz pytania dotyczące interfejsu API przesyłania do sklepu Microsoft Store lub potrzebujesz pomocy w zarządzaniu przesyłaniem za pomocą tego interfejsu API, skorzystaj z następujących zasobów:
- Zadaj swoje pytania na naszych forach.
- Odwiedź naszą stronę pomocy technicznej i poproś o jedną z opcji wsparcia asystowanego dla Partner Center. Jeśli zostanie wyświetlony monit o wybranie typu i kategorii problemu, wybierz odpowiednio pozycję Przesyłanie aplikacji i certyfikacja oraz Przesyłanie aplikacji.