Freigeben über


Microsoft Store-Übermittlungs-API für MSI- oder EXE-App

Verwenden Sie die Microsoft Store-Übermittlungs-API für MSI- oder EXE-App zum programmgesteuerten Abfragen und Erstellen von Übermittlungen für MSI- oder EXE-Apps für das Partner Center-Konto Ihrer Organisation. Diese API ist nützlich, wenn Ihr Konto viele Apps verwaltet und Sie den Übermittlungsvorgang für diese Objekte automatisieren und optimieren möchten. Diese API verwendet Azure Active Directory (Azure AD) zum Autorisieren der Aufrufe von Ihrer App oder Ihrem Dienst.

Die folgenden Schritte beschreiben den End-to-End-Prozess der Verwendung der Microsoft Store-Übermittlungs-API:

  1. Stellen Sie sicher, dass alle Voraussetzungen erfüllt sind.
  2. Rufen Sie vor dem Aufrufen einer Methode in der Microsoft Store-Übermittlungs-API ein Azure AD-Zugriffstoken ab. Nach dem Abruf eines Tokens können Sie es für einen Zeitraum von 60 Minuten in Aufrufen der Microsoft Store-Übermittlungs-API verwenden, bevor es abläuft. Nach Ablauf des Tokens können Sie ein neues Token generieren.
  3. Rufen Sie die Microsoft Store-Übermittlungs-API für MSI- oder EXE-App auf.

Schritt 1: Erfüllen der Voraussetzungen für die Verwendung der Microsoft Store-Übermittlungs-API

Stellen Sie sicher, dass die folgenden Voraussetzungen erfüllt sind, bevor Sie mit dem Schreiben von Code zum Aufrufen der Microsoft Store-Übermittlungs-API für MSI- oder EXE-App beginnen.

  • Sie (oder Ihre Organisation) müssen über ein Azure AD-Verzeichnis verfügen, und Ihnen müssen die Berechtigungen globaler Administrator für das Verzeichnis gewährt worden sein. Wenn Sie Microsoft 365 oder andere Unternehmensdienste von Microsoft verwenden, verfügen Sie bereits über ein Azure AD-Verzeichnis. Andernfalls können Sie ohne zusätzliche Kosten eine neue Azure AD-Instanz in Partner Center erstellen.
  • Sie müssen Ihrem Partner Center-Konto eine Azure AD-Anwendung zuordnen und Ihre Mandanten-ID, die Client-ID und den Schlüssel abrufen. Sie benötigen diese Werte, um ein Azure AD-Zugriffstoken zu erhalten, das Sie in Aufrufen der Microsoft Store-Übermittlungs-API verwenden.
  • Bereiten Sie Ihre App mit der Microsoft Store-Übermittlungs-API auf den Einsatz vor:
    • Wenn Ihre App noch nicht im Partner Center vorhanden ist, müssen Sie im Partner Center Ihre App durch Reservieren eines Namens erstellen. Sie können die Microsoft Store-Übermittlungs-API nicht zum Erstellen einer App im Partner Center verwenden. Sie müssen für die Erstellung im Partner Center arbeiten und können danach über die API auf die App zugreifen und programmgesteuert Übermittlungen dafür erstellen.
    • Bevor Sie eine Übermittlung für eine bestimmte App mit dieser API erstellen können, müssen Sie zuerst eine Übermittlung für die App im Partner Center erstellen, einschließlich der Beantwortung des Fragebogens für Altersfreigaben . Anschließend können Sie über die API programmgesteuert neue Übermittlungen für diese App erstellen.
    • Wenn Sie eine App-Übermittlung erstellen oder aktualisieren und ein neues Paket aufnehmen müssen, müssen Sie die Paketdetails vorbereiten.
    • Wenn Sie eine App-Übermittlung erstellen oder aktualisieren und Screenshots oder Bilder für den Store-Eintrag aufnehmen müssen, müssen Sie die Screenshots und Bilder für die App vorbereiten.

Zuordnen einer Azure AD-Anwendung zu Ihrem Partner Center-Konto

Bevor Sie die Microsoft Store-Übermittlungs-API für MSI- oder EXE-App verwenden können, müssen Sie Ihrem Partner Center-Konto eine Azure AD-Anwendung zuordnen, die Mandanten-ID und die Client-ID für die Anwendung abrufen und einen Schlüssel generieren. Die Azure AD-Anwendung stellt die App oder den Dienst dar, von der bzw. dem aus Sie die Microsoft Store-Übermittlungs-API aufrufen möchten. Sie benötigen die Mandanten-ID, die Client-ID und den Schlüssel, um ein Azure AD-Zugriffstoken zu erhalten, das Sie an die API übergeben.

Hinweis

Sie müssen diese Aufgabe nur einmal ausführen. Nachdem Sie über die Mandanten-ID, die Client-ID und den Schlüssel verfügen, können Sie diese jederzeit wiederverwenden, wenn Sie ein neues Azure AD-Zugriffstoken erstellen müssen.

  1. Verknüpfen Sie in Partner Center das Partner Center-Konto Ihrer Organisation mit dem Azure AD-Verzeichnis Ihrer Organisation.
  2. Als Nächstes müssen Sie auf der Seite „Benutzer“ im Abschnitt „Kontoeinstellungen“ von Partner Center die Azure AD-Anwendung hinzufügen, die die App oder den Dienst darstellt, mit der bzw. dem Sie auf die Übermittlungen Ihres Partner Center-Kontos zugreifen. Stellen Sie sicher, dass Sie dieser Anwendung die Rolle Manager zuweisen. Wenn die Anwendung noch nicht in Ihrem Azure AD-Verzeichnis vorhanden ist, können Sie in Partner Center eine neue Azure AD-Anwendung erstellen.
  3. Kehren Sie zur Seite Benutzer zurück, klicken Sie auf den Namen Ihrer Azure AD-Anwendung, um die Anwendungseinstellungen zu öffnen, und schreiben Sie die Werte Mandanten-ID und Client-ID auf.
  4. Informationen zum Hinzufügen eines neuen Schlüssels oder geheimen Clientschlüssels finden Sie in den folgenden Anweisungen oder in den Anweisungen zum Registrieren der App über das Azure-Portal:

So registrieren Sie Ihre App:

  1. Melden Sie sich beim Azure-Portal an.

  2. Wenn Sie Zugriff auf mehrere Mandanten haben, verwenden Sie im Menü am oberen Rand den Filter Verzeichnis + Abonnement , um den Mandanten auszuwählen, in dem Sie die Anwendung registrieren möchten.

  3. Suchen Sie nach Azure Active Directory, und wählen Sie diese Option aus.

  4. Wählen Sie unter „Verwalten“ die „App-Registrierungen“ aus > wählen Sie Ihre Anwendung aus.

  5. Wählen Sie „Zertifikate und Geheimnisse“ > „Geheime Clientschlüssel“ > „Neuer geheimer Clientschlüssel“ aus.

  6. Fügen Sie eine Beschreibung für Ihren geheimen Clientschlüssel hinzu.

  7. Wählen Sie für das Geheimnis eine Ablauffrist aus, oder geben Sie eine benutzerdefinierte Lebensdauer an.

  8. Die Lebensdauer eines geheimen Clientschlüssels ist auf maximal zwei Jahre (24 Monate) begrenzt. Das bedeutet, dass keine benutzerdefinierte Lebensdauer angegeben werden kann, die über die 24 Monate hinausgeht.

    Hinweis

    Microsoft empfiehlt, den Wert für die Ablauffrist auf maximal 12 Monate festzulegen.

  9. Wählen Sie Hinzufügen.

  10. Notieren Sie sich den Wert des Geheimnisses, das in Ihrem Clientanwendungscode verwendet werden soll. Dieser Geheimniswert kann nach Verlassen dieser Seite nicht erneut angezeigt werden.

Schritt 2: Abrufen eines Azure AD-Zugriffstokens

Bevor Sie eine der Methoden in der Microsoft Store-Übermittlungs-API für MSI- oder EXE-App aufrufen, müssen Sie zunächst ein Azure AD-Zugriffstoken abrufen, das Sie an den Autorisierungsheader jeder Methode in der API übergeben. Nachdem Sie ein Zugriffstoken erhalten haben, haben Sie 60 Minuten Zeit, es zu verwenden, bevor es abläuft. Nach dem Ablauf können Sie das Token aktualisieren, damit Sie es in weiteren Aufrufen der API weiterhin verwenden können.

Gehen Sie zum Abrufen des Zugriffstokens nach den Anweisungen unter [Dienst-zu-Dienst-Aufrufe mit Clientanmeldedaten]/azure/active-directory/azuread-dev/v1-oauth2-client-creds-grant-flow) vor, um einen HTTP POST an den https://login.microsoftonline.com/<tenant_id>/oauth2/token-Endpunkt zu senden. Hier ist eine Beispielanforderung:

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

Geben Sie die Mandanten-ID, die Client-ID und den Schlüssel für die Anwendung, die Sie im vorherigen Abschnitt aus Partner Center abgerufen haben, für den Wert tenant_id im POST-URI sowie die Parameter client_id und client_secret an. Für den Bereichsparameter müssen Sie https://api.store.microsoft.com/.default angeben.

Nachdem Ihr Zugriffstoken abgelaufen ist, können Sie es nach den hier beschriebenen Anweisungen erneuern.

Beispiele zum Abrufen eines Zugriffstokens unter Verwendung von C# oder Node.js finden Sie in den Codebeispielen für die Microsoft Store-Übermittlungs-API für MSI- oder EXE-App.

Schritt 3: Verwenden der Microsoft Store-Übermittlungs-API

Nachdem Sie über ein Azure AD-Zugriffstoken verfügen, können Sie in der Microsoft Store-Übermittlungs-API für MSI- oder EXE-App Methoden aufrufen. Die API enthält viele Methoden, die in Szenarien für Apps gruppiert sind. Zum Erstellen oder Aktualisieren von Übermittlungen werden in der Regel mehrere Methoden in einer bestimmten Reihenfolge aufgerufen. Informationen zu den einzelnen Szenarien und zur Syntax der einzelnen Methoden finden Sie in den folgenden Abschnitten:

Hinweis

Nach dem Abruf eines Zugriffstokens haben Sie 60 Minuten Zeit zum Aufrufen von Methoden in der Microsoft Store-Übermittlungs-API für MSI- oder EXE-App, bevor es abläuft.

Basis-URL

Die Basis-URL für die Microsoft Store-Übermittlungs-API für MSI- oder EXE-App ist: https://api.store.microsoft.com

API-Verträge

API zum Abrufen der aktuellen Metadaten für Übermittlungsentwürfe

Ruft Metadaten in jedem Modul (Listings, Eigenschaften oder Verfügbarkeit) zum aktuellen Übermittlungsentwurf ab.

Pfad [Alle Module]: /submission/v1/product/{productId}/metadata?languages={languages}&includelanguagelist={true/false}
Pfad [Einzelnes Modul]: /submission/v1/product/{productId}/metadata/{moduleName}?languages={languages}&includelanguagelist={true/false}
Methode: GET

Pfadparameter

Parameter Beschreibung
Produkt-ID Die Partner Center-ID des Produkts
Modulname Partner Center-Modul – Listings, Eigenschaften oder Verfügbarkeit

Abfrageparameter

Parameter Beschreibung
Sprachen Optional Der Listingsprachenfilter als kommagetrennte Zeichenkette [maximal 200 Sprachen].

Wenn nicht vorhanden, werden die Metadaten der ersten 200 verfügbaren Listingsprachen abgerufen. [ z. B. „en-us, en-gb“].
SprachlisteEinfügen Optional Boolean – wenn „true“, wird die Liste der hinzugefügten Listingsprachen und der Status ihrer Abgeschlossenheit zurückgegeben.

Erforderliche Header

Kopfzeile Wert
Authorization: Bearer <Token> Die im Partner Center-Konto registrierte Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Antwortheader

Kopfzeile Wert
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
Barrierefreiheitsunterstützung Boolescher Typ (Boolean)
zusätzliche Lizenzbedingungen Schnur
Verfügbarkeit Objekt Daten des Verfügbarkeitsmoduls
Kategorie Schnur Siehe Liste der Kategorien unten
Zertifizierungsnotizen Schnur
Code Schnur Der Fehlercode der Meldung
Kontaktinformationen Schnur
Urheberrecht Schnur
dependsOnDriversOrNT Boolescher Typ (Boolean)
Beschreibung Schnur
entwickelt von Schnur
Auffindbarkeit Schnur [AUFFINDBAR, DEEPLINK_ONLY]
enableInFutureMarkets Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
kostenlose Testversion Schnur [NO_FREE_TRIAL; FREE_TRIAL]
Hardwareelementtyp Schnur
IstDatenschutzrichtlinieErforderlich Boolescher Typ (Boolean)
wirdEmpfohlen Boolescher Typ (Boolean)
erforderlich Boolescher Typ (Boolean)
IsSuccess Boolescher Typ (Boolean)
isSystemFeatureRequired Array von Objekten
Sprache Schnur Siehe Liste der Sprachen unten
Auflistungen Array von Objekten Daten des Listingmoduls für jede Sprache
Märkte Array aus Zeichenfolgen Siehe Liste der Märkte unten
Nachricht Schnur Die Beschreibung des Fehlers
Minimale Hardware Schnur
Mindestanforderung Schnur
penAndInkSupport Boolescher Typ (Boolean)
Preise Schnur [KOSTENLOS, FREEMIUM, ABONNEMENT, BEZAHLT]
Datenschutzrichtlinie-URL Schnur
Produktdeklarationen Objekt
Produkteigenschaften Array aus Zeichenfolgen
Eigenschaften Objekt Daten des Eigenschaftenmoduls
empfohlene Hardware Schnur
empfohleneAnforderung Schnur
Antwortdaten Objekt Enthält die tatsächliche Antwort-Payload für die Anforderung.
Anforderungen Array von Objekten
Suchbegriffe Array aus Zeichenfolgen
kurzeBeschreibung Schnur
Unterkategorie Schnur Siehe Liste der Unterkategorien unten
Support-Kontaktinformationen Schnur
Systemanforderungsdetails Array von Objekten
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Website Schnur
Neues Schnur

Beispiel für eine Antwort

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

API zum Aktualisieren der aktuellen Metadaten für Übermittlungsentwürfe

Aktualisiert Metadaten in jedem Modul des Übermittlungsentwurfs Die API-Prüfungen

  • Für aktive Übermittlung. Wenn vorhanden, Fehler mit Fehlermeldung.
  • Zum Zulassen des Vorgangs „Entwurf speichern“, wenn alle Module den Status „Bereit“ haben.
  • Jedes Feld in der Übermittlung wird gemäß den Anforderungen des Store auf Gültigkeit geprüft.
  • Gültigkeitsprüfungsregeln für Details der Systemanforderungen:
    • Zulässige Werte in hardwareItemType = Memory: 300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB
    • Zulässige Werte in hardwareItemType = DirectX: DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12
    • Zulässige Werte in hardwareItemType = Video_Memory: 1GB, 2GB, 4GB, 6GB

Pfad [Vollständiges Update des Moduls]: /submission/v1/product/{productId}/metadata
Methode: PUT

Pfad [Patch-Update des Moduls]: /submission/v1/product/{productId}/metadata
Methode: PATCH

API-Verhalten

Im Fall der API für ein vollständiges Update des Moduls müssen für eine vollständige Aktualisierung jedes Felds sämtliche Moduldaten in der Anforderung vorhanden sein. Bei jedem in der Anforderung nicht vorhanden Feld wird zum Überschreiben des aktuellen Werts für das betreffende Modul der Standardwert verwendet.
Im Fall der API für ein Patch-Update des Moduls müssen nur die zu aktualisierenden Felder in der Anforderung vorhanden sein. Diese Feldwerte aus der Anforderung überschreiben die jeweils vorhandenen Werte, wobei alle anderen Felder, die in der Anforderung nicht vorhanden sind, für das betreffende Modul unverändert bleiben.

Pfadparameter

Parameter Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Erforderliche Header

Kopfzeile Wert
Authorization: Bearer <Token> Die im Partner Center-Konto registrierte Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Anforderungsparameter

Name Typ Beschreibung
Verfügbarkeit Objekt Objekt zum Aufnehmen der Metadaten des Verfügbarkeitsmoduls
Märkte Array aus Zeichenfolgen Erforderlich Siehe Liste der Märkte unten
Auffindbarkeit Schnur Erforderlich [DISCOVERABLE, DEEPLINK_ONLY]
enableInFutureMarkets Boolescher Typ (Boolean) Erforderlich
Preise Schnur Erforderlich [FREE, FREEMIUM, SUBSCRIPTION, PAID]
kostenlose Testversion Schnur Erforderlich, wenn für Preise PAID oder SUBSCRIPTION angegeben ist [NO_FREE_TRIAL, FREE_TRIAL]
Eigenschaften Objekt Objekt zum Aufnehmen der Metadaten des Eigenschaftenmoduls
IstDatenschutzrichtlinieErforderlich Boolescher Typ (Boolean) Erforderlich
Datenschutzrichtlinie-URL Schnur Erforderlich, wenn isPrivacyPolicyRequired = true Muss eine gültige URL sein
Website Schnur Muss eine gültige URL sein
Support-Kontaktinformationen Schnur Muss eine gültige URL oder E-Mail Adresse sein
Zertifizierungsnotizen Schnur Empfohlen Maximal 2000 Zeichen
Kategorie Schnur Erforderlich Siehe Liste der Kategorien unten
Unterkategorie Schnur Erforderlich Siehe Liste der Unterkategorien unten
Produktdeklarationen Objekt Erforderlich
isSystemFeatureRequired Array von Objekten [Toucheingabe, Tastatur, Maus, Kamera, NFC_HCE, NFC_Proximity, Bluetooth_LE, Telefonie, Mikrofon]
erforderlich Boolescher Typ (Boolean) Erforderlich
wirdEmpfohlen Boolescher Typ (Boolean) Erforderlich
Hardwareelementtyp Schnur Erforderlich
Systemanforderungsdetails Array von Objekten [Prozessor, Grafiken, Arbeitsspeicher, DirectX, Video_Memory]
Mindestanforderung Schnur Erforderlich Für systemRequirementsText, MaxLength = 200

Zulässige Werte in hardwareItemType = Memory: [300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB]

Zulässige Werte in hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12]

Zulässige Werte in hardwareItemType = Video_Memory: [1GB, 2GB, 4GB, 6GB]
empfohleneAnforderung Schnur Erforderlich Für systemRequirementsText, MaxLength = 200

Zulässige Werte in hardwareItemType = Memory: [300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB]

Zulässige Werte in hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12]

Zulässige Werte in hardwareItemType = Video_Memory: [1GB, 2GB, 4GB, 6GB]
dependsOnDriversOrNT Boolescher Typ (Boolean) Erforderlich
Barrierefreiheitsunterstützung Boolescher Typ (Boolean) Erforderlich
penAndInkSupport Boolescher Typ (Boolean) Erforderlich
Auflistungen Objekt Objekt für die Daten des Listingmoduls für eine einzelne Sprache
Sprache Schnur Erforderlich Siehe Liste der Sprachen unten
Beschreibung Schnur Erforderlich Maximal 10000 Zeichen
Neues Schnur Maximal 1500 Zeichen
Produkteigenschaften Zeichenfolgenarray 200 Zeichen pro Feature; bis zu 20 Features
kurzeBeschreibung Schnur Maximal 1000 Zeichen
Suchbegriffe Zeichenfolgenarray 30 Zeichen pro Suchbegriff; bis zu 7 Suchbegriffe

21 eindeutige Wörter INSGESAMT für alle Suchbegriffe
zusätzliche Lizenzbedingungen Schnur Erforderlich Maximal 10000 Zeichen
Urheberrecht Schnur Maximal 200 Zeichen
entwickelt von Schnur Maximal 255 Zeichen
Anforderungen Array von Objekten 200 Zeichen pro Element; bis zu 11 Elemente INSGESAMT zwischen Minimum und empfohlen]
Minimale Hardware Schnur Maximal 200 Zeichen
empfohlene Hardware Schnur Maximal 200 Zeichen
Kontaktinformationen Schnur Maximal 200 Zeichen
listingsToAdd Array aus Zeichenfolgen Siehe Liste der Sprachen unten
EinträgeZumEntfernen Array aus Zeichenfolgen Siehe Liste der Sprachen unten

Märkte

Markt Abkürzung
Afghanistan AF
Albanien AL
Algerien DZ
Amerikanisch-Samoa WIE
Andorra INSERAT
Angola AO
Anguilla KI
Antarktis .AQ
Antigua und Barbuda Verfügbarkeitsgruppe
Argentinien Augmented Reality
Armenien BIN
Aruba AW
Australien AU
Österreich AN
Aserbaidschan RP
Bahamas B.Sc.
Bahrain Bahrain
Bangladesch BD
Barbados BB
Weißrussland BIS
Belgien SEIN
Belize BZ
Benin BJ
Bermudas BM
Bhutan BT
Bolivarische Republik Venezuela VE
Bolivien BO
Bonaire BQ
Bosnien und Herzegowina B.A.
Botsuana Baden-Württemberg
Bouvetinsel BV
Brasilien BR
Britisches Territorium im Indischen Ozean IO
Britische Jungferninseln VG
Brunei Mrd.
Bulgarien BG
Burkina Faso BF
Burundi Business Intelligence (BI)
Kambodscha KH
Kamerun ZENTIMETER
Kanada CA
Cabo Verde Lebenslauf
Kaimaninseln HE
Zentralafrikanische Republik VGL
Tschad TD
Chile CL
China China
Weihnachtsinsel CX
Kokosinseln CC
Kolumbien Kohlenmonoxid
Komoren KILOMETER
Kongo (Demokratische Republik) CG
Kongo (DRC) CD
Cookinseln CK
Costa Rica CR
Kroatien Personalwesen
Curaçao CW
Zypern CY
Tschechische Republik CZ
Côte d'Ivoire Corporate Identity
Dänemark DK
Dschibuti DJ
Dominica D-Mark
Dominikanische Republik TUN
Ecuador EG
Ägypten ZB
El Salvador SV
Äquatorialguinea GQ
Eritrea ÄH
Estland EE
Äthiopien ET
Falklandinseln FS
Färöer FO
Fidschi FJ
Finnland FI
Frankreich BV
Französisch-Guayana GF
Französisch-Polynesien PF
Französische Süd- und Antarktisgebiete TF
Gabun Allgemein verfügbar
Gambia GM
Georgien GE
Deutschland Deutschland
Ghana GH
Gibraltar Glykämischer Index
Griechenland GR
Grönland GL
Grenada GD
Guadeloupe HAUSARZT
Guam GU
Guatemala GT
Guernsey GG
Guinea GN
Guinea-Bissau GW
Guayana GY
Haiti HT
Heard und McDonaldinseln HM
Vatikanstadt VA
Honduras HN
Hongkong (SAR) Hongkong
Ungarn HU
Island IST
Indien IN
Indonesien Kennung
Irak IQ
Irland Internet Explorer
Israel BY
Italien ES
Jamaika JM
Japan JP
Jersey JE
Jordanien JO
Kasachstan KZ
Kenia KE
Kiribati KI
Korea KR
Kuwait kW
Kirgisistan kg
Laos LA
Lettland LV
Libanon lbs
Lesotho LS
Liberia LR
Libyen LY
Liechtenstein LI
Litauen LT
Luxemburg LU
Macau (SAR) MOMENT
Nordmazedonien MK
Madagaskar MG
Malawi MW
Malaysien MEIN
Malediven MV
Mali Maschinelles Lernen
Malta MT
Insel Man Chat
Marshallinseln MH
Martinique MQ
Mauretanien HERR
Mauritius MY
Mayotte YouTube
Mexiko MX
Mikronesien FM
Moldau MD
Monaco MC
Mongolei BB
Montenegro – ME
Montserrat FRAU
Marokko NI
Mosambik MZ
Myanmar MM
Namibia Nicht verfügbar
Nauru NR
Nepal NP
Niederlande Niederlande
Neukaledonien NC
Neuseeland NZ
Nicaragua NI
Niger NE
Nigeria NG
Niue NY
Norfolkinsel NF
Nördliche Marianen MP
Norwegen NEIN
Oman OM
Pakistan PK
Palau KRIEGSGEFANGENER
Palästinensische Autonomiegebiete PS
Panama PAPA
Papua-Neuguinea PG
Paraguay PY
Peru Polyethylen
Philippinen PH
Pitcairninseln PN
Polen PL
Portugal Teilzeit
Katar Qualitätssicherung
Réunion RE
Rumänien RO
Russland Russland
Ruanda RW
St. Barthélemy BL
St. Helena, Ascension und Tristan da Cunha PST
St. Kitts und Nevis KN
St. Lucia LC
St. Martin (französischer Teil) MF
St. Pierre und Miquelon nachmittags
St. Vincent und die Grenadinen VC
Samoa WS
San Marino SM
Saudi-Arabien SA
Senegal SN
Serbien RS
Seychellen SC
Sierra Leone SL
Singapur SG
Sint Maarten (niederländischer Teil) SX
Slowakei SK
Slowenien Internationales Einheitensystem
Salomonen SB
Somalia Na gut
Südafrika ZA
Südgeorgien und die Südlichen Sandwichinseln GS
Spanien ES
Sri Lanka LK
Surinam SR
Spitzbergen und Jan Mayen SJ
Swasiland SZ
Schweden SE
Schweiz CH
São Tomé und Príncipe ST
Taiwan TW
Tadschikistan TJ
Tansania TZ
Thailand HEIT
Timor-Leste TL
Togo – TG
Tokelau TK
Tonga AN
Trinidad und Tobago – TT
Tunesien TN
Türkei TR
Turkmenistan TM
Turks- und Caicosinseln TC
Tuwalu Fernseher
USA Kleinere Amerikanische Überseeinseln äh
Amerikanische Jungferninseln VI
Uganda UG
Ukraine UA
Vereinigte Arabische Emirate AE
Vereinigtes Königreich Großbritannien
USA USA
Uruguay UY
Usbekistan UZ
Vanuatu VU
Vietnam VN
Wallis und Futuna WF
Jemen IHR
Sambia ZM
Simbabwe ZW
Ålandinseln AXT

Kategorien und Unterkategorien

Kategorie Unterkategorien
Bücher und Nachschlagewerke EReader, Fiktion, Sachbuch, Nachschlagewerk
Geschäft Buchhaltung und Finanzen, Zusammenarbeit, CRM, Daten und Analysen, Dateiverwaltung, Bestands- und Logistikmanagement, Recht und HR, Projektmanagement, Fernzugriff, Vertrieb und Marketing, Zeit- und Ausgabenverwaltung
Entwicklerwerkzeuge Datenbank, Design-Tools, Entwicklungskits, Netzwerk, Referenz und Schulung, Server, Dienstprogramme, Webhosting
Bildung BildungsbücherUndNachschlagewerke, FrühesLernen, Lehrmittel, Sprache, Lernhilfen
Unterhaltung (Keine)
Essen und Gastronomie (Keine)
RegierungUndPolitik (Keine)
GesundheitUndFitness (Keine)
KidsAndFamily KinderUndFamilienBücherUndNachschlagewerke, KinderUndFamilienUnterhaltung, HobbysUndSpielzeuge, SportUndAktivitäten, KinderUndFamilienReisen
Lebensstil Automobil, Heimwerken, HausUndGarten, Beziehungen, Spezialinteressen, StilUndMode
Medizin (Keine)
MultimediaDesign Illustration und Grafikdesign, Musikproduktion, Foto- und Videoproduktion
Musik (Keine)
Navigation und Karten (Keine)
Nachrichten und Wetter Nachrichten, Wetter
Persönliche Finanzen BankenUndInvestitionen, BudgetierungUndSteuern
Personalisierung Klingeltöne und Töne, Designs, Hintergründe und Sperrbildschirme
Foto und Video (Keine)
Produktivität (Keine)
Sicherheit PCProtection, PersonalSecurity
Einkaufen (Keine)
Soziale Netzwerke (Keine)
Sport (Keine)
Anfahrt Stadtführer, Hotels
Dienstprogramme und Werkzeuge BackupAndManage, FileManager

Sprachen

Name der Sprache Unterstützte Sprachcodes
Afrikaans af, af-za
Albanisch sq, sq-al
Amharisch am, am-et
Armenisch Hallo, hy-am
Assamesisch als, as-in
Aserbaidschanisch az-arab, az-arab-az, az-cyrl, az-cyrl-az, az-latn, az-latn-az
Baskisch (Baskisch) EU, eu-es
Belarussisch be, be-by
Bengalisch bn, bn-bd, bn-in
Bosnisch bs, bs-cyrl, bs-cyrl-ba, bs-latn, bs-latn-ba
Bulgarisch bg, bg-bg
Katalanisch ca, ca-es, ca-es-valencia
Cherokee chr-cher, chr-cher-us, chr-latn
Chinesisch (vereinfacht) zh-Hans, zh-cn, zh-hans-cn, zh-sg, zh-hans-sg
Chinesisch (traditionell) zh-Hant, zh-hk, zh-mo, zh-tw, zh-hant-hk, zh-hant-mo, zh-hant-tw, zh-mo, zh-tw, zh-hant-hk, zh-hant-mo, zh-hant-tw
Kroatisch hr, hr-hr, hr-ba
Tschechisch cs, cs-cz
Dänisch da, da-dk
Dari prs, prs-af, prs-arab
Niederländisch nl, nl-nl, nl-be
Englisch en, en-au, en-ca, en-gb, en-ie, en-in, en-nz, en-sg, en-us, en-za, en-bz, en-hk, en-id, en-jm, en-kz, en-mt, en-my, en-ph, en-pk, en-tt, en-vn, en-zw
Estnisch et, et-ee
Philippinisch – fil, fil-latn, fil-ph
Finnisch fi, fi-fi
Französisch 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
Galicisch gl, gl-es
Georgisch ka, ka-ge
Deutsch de, de-at, de-ch, de-de, de-lu, de-li
Griechisch el, el-gr
Gujarati gu, gu-in
Haussa ha, ha-latn, ha-latn-ng
Hebräisch er, he-il
Hindi hallo, hi-in
Ungarisch hu, hu-hu
Isländisch ist, is-is
Igbo – ig-latn, ig-ng
Indonesisch ID, id-id
Inuktitut (Lateinisch) iu-cans, iu-latn, iu-latn-ca
Irisch ga, ga-ie
isi Xhosa xh, xh-za
isi Zulu zu, zu-za
Italienisch es, it-it, it-ch
Japanisch ja , ja-jp
Kannada kn, kn-in
Kasachisch kk, kk-kz
Khmer km, km-kh
K'iche' quc-latn, qut-gt, qut-latn
Kinyarwanda rw, rw-rw
Kisuaheli sw, sw-ke
Konkani kok, kok-in
Koreanisch ko, ko-kr
Kurdisch ku-arab, ku-arab-iq
Kirgisisch ky-kg, ky-cyrl
Laotisch Hallo, lo-la
Lettisch lv, lv-lv
Litauisch lt, lt-lt
Luxemburgisch lb, lb-lu
Mazedonisch mk, mk-mk
Malaiisch ms, ms-bn, ms-my
Malayalam ml, ml-in
Maltesisch mt, mt-mt
Maori mi, mi-latn, mi-nz
Marathi Herr, mr-in
Mongolisch (Kyrillisch) mn-cyrl, mn-mong, mn-mn, mn-phag
Nepalesisch Nein, ne-np
Norwegisch nb, nb-no, nn, nn-no, nein, no-no
Odia oder or-in
Persisch fa, fa-ir
Polnisch pl, pl-pl
Portugiesisch (Brasilien) pt-br
Portugiesisch (Portugal) pt, pt-pt
Pandschabi pa, pa-arab, pa-arab-pk, pa-deva, pa-in
Quechua quz, quz-bo, quz-ec, quz-pe
Rumänisch ro, ro-ro
Russisch ru , ru-ru
Schottisch-Gälisch gd-gb, gd-latn
Serbisch (Lateinisch) sr-Latn, sr-latn-cs, sr, sr-latn-ba, sr-latn-me, sr-latn-rs
Serbisch (Kyrillisch) sr-cyrl, sr-cyrl-ba, sr-cyrl-cs, sr-cyrl-me, sr-cyrl-rs
Nord-Sotho nso, nso-za
Tswana tn, tn-bw, tn-za
Sindhi sd-arab, sd-arab-pk, sd-deva
Singhalesisch ja, si-lk
Slowakisch sk, sk-sk
Slowenisch sl, sl-si
Spanisch es, es-cl, es-co, es-es, es-mx, es-ar, es-bo, es-cr, es-do, es-ec, es-gt, es-hn, es-ni, es-pa, es-pe, es-pr, es-py, es-sv, es-us, es-uy, es-ve
Schwedisch sv, sv-se, sv-fi
Tadschikisch (Kyrillisch) tg-arab, tg-cyrl, tg-cyrl-tj, tg-latn
Tamilisch ta, ta-in
Tatarisch tt-arab, tt-cyrl, tt-latn, tt-ru
Telugu te, te-in
Thailändisch th, th-th
Tigrinya ti, ti-et
Türkisch tr, tr-tr
Turkmenisch tk-cyrl, tk-latn, tk-tm, tk-latn-tr, tk-cyrl-tr
Ukrainisch Vereinigtes Königreich, uk-ua
Urdu Ihr, ur-pk
Uigurisch ug-arab, ug-cn, ug-cyrl, ug-latn
Usbekisch (Lateinisch) uz, uz-cyrl, uz-latn, uz-latn-uz
Vietnamesisch vi, vi-vn
Walisisch cy, cy-gb
Wolof wo, wo-sn
Yoruba Yo-latn, yo-ng

Beispiel für eine Anforderung

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

Antwortheader

Kopfzeile Wert
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt Enthält die tatsächliche Antwort-Payload für die Anforderung.
Abfrage-URL Schnur Abruf-URL zum Abrufen des Status einer laufenden Übermittlung
laufendeEinreichungsId Schnur Übermittlungs-ID einer bereits laufenden Übermittlung

Beispiel für eine Antwort

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

API zum Abrufen der aktuellen Paketentwürfe

Ruft Paketdetails zum aktuellen Übermittlungsentwurf ab.

Pfad [Alle Pakete]: /submission/v1/product/{productId}/packages
Methode: GET

Pfad [Einzelnes Paket]: /submission/v1/product/{productId}/packages/{packageId}
Methode: GET

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts
Paket-ID Die eindeutige ID des abzurufenden Pakets

Erforderliche Header

Kopfzeile Wert
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Antwortheader

Kopfzeile Wert
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
pakete Array von Objekten Objekt zum Aufnehmen der Daten des Paketmoduls
Paket-ID Schnur
Paket-URL Schnur
Sprachen Array aus Zeichenfolgen
Architekturen Array aus Zeichenfolgen [Neutral; X86; X64; Arm; Arm64]
isSilentInstall Boolescher Typ (Boolean) Sollte als „true“ markiert sein, wenn das Installationsprogramm ohne erforderliche Switches im unbeaufsichtigten Modus ausgeführt wird, oder andernfalls als „false“
installerParameters Schnur
genericDocUrl Schnur
Fehlerdetails Array von Objekten
Fehlerszenario Schnur
errorScenarioDetails Array von Objekten
Fehlerwert Schnur
Fehler-URL Schnur
Pakettentyp Schnur

Beispiel für eine Antwort

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

API zum Aktualisieren der aktuellen Paketentwürfe

Aktualisiert Paketdetails zum aktuellen Übermittlungsentwurf.

Pfad [Vollständiges Update des Moduls]: /submission/v1/product/{productId}/packages
Methode: PUT

Pfad [Patch-Update eines einzelnen Pakets]: /submission/v1/product/{productId}/packages/{packageId}
Methode: PATCH

API-Verhalten

Im Fall der API für ein vollständiges Update des Moduls müssen für eine vollständige Aktualisierung jedes Felds sämtliche Paketdaten in der Anforderung vorhanden sein. Bei jedem in der Anforderung nicht vorhanden Feld wird zum Überschreiben des aktuellen Werts für das betreffende Modul der Standardwert verwendet. Dadurch werden alle vorhandenen Pakete mit einem neuen Satz von Paketen aus der Anforderung überschrieben. Dadurch werden Paket-IDs neu generiert, und der Benutzer sollte für die neuesten Paket-IDs die API zum Abrufen von Paketen aufrufen.

Im Fall der API für ein Patch-Update eines einzelnen Pakets müssen nur die für ein bestimmtes Paket zu aktualisierenden Felder in der Anforderung vorhanden sein. Diese Feldwerte aus der Anforderung überschreiben die jeweils vorhandenen Werte, wobei alle anderen Felder, die in der Anforderung nicht vorhanden sind, für das betreffende Paket unverändert bleiben. Andere Pakete im Satz bleiben unverändert.

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts
Paket-ID Die eindeutige ID des Pakets

Erforderliche Header

Kopfzeile Wert
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Anforderungsparameter

Name Typ Beschreibung
pakete Array von Objekten Objekt zum Aufnehmen der Daten des Paketmoduls [Nur erforderlich für vollständiges Update des Moduls]
Paket-URL Schnur Erforderlich
Sprachen Array aus Zeichenfolgen Erforderlich
Architekturen Array aus Zeichenfolgen Erforderlich Sollte eine einzelne Architektur enthalten – Neutral, X86, X64, Arm, Arm64
isSilentInstall Boolescher Typ (Boolean) Erforderlich Sollte als „true“ markiert sein, wenn das Installationsprogramm ohne erforderliche Switches im unbeaufsichtigten Modus ausgeführt wird, oder andernfalls als „false“
installerParameters Schnur Erforderlich, wenn isSilentInstall „false“ ist
genericDocUrl Schnur Erforderlich, wenn packageType „exe“ ist Link zum Dokument mit Details der benutzerdefinierten Fehlercodes für das EXE-Typ-Installationsprogramm
Fehlerdetails Array von Objekten Metadaten zum Aufnehmen benutzerdefinierter Fehlercodes und Details für EXE-Typ-Installationsprogramme.
Fehlerszenario Schnur Bestimmung des spezifischen Fehlerszenarios. [installationVomBenutzerAbgebrochen, anwendungExistiertBereits, installationBereitsImGange, speicherplatzVoll, neustartErforderlich, netzwerkfehler, paketWährendDerInstallationAbgelehnt, installationErfolgreich, divers]
errorScenarioDetails Array von Objekten
Fehlerwert Schnur Fehlercode, der während der Installation vorhanden sein kann
Fehler-URL Schnur URL mit Details zum Fehler
Pakettentyp Schnur Erforderlich [exe, msi]

Beispielanforderung [Vollständiges Update des Moduls]

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

Beispielanforderung [Patch-Update eines einzelnen Pakets]

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

Antwortheader

Kopfzeile Wert
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten [Die Liste der eventuellen Fehler- oder Warnmeldungen]
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
Abfrage-URL Schnur [Abruf-URL zum Abrufen des Status im Fall einer bereits laufenden Übermittlung]
laufendeEinreichungsId Schnur [Übermittlungs-ID einer bereits laufenden Übermittlung]

Beispiel für eine Antwort

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

API zum Committen von Paketen

Committet den neuen Satz von Paketen, die mit den APIs zum Aktualisieren von Paketen zum aktuellen Übermittlungsentwurf aktualisiert wurden. Diese API gibt eine Abruf-URL zum Nachverfolgen des Paketuploads zurück.

Pfad: /submission/v1/product/{productId}/packages/commit
Methode: POST

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Erforderliche Header

Kopfzeile Wert
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Antwortheader

Kopfzeile Wert
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten [Die Liste der eventuellen Fehler- oder Warnmeldungen]
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
Abfrage-URL Schnur [Abruf-URL zum Abrufen des Status von Paketuploads oder des Übermittlungsstatus im Fall einer bereits laufenden Übermittlung]
laufendeEinreichungsId Schnur [Übermittlungs-ID einer bereits laufenden Übermittlung]

Beispiel für eine Antwort

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

API zum Abrufen der aktuellen Listingentwurfsobjekte

Ruft Details zu Listingobjekten zum aktuellen Übermittlungsentwurf ab.

Pfad: /submission/v1/product/{productId}/listings/assets?languages={languages}
Methode: GET

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Abfrageparameter

Name Beschreibung
Sprachen [Optional] Der Listingsprachenfilter als kommagetrennte Zeichenkette [maximal 200 Sprachen]. Wenn nicht vorhanden, werden die Objektdaten der ersten 200 verfügbaren Listingsprachen abgerufen. (z. B. „en-us, en-gb“)

Erforderliche Header

Kopfzeile Wert
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Antwortheader

Kopfzeile Wert
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
Assetauflistung Array von Objekten Details zu Listingobjekten für jede Sprache
Sprache Schnur
storeLogos Array von Objekten
Bildschirmfotos Array von Objekten
id Schnur
assetUrl Schnur Muss eine gültige URL sein
Bildgröße Objekt
Breite Ganzzahl
Höhe Ganzzahl

Beispiel für eine Antwort

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

API zum Erstellen von Listingobjekten

Erstellt einen neuen Upload von Listingobjekten zum aktuellen Übermittlungsentwurf.

Aktualisieren von Listingobjekten

Die Microsoft Store-Übermittlungs-API für EXE- oder MSI-App verwendet laufzeitgenerierte SAS-URLs für Blob-Stores für die einzelnen Uploads von Bildobjekten zusammen mit einem Commit-API-Aufruf nach erfolgreichem Upload. Um die Möglichkeit zu haben, Listingobjekte zu aktualisieren und im Gegenzug Gebietsschemas im Listingmodul hinzuzufügen/zu entfernen, können Sie folgendermaßen vorgehen:

  1. Senden Sie über die API zum Erstellen von Listingobjekten eine Anforderung zum Ressourcenupload unter Angabe von Sprache, Typ und Anzahl der Ressourcen.
  2. Basierend auf der Anzahl der angeforderten Objekte werden Objekt-IDs nach Bedarf erstellt, und es wird eine kurzzeitige SAS-URL erstellt und im Antworttext unter dem Objekttyp zurückgesendet. Anhand dieser URL können Sie Bildobjekte des betreffenden Typs über HTTP-Clients hochladen [Put Blob (REST-API) – Azure Storage | Microsoft-Dokumentation].
  3. Nach dem Hochladen können Sie über die API zum Committen von Listingobjekten auch die zuvor aus dem vorherigen API-Aufruf empfangenen neuen Objekt-ID-Informationen senden. Die einzelne API führt nach der Validierung intern einen Commit für die Daten der Listingobjekte durch.
  4. Dadurch wird der gesamte Satz früherer Bilder des Objekttyps zu einer bestimmten Sprache aus der gesendeten Anforderung effektiv überschrieben. Daher werden zuvor hochgeladene Objekte entfernt.

Pfad: /submission/v1/product/{productId}/listings/assets/create
Methode: POST

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Erforderliche Header

Kopfzeile Beschreibung
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Anforderungsparameter

Name Typ Beschreibung
Sprache Schnur Erforderlich
createAssetRequest Objekt Erforderlich
Bildschirmfoto Ganzzahl Erforderlich, wenn ISV Screenshots aktualisieren oder eine neue Listingsprache hinzufügen muss [1 – 10]
Logo Ganzzahl Erforderlich, wenn ISV Logos aktualisieren oder eine neue Listingsprache hinzufügen muss [1 oder 2]

Antwortheader

Kopfzeile Beschreibung
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
Assetauflistung Objekt Objekt mit Details zu StoreLogos und Screenshots, die hochgeladen werden sollen
Sprache Schnur
storeLogos Array von Objekten
Bildschirmfotos Array von Objekten
id Schnur
primaryAssetUploadUrl Schnur Primäre URL zum Hochladen eines Listingobjekts über die Azure Blob REST-API
secondaryAssetUploadUrl Schnur Sekundäre URL zum Hochladen eines Listingobjekts über die Azure Blob REST-API
HTTP-Methode HTTP-Methode Die HTTP-Methode, die zum Hochladen von Objekten über die Objektupload-URLs verwendet werden muss – primär oder sekundär
httpHeaders Objekt Ein Objekt mit Schlüsseln als erforderliche Header, das im Upload-API-Aufruf an Objektupload-URLs vorhanden sein muss. Wenn der Wert nicht leer ist, müssen die Header bestimmte Werte haben. Andernfalls werden während des API-Aufrufs Werte berechnet.

Beispiel für eine Antwort

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

            }]
        }
    } 
}

API zum Committen von Listingobjekten

Committet das neue hochgeladene Listingobjekt anhand der Details aus der API zum Erstellen von Objekten zum aktuellen Übermittlungsentwurf.

Pfad: /submission/v1/product/{productId}/listings/assets/commit
Methode: PUT

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Erforderliche Header

Kopfzeile Beschreibung
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Anforderungsparameter

Name Typ Beschreibung
Assetauflistung Objekt
Sprache Schnur
storeLogos Array von Objekten
Bildschirmfotos Array von Objekten
id Schnur Sollte entweder eine vorhandene ID aus der API zum Abrufen der aktuellen Listingobjekte sein, die der Benutzer beibehalten möchte, oder eine neue ID, unter der ein neues Objekt in die API zum Erstellen von Listingobjekten hochgeladen wurde.
assetUrl Schnur Sollte entweder die URL des vorhandenen Objekts aus der API zum Abrufen der aktuellen Listingobjekte sein, die der Benutzer beibehalten möchte, oder die Upload-URL – primär oder sekundär –, mit der ein neues Objekt in die API zum Erstellen von Listingobjekten hochgeladen wurde. Muss eine gültige URL sein

Beispiel für eine Anforderung

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

Antwortheader

Kopfzeile Beschreibung
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
Abfrage-URL Schnur Abruf-URL zum Abrufen des Status einer laufenden Übermittlung
laufendeEinreichungsId Schnur Übermittlungs-ID einer bereits laufenden Übermittlung

Beispiel für eine Antwort

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

API zum Abrufen des Modulstatus

API zum Überprüfen der Bereitschaft des Moduls, bevor die Übermittlung erstellt werden kann. Validiert außerdem den Uploadstatus des Pakets.

Pfad: /submission/v1/product/{productId}/status
Methode: GET

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Erforderliche Header

Kopfzeile Beschreibung
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Antwortheader

Kopfzeile Beschreibung
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
istBereit Boolescher Typ (Boolean) Gibt an, ob alle Module den Status „Bereit“ haben, einschließlich Paketupload
laufendeEinreichungsId Schnur Übermittlungs-ID einer bereits laufenden Übermittlung

Beispiel für eine Antwort

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

API zum Erstellen von Übermittlungen

Erstellt eine Übermittlung aus dem aktuellen Entwurf für MSI- oder EXE-App. Die API überprüft:

  • auf aktive Übermittlung und Fehler mit Fehlermeldung, es eine aktive Übermittlung gibt.
  • ob alle Module den Status „Bereit“ haben, um die Übermittlung zu erstellen.
  • Jedes Feld in der Übermittlung wird gemäß den Anforderungen des Store auf Gültigkeit geprüft.

Pfad:/submission/v1/product/{productId}/submit
Methode: POST

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Erforderliche Header

Kopfzeile Beschreibung
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Antwortheader

Kopfzeile Beschreibung
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
Abfrage-URL Schnur Abruf-URL zum Abrufen des Status der Modulbereitschaft einschließlich Paketupload für Übermittlung
Einreichungs-ID Schnur Die ID für die neu erstellte Übermittlung
laufendeEinreichungsId Schnur Übermittlungs-ID einer bereits laufenden Übermittlung

Beispiel für eine Antwort

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

API zum Abrufen des Übermittlungsstatus

API zum Überprüfen des Übermittlungsstatus.

Pfad: /submission/v1/product/{productId}/submission/{submissionId}/status
Methode: GET

Pfadparameter

Name Beschreibung
Produkt-ID Die Partner Center-ID des Produkts

Erforderliche Header

Kopfzeile Beschreibung
Authorization: Bearer <Token> Verwenden der im Partner Center-Konto registrierten Azure AD-App-ID
X-Seller-Account-Id Verkäufer-ID des Partner Center-Kontos

Antwortheader

Kopfzeile Beschreibung
X-Correlation-ID Die eindeutige GUID-Typ-ID für jede Anforderung. Sie kann zur Analyse von Problemen an das Supportteam weitergegeben werden.
Retry-After Die Zeit in Sekunden, die der Client aufgrund der Ratenbegrenzung warten muss, bevor er die APIs erneut aufruft.

Antwortparameter

Name Typ Beschreibung
IsSuccess Boolescher Typ (Boolean)
Irrtümer Array von Objekten Die Liste der eventuellen Fehler- oder Warnmeldungen
Code Schnur Der Fehlercode der Meldung
Nachricht Schnur Die Beschreibung des Fehlers
Ziel Schnur Die Entität, in der der Fehler seinen Ursprung hat
Antwortdaten Objekt
Veröffentlichungsstatus Schnur Veröffentlichungsstatus der Übermittlung – [INPROGRESS, PUBLISHED, FAILED, UNKNOWN]
istFehlgeschlagen Boolescher Typ (Boolean) Gibt an, ob die Veröffentlichung fehlgeschlagen ist und nicht wiederholt wird.

Beispiel für eine Antwort

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

Codebeispiele

Die folgenden Artikel enthalten detaillierte Codebeispiele, die veranschaulichen, wie die Microsoft Store-Übermittlungs-API in verschiedenen Programmiersprachen verwendet wird:

Beispiel für C#: Microsoft Store-Übermittlungs-API für MSI- oder EXE-App

Dieser Artikel enthält C#-Codebeispiele, die die Verwendung der Microsoft Store-Übermittlungs-API für MSI- oder EXE-App veranschaulichen. Sie können jedes Beispiel durchgehen, um mehr über die beschriebene Aufgabe zu erfahren, oder Sie können alle Codebeispiele in diesem Artikel in einer Konsolenanwendung erstellen.

Voraussetzungen In diesen Beispielen wird die folgende Bibliothek verwendet:

  • Newtonsoft.Json NuGet-Paket von Newtonsoft.

Standardprogramm Das folgende Beispiel implementiert ein Befehlszeilenprogramm, das die anderen Beispielmethoden in diesem Artikel aufruft, um verschiedene Möglichkeiten zur Verwendung der Microsoft Store-Übermittlungs-API zu veranschaulichen. So passen Sie dieses Programm für eigene Zwecke an:

  • Weisen Sie die Eigenschaft SellerId der Verkäufer-ID Ihres Partner Center-Kontos zu.
  • Weisen Sie die Eigenschaft ApplicationId der ID der zu verwaltenden App zu.
  • Weisen Sie die Eigenschaften ClientId und ClientSecret der Client-ID und dem Schlüssel für Ihre App zu und ersetzen Sie die Zeichenkette „tenantid“ in der TokenEndpoint-URL durch die Mandanten-ID für Ihre App. Weitere Informationen finden Sie unter Zuordnen einer Azure AD-Anwendung zu Ihrem Partner Center-Konto.
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();

        }
    }
}

Hilfsprogrammklasse ClientConfiguration bei Verwendung von C#

Die Beispiel-App verwendet die Hilfsprogrammklasse ClientConfiguration, um Azure Active Directory-Daten und App-Daten an jede der Beispielmethoden zu übergeben, die die Microsoft Store-Übermittlungs-API verwenden.

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

Erstellen einer App-Übermittlung bei Verwendung von C#

Das folgende Beispiel implementiert eine Klasse, die verschiedene Methoden in der Microsoft Store-Übermittlungs-API verwendet, um eine App-Übermittlung zu aktualisieren.

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

Hilfklasse IngestionClient bei Verwendung von C#

Die Hilfsprogrammklasse IngestionClient stellt Hilfsmethoden bereit, die von anderen Methoden in der Beispiel-App zum Ausführen der folgenden Aufgaben verwendet werden:

  • Abrufen eines Azure AD-Zugriffstokens, das zum Aufrufen von Methoden in der Microsoft Store-Übermittlungs-API verwendet werden kann. Nach dem Abruf eines Tokens können Sie es für einen Zeitraum von 60 Minuten in Aufrufen der Microsoft Store-Übermittlungs-API verwenden, bevor es abläuft. Nach Ablauf des Tokens können Sie ein neues Token generieren.
  • Verarbeiten der HTTP-Anforderungen für die Microsoft Store-Übermittlungs-API.
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;
        }
    }
}

Beispiel für Node.js: Microsoft Store-Übermittlungs-API für MSI- oder EXE-App

Dieser Artikel enthält Node.js-Codebeispiele zeigt das Verwenden der Microsoft Store-Übermittlungs-API für MSI- oder EXE-App. Sie können jedes Beispiel durchgehen, um mehr über die beschriebene Aufgabe zu erfahren, oder Sie können alle Codebeispiele in diesem Artikel in einer Konsolenanwendung erstellen.

Voraussetzungen In diesen Beispielen wird die folgende Bibliothek verwendet:

  • node-fetch v2 [npm install node-fetch@2]

Erstellen einer App-Übermittlung bei Verwendung von node.js

Das folgende Beispiel ruft die anderen Beispielmethoden in diesem Artikel auf, um verschiedene Möglichkeiten zur Verwendung der Microsoft Store-Übermittlungs-API zu veranschaulichen. So passen Sie dieses Programm für eigene Zwecke an:

  • Weisen Sie die Eigenschaft SellerId der Verkäufer-ID Ihres Partner Center-Kontos zu.
  • Weisen Sie die Eigenschaft ApplicationId der ID der zu verwaltenden App zu.
  • Weisen Sie die Eigenschaften ClientId und ClientSecret der Client-ID und dem Schlüssel für Ihre App zu und ersetzen Sie die Zeichenkette „tenantid“ in der TokenEndpoint-URL durch die Mandanten-ID für Ihre App. Weitere Informationen finden Sie unter Zuordnen einer Azure AD-Anwendung zu Ihrem Partner Center-Konto.

Das folgende Beispiel implementiert eine Klasse, die verschiedene Methoden in der Microsoft Store-Übermittlungs-API verwendet, um eine App-Übermittlung zu aktualisieren.

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();

Hilfsprogramm ClientConfiguration

Die Beispiel-App verwendet die Hilfsprogrammklasse ClientConfiguration, um Azure Active Directory-Daten und App-Daten an jede der Beispielmethoden zu übergeben, die die Microsoft Store-Übermittlungs-API verwenden.

/** 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;

Hilfsprogramm IngestionClient bei Verwendung von node.js

Die Hilfsprogrammklasse IngestionClient stellt Hilfsmethoden bereit, die von anderen Methoden in der Beispiel-App zum Ausführen der folgenden Aufgaben verwendet werden:

  • Abrufen eines Azure AD-Zugriffstokens, das zum Aufrufen von Methoden in der Microsoft Store-Übermittlungs-API verwendet werden kann. Nach dem Abruf eines Tokens können Sie es für einen Zeitraum von 60 Minuten in Aufrufen der Microsoft Store-Übermittlungs-API verwenden, bevor es abläuft. Nach Ablauf des Tokens können Sie ein neues Token generieren.
  • Verarbeiten der HTTP-Anforderungen für die Microsoft Store-Übermittlungs-API.
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;

Weitere Hilfe

Wenn Sie Fragen zur Microsoft Store-Übermittlungs-API haben oder Unterstützung beim Verwalten Ihrer Übermittlungen mit dieser API benötigen, können Sie die folgenden Ressourcen verwenden:

  • Stellen Sie Fragen in unseren Foren.
  • Besuchen Sie unsere Supportseite und fordern Sie eine der unterstützten Supportoptionen für Partner Center an. Wenn Sie aufgefordert werden, einen Problemtyp und eine Kategorie auszuwählen, wählen Sie „App-Übermittlung und -Zertifizierung“ bzw. „Übermitteln einer App“ aus.