Integre sua solução de SaaS com a API Google Cloud Marketplace usando o Portal do Produtor (Python)

1. Introdução

As soluções SaaS no Google Cloud Marketplace são soluções de software que são executadas na sua infraestrutura, não importa o local, mas são faturadas pelo Google.

Neste codelab, você vai configurar uma solução SaaS básica que se integra ao Google Cloud Marketplace para:

  • Receber notificações quando um usuário se inscrever na solução de exemplo.
  • Aprove os clientes que querem se inscrever e adicione-os ao seu banco de dados.
  • Lidar com cenários em que os clientes querem mudar ou cancelar os planos de faturamento.
  • Enviar relatórios de uso ao Google.

Este codelab ajuda você a conhecer as APIs de compras e controle de serviços do Google Cloud Marketplace. Este guia não oferece um ambiente de produto completo para testes.

2. Antes de começar

  • Use o Producer Portal para ativar o codelab no seu projeto, caso ainda não tenha feito isso.

O link direto para o Portal do Produtor é:

https://console.cloud.google.com/producer-portal?project=YOUR_PROJECT_ID

Para ativar o codelab, clique em Ativar no painel "Codelabs" à direita da tela.

Para instalar os módulos do Python, use o seguinte comando:

pip install --upgrade google-api-python-client google-cloud-pubsub
git clone https://github.com/googlecodelabs/gcp-marketplace-integrated-saas.git
cd gcp-marketplace-integrated-saas

  • Defina a variável de ambiente GOOGLE_CLOUD_PROJECT como o ID deste projeto:
  • Linux:
export GOOGLE_CLOUD_PROJECT="YOUR_PROJECT_ID"
  • Windows:
set GOOGLE_CLOUD_PROJECT=YOUR_PROJECT_ID
  • Defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS como o caminho completo para o arquivo baixado:
  • Linux:
export GOOGLE_APPLICATION_CREDENTIALS="[YOUR_MACHINE]/path/service-account-key.json"
  • Windows:
set GOOGLE_APPLICATION_CREDENTIALS=[YOUR_MACHINE]/path/service-account-key.json
  • Para conferir uma solução de exemplo no Google Cloud Marketplace, acesse o Portal do Produtor e clique em Produto do codelab no painel "Codelabs". Você também pode acessar a solução diretamente em https://console.cloud.google.com/marketplace/product/DEMO-YOUR_PROJECT_ID/isaas-codelab
  • No Console do Google Cloud, no novo projeto, ative a API Partner Procurement.

Em seguida, configure o back-end para a solução de exemplo.

3. Integração com o Google Cloud Marketplace

Em alto nível, você integra a solução de exemplo ao Google Cloud Marketplace das seguintes maneiras:

  • Integre-se ao Cloud Pub/Sub para receber notificações do Google Cloud Marketplace, como quando um usuário se inscreve na solução. Seu engenheiro parceiro cria um tópico do Cloud Pub/Sub em que você precisa se inscrever para receber notificações.
  • Integre-se à API Partner Procurement para criar contas para novos clientes. Você usa a API Partner Procurement para atualizar as contas quando os usuários selecionam, mudam ou cancelam os planos de assinatura. Para se integrar à API, é necessário criar sua própria biblioteca de cliente.
  • Integre com o Google Service Control para informar os dados de uso.

4. Inscrever-se no tópico do Cloud Pub/Sub

Quando um usuário escolhe um plano de assinatura, você recebe uma notificação do Google Cloud Marketplace por um tópico do Cloud Pub/Sub.

Para ouvir mensagens em um tópico do Cloud Pub/Sub, primeiro crie uma assinatura.

Para criar uma assinatura, use o script create_subscription.py:

cd gcp-marketplace-integrated-saas/tools
python create_subscription.py

Para ver a assinatura, abra o painel do Cloud Pub/Sub no Console do Cloud:

https://console.cloud.google.com/cloudpubsub/subscriptions

Teste uma solicitação de assinatura de teste

Para testar este app de exemplo como usuário, abra o produto do codelab no Marketplace acessando https://console.cloud.google.com/marketplace/product/DEMO-YOUR_PROJECT_ID/isaas-codelab. Verifique se o projeto do codelab está selecionado e escolha um plano de assinatura.

Para ver as mensagens do Cloud Pub/Sub enviadas quando você escolhe um plano, navegue até a raiz do diretório python3 no repositório e execute o seguinte comando:

~/gcp-marketplace-integrated-saas/python3$ python -m impl.step_1_pubsub.app

Para conferir o exemplo de código que detecta mensagens do Cloud Pub/Sub, acesse https://github.com/googlecodelabs/gcp-marketplace-integrated-saas/blob/master/python3/impl/step_1_pubsub/app.py.

Na mensagem do Cloud Pub/Sub, o campo eventType mostra por que a mensagem foi enviada. Ao escolher um plano, você vai ver uma mensagem para eventType: ENTITLEMENT_CREATION_REQUESTED, que representa sua escolha anterior de plano de assinatura.

Se você cancelar o plano enquanto esse script estiver em execução, uma nova mensagem vai aparecer para eventType: ENTITLEMENT_CANCELLED.

A amostra acima não confirma o recebimento das mensagens. Isso permite testar com mais facilidade recebendo as mesmas mensagens sempre que você executa o app.

Para fechar o script, pressione CTRL + \.

5. Aprovar o pedido de conta

Agora que você pode receber mensagens do Google Cloud Marketplace, comece a processar os recursos que o serviço de compras do Google Cloud Marketplace cria em nome do cliente.

O primeiro é o recurso account. Uma conta representa a conexão de um cliente com seu produto. Você precisa armazenar o ID da conta de compras do cliente no seu banco de dados para mapear a relação entre a Conta do Google e a conta do seu serviço.

Quando um cliente escolhe um plano, o Google Cloud Marketplace envia uma notificação do Cloud Pub/Sub informando que o cliente está solicitando uma conta. Seu app precisa aprovar a solicitação. Neste codelab, você vai aprovar as solicitações de conta quando as mensagens do Cloud Pub/Sub forem recebidas.

Criar o banco de dados para as informações da conta

Neste codelab, usamos um banco de dados JSON simples que pode rastrear contas e compras de clientes.

Para testar esta amostra, crie um arquivo com um objeto JSON vazio em qualquer lugar da sua estação de trabalho:

{}

Defina a variável de ambiente PROCUREMENT_CODELAB_DATABASE como o caminho completo para esse arquivo:

  • Linux:
export PROCUREMENT_CODELAB_DATABASE="YOUR_MACHINE/path/EMPTY_JSON_OBJECT.json"
  • Windows:
set PROCUREMENT_CODELAB_DATABASE=YOUR_MACHINE/path/EMPTY_JSON_OBJECT.json

O módulo que lê e grava o banco de dados está em python3/impl/database.

A implementação de exemplo usa um esquema que pode ser estendido se você estiver integrando mais de uma oferta de produto ao Google Cloud Marketplace. Confira a seguir um exemplo de entrada de banco de dados para um usuário que assinou o plano Very Good no app de exemplo:

{
   "a2b3c4d5-b3f1-4dea-b134-generated_id":{
      "procurement_account_id":"generated-b3f1-4dea-b134-4a1d100c0335",
      "internal_account_id":"generated-45b7-4f4d-1bcd-2abb114f77de",
      "products":{
         "isaas-codelab":{
            "start_time":"2019-01-04T01:21:16.188Z",
            "plan_id":"very-good",
            "product_id":"isaas-codelab",
            "consumer_id":"project_number:123123345345"
         }
      }
   }
}

Na implementação final, conecte seu app aos seus próprios bancos de dados para vincular as contas do Google Cloud Marketplace dos clientes aos seus recursos de clientes.

Aprovar a conta

Para aprovar a solicitação de conta, execute o seguinte comando:

~/gcp-marketplace-integrated-saas/python3$ python3 -m impl.step_2_account.app

O exemplo de código para aprovar uma conta está em impl/step_2_account.

A implementação de exemplo usa a classe Procurement, que processa as interações com a API Procurement. Confira os métodos get_account() e approve_account():

step_2_account/app.py

def _get_account_name(self, account_id):
    return 'providers/DEMO-{}/accounts/{}'.format(PROJECT_ID,
                                                  account_id)

def get_account(self, account_id):
    """Gets an account from the Procurement Service."""
    name = self._get_account_name(account_id)
    request = self.service.providers().accounts().get(name=name)
    try:
        response = request.execute()
        return response
    except HttpError as err:
        if err.resp.status == 404:
            return None

def approve_account(self, account_id):
    """Approves the account in the Procurement Service."""
    name = self._get_account_name(account_id)
    request = self.service.providers().accounts().approve(
        name=name, body={'approvalName': 'signup'})
    request.execute()

Para este codelab, no serviço de compras, o ID do provedor é DEMO-YOUR_PROJECT_ID, em que YOUR_PROJECT_ID é o projeto que você criou. Ao interagir com a API Procurement, o nome da conta precisa usar o seguinte formato:

providers/DEMO-YOUR_PROJECT_ID/accounts/account-id

Em seguida, você aprova um direito, que é um registro da compra do cliente.

6. Aprovar o direito

Quando um cliente escolhe um plano de assinatura no Google Cloud Marketplace, uma conta é criada, e uma nova solicitação de direito é criada imediatamente. O direito representa a compra de um serviço. Antes que o cliente possa começar a usar o serviço, você precisa aprovar a solicitação de direito e configurar o serviço para que ele possa começar a usar.

Quando o app de exemplo recebe uma mensagem do Cloud Pub/Sub com o eventType ENTITLEMENT_CREATION_REQUESTED, o direito é aprovado, e o app precisa aguardar uma mensagem ENTITLEMENT_ACTIVE para registrar o direito no banco de dados e configurar os recursos para o cliente.

Para criar o direito, execute o seguinte comando:

~/gcp-marketplace-integrated-saas/python3$ python3 -m impl.step_3_entitlement_create.app

O código para aprovar o direito está na implementação de amostra.

Em seguida, você lida com situações em que um cliente pede uma mudança no plano de assinatura.

7. Aprovar mudanças em um direito de acesso

Se o serviço tiver vários planos, você precisará processar solicitações de clientes que queiram fazer upgrade ou downgrade do plano atual.

Se o serviço tiver apenas um plano, pule para "Processar compras canceladas".

Não há diferença técnica entre um direito se tornar ativo pela primeira vez e se tornar ativo após uma mudança de plano. Por isso, a implementação de amostra tem um método handleActiveEntitlement() compartilhado para os dois casos. Esse método verifica se há eventos relacionados a direitos nas mensagens recebidas:

step_4_entitlement_change/app.py

def handleActiveEntitlement(self, entitlement, customer, accountId):
  """Updates the database to match the active entitlement."""

  product = {
      'product_id': entitlement['product'],
      'plan_id': entitlement['plan'],
  }

  if 'consumerId' in entitlement:
    product['consumer_id'] = entitlement['consumerId']

  customer['products'][entitlement['product']] = product

  self.db.write(accountId, customer)

O snippet a seguir verifica se o eventType é ENTITLEMENT_PLAN_CHANGE_REQUESTED ou ENTITLEMENT_PLAN_CHANGED:

step_4_entitlement_change/app.py

elif eventType == 'ENTITLEMENT_PLAN_CHANGE_REQUESTED':
  if state == 'ENTITLEMENT_PENDING_PLAN_CHANGE_APPROVAL':
    # Don't write anything to our database until the entitlement becomes
    # active within the Procurement Service.
    self.approveEntitlementPlanChange(id, entitlement['newPendingPlan'])
    return True

elif eventType == 'ENTITLEMENT_PLAN_CHANGED':
  if state == 'ENTITLEMENT_ACTIVE':
    # Handle an active entitlement after a plan change.
    self.handleActiveEntitlement(entitlement, customer, accountId)
    return True

Na implementação final, quando o direito voltar ao estado ENTITLEMENT_ACTIVE, o método listener vai atualizar o banco de dados para refletir a mudança e fazer o provisionamento necessário.

Dependendo de como você configurou o produto com o engenheiro de parceiros, talvez não seja possível fazer downgrades ou cancelamentos até o fim de um ciclo de faturamento. Nesses casos, a mudança de plano vai continuar pendente mesmo após a aprovação, mas o direito não vai voltar ao estado ENTITLEMENT_ACTIVE até que a mudança de plano seja concluída.

Para conferir o código que verifica e aprova mudanças de direitos, consulte a implementação de exemplo.

Em seguida, você lida com situações em que os clientes cancelam as compras.

8. Processar compras canceladas

Os clientes podem cancelar as compras. Dependendo de como você configurou o produto com o Parceiro de engenharia, o cancelamento pode entrar em vigor imediatamente ou no final do ciclo de faturamento.

Quando um cliente cancela a compra, uma mensagem com o eventType ENTITLEMENT_PENDING_CANCELLATION é enviada. Se você configurou o produto para processar cancelamentos imediatamente, uma mensagem com o eventType ENTITLEMENT_CANCELLED será enviada logo depois.

step_5_entitlement_cancel/app.py

elif eventType == 'ENTITLEMENT_CANCELLED':
  # Clear out our records of the customer's plan.
  if entitlement['product'] in customer['products']:
    del customer['products'][entitlement['product']]

  ### TODO: Turn off customer's service. ###
  self.db.write(accountId, customer)
  return True

elif eventType == 'ENTITLEMENT_PENDING_CANCELLATION':
  # Do nothing. We want to cancel once it's truly canceled. For now it's
  # just set to not renew at the end of the billing cycle.
  return True

elif eventType == 'ENTITLEMENT_CANCELLATION_REVERTED':
  # Do nothing. The service was already active, but now it's set to renew
  # automatically at the end of the billing cycle.
  return True

Seu serviço precisa aguardar a mensagem ENTITLEMENT_CANCELLED para remover o direito do seu banco de dados e desativar o serviço para o cliente.

Depois que o direito é cancelado, ele é excluído dos sistemas do Google, e uma mensagem com o eventType ENTITLEMENT_DELETED é enviada:

step_5_entitlement_cancel/app.py

elif eventType == 'ENTITLEMENT_DELETED':
  # Do nothing. Entitlements can only be deleted when they are already
  # cancelled, so our state is already up-to-date.
  return True

Para o código que cancela o direito, consulte a implementação de exemplo.

9. Envio de relatórios de uso

Alguns serviços têm componentes baseados no uso, em que o Google precisa saber sobre o uso do serviço pelos clientes para cobrar o valor correto. Seu serviço precisa informar o uso pela API Google Service Control.

Se o serviço não tiver componentes baseados no uso, pule esta seção.

Para informações detalhadas sobre o envio de relatórios de uso, consulte a documentação de integração.

Os relatórios de uso precisam ser enviados à API Service Control do Google a cada hora. Neste codelab, os relatórios são enviados usando um script que pode ser programado como um cron job. O script armazena o horário do último relatório de uso no banco de dados e o usa como horário de início para medir o uso.

O script verifica cada cliente ativo do serviço e envia um relatório de uso ao Controle de Serviço do Google usando o campo consumer_id do direito do cliente. Em seguida, o script atualiza a entrada do banco de dados do cliente para que um last_report_time seja definido como o horário de término do relatório de uso recém-enviado.

O Google Service Control expõe dois métodos: check e report. O primeiro sempre precisa ser chamado imediatamente antes de uma chamada para o segundo. Se o primeiro tiver erros, o serviço do cliente deverá ser desativado até que seja corrigido.

Todo o uso de um determinado direito é atribuído a um único usageReportingId. No entanto, para produtos SaaS, esse uso está associado ao item de linha [Charges not specific to a project] no Google Cloud Billing. Se o produto SaaS puder ser compartilhado em toda a organização de um cliente e você quiser oferecer suporte à atribuição de custos, recomendamos que todos os seus serviços incluam o campo opcional userLabels na operação do relatório de uso.

O Google Cloud Marketplace reserva as chaves de rótulo cloudmarketplace.googleapis.com/resource_name e cloudmarketplace.googleapis.com/container_name. Esses rótulos têm como objetivo capturar o contexto do uso na sua hierarquia de serviços e recursos nativos. Os nomes atribuídos pelo cliente a esses recursos seriam incluídos como valores de rótulo nos relatórios de uso. Recomendamos que você inclua esses rótulos nos relatórios de uso por padrão.

Chave do rótulo

Valor do rótulo

Descrição

cloudmarketplace.googleapis.com/resource_name

RESOURCE_NAME

O nome do recurso associado a uma métrica de uso.

cloudmarketplace.googleapis.com/container_name

CONTAINER_NAME

O nome de um contêiner de recursos.

O snippet a seguir informa o uso do app de demonstração e atribui o uso do produto SaaS ao recurso atribuído pelo cliente chamado products_db. Neste codelab, o service_name é isaas-codelab.mp-marketplace-partner-demos.appspot.com.

operation = {
  'operationId': '<UUID>',
  'operationName': 'Codelab Usage Report',
  'consumerId': 'project_number:<Project Number>',
  'startTime': '<Timestamp>',
  'endTime': '<Timestamp>',
  'metricValues': [{
      'int64Value': 100,
  }],
  'userLabels': {
    'cloudmarketplace.googleapis.com/container_name': 'saas-storage-solutions',
    'cloudmarketplace.googleapis.com/resource_name': 'products_db'
  }
}

service.services().report(
    serviceName=service_name, body={
        'operations': [operation]
    }).execute()
product['last_report_time'] = end_time
database.write(customer_id, customer)

Confira o código completo na implementação de exemplo desse script. Para criar um relatório de uso de exemplo, execute o seguinte comando:

~/gcp-marketplace-integrated-saas/python3$ python3 -m impl.step_6_usage_reporting.report isaas-codelab.mp-marketplace-partner-demos.appspot.com

10. Parabéns!

Você aprendeu como sua solução SaaS pode se integrar ao Google Cloud Marketplace para processar contas e direitos de clientes e informar o uso de um serviço. Para conferir as etapas completas de integração, consulte a documentação de integração de back-end.

Limpar

Se você não planeja mais usá-los, exclua os seguintes recursos:

  • A assinatura do Cloud Pub/Sub
  • A conta de serviço e as chaves dela
  • Opcional: o projeto que você criou
  • Opcional: a conta de faturamento que você criou

A seguir

Integrar o front-end

As amostras neste codelab aprovam automaticamente contas e direitos. Na prática, os clientes precisam ser direcionados a uma página de inscrição criada por você, em que podem criar contas no seu sistema. Depois que eles se inscreverem, você precisará fazer as solicitações de API para aprovar as contas e os direitos deles.

Para informações sobre como integrar o front-end do app, consulte a documentação do Google Cloud Marketplace.

Saiba mais sobre como oferecer soluções de SaaS

Para uma visão geral de como oferecer soluções SaaS no Google Cloud Marketplace, consulte Oferecer soluções SaaS.