Iniciando os trabalhos dos Endpoints jeito que o Cron faria, alguem vai revisar isso!
Para escrever estes endpoints eu precisei pensar no workflow de como eu quero comprar café online!
- Acesso o site, kafeka.com.br
- Vejo as imagens dos cafes, o nome e o preço deles.
-
- podemos pensar em adicionar: comentarios dos compradores, reviews, cadastro de lojas, disponibilidade de entrega, previsao de entrega, muitos problemas. Precisamos alinhar até onde vai ser feito.
- Abro a pagina de algum cafe
- Clico em comprar
- recebo um aviso que o codigo Equinocio2012 tem desconto de 100%! =)
- uma tela me pergunta se eu ja sou cadastrado, email/senha. ou E-mail/senha + nome + endereço para criar e pagar.
- recebo um e-mail com o meu café!
Acho que estes passos são suficiente para podemos dar exemplos de pelo menos um dos Backing Services [queue para email].
Para construir este site, e demonstrar mais coisas do 12factor, também precisaremos de um painel de controle admin.
Isso aqui é um apanhado geral das várias leituras e discussões recententes. Como o prazo do equinócio está ficando curto, estou colocando aqui logo para começarmos a discutir e refinarmos juntos. -- nuba.
Para que a gente exercite REST dentro do que Roy Fielding definiu como o estilo de arquitetura http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm , e no nível mais alto de maturidade proposto por Richardson em http://www.crummy.com/writing/speaking/2008-QCon/ (e discutido extensivamente no REST in Practice http://restinpractice.com/book/), sugiro:
- URLs sem verbos, versões, enxutos, e passando longe do REST como tunelamento de RPC
- CRUD para recursos estáticos
- Uso parcimonioso dos recursos do servidor, e da rede, com uso de etag ou last-modified + requests condicionais para updates e gets
- Fazermos o mapa, dentro do possível, da semantica dos verbos e dos status HTTP para a nossa aplicação
- Evitar ao máximo a manutenção de estado no servidor
- API com um ou poucos pontos de entrada
- Oferecer hiperlinks junto às representações para que a API seja navegável (aqui entra o HATEOAS, ou Hypertext as the Engine of Application State).
- HAL+JSON ou HAL+XML como formato que nos permita entregar a representação dos recursos, recursos embutidos, e seus links.
- Uso do nosso próprio internet media type para apoiar a escolha do formato de representação e versão da api
- por exemplo: application/vnd.kafeka.v1+json
Uma proposta do ciclo de vida de uma compra é a seguinte:
Onde os links em vermelho são transições "nos bastidores", e os outros links são transições oferecidas ao usuáro em momentos pertinentes e junto das representações dos recursos pedidos.
Segue uma proposta pra o contrato da nossa API REST:
recurso | url | verbo | semântica | links ou recursos embutidos na resposta | notas | re: cache | requer autenticacao, autorizacao? |
Produtos | /produto | get | a lista de produtos | amarrar autenticacao em openid ou oauth, autorizar apenas os pedidos do usuario |
|||
Um produto | /produto/{UUID_produto} | get | um produto | * opcionais * tamanhos |
e-tag relativo ao conjunto: produto, opcionais e tamanhos. ou last-modified | não | |
Tamanhos de um produto | /produto/{UUID_produto}/tamanhos | get | os tamanhos em que um produto está disponível | * produto | e-tag relativo ao conjunto: produto, opcionais e tamanhos. ou last-modified | não | |
Opcionais de um produto | /produto/{UUID_produto}/opcionais | get | Os opcionais disponíveis para um produto | * produto | e-tag relativo ao conjunto: produto, opcionais e tamanhos. ou last-modified | não | |
Opcionais de um produto | /produto/{UUID_produto}/opcionais/{UUID_opcional} | get | Um opcional disponível para um produto | * produto | e-tag relativo ao conjunto: produto, opcionais e tamanhos. ou last-modified | não | |
Pedidos | /pedido | get | retorna os pedidos | sim | |||
Pedidos | /pedido | post | cria um novo pedido, UUID gerado e informado pelo servidor, put é recomendado apenas se o cliente sempre puder gerar o UUID, não é o caso | retorna no header Location: o endereço do pedido criado | sim | ||
Um pedido | /pedido/{UUID_pedido} | get | retorna um pedido | * Itens de um pedido * a cobrança * o recibo ou pagamento |
usar e-tag ou last-modified | sim | |
Um pedido | /pedido/{UUID_pedido} | put | modifica um pedido | * Itens de um pedido * a cobrança * o recibo ou pagamento |
a representação completa do pedido é enviada e recebida | usar e-tag ou last-modified | sim |
Um pedido | /pedido/{UUID_pedido} | delete | apaga um pedido | sim | |||
Itens em um pedido | /pedido/{UUID_pedido}/item | get | retorna os itens em um pedido | lista de itens em um pedido | usar e-tag ou last-modified | sim | |
Itens em um pedido | /pedido/{UUID_pedido}/item | post | cria um novo item em um pedido | retorna no header Location: o endereço do item criado | sim | ||
Itens em um pedido | /pedido/{UUID_pedido}/item | delete | remove todos os itens em um pedido | sim | |||
Um item em um pedido | /pedido/{UUID_pedido}/item/{UUID_item} | get | retorna um item em um pedido | * o pedido * o produto * o tamanho * os opcionais |
a representação completa do pedido é enviada e recebida | sim | |
Um item em um pedido | /pedido/{UUID_pedido}/item/{UUID_item} | put | modifica um item em um pedido | * o pedido * o produto * o tamanho * os opcionais |
a representação completa do pedido é enviada e recebida | sim | |
Um item em um pedido | /pedido/{UUID_pedido}/item/{UUID_item} | delete | remove um item de um pedido | sim | |||
As cobranças | /cobranca | get | retorna a lista de cobranças | * pagamento ou recibo * pedido |
sim, presumindo: imutáveis, sempre válidas. | sim | |
Uma cobranca | /cobranca/{UUID_cobranca} | get | retorna uma cobrança | sim, presumindo: imutáveis, sempre válidas. | sim | ||
Pagamentos | /pagamento | get | retorna os pagamentos do usuário | sim | |||
Pagamentos | /pagamento | post | cria um pagamento | * a cobrança | decidir: se o pagamento não for aceito: * vamos retorna um status de erro agora; ou * vamos criar o recurso mesmo assim, mas sinalizar isso para o usuário através de alguma propriedade? |
sim | |
Um pagamento | /pagamento/{UUID_pagamento} | get | retorna um pagamento | * a cobrança * o recibo, se houver |
e-tag ou last-modified | sim | |
Um pagamento | /pagamento/{UUID_pagamento} | put | modifica um pagamento | * a cobrança * o recibo, se houver |
só faz sentido o usuário modificar um pagamento que não tenha sido aprovado, estamos então falando de tentativas de pagamento | sim | |
Um pagamento | /pagamento/{UUID_pagamento} | delete | apaga um pagamento | * a cobrança * o recibo, se houver |
só faz sentido o usuário modificar um pagamento que não tenha sido aprovado, estamos então falando de tentativas de pagamento | sim | |
Recibos | /recibo | get | retorna os recibos | e-tag ou last-modified | sim | ||
Um recibo | /recibo/{UUID_recibo} | get | retorna um recibo | * a cobrança * o pagamento * o pedido |
e-tag ou last-modified | sim |
:METHOD | URI | Params | Description | Return |
---|---|---|---|---|
GET | /v1/api/produtos | - | lista dos produtos | { produtos : [ { nome: cafe123, id: 3, preco: 5.55 } ], message: ok } |
GET | /v1/api/produtos/ | - | retorna um produto | { produto : { nome: cafe123, id: 3, preco: 5.55 }, comentarios: [ { user_id: 123, mensagem: gostei do sabor bla bla } ], message: ok } |
POST | /v1/api/efetuar_pagamento | { codigo_promocional: '123', compra_id: 123 } | efetua a compra, add queue e-mail | { message: ok } |
POST | /v1/api/clientes | { email: 'rento.cron@xpto.com', nome: 'a name', senha: fuba } | ... | { message: ok } |
POST | /v1/api/clientes/login | { email: 'rento.cron@xpto.com', senha: fuba } | ... | { message: ok } |
POST | /v1/api/produtos | { nome: 'kafe gostoso', preco: 3.20, loja: 1 }, | cadastra o produto, role=admin | { message: ok } |
:METHOD | URI | CONTENT | Description |
---|---|---|---|
GET | / | - | homepage, consulta os produtos, cria session |
GET | /logout | - | destroi a sessao, rediciona para home |
POST | /login | email, senha | faz o login e atualiza session |
GET | /carrinho | mostra os itens no carrinho com a opcao de digitar o codigo promocional e confirmar o pagamento | |
POST | /carrinho/produto | { produto_id : 1 } | adiciona o produto no carrinho |
DELETE | /carrinho/produto/ | - | remove o produto no carrinho |
PUT | /carrinho/produto/ | { qtde: nova_qtde} | atualiza a quantidade do produto no carrinho |
GET | /carrinho/produto/ | - | na verdade, nao precisa! pois o GET /carrinho retornara todos os produtos para evitar querys... |
GET | /cliente/recuperar_senha | - | pergunta e-mail |
POST | /cliente/recuperar_senha | {email:x} | envia email com chave para resetar |
GET | /cliente/resetar_senha | ?email=xpto&chave= | confere a chave, exibe formulario |
POST | /cliente/resetar_senha | {email=xpto, chave=, senha1, senha2} | ... |
Template do site eu pensei nesse daqui: http://www.freewebsitetemplates.com/preview/clothesfashion/ é simples, da pra por uns cafes no lugar da mulher, e na interface do admin usar o twitter.github.com/bootstrap/ mesmo