Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Use a API de envio da Microsoft Store para aplicativos MSI ou EXE para consultar e criar envios programaticamente para aplicativos MSI ou EXE para sua conta do Partner Center ou da sua organização. Essa API é útil se sua conta gerencia muitos aplicativos e você deseja automatizar e otimizar o processo de envio para esses ativos. Essa API usa a ID do Microsoft Entra para autenticar as chamadas do seu aplicativo ou serviço.
As etapas a seguir descrevem o processo de ponta a ponta do uso da API de envio da Microsoft Store:
- Certifique-se de que preencheu todos os pré-requisitos.
- Antes de chamar um método na API de envio da Microsoft Store, obtenha um token de acesso do Microsoft Entra ID. Depois de obter um token, você tem 60 minutos para usá-lo em chamadas para a API de envio da Microsoft Store antes que o token expire. Depois que o token expirar, você poderá gerar um novo token.
- Chame a API de submissão da Microsoft Store para aplicações MSI ou EXE.
Etapa 1: concluir os pré-requisitos para usar a API de envio da Microsoft Store
Antes de começar a escrever código para chamar a API de envio da Microsoft Store para o aplicativo MSI ou EXE, verifique se você concluiu os seguintes pré-requisitos.
- Você (ou sua organização) deve ter um diretório de ID do Microsoft Entra e deve ter permissão de administrador global para o diretório. Se você já usa o Microsoft 365 ou outros serviços empresariais da Microsoft, você já tem o diretório Microsoft Entra ID. Caso contrário, você pode criar uma nova ID do Microsoft Entra no Partner Center sem custo adicional.
- Você deve associar um aplicativo Microsoft Entra ID à sua conta do Partner Center e obter sua ID de locatário, ID do cliente e chave. Você precisa desses valores para obter um token de acesso do Microsoft Entra ID, que será usado em chamadas para a API de submissão da Microsoft Store.
- Prepare seu aplicativo para uso com a API de envio da Microsoft Store:
- Se seu aplicativo ainda não existir no Partner Center, você deverá criá-lo reservando seu nome no Partner Center. Não é possível usar a API de envio da Microsoft Store para criar um aplicativo no Partner Center; você deve trabalhar no Partner Center para criá-lo e, depois disso, você pode usar a API para acessar o aplicativo e criar envios programaticamente para ele.
- Antes de criar um envio para um determinado aplicativo usando essa API, você deve primeiro criar um envio para o aplicativo no Partner Center, incluindo responder ao questionário de classificações etárias . Depois de fazer isso, você será capaz de criar programaticamente novos envios para este aplicativo usando a API.
- Se estiver a criar ou atualizar uma submissão de aplicação e precisar incluir um novo pacote, prepare os detalhes do pacote.
- Se estiver a criar ou atualizar uma submissão de aplicação e precisar incluir capturas de ecrã ou imagens para a listagem da Loja, prepare as capturas de ecrã e as imagens da aplicação.
Como associar um aplicativo Microsoft Entra ID à sua conta do Partner Center
Antes de poder usar a API de envio da Microsoft Store para aplicativos MSI ou EXE, você deve associar um aplicativo Microsoft Entra ID à sua conta do Partner Center, recuperar a ID do locatário e a ID do cliente do aplicativo e gerar uma chave. O aplicativo Microsoft Entra ID representa o aplicativo ou serviço do qual você deseja chamar a API de envio da Microsoft Store. Você precisa da ID do locatário, da ID do cliente e da chave para obter um token de acesso do Microsoft Entra ID que você passa para a API.
Observação
Você só precisa executar essa tarefa uma vez. Depois de ter a ID do locatário, a ID do cliente e a chave, você pode reutilizá-los sempre que precisar criar um novo token de acesso do Microsoft Entra ID.
- No Partner Center, associe a conta do Partner Center da sua organização ao diretório Microsoft Entra ID da sua organização.
- Em seguida, na página Usuários na seção Configurações de conta do Partner Center, adicione o aplicativo Microsoft Entra ID que representa o aplicativo ou serviço que você usará para acessar envios para sua conta do Partner Center. Certifique-se de atribuir a este aplicativo a função de gerente. Se o aplicativo ainda não existir no diretório do Microsoft Entra ID, você poderá criar um novo aplicativo Microsoft Entra ID no Partner Center.
- Retorne à página Usuários, clique no nome do seu aplicativo Microsoft Entra ID para ir para as configurações do aplicativo e copie os valores ID do Locatário e ID do Cliente.
- Para adicionar uma nova chave ou segredo de cliente, siga as instruções a seguir ou consulte as instruções para registar a aplicação através do Portal do Azure:
Para registrar seu aplicativo:
Inicie sessão no portal Azure.
Se você tiver acesso a vários locatários, use o filtro Diretórios + assinaturas no menu superior para alternar para o locatário no qual deseja registrar o aplicativo.
Procure e selecione Microsoft Entra ID Directory.
Em Gerir, selecione Registos de > aplicações Selecione a sua aplicação.
Selecione Certificados & segredos Segredos do > cliente Novo segredo do > cliente.
Adicione uma descrição do segredo do cliente.
Selecione uma expiração para o segredo ou especifique um tempo de vida personalizado.
O tempo de vida do segredo do cliente é limitado a dois anos (24 meses) ou menos. Não é possível especificar um tempo de vida personalizado superior a 24 meses.
Observação
A Microsoft recomenda que você defina um valor de expiração inferior a 12 meses.
Selecione Adicionar.
Registe o valor do segredo para uso no código da aplicação cliente. Este valor secreto nunca mais é apresentado depois de sair desta página.
Etapa 2: Obter um token de acesso do Microsoft Entra ID
Antes de chamar qualquer um dos métodos na API de envio da Microsoft Store para o aplicativo MSI ou EXE, você deve primeiro obter um token de acesso do Microsoft Entra ID que você passa para o cabeçalho Authorization de cada método na API. Depois de obter um token de acesso, você tem 60 minutos para usá-lo antes que ele expire. Depois que o token expirar, você poderá atualizá-lo para continuar a usá-lo em outras chamadas para a API.
Para obter o token de acesso, siga as instruções em Service to Service Calls Using Client Credentials para enviar um HTTP POST para o endpoint tenant_id/oauth2/token. Aqui está um pedido de amostra.
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
Para o valor de tenant_id no URI POST e os parâmetros client_id e client_secret, especifique o ID do locatário, o ID do cliente e a chave da sua aplicação que recuperou do Partner Center na seção anterior. Para o parâmetro scope, você deve especificar https://api.store.microsoft.com/.default.
Depois que seu token de acesso expirar, você poderá atualizá-lo seguindo as instruções aqui.
Para obter exemplos que demonstram como obter um token de acesso usando C# ou Node.js, consulte os exemplos de código para API de envio da Microsoft Store para aplicativo MSI ou EXE.
Etapa 3: Usar a API de envio da Microsoft Store
Depois de ter um token de acesso do Microsoft Entra ID, pode-se chamar métodos na API de submissão da Microsoft Store para aplicações MSI ou EXE. A API inclui muitos métodos que são agrupados em cenários para aplicativos. Para criar ou atualizar envios, você normalmente chama vários métodos em uma ordem específica. Para obter informações sobre cada cenário e a sintaxe de cada método, consulte as seguintes seções:
Observação
Depois de obter um token de acesso, tem 60 minutos para chamar métodos na API de submissão da Microsoft Store para um aplicativo MSI ou EXE antes que o token expire.
URL base
A URL base para o aplicativo Microsoft Store Submission API for EXE ou MSI é: https://api.store.microsoft.com
Contratos API
API para Obter Metadados do Envio de Rascunho Atual
Busca metadados em cada módulo (listagens, propriedades ou disponibilidade) no âmbito da atual submissão de rascunho.
Caminho [Todos os módulos]: /submission/v1/product/{productId}/metadata?languages={languages}&includelanguagelist={true/false}
Caminho [Módulo único]: /submission/v1/product/{productId}/metadata/{moduleName}?languages={languages}&includelanguagelist={true/false}
Método: GET
parâmetros de caminho
| Parâmetro | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
| nome_do_módulo | Módulo Partner Center – anúncios, propriedades ou disponibilidade |
Parâmetros de Consulta
| Parâmetro | Descrição |
|---|---|
| Idiomas |
Opcional Os idiomas da listagem filtram como uma cadeia de caracteres separada por vírgulas [limite de até 200 idiomas]. Se ausente, os primeiros 200 metadados de idiomas de listagem disponíveis são recuperados. [ por exemplo, "en-us, en-gb"]. |
| IncluirLista de Idiomas | Opcional Booleano – se verdadeiro, retorna a lista de idiomas de listagem adicionados e seu status de completude. |
cabeçalhos necessários
| Cabeçalho | Valor |
|---|---|
Authorization: Bearer <Token> |
A ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
cabeçalhos de resposta
| Cabeçalho | Valor |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| suporte de acessibilidade | booleano | |
| Termos Adicionais de Licença | Cordão | |
| disponibilidade | Objeto | Dados do módulo de disponibilidade |
| categoria | Cordão | Veja a lista de categorias abaixo |
| Notas de Certificação | Cordão | |
| código | Cordão | O código de erro da mensagem |
| informações de contacto | Cordão | |
| Copyright | Cordão | |
| depende de drivers ou NT | booleano | |
| descrição | Cordão | |
| desenvolvidoPor | Cordão | |
| capacidade de descoberta | Cordão | [DESCUBRÍVEL, DEEPLINK_ONLY] |
| habilitarInFutureMarkets | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| Versão experimental gratuita | Cordão | [SEM_PERÍODO_DE_EXPERIÊNCIA_GRATUITO, PERÍODO_DE_EXPERIÊNCIA_GRATUITO] |
| hardwareItemType | Cordão | |
| éPoliticaDePrivacidadeNecessária | booleano | |
| éRecomendado | booleano | |
| é obrigatório | booleano | |
| éSucesso | booleano | |
| éFuncionalidadeDoSistemaObrigatória | Matriz de objetos | |
| linguagem | Cordão | Ver lista de línguas abaixo |
| Anúncios | Matriz de objetos | Dados do módulo de listagens para cada idioma |
| mercados | Matriz de cadeias de caracteres | Veja a lista de mercados abaixo |
| mensagem | Cordão | A descrição do erro |
| Hardware mínimo | Cordão | |
| mínimoRequisito | Cordão | |
| suporte para caneta e tinta digital | booleano | |
| preços | Cordão | [GRÁTIS, FREEMIUM, ASSINATURA, PAGO] |
| URL da Política de Privacidade | Cordão | |
| declarações de produto | Objeto | |
| características do produto | Matriz de cadeias de caracteres | |
| propriedades | Objeto | Dados do módulo de propriedades |
| Hardware recomendado | Cordão | |
| Requisito Recomendado | Cordão | |
| dadosDeResposta | Objeto | Contém a carga útil de resposta real para a solicitação |
| Requerimentos | Matriz de objetos | |
| termos de pesquisa | Matriz de cadeias de caracteres | |
| breveDescrição | Cordão | |
| Subcategoria | Cordão | Ver lista de subcategorias abaixo |
| suporteContactInfo | Cordão | |
| DetalhesDosRequisitosDoSistema | Matriz de objetos | |
| destino | Cordão | A entidade da qual o erro se originou |
| site | Cordão | |
| O que há de novo | Cordão |
Atualizar a API de metadados de envio de rascunho atual
Atualiza metadados em cada módulo em fase de rascunho. A API verifica
- Para Submissão Ativa. Se existir, falha com mensagem de erro.
- Se todos os módulos estiverem no estado pronto para permitir a operação de salvar rascunho.
- Cada campo na submissão é validado de acordo com os requisitos da Loja
- Requisitos do sistema Regras de validação de detalhes:
- Valores permitidos em hardwareItemType = Memória: 300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB
- Valores permitidos em hardwareItemType = DirectX: DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12
- Valores permitidos em hardwareItemType = Video_Memory: 1GB, 2GB, 4GB, 6GB
Path [Atualização completa do módulo]: /submission/v1/product/{productId}/metadata
Método: PUT
Path [Atualização do patch do módulo]: /submission/v1/product/{productId}/metadata
Método: PATCH
Comportamento da API
No caso da API de Atualização do Módulo Completo – os Dados do Módulo inteiro precisam estar presentes na Solicitação de atualização completa de cada campo. Qualquer campo que não esteja presente em Solicitação, seu valor padrão é usado para substituir o valor atual para esse módulo específico.
No caso da API de Atualização do Módulo de Patch – apenas os campos que devem ser atualizados precisam estar presentes na Solicitação. Esses valores de campo de Solicitação substituirão seus valores existentes, mantendo todos os outros campos que não estão presentes na Solicitação, iguais aos atuais para esse Módulo específico.
parâmetros de caminho
| Parâmetro | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
cabeçalhos necessários
| Cabeçalho | Valor |
|---|---|
Authorization: Bearer <Token> |
A ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
Parâmetros de solicitação
| Nome | Tipo | Descrição |
|---|---|---|
| disponibilidade | Objeto | Objeto para armazenar metadados do Módulo de Disponibilidade |
| mercados | Matriz de cadeias de caracteres | Necessário Veja a lista de mercados abaixo |
| capacidade de descoberta | Cordão | Necessário [DETETÁVEL, DEEPLINK_ONLY] |
| habilitarInFutureMarkets | booleano | Obrigatório |
| preços | Cordão | Obrigatório [GRÁTIS, FREEMIUM, ASSINATURA, PAGO] |
| Versão experimental gratuita | Cordão | Obrigatório se o preço for PAGO ou SUBSCRIÇÃO [NO_FREE_TRIAL, FREE_TRIAL] |
| propriedades | Objeto | Objeto para armazenar metadados do módulo de propriedades |
| éPoliticaDePrivacidadeNecessária | booleano | Obrigatório |
| URL da Política de Privacidade | Cordão | Obrigatório se isPrivacyPolicyRequired = true Deve ser um URL válido |
| site | Cordão | Deve ser um URL válido |
| suporteContactInfo | Cordão | Deve ser um URL ou endereço de e-mail válido |
| Notas de Certificação | Cordão | Recomendado Limite de caracteres = 2000 |
| categoria | Cordão | Necessário Veja a lista de categorias abaixo |
| Subcategoria | Cordão | Necessário Ver lista de subcategorias abaixo |
| declarações de produto | Objeto | Obrigatório |
| éFuncionalidadeDoSistemaObrigatória | Matriz de objetos | [Toque, teclado, mouse, câmera, NFC_HCE, NFC_Proximity, Bluetooth_LE, telefonia, microfone] |
| é obrigatório | booleano | Obrigatório |
| éRecomendado | booleano | Obrigatório |
| hardwareItemType | Cordão | Obrigatório |
| DetalhesDosRequisitosDoSistema | Matriz de objetos | [Processador, gráficos, memória, DirectX Video_Memory] |
| mínimoRequisito | Cordão |
necessário para systemRequirementsText, MaxLength = 200 Valores permitidos em hardwareItemType = Memória: [300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB] Valores permitidos em hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12] Valores permitidos em hardwareItemType = Video_Memory: [1GB, 2GB, 4GB, 6GB] |
| Requisito Recomendado | Cordão |
necessário para systemRequirementsText, MaxLength = 200 Valores permitidos em hardwareItemType = Memória: [300MB, 750MB, 1GB, 2GB, 4GB, 6GB, 8GB, 12GB, 16GB, 20GB] Valores permitidos em hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12] Valores permitidos em hardwareItemType = Video_Memory: [1GB, 2GB, 4GB, 6GB] |
| depende de drivers ou NT | booleano | Obrigatório |
| suporte de acessibilidade | booleano | Obrigatório |
| suporte para caneta e tinta digital | booleano | Obrigatório |
| Anúncios | Objeto | Opor-se à listagem de dados do módulo para um único idioma |
| linguagem | Cordão | Necessário Ver lista de línguas abaixo |
| descrição | Cordão | Necessário Limite de caracteres = 10000 |
| O que há de novo | Cordão | Limite de caracteres = 1500 |
| características do produto | Matriz de String | 200 caracteres por recurso; Até 20 funcionalidades |
| breveDescrição | Cordão | Limite de caracteres = 1000 |
| termos de pesquisa | Matriz de String | 30 caracteres por termo de pesquisa; Até 7 termos de pesquisa 21 palavras únicas no total em todos os termos de pesquisa |
| Termos Adicionais de Licença | Cordão | Necessário Limite de caracteres = 10000 |
| Copyright | Cordão | Limite de caracteres = 200 |
| desenvolvidoPor | Cordão | Limite de caracteres = 255 |
| Requerimentos | Matriz de objetos | 200 caracteres por item; Até 11 itens TOTAL entre mínimo e recomendado] |
| Hardware mínimo | Cordão | Limite de caracteres = 200 |
| Hardware recomendado | Cordão | Limite de caracteres = 200 |
| informações de contacto | Cordão | Limite de caracteres = 200 |
| anúncios para adicionar | Matriz de cadeias de caracteres | Ver lista de línguas abaixo |
| listagensParaRemover | Matriz de cadeias de caracteres | Ver lista de línguas abaixo |
Mercados
Ver tabela
| Mercado | Abreviatura | |--------|--------------| | Afeganistão | AF | | Albânia | AL | | Argélia | DZ | | Samoa Americana | AS | | Andorra | AD | | Angola | AO | | Anguila | AI | | Antártida | AQ | | Antígua e Barbuda | AG | | Argentina | AR | | Arménia | AM | | Aruba | AW | | Austrália | AU | | Áustria | AT | | Azerbaijão | AZ | | Bahamas | BS | | Bahrein | BH | | Bangladeche | BD | | Barbados | BB | | Bielorrússia | BY | | Bélgica | BE | | Belize | BZ | | Benim | BJ | | Bermudas | BM | | Butão | BT | | Venezuela | VE | | Bolívia | BO | | Bonaire | BQ | | Bósnia e Herzegovina | BA | | Botsuana | BW | | Ilha Bouvet | BV | | Brasil | BR | | Território Britânico do Oceano Índico | IO | | Ilhas Virgens Britânicas | VG | | Brunei | BN | | Bulgária | BG | | Burkina Faso | BF | | Burundi | BI | | Camboja | KH | | Camarões | CM | | Canadá | CA | | Cabo Verde | CV | | Ilhas Caimão | KY | | República Centro-Africana | CF | | Chade | TD | | Chile | CL | | China | CN | | Ilha Christmas | CX | | Ilhas Cocos (Keeling) | CC | | Colômbia | CO | | Comores | KM | | Congo | CG | | Congo (RDC) | CD | | Ilhas Cook | CK | | Costa Rica | CR | | Croácia | HR | | Curaçau | CW | | Chipre | CY | | República Checa | CZ | | Costa do Marfim | CI | | Dinamarca | DK | | Djibuti | DJ | | Dominica | DM | | República Dominicana | DO | | Equador | EC | | Egito | EG | | El Salvador | SV | | Guiné Equatorial | GQ | | Eritreia | ER | | Estónia | EE | | Etiópia | ET | | Ilhas Malvinas | FK | | Ilhas Faroé | FO | | Fiji | FJ | | Finlândia | FI | | França | FR | | Guiana Francesa | GF | | Polinésia Francesa | PF | | Terras Austrais e Antárticas Francesas | TF | | Gabão | GA | | Gâmbia | GM | | Geórgia | GE | | Alemanha | DE | | Gana | GH | | Gibraltar | GI | | Grécia | GR | | Gronelândia | GL | | Granada | GD | | Guadalupe | GP | | Guam | GU | | Guatemala | GT | | Guernsey | GG | | Guiné | GN | | Guiné-Bissau | GW | | Guiana | GY | | Haiti | HT | | Ilha Heard e Ilhas McDonald | HM | | Cidade do Vaticano | VA | | Honduras | HN | | Região Administrativa Especial de Hong Kong | HK | | Hungria | HU | | Islândia | IS | | Índia | IN | | Indonésia | ID | | Iraque | IQ | | Irlanda | IE | | Israel | IL | | Itália | IT | | Jamaica | JM | | Japão | JP | | Jersey | JE | | Jordânia | JO | | Cazaquistão | KZ | | Quénia | KE | | Kiribati | KI | | Coreia | KR | | Koweit | KW | | Quirguizistão | KG | | Laos | LA | | Letónia | LV | | Líbano | LB | | Lesoto | LS | | Libéria | LR | | Líbia | LY | | Liechtenstein | LI | | Lituânia | LT | | Luxemburgo | LU | | Macau | MO | | Macedónia do Norte | MK | | Madagáscar | MG | | Maláui | MW | | Malásia | MY | | Maldivas | MV | | Mali | ML | | Malta | MT | | Ilha de Man | IM | | Ilhas Marshall | MH | | Martinica | MQ | | Mauritânia | MR | | Maurícia | MU | | Maiote | YT | | México | MX | | Micronésia | FM | | Moldávia | MD | | Mónaco | MC | | Mongólia | MN | | Montenegro | ME | | Montserrat | MS | | Marrocos | MA | | Moçambique | MZ | | Mianmar | MM | | Namíbia | NA | | Nauru | NR | | Nepal | NP | | Países Baixos | NL | | Nova Caledónia | NC | | Nova Zelândia | NZ | | Nicarágua | NI | | Níger | NE | | Nigéria | NG | | Niue | NU | | Ilha de Norfolk | NF | | Ilhas Marianas do Norte | MP | | Noruega | NO | | Omã | OM | | Paquistão | PK | | Palau | PW | | Autoridade Palestiniana | PS | | Panamá | PA | | Papua-Nova Guiné | PG | | Paraguai | PY | | Peru | PE | | Filipinas | PH | | Ilhas Pitcairn | PN | | Polónia | PL | | Portugal | PT | | Catar | QA | | Reunião | RE | | Roménia | RO | | Rússia | RU | | Ruanda | RW | | São Bartolomeu | BL | | Santa Helena, Ascensão e Tristão da Cunha | SH | | São Cristóvão e Neves | KN | | Santa Lúcia | LC | | São Martinho (parte francesa) | MF | | São Pedro e Miquelon | PM | | São Vicente e Granadinas | VC | | Samoa | WS | | São Marinho | SM | | Arábia Saudita | SA | | Senegal | SN | | Sérvia | RS | | Seicheles | SC | | Serra Leoa | SL | | Singapura | SG | | São Martinho (parte holandesa) | SX | | Eslováquia | SK | | Eslovénia | SI | | Ilhas Salomão | SB | | Somália | SO | | África do Sul | ZA | | Geórgia do Sul e Ilhas Sandwich do Sul | GS | | Espanha | ES | | Sri Lanka | LK | | Suriname | SR | | Svalbard e Jan Mayen | SJ | | Suazilândia | SZ | | Suécia | SE | | Suíça | CH | | São Tomé e Príncipe | ST | | Taiwan | TW | | Tajiquistão | TJ | | Tanzânia | TZ | | Tailândia | TH | | Timor-Leste | TL | | Togo | TG | | Tokelau | TK | | Tonga | TO | | Trindade e Tobago | TT | | Tunísia | TN | | Turquia | TR | | Turquemenistão | TM | | Ilhas Turcas e Caicos | TC | | Tuvalu | TV | | Ilhas Menores Distantes dos EUA | UM | | Ilhas Virgens Americanas | VI | | Uganda | UG | | Ucrânia | UA | | Emirados Árabes Unidos | AE | | Reino Unido | GB | | Estados Unidos | US | | Uruguai | UY | | Usbequistão | UZ | | Vanuatu | VU | | Vietname | VN | | Wallis e Futuna | WF | | Iémen | YE | | Zâmbia | ZM | | Zimbabué | ZW | | Ilhas Åland | AX |Categorias e subcategorias
Mostrar tabela
| Categoria | Subcategorias | |-----------------------|---------------| | Livros e Referência | EReader, Ficção, Não Ficção, Referência | | Negócios | Contabilidade e Finanças, Colaboração, CRM, Dados e Análise, Gestão de Ficheiros, Inventário e Logística, Legal e Recursos Humanos, Gestão de Projetos, Desktop Remoto, Vendas e Marketing, Tempo e Despesas | | Ferramentas de Desenvolvimento | Base de Dados, Ferramentas de Design, Kits de Desenvolvimento, Redes, Referência e Formação, Servidores, Utilitários, Alojamento Web | Educação | Livros e Referência Educativa, Aprendizagem Inicial, Ferramentas de Instrução, Língua, Auxílios de Estudo | | Entretenimento | (Nenhum) | | Alimentação e Refeições | (Nenhum) | | Governo e Política | (Nenhum) | | Saúde e Fitness | (Nenhum) | | Crianças e Família | Livros e Referência para Crianças e Família, Entretenimento para Crianças e Família, Hobbies e Brinquedos, Desportos e Atividades, Viagens para Crianças e Família | | Estilo de Vida | Automotivo, DIY, Casa e Jardim, Relacionamentos, Interesse Especial, Estilo e Moda | | Medicina | (Nenhum) | | Design Multimedia | Ilustração e Design Gráfico, Produção Musical, Produção de Foto e Vídeo | | Música | (Nenhum) | | Navegação e Mapas | (Nenhum) | | Notícias e Meteorologia | Notícias, Meteorologia | | Finanças Pessoais | Banca e Investimentos, Orçamentação e Impostos | | Personalização | Toques e Sons, temas, Papel de Parede e Ecrãs de Bloqueio | | Foto e Vídeo | (Nenhum) | | Produtividade | (Nenhum) | | Segurança | Proteção de PC, Segurança Pessoal | | Compras | (Nenhum) | | Social | (Nenhum) | | Desporto | (Nenhum) | | Viagens | Guias de Cidade, Hotéis | | Ferramentas e Utilitários | Cópia de Segurança e Gestão, Gestor de Ficheiros |Idiomas
Ver tabela
| Nome da língua | Códigos de idioma suportados | |---------------|--------------------------| | Africâner | af, af-za | | Albanês | sq, sq-al | | Amárico | am, am-et | | Arménio | hy, hy-am | | Assamese | as, as-in | | Azerbaijano | az-arab, az-arab-az, az-cyrl, az-cyrl-az, az-latn, az-latn-az | | Basco (Basco) | eu, eu-es | | Belarusso | be, be-by | | Bangla | bn, bn-bd, bn-in | | Bósnio | bs, bs-cyrl, bs-cyrl-ba, bs-latn, bs-latn-ba | | Búlgaro | bg, bg-bg | | Catalão | ca, ca-es, ca-es-valencia | | Cherokee | chr-cher, chr-cher-us, chr-latn | | Chinês (simplificado) | zh-Hans, zh-cn, zh-hans-cn, zh-sg, zh-hans-sg | | Chinês (Tradicional) | 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 | | Croata | hr, hr-hr, hr-ba | | Checo | cs, cs-cz | | Dinamarquês | da, da-dk | | Dari | prs, prs-af, prs-arab | | Holandês | nl, nl-nl, nl-be | | Inglês | 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 | | Estónio | et, et-ee | | Filipino | fil, fil-latn, fil-ph | | Finlandês | fi, fi-fi | | Francês | fr, fr-be , fr-ca , fr-ch , fr-fr , fr-lu, fr-cd, frc-latn, frp-latn | | Galego | gl, gl-es | | Georgiano | ka, ka-ge | | Alemão | de, de-at, de-ch, de-de, de-lu, de-li | | Grego | el, el-gr | | Gujarati | gu, gu-in | | Hausa | ha, ha-latn, ha-latn-ng | | Hebraico | he, he-il | | Hindi | hi, hi-in | | Húngaro | hu, hu-hu | | Islandês | is, is-is | | Igbo | ig-latn, ig-ng | | Indonésio | id, id-id | | Inuktitut (Latim) | iu-cans, iu-latn, iu-latn-ca | | Irlandês | ga, ga-ie | | isiXhosa | xh, xh-za | | isiZulu | zu, zu-za | | Italiano | it, it-it, it-ch | | Japonês | ja, ja-jp | | Canarês | kn, kn-in | | Cazaque | kk, kk-kz | | Khmer | km, km-kh | | K'iche' | quc-latn, qut-gt, qut-latn | | Kinyarwanda | rw, rw-rw | | KiSwahili | sw, sw-ke | | Konkani | kok, kok-in | | Coreano | ko, ko-kr | | Curdo | ku-arab, ku-arab-iq | | Quirguiz | ky-kg, ky-cyrl | | Laosiano | lo, lo-la | | Letão | lv, lv-lv | | Lituano | lt, lt-lt | | Luxemburguês | lb, lb-lu | | Macedónio | mk, mk-mk | | Malaio | ms, ms-bn, ms-my | | Malaiala | ml, ml-in | | Maltês | mt, mt-mt | | Maori | mi, mi-latn, mi-nz | | Marathi | mr, mr-in | | Mongol (Cirílico) | mn-cyrl, mn-mong, mn-mn, mn-phag | | Nepalês | ne, ne-np | | Norueguês | nb, nb-no, nn, nn-no, no, no-no | | Odia | or, or-in | | Persa | fa, fa-ir | | Polaco | pl, pl-pl | | Português (Brasil) | pt-br | | Português (Portugal) | pt, pt-pt | | Punjabi | pa, pa-arab, pa-arab-pk, pa-deva, pa-in | | Quéchua | quz, quz-bo, quz-ec, quz-pe | | Romeno | ro, ro-ro | | Russo | ru , ru-ru | | Gaélico Escocês | gd-gb, gd-latn | | Sérvio (Latim) | sr-Latn, sr-latn-cs, sr, sr-latn-ba, sr-latn-me, sr-latn-rs | | Sérvio (Cirílico) | sr-cyrl, sr-cyrl-ba, sr-cyrl-cs, sr-cyrl-me, sr-cyrl-rs | | Sesotho sa Leboa | nso, nso-za | | Setsuana | tn, tn-bw, tn-za | | Sindhi | sd-arab, sd-arab-pk, sd-deva | | Cingalês | si, si-lk | | Eslovaco | sk, sk-sk | | Esloveno | sl, sl-si | | Espanhol | 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 | | Sueco | sv, sv-se, sv-fi | | Tajique (Cirílico) | tg-arab, tg-cyrl, tg-cyrl-tj, tg-latn | | Tâmil | ta, ta-in | | Tártaro | tt-arab, tt-cyrl, tt-latn, tt-ru | | Telugu | te, te-in | | Tailandês | th, th-th | | Tigrínia | ti, ti-et | | Turco | tr, tr-tr | | Turcomeno | tk-cyrl, tk-latn, tk-tm, tk-latn-tr, tk-cyrl-tr | | Ucraniano | uk, uk-ua | | Urdu | ur, ur-pk | | Uigur | ug-arab, ug-cn, ug-cyrl, ug-latn | | Uzbeque (Latim) | uz, uz-cyrl, uz-latn, uz-latn-uz | | Vietnamita | vi, vi-vn | | Galês | cy, cy-gb | | Wolof | wo, wo-sn | | Iorubá | yo-latn, yo-ng |Pedido de amostra
{
"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"]
}
cabeçalhos de resposta
| Cabeçalho | Valor |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | Contém a carga útil de resposta real para a solicitação |
| URL de sondagem | Cordão | URL de consulta para obter o estado de qualquer submissão In-Progress |
| idSubmissaoEmAndamento | Cordão | ID de qualquer submissão já do tipo In-Progress |
Exemplo de resposta
{
"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": ""
}
}
Obter API de pacotes de rascunho atuais
Busca detalhes do pacote no envio de rascunho atual.
Path [Todos os pacotes]: /submission/v1/product/{productId}/packages
Método: GET
Caminho [Pacote único]: /submission/v1/product/{productId}/packages/{packageId}
Método: GET
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
| packageId | O ID exclusivo do pacote a ser buscado |
cabeçalhos necessários
| Cabeçalho | Valor |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
cabeçalhos de resposta
| Cabeçalho | Valor |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de erros ou mensagens de aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| Pacotes | Matriz de objetos | Objeto para armazenar dados do módulo do pacote |
| packageId | Cordão | |
| URL do Pacote | Cordão | |
| Idiomas | Matriz de cadeias de caracteres | |
| Arquiteturas | Matriz de cadeias de caracteres | [Neutro, x86, x64, Arm, Arm64] |
| isSilentInstall | booleano | Isso deve ser marcado como verdadeiro se o instalador for executado no modo silencioso sem exigir parâmetros ou então falso. |
| parâmetros do instalador | Cordão | |
| genéricoDocUrl | Cordão | |
| detalhes do erro | Matriz de objetos | |
| Cenário de Erro | Cordão | |
| detalhesDoCenárioDeErro | Matriz de objetos | |
| errorValue | Cordão | |
| errorUrl | Cordão | |
| Tipo de pacote | Cordão |
Exemplo de resposta
{
"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",
}]
}
}
Atualizar a API de Pacotes de Rascunhos Atuais
Atualiza os detalhes do pacote nesta submissão de rascunho atual.
Path [Atualização completa do módulo]: /submission/v1/product/{productId}/packages
Método: PUT
Path [Atualização de patch de pacote único]: /submission/v1/product/{productId}/packages/{packageId}
Método: PATCH
Comportamento da API
No caso da API de Atualização de Módulo Completo – os dados de pacotes inteiros precisam estar presentes na solicitação de atualização completa de cada campo. Qualquer campo que não esteja presente na solicitação, seu valor padrão é usado para substituir o valor atual para esse módulo específico. Isso resulta na substituição de todos os pacotes existentes por um novo conjunto de pacotes da solicitação. Isso resultará na regeneração de IDs de Pacote e o usuário deverá chamar a API de Pacotes GET para obter as Ids de Pacote mais recentes.
No caso da API de Atualização de Patch de Pacote Único – apenas os campos que devem ser atualizados para um determinado pacote precisam estar presentes na solicitação. Esses valores de campo da solicitação substituirão seus valores existentes, mantendo todos os outros campos que não estão presentes na solicitação, iguais aos atuais para esse pacote específico. Outros pacotes no conjunto permanecem como estão.
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
| packageId | A ID exclusiva do pacote |
cabeçalhos necessários
| Cabeçalho | Valor |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
Parâmetros de solicitação
| Nome | Tipo | Descrição |
|---|---|---|
| Pacotes | Matriz de objetos | Objeto para armazenar dados do módulo de pacote [Apenas necessário para atualização completa do módulo] |
| URL do Pacote | Cordão | Obrigatório |
| Idiomas | Matriz de cadeias de caracteres | Obrigatório |
| Arquiteturas | Matriz de cadeias de caracteres | Necessário Deve conter uma única arquitetura - Neutro, X86, X64, Arm, Arm64 |
| isSilentInstall | booleano | Obrigatório Isto deve ser marcado como verdadeiro se o instalador for executado no modo silencioso sem exigir parâmetros, caso contrário, falso. |
| parâmetros do instalador | Cordão | Obrigatório se isSilentInstall for false |
| genéricoDocUrl | Cordão | Necessário se packageType for exe Link para documento que contém detalhes de códigos de erro personalizados para o instalador do tipo EXE |
| detalhes do erro | Matriz de objetos | Metadados para armazenar códigos de erro personalizados e detalhes para instaladores do tipo EXE. |
| Cenário de Erro | Cordão | Identifique o cenário de erro específico. [instalaçãoCanceladaPeloUtilizador, aplicaçãoJáExiste, instalaçãoJáEmProgresso, espaçoEmDiscoCheio, reinícioNecessário, falhaDeRede, pacoteRejeitadoDuranteInstalação, instalaçãoBemSucedida, diversos] |
| detalhesDoCenárioDeErro | Matriz de objetos | |
| errorValue | Cordão | Código de erro que pode estar presente durante a instalação |
| errorUrl | Cordão | URL para ter detalhes sobre o erro |
| Tipo de pacote | Cordão | Necessário [exe, msi] |
Solicitação de amostra [Atualização completa do módulo]
{
"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",
}]
}
Solicitação de exemplo [Atualização de patch de pacote único]
{
"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",
}
cabeçalhos de resposta
| Cabeçalho | Valor |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | [A lista de mensagens de erro ou aviso, se houver] |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A Entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| URL de sondagem | Cordão | [URL para consulta para obter o estado de submissão em caso de qualquer envio existente já com In-Progress] |
| idSubmissaoEmAndamento | Cordão | [ID de submissão de qualquer submissão já In-Progress] |
Exemplo de resposta
{
"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 de Consolidação de Pacotes
Confirma o novo conjunto de Pacotes atualizados utilizando as APIs de Atualização de Pacotes na submissão de rascunho atual. Esta API devolve um URL de sondagem para acompanhar o upload do pacote.
Caminho: /submission/v1/product/{productId}/packages/commit
Método: POST
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
cabeçalhos necessários
| Cabeçalho | Valor |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
cabeçalhos de resposta
| Cabeçalho | Valor |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | [A lista de mensagens de erro ou aviso, se houver] |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| URL de sondagem | Cordão | [Consulta de URL para obter o status de Upload de Pacote ou Status de Submissão no caso de qualquer Envio Anterior In-Progress] |
| idSubmissaoEmAndamento | Cordão | [ID de qualquer submissão que já seja In-Progress] |
Exemplo de resposta
{
"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": ""
}
}
Obter a API dos Ativos da Listagem de Rascunho Atual
Busca detalhes de ativos de listagem no envio de rascunho atual.
Caminho: /submission/v1/product/{productId}/listings/assets?languages={languages}
Método: GET
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
Parâmetros de Consulta
| Nome | Descrição |
|---|---|
| Idiomas | [Opcional] O filtro de idiomas listados como lista separada por vírgulas [limite de até 200 idiomas]. Se não existirem, os primeiros 200 dados de ativos do idioma de listagem disponíveis são recuperados. (por exemplo, "en-us, en-gb") |
cabeçalhos necessários
| Cabeçalho | Valor |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
cabeçalhos de resposta
| Cabeçalho | Valor |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| listagem de Ativos | Matriz de objetos | Listando detalhes de ativos para cada idioma |
| linguagem | Cordão | |
| logótipos de loja | Matriz de objetos | |
| capturas de ecrã | Matriz de objetos | |
| ID | Cordão | |
| URL do ativo | Cordão | Deve ser um URL válido |
| tamanho da imagem | Objeto | |
| Largura | Número inteiro | |
| altura | Número inteiro |
Exemplo de resposta
{
"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
}
}
]
}]
}
}
Criar API de listagem de ativos
Cria um novo Carregamento de Recursos de Listagem na submissão de rascunho atual.
Atualização de ativos de listagem
A API de Submissão da Microsoft Store para aplicações EXE ou MSI utiliza URLs SAS geradas em tempo de execução para Repositórios de Blobs em cada upload de ativo de imagem individual, juntamente com uma chamada à API de Commit após a conclusão bem-sucedida do upload. Para ter a capacidade de atualizar ativos de listagem e, por sua vez, para poder adicionar/remover localidades no módulo de listagem, a seguinte abordagem pode ser usada:
- Utilize a API Criar Listagem de Ativos para enviar pedido referente ao carregamento de ativos, com o idioma, o tipo e a contagem de ativos.
- Com base no número de ativos solicitados, os IDs de ativos são criados sob demanda e criariam uma URL SAS de curto prazo e a enviariam de volta no Corpo de Resposta sob o tipo de ativos. Você pode usar este URL para carregar ativos de imagem de tipo específico usando clientes HTTP [Colocar Blob (API REST) - Armazenamento do Azure | Microsoft Docs].
- Depois de carregar, você pode usar a API Confirmar Listagem de Ativos para também enviar as novas informações de ID de Ativo recebidas anteriormente da chamada de API anterior. A API única confirmará internamente os dados de listagem de ativos após a validação.
- Essa abordagem substituirá efetivamente todo o conjunto de Imagens anteriores do Tipo de Ativo em Idioma específico que está sendo enviado em Solicitação. Assim, os Ativos carregados anteriormente serão removidos.
Caminho: /submission/v1/product/{productId}/listings/assets/create
Método: POST
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
cabeçalhos necessários
| Cabeçalho | Descrição |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
Parâmetros de solicitação
| Nome | Tipo | Descrição |
|---|---|---|
| linguagem | Cordão | Obrigatório |
| createAssetRequest | Objeto | Obrigatório |
| Captura de ecrã | Número inteiro | Necessário se o ISV precisar atualizar capturas de tela ou adicionar novo idioma de listagem [1 - 10] |
| Logótipo | Número inteiro | Obrigatório se o ISV precisar atualizar logotipos ou adicionar novo idioma de listagem [1 ou 2] |
cabeçalhos de resposta
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| listagem de Ativos | Objeto | Objeto contendo detalhes dos logotipos da loja e das capturas de ecrã a serem carregados |
| linguagem | Cordão | |
| logótipos de loja | Matriz de objetos | |
| capturas de ecrã | Matriz de objetos | |
| ID | Cordão | |
| URL de Carregamento de Ativo Principal | Cordão | URL principal para transferir um recurso de listagem usando a API REST do Azure Blob |
| secundárioAtivoCarregarURL | Cordão | URL secundária para carregar recurso de listagem usando a API REST do Blob do Azure |
| Método http | Método HTTP | O método HTTP precisava ser usado para carregar ativos por meio das URLs de carregamento de ativos – primária ou secundária |
| Cabeçalhos HTTP | Objeto | Um objeto com chaves como cabeçalhos obrigatórios para estar presente na chamada da API de carregamento para URLs de envio de ativos. Se o valor não estiver vazio, os cabeçalhos precisarão ter valores específicos. Caso contrário, os valores são calculados durante a chamada de API. |
Exemplo de resposta
{
"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 de Comprometimento de Listagem de Ativos
Confirma o novo Ativo de Listagem carregado usando os detalhes da API Criar Ativos na submissão de rascunho atual.
Caminho: /submission/v1/product/{productId}/listings/assets/commit
Método: PUT
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
cabeçalhos necessários
| Cabeçalho | Descrição |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
Parâmetros de solicitação
| Nome | Tipo | Descrição |
|---|---|---|
| listagem de Ativos | Objeto | |
| linguagem | Cordão | |
| logótipos de loja | Matriz de objeto | |
| capturas de ecrã | Matriz de objeto | |
| ID | Cordão | Deve ser uma ID existente que o usuário deseja persistir da API Get Current Listing Assets ou uma nova ID sob a qual um novo Asset foi carregado na Create Listing Assets API. |
| URL do ativo | Cordão | Deve ser a URL do ativo existente que o usuário deseja persistir da API Get Current Listing Assets ou a URL de upload – primária ou secundária, usando a qual um novo ativo foi carregado na API Create Listing Assets. Deve ser um URL válido |
Pedido de amostra
{
"listingAssets": {
"language": "en-us",
"storeLogos": [
{
"id": "1234567890abcdefgh",
"assetUrl": "https://contoso.com/blob=1234567890abcdefgh",
}
],
"screenshots": [
{
"id": "1234567891abcdefgh",
"assetUrl": "https://contoso.com/blob=1234567891abcdefgh",
}
]
}
}
cabeçalhos de resposta
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| URL de sondagem | Cordão | URL de sondagem para obter o status de qualquer envio em andamento |
| idSubmissaoEmAndamento | Cordão | ID de submissão de qualquer submissão já em curso |
Exemplo de resposta
{
"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 de sondagem de status do módulo
API para verificar a prontidão do módulo antes que o envio possa ser criado. Também valida o status de carregamento do pacote.
Caminho: /submission/v1/product/{productId}/status
Método: GET
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
cabeçalhos necessários
| Cabeçalho | Descrição |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
cabeçalhos de resposta
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| estáPronto | booleano | Indica se todos os módulos estão no estado pronto, incluindo o carregamento do pacote |
| idSubmissaoEmAndamento | Cordão | ID de submissão de qualquer submissão já em curso |
Exemplo de resposta
{
"isSuccess": true,
"errors": [{
"code": "badrequest",
"message": "Error Message 1",
"target": "listings"
}, {
"code": "warning",
"message": "Warning Message 1",
"target": "properties"
}],
"responseData": {
"isReady": true,
"ongoingSubmissionId": ""
}
}
Criar API de envio
Cria uma submissão a partir do rascunho atual para uma aplicação MSI ou EXE. A API verifica:
- para envio ativo e falha com mensagem de erro se existir um envio ativo.
- se todos os módulos estiverem no estado pronto para criar submissão.
- cada campo na submissão é validado de acordo com os requisitos da Loja
Caminho:/submission/v1/product/{productId}/submit
Método: POST
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
cabeçalhos necessários
| Cabeçalho | Descrição |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
cabeçalhos de resposta
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| URL de sondagem | Cordão | URL de consulta para obter o estado de preparação do módulo, incluindo o carregamento do pacote para submissão |
| ID da submissão | Cordão | O ID da submissão recém-criada |
| idSubmissaoEmAndamento | Cordão | ID de submissão de qualquer submissão já em curso |
Exemplo de resposta
{
"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 de pesquisa de status de envio
API para verificar o status de envio.
Caminho: /submission/v1/product/{productId}/submission/{submissionId}/status
Método: GET
parâmetros de caminho
| Nome | Descrição |
|---|---|
| productId | O ID do Centro de Parceiros do produto |
cabeçalhos necessários
| Cabeçalho | Descrição |
|---|---|
Authorization: Bearer <Token> |
Usando a ID do aplicativo Microsoft Entra ID registrada com a conta do Partner Center |
X-Seller-Account-Id |
ID do vendedor da conta do Partner Center |
cabeçalhos de resposta
| Cabeçalho | Descrição |
|---|---|
X-Correlation-ID |
O ID único do tipo GUID para cada pedido. Isso pode ser compartilhado com a equipe de suporte para analisar qualquer problema. |
Retry-After |
O tempo, em segundos, que o cliente precisa esperar antes de chamar as APIs novamente devido ao limite de taxa. |
Parâmetros de resposta
| Nome | Tipo | Descrição |
|---|---|---|
| éSucesso | booleano | |
| erros | Matriz de objetos | A lista de mensagens de erro ou aviso, se houver |
| código | Cordão | O código de erro da mensagem |
| mensagem | Cordão | A descrição do erro |
| destino | Cordão | A entidade da qual o erro se originou |
| dadosDeResposta | Objeto | |
| estado de publicação | Cordão | Status de publicação do envio - [EM PROGRESSO, PUBLICADO, FALHOU, DESCONHECIDO] |
| hasFailed | booleano | Indica se a publicação falhou e não será repetida |
Exemplo de resposta
{
"isSuccess": true,
"errors": [{
"code": "badrequest",
"message": "Error Message 1",
"target": "listings"
}, {
"code": "warning",
"message": "Warning Message 1",
"target": "properties"
}],
"responseData": {
"publishingStatus": "INPROGRESS",
"hasFailed": false
}
}
Exemplos de código
Os artigos a seguir fornecem exemplos de código detalhados que demonstram como usar a API de envio da Microsoft Store em diferentes linguagens de programação:
Exemplo de C#: API de envio da Microsoft Store para aplicativo MSI ou EXE
Este artigo fornece exemplos de código C# que demonstram como usar a API de envio da Microsoft Store para aplicativos MSI ou EXE. Você pode revisar cada exemplo para saber mais sobre a tarefa que ele demonstra ou pode criar todos os exemplos de código neste artigo em um aplicativo de console.
Pré-requisitos Estes exemplos usam a seguinte biblioteca:
- Newtonsoft.Json pacote NuGet da Newtonsoft.
Programa principal O exemplo a seguir implementa um programa de linha de comando que chama os outros métodos de exemplo neste artigo para demonstrar diferentes maneiras de usar a API de envio da Microsoft Store. Para adaptar este programa para seu próprio uso:
- Atribua a propriedade SellerId à ID do vendedor da sua conta do Partner Center.
- Atribua a propriedade ApplicationId à ID do aplicativo que você deseja gerenciar.
- Atribua as propriedades ClientId e ClientSecret ao ID do cliente e à chave da sua aplicação e substitua o string tenantid na URL TokenEndpoint pelo ID do locatário da sua aplicação. Para obter mais informações, consulte Como associar um aplicativo Microsoft Entra ID à sua conta do Partner Center
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();
}
}
}
Classe auxiliar ClientConfiguration usando C#
O aplicativo de exemplo usa a classe auxiliar ClientConfiguration para passar dados do Microsoft Entra ID Directory e dados do aplicativo para cada um dos métodos de exemplo que usam a API de envio da Microsoft Store.
using System;
using System.Collections.Generic;
using System.Text;
namespace Win32SubmissionApiCSharpSample
{
public class ClientConfiguration
{
/// <summary>
/// Client Id of your Microsoft Entra ID Directory app.
/// Example" 00001111-aaaa-2222-bbbb-3333cccc4444
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// Client secret of your Microsoft Entra ID 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 Microsoft Entra ID 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; }
}
}
Criar um envio de aplicativo usando C#
O exemplo a seguir implementa uma classe que usa vários métodos na API de envio da Microsoft Store para atualizar um envio de aplicativo.
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Win32SubmissionApiCSharpSample
{
public class AppSubmissionUpdateSample
{
private ClientConfiguration ClientConfig;
/// <summary>
/// Constructor
/// </summary>
/// <param name="configuration">An instance of ClientConfiguration that contains all parameters populated</param>
public AppSubmissionUpdateSample(ClientConfiguration configuration)
{
this.ClientConfig = configuration;
}
/// <summary>
/// Main method to Run the Sample Application
/// </summary>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task RunAppSubmissionUpdateSample()
{
// **********************
// SETTINGS
// **********************
var appId = this.ClientConfig.ApplicationId;
var clientId = this.ClientConfig.ClientId;
var clientSecret = this.ClientConfig.ClientSecret;
var serviceEndpoint = this.ClientConfig.ServiceUrl;
var tokenEndpoint = this.ClientConfig.TokenEndpoint;
var scope = this.ClientConfig.Scope;
// Get authorization token.
Console.WriteLine("Getting authorization token");
var accessToken = await SubmissionClient.GetClientCredentialAccessToken(
tokenEndpoint,
clientId,
clientSecret,
scope);
var client = new SubmissionClient(accessToken, serviceEndpoint);
client.DefaultHeaders = new Dictionary<string, string>()
{
{"X-Seller-Account-Id", this.ClientConfig.SellerId.ToString() }
};
Console.WriteLine("Getting Current Application Draft Status");
dynamic AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(AppDraftStatus.ToString());
Console.WriteLine("Getting Application Packages ");
dynamic PackagesResponse = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.PackagesUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(PackagesResponse.ToString());
Console.WriteLine("Getting Single Package");
dynamic SinglePackageResponse = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.PackageByIdUrlTemplate,
SubmissionClient.Version, appId, (string)PackagesResponse.responseData.packages[0].packageId), null);
Console.WriteLine(SinglePackageResponse.ToString());
Console.WriteLine("Updating Entire Package Set");
// Update data in Packages list to have final set of updated Packages
// Example - Updating Installer Parameters
PackagesResponse.responseData.packages[0].installerParameters = "/s /r new-args";
dynamic PackagesUpdateRequest = new
{
packages = PackagesResponse.responseData.packages
};
dynamic PackagesUpdateResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.PackagesUrlTemplate,
SubmissionClient.Version, appId), PackagesUpdateRequest);
Console.WriteLine(PackagesUpdateResponse.ToString());
Console.WriteLine("Updating Single Package's Download Url");
// Update data in the SinglePackage object
var SinglePackageUpdateRequest = SinglePackageResponse.responseData.packages[0];
// Example - Updating Installer Parameters
SinglePackageUpdateRequest.installerParameters = "/s /r /t new-args";
dynamic PackageUpdateResponse = await client.Invoke<dynamic>(HttpMethod.Patch, string.Format(SubmissionClient.PackageByIdUrlTemplate,
SubmissionClient.Version, appId, SinglePackageUpdateRequest.packageId), SinglePackageUpdateRequest);
Console.WriteLine("Committing Packages");
dynamic PackageCommitResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.PackagesCommitUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(PackageCommitResponse.ToString());
Console.WriteLine("Polling Package Upload Status");
AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
SubmissionClient.Version, appId), null);
while (!((bool)AppDraftStatus.responseData.isReady))
{
AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine("Waiting for Upload to finish");
await Task.Delay(TimeSpan.FromSeconds(2));
if(AppDraftStatus.errors != null && AppDraftStatus.errors.Count > 0)
{
for(var index = 0; index < AppDraftStatus.errors.Count; index++)
{
if(AppDraftStatus.errors[index].code == "packageuploaderror")
{
throw new InvalidOperationException("Package Upload Failed. Please try committing packages again.");
}
}
}
}
Console.WriteLine("Getting Application Metadata - All Modules");
dynamic AppMetadata = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.AppMetadataUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(AppMetadata.ToString());
Console.WriteLine("Getting Application Metadata - Listings");
dynamic AppListingsMetadata = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.AppListingsFetchMetadataUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(AppListingsMetadata.ToString());
Console.WriteLine("Updating Listings Metadata - Description");
// Update Required Fields in Listings Metadata Object - Per Language. For eg. AppListingsMetadata.responseData.listings[0]
// Example - Updating Description
AppListingsMetadata.responseData.listings[0].description = "New Description Updated By C# Sample Code";
dynamic ListingsUpdateRequest = new
{
listings = AppListingsMetadata.responseData.listings[0]
};
dynamic UpdateListingsMetadataResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.AppMetadataUrlTemplate,
SubmissionClient.Version, appId), ListingsUpdateRequest);
Console.WriteLine(UpdateListingsMetadataResponse.ToString());
Console.WriteLine("Getting All Listings Assets");
dynamic ListingAssets = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ListingAssetsUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(ListingAssets.ToString());
Console.WriteLine("Creating Listing Assets for 1 Screenshot");
dynamic AssetCreateRequest = new
{
language = ListingAssets.responseData.listingAssets[0].language,
createAssetRequest = new Dictionary<string, int>()
{
{"Screenshot", 1 },
{"Logo", 0 }
}
};
dynamic AssetCreateResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.ListingAssetsCreateUrlTemplate,
SubmissionClient.Version, appId), AssetCreateRequest);
Console.WriteLine(AssetCreateResponse.ToString());
Console.WriteLine("Uploading Listing Assets");
// Path to PNG File to be Uploaded as Screenshot / Logo
var PathToFile = "./Image.png";
var AssetToUpload = File.OpenRead(PathToFile);
await client.UploadAsset(AssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl.Value as string, AssetToUpload);
Console.WriteLine("Committing Listing Assets");
dynamic AssetCommitRequest = new
{
listingAssets = new
{
language = ListingAssets.responseData.listingAssets[0].language,
storeLogos = ListingAssets.responseData.listingAssets[0].storeLogos,
screenshots = JToken.FromObject(new List<dynamic>() { new
{
id = AssetCreateResponse.responseData.listingAssets.screenshots[0].id.Value as string,
assetUrl = AssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl.Value as string
}
}.ToArray())
}
};
dynamic AssetCommitResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.ListingAssetsCommitUrlTemplate,
SubmissionClient.Version, appId), AssetCommitRequest);
Console.WriteLine(AssetCommitResponse.ToString());
Console.WriteLine("Getting Current Application Draft Status before Submission");
AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(AppDraftStatus.ToString());
if (AppDraftStatus == null || !((bool)AppDraftStatus.responseData.isReady))
{
throw new InvalidOperationException("Application Current Status is not in Ready Status for All Modules");
}
Console.WriteLine("Creating Submission");
dynamic SubmissionCreationResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.CreateSubmissionUrlTemplate,
SubmissionClient.Version, appId), null);
Console.WriteLine(SubmissionCreationResponse.ToString());
Console.WriteLine("Current Submission Status");
dynamic SubmissionStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.SubmissionStatusPollingUrlTemplate,
SubmissionClient.Version, appId, SubmissionCreationResponse.responseData.submissionId.Value as string), null);
Console.Write(SubmissionStatus.ToString());
// User can Poll on this API to know if Submission Status is INPROGRESS, PUBLISHED or FAILED.
// This Process involves File Scanning, App Certification and Publishing and can take more than a day.
}
}
}
IngestionClient classe auxiliar usando C#
A classe IngestionClient fornece métodos auxiliares que são usados por outros métodos no aplicativo de exemplo para executar as seguintes tarefas:
- Obtenha um token de acesso do Microsoft Entra ID que pode ser usado para invocar métodos na API de submissão da Microsoft Store. Depois de obter um token, você tem 60 minutos para usá-lo em chamadas para a API de envio da Microsoft Store antes que o token expire. Depois que o token expirar, você poderá gerar um novo token.
- Processe as solicitações HTTP para a API de envio da Microsoft Store.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Win32SubmissionApiCSharpSample
{
/// <summary>
/// This class is a proxy that abstracts the functionality of the API service
/// </summary>
public class SubmissionClient : IDisposable
{
public static readonly string Version = "1";
private HttpClient httpClient;
private HttpClient imageUploadClient;
private readonly string accessToken;
public static readonly string PackagesUrlTemplate = "/submission/v{0}/product/{1}/packages";
public static readonly string PackageByIdUrlTemplate = "/submission/v{0}/product/{1}/packages/{2}";
public static readonly string PackagesCommitUrlTemplate = "/submission/v{0}/product/{1}/packages/commit";
public static readonly string AppMetadataUrlTemplate = "/submission/v{0}/product/{1}/metadata";
public static readonly string AppListingsFetchMetadataUrlTemplate = "/submission/v{0}/product/{1}/metadata/listings";
public static readonly string ListingAssetsUrlTemplate = "/submission/v{0}/product/{1}/listings/assets";
public static readonly string ListingAssetsCreateUrlTemplate = "/submission/v{0}/product/{1}/listings/assets/create";
public static readonly string ListingAssetsCommitUrlTemplate = "/submission/v{0}/product/{1}/listings/assets/commit";
public static readonly string ProductDraftStatusPollingUrlTemplate = "/submission/v{0}/product/{1}/status";
public static readonly string CreateSubmissionUrlTemplate = "/submission/v{0}/product/{1}/submit";
public static readonly string SubmissionStatusPollingUrlTemplate = "/submission/v{0}/product/{1}/submission/{2}/status";
public const string JsonContentType = "application/json";
public const string PngContentType = "image/png";
public const string BinaryStreamContentType = "application/octet-stream";
/// <summary>
/// Initializes a new instance of the <see cref="SubmissionClient" /> class.
/// </summary>
/// <param name="accessToken">
/// The access token. This is JWT a token obtained from Microsoft Entra ID 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
/// Microsoft Entra ID Directory app. Example: https://login.microsoftonline.com/d454d300-128e-2d81-334a-27d9b2baf002/oauth2/v2.0/token </param>
/// <param name="clientId">Client Id of your Microsoft Entra ID Directory app. Example" 00001111-aaaa-2222-bbbb-3333cccc4444</param>
/// <param name="clientSecret">Client secret of your Microsoft Entra ID 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;
}
}
}
Node.js exemplo: API de envio da Microsoft Store para aplicativo MSI ou EXE
Este artigo fornece exemplos de código Node.js que demonstram como usar a API de submissão da Microsoft Store para aplicações MSI ou EXE. Você pode revisar cada exemplo para saber mais sobre a tarefa que ele demonstra ou pode criar todos os exemplos de código neste artigo em um aplicativo de console.
Pré-requisitos Estes exemplos usam a seguinte biblioteca:
- node-fetch v2 [npm instalar node-fetch@2]
Criar um envio de aplicativo usando node.js
O exemplo a seguir invoca os outros métodos exemplificados neste artigo para demonstrar diferentes maneiras de usar a API de submissão da Microsoft Store. Para adaptar este programa para seu próprio uso:
- Atribua a propriedade SellerId à ID do vendedor da sua conta do Partner Center.
- Atribua a propriedade ApplicationId à ID do aplicativo que você deseja gerenciar.
- Atribua as propriedades ClientId e ClientSecret ao ID do cliente e à chave da sua aplicação e substitua o string tenantid na URL TokenEndpoint pelo ID do locatário da sua aplicação. Para obter mais informações, consulte Como associar um aplicativo Microsoft Entra ID à sua conta do Partner Center
O exemplo a seguir implementa uma classe que usa vários métodos na API de envio da Microsoft Store para atualizar um envio de aplicativo.
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();
Auxiliar de configuração do cliente
O aplicativo de exemplo usa a classe auxiliar ClientConfiguration para passar dados do Microsoft Entra ID Directory e dados do aplicativo para cada um dos métodos de exemplo que usam a API de envio da Microsoft Store.
/** Configuration Object for Store Submission API */
var config = {
version : "1",
applicationId : "...",
clientId : "...",
clientSecret : "...",
serviceEndpoint : "https://api.store.microsoft.com",
tokenEndpoint : "...",
scope : "https://api.store.microsoft.com/.default",
sellerId : "...",
jsonContentType : "application/json",
pngContentType : "image/png",
binaryStreamContentType : "application/octet-stream"
};
module.exports = config;
IngestionClient helper usando node.js
A classe IngestionClient fornece métodos auxiliares que são usados por outros métodos no aplicativo de exemplo para executar as seguintes tarefas:
- Obtenha um token de acesso do Microsoft Entra ID que pode ser usado para invocar métodos na API de submissão da Microsoft Store. Depois de obter um token, você tem 60 minutos para usá-lo em chamadas para a API de envio da Microsoft Store antes que o token expire. Depois que o token expirar, você poderá gerar um novo token.
- Processe as solicitações HTTP para a API de envio da Microsoft Store.
const fetch = require('node-fetch');
/**
* Submission Client to invoke all available Store Submission API and Asset Upload to Blob Store
*/
class SubmissionClient{
constructor(config){
this.configuration = config;
this.accessToken = "";
this.packagesUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages`;
this.packageByIdUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages/{packageId}`;
this.packagesCommitUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages/commit`;
this.appMetadataUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/metadata`;
this.appListingsFetchMetadataUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/metadata/listings`;
this.listingAssetsUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets`;
this.listingAssetsCreateUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets/create`;
this.listingAssetsCommitUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets/commit`;
this.productDraftStatusPollingUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/status`;
this.createSubmissionUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/submit`;
this.submissionStatusPollingUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/submission/{submissionId}/status`;
}
async getAccessToken(){
var params = new URLSearchParams();
params.append('grant_type','client_credentials');
params.append('client_id',this.configuration.clientId);
params.append('client_secret',this.configuration.clientSecret);
params.append('scope',this.configuration.scope);
var response = await fetch(this.configuration.tokenEndpoint,{
method: "POST",
body: params
});
var data = await response.json();
this.accessToken = data.access_token;
}
async callStoreAPI(url, method, data){
var request = {
method: method,
headers:{
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': this.configuration.jsonContentType,
'X-Seller-Account-Id': this.configuration.sellerId
},
};
if(data){
request.body = JSON.stringify(data);
}
var response = await fetch(`${this.configuration.serviceEndpoint}${url}`,request);
var jsonResponse = await response.json();
return jsonResponse;
}
async uploadAssets(url, stream, size){
var request = {
method: 'put',
headers:{
'Content-Type': this.configuration.pngContentType,
'x-ms-blob-type': 'BlockBlob',
"Content-length": size
},
body: stream
};
var response = await fetch(`${url}`,request);
if(response.ok){
return response;
}
else{
throw new Error('Uploading of assets failed');
}
}
}
module.exports = SubmissionClient;
Ajuda adicional
Se você tiver dúvidas sobre a API de envio da Microsoft Store ou precisar de ajuda para gerenciar seus envios com essa API, use os seguintes recursos:
- Faça as suas perguntas nos fóruns.
- Visite nossa página de suporte e solicite uma das opções de suporte assistido para o Partner Center. Se você for solicitado a escolher um tipo e categoria de problema, escolha Envio e certificação de aplicativos e Enviar um aplicativo, respectivamente.
Perguntas frequentes
O que posso fazer através da API de submissão da Microsoft Store?
A API de envio da Microsoft Store permite que os desenvolvedores automatizem tarefas de gerenciamento de aplicativos, incluindo:
- Criação e envio de novas atualizações de aplicativos.
- Carregar e gerir pacotes de aplicações.
- Atualização de metadados e listagens da Loja.
Você pode integrar essa API em sua integração contínua ou criar fluxos de trabalho, automatizando tarefas de rotina para simplificar seu processo de publicação.
Windows developer