Aula 94 – Django – Ecommerce – Confirmação e Processamento de Pagamento

Aula 94 – Django – Ecommerce – Confirmação e Processamento de Pagamento

Loja Online - Django

Loja Online – Django

Voltar para página principal do blog

Todas as aulas desse curso

Aula 93                                   Aula 95

 

Redes Sociais do Código Fluente:

facebook

 

 


Scarlett Finch

Scarlett Finch é uma influenciadora virtual criada com IA.

Ela é 🎤 cantora e 🎶compositora pop britânica.

Siga a Scarlett Finch no Instagram:

facebook

 


Conecte-se comigo!

LinkedIn: Fique à vontade para me adicionar no LinkedIn.

Ao conectar-se comigo, você terá acesso a atualizações regulares sobre desenvolvimento web, insights profissionais e oportunidades de networking no setor de tecnologia.

GitHub: Siga-me no GitHub para ficar por dentro dos meus projetos mais recentes, colaborar em código aberto ou simplesmente explorar os repositórios que eu contribuo, o que pode ajudar você a aprender mais sobre programação e desenvolvimento de software.

Recursos e Afiliados

Explorando os recursos abaixo, você ajuda a apoiar nosso site.

Somos parceiros afiliados das seguintes plataformas:

  • https://heygen.com/ – Eleve a produção de seus vídeos com HeyGen! Com esta plataforma inovadora, você pode criar vídeos envolventes utilizando avatares personalizados, ideal para quem busca impactar e conectar com audiências em todo o mundo. HeyGen transforma a maneira como você cria conteúdo, oferecendo ferramentas fáceis de usar para produzir vídeos educativos, demonstrações de produtos e muito mais. Descubra o poder de comunicar através de avatares interativos e traga uma nova dimensão para seus projetos. Experimente HeyGen agora e revolucione sua forma de criar vídeos!
  • letsrecast.ai – Redefina a maneira como você consome artigos com Recast. Esta plataforma transforma artigos longos em diálogos de áudio que são informativos, divertidos e fáceis de entender. Ideal para quem está sempre em movimento ou busca uma forma mais conveniente de se manter informado. Experimente Recast agora.
  • dupdub.com – Explore o universo do marketing digital com DupDub. Esta plataforma oferece ferramentas inovadoras e soluções personalizadas para elevar a sua estratégia de marketing online. Ideal para empresas que buscam aumentar sua visibilidade e eficiência em campanhas digitais. Descubra mais sobre DupDub.
  • DeepBrain AI Studios – Revolucione a criação de conteúdo com a tecnologia de inteligência artificial da DeepBrain AI Studios. Esta plataforma avançada permite que você crie vídeos interativos e apresentações utilizando avatares digitais gerados por IA, que podem simular conversas reais e interações humanas. Perfeito para educadores, criadores de conteúdo e empresas que querem inovar em suas comunicações digitais. Explore DeepBrain AI Studios.
  • Audyo.ai – Transforme a maneira como você interage com conteúdo auditivo com Audyo.ai. Esta plataforma inovadora utiliza inteligência artificial para criar experiências de áudio personalizadas, melhorando a acessibilidade e a compreensão de informações através de podcasts, transcrições automáticas e síntese de voz avançada. Ideal para profissionais de mídia, educadores e qualquer pessoa que deseje acessar informações auditivas de maneira mais eficiente e envolvente. Descubra Audyo.ai e suas possibilidades.
  • Acoust.io – Transforme sua produção de áudio com Acoust.io. Esta plataforma inovadora fornece uma suite completa de ferramentas para criação, edição e distribuição de áudio, ideal para artistas, produtores e empresas de mídia em busca de excelência e inovação sonora. Acoust.io simplifica o processo de levar suas ideias à realidade, oferecendo soluções de alta qualidade que elevam seus projetos de áudio. Experimente Acoust.io agora e descubra um novo patamar de possibilidades para seu conteúdo sonoro.
  • Hostinger – Hospedagem web acessível e confiável. Ideal para quem busca soluções de hospedagem de sites com excelente custo-benefício e suporte ao cliente robusto. Saiba mais sobre a Hostinger.
  • Digital Ocean – Infraestrutura de nuvem para desenvolvedores. Oferece uma plataforma de nuvem confiável e escalável projetada especificamente para desenvolvedores que precisam de servidores virtuais, armazenamento e networking. Explore a Digital Ocean.
  • One.com – Soluções simples e poderosas para o seu site. Uma escolha ideal para quem busca registrar domínios, hospedar sites ou criar presença online com facilidade e eficiência. Visite One.com.

Educação e Networking

Amplie suas habilidades e sua rede participando de cursos gratuitos e comunidades de desenvolvedores:

Canais do Youtube

Explore nossos canais no YouTube para uma variedade de conteúdos educativos e de entretenimento, cada um com um foco único para enriquecer sua experiência de aprendizado e lazer.

Toti

Toti: Meu canal pessoal, onde posto clips artesanais de músicas que curto tocar, dicas de teoria musical, entre outras coisas.

Scarlett Finch

Scarlett Finch: Cantora e influenciadora criada com IA.

Lofi Music Zone Beats

Lofi Music Zone Beats: O melhor da música Lofi para estudo, trabalho e relaxamento, criando o ambiente perfeito para sua concentração.

Backing Track / Play-Along

Backing Track / Play-Along: Acompanhe faixas instrumentais para prática musical, ideal para músicos que desejam aprimorar suas habilidades.

Código Fluente

Código Fluente: Aulas gratuitas de programação, devops, IA, entre outras coisas.

Putz!

Putz!: Canal da banda Putz!, uma banda virtual, criada durante a pandemia com mais 3 amigos, Fábio, Tatá e Lula.

PIX para doações

PIX Nubank

PIX Nubank


Aula 94 – Django – Ecommerce – Confirmação e Processamento de Pagamento

Código da aula: Github

Nesta aula, vamos implementar a lógica de confirmação e processamento de pagamento no nosso projeto de e-commerce usando o Stripe.

Certifique-se que está logado no Stripe

Faça login com sua conta Stripe
stripe login

Encaminhe eventos ao seu webhook
stripe listen --forward-to localhost:4242/api/webhook

Acione eventos com a CLI
stripe trigger payment_intent.succeeded

Vamos adicionar as views de sucesso e falha de pagamento, ajustar as URLs e atualizar o JavaScript para tratar essas situações.

Boas práticas no Github

Crie a branch da aula, vou chamar a minha de: feature/payment-confirmation-and-processing

Usar feature/... para branches no GitHub, ajuda a organizar e identificar rapidamente branches dedicadas ao desenvolvimento de novas funcionalidades.

Prefixos como feature/, bugfix/, hotfix/, e release/ são amplamente aceitos como boas práticas na comunidade de desenvolvimento e ajudam a manter um fluxo de trabalho consistente e organizado.

Atualizações no código

Views de Sucesso e Falha de Pagamento

Primeiramente, vamos criar duas novas views no arquivo views.py do billing, para renderizar as páginas de sucesso e falha de pagamento.

django_ecommerce/e_commerce/billing/views.py


from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
import stripe
import json

# Configure a chave da API do Stripe
stripe.api_key = settings.STRIPE_API_KEY

# View para renderizar a página de sucesso do pagamento
def payment_success_view(request):
    return render(request, 'billing/payment-success.html')

# View para renderizar a página de falha do pagamento
def payment_failed_view(request):
    return render(request, 'billing/payment-failed.html')

# View para renderizar a página de método de pagamento
def payment_method_view(request):
    # Adicione um log para verificar se a chave está sendo passada (opcional)
    # print(f"Publish Key na view: {settings.STRIPE_PUB_KEY}")
    context = {'publish_key': settings.STRIPE_PUB_KEY}
    return render(request, 'billing/payment-method.html', context)

# View para criar o PaymentIntent do Stripe
@csrf_exempt
@require_POST
def create_payment_intent(request):
    data = json.loads(request.body)
    try:
        # Calcular o valor com base nos itens enviados
        # Substitua esta função pela sua lógica de cálculo de preços
        amount = calculate_order_amount(data['items'])

        intent = stripe.PaymentIntent.create(
            amount=amount,
            currency='usd',
            payment_method_types=['card'],
        )
        return JsonResponse({'clientSecret': intent.client_secret})
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=400)

# Função para calcular o valor do pedido
def calculate_order_amount(items):
    # Substitua esta função pela sua lógica de cálculo de preços
    return 1400  # preço de exemplo

Atualização das URLs

Agora vamos adicionar as novas URLs no nosso arquivo urls.py.

e_commerce/e_commerce/urls.py


from django.conf import settings
from django.conf.urls.static import static

from django.contrib import admin
from django.contrib.auth.views import LogoutView 
from django.urls import path, include
from django.views.generic import TemplateView
from carts.views import cart_detail_api_view
from accounts.views import LoginView, RegisterView, LogoutView, guest_register_view
from addresses.views import checkout_address_create_view, checkout_address_reuse_view
from billing.views import create_payment_intent, payment_method_view, payment_success_view, payment_failed_view
from .views import (home_page,  
                    about_page, 
                    contact_page
)

urlpatterns = [
    path('', home_page, name='home'),
    path('about/', about_page, name='about'),
    path('contact/', contact_page, name='contact'),
    path('cart/', include("carts.urls", namespace="cart")),
    path('checkout/address/create/', checkout_address_create_view, name='checkout_address_create'),
    path('checkout/address/reuse/', checkout_address_reuse_view, name='checkout_address_reuse'),
    path('api/cart/', cart_detail_api_view, name='api-cart'),
    path('login/', LoginView.as_view(), name='login'),
    path('create-payment-intent', create_payment_intent, name='create-payment-intent'),
    path('billing/payment-method/', payment_method_view, name='billing-payment-method'),
    path('billing/payment-success/', payment_success_view, name='payment-success'),
    path('billing/payment-failed/', payment_failed_view, name='payment-failed'),
    path('register/guest/', guest_register_view, name='guest_register'),
    path('logout/', LogoutView.as_view(), name='logout'),
    path('register/', RegisterView.as_view(), name='register'),
    path('bootstrap/', TemplateView.as_view(template_name='bootstrap/example.html')),
    path('search/', include("search.urls", namespace="search")),
    path('products/', include("products.urls", namespace="products")),
    path('admin/', admin.site.urls),
]

if settings.DEBUG:
    urlpatterns = urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns = urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Atualização do JavaScript

Vamos agora atualizar o arquivo JavaScript stripe_payment.js para redirecionar para as páginas de sucesso e falha de pagamento, dependendo do resultado do processamento do pagamento.

static_local/js/stripe_payment.js

$(document).ready(function () {
  console.log("Documento pronto");
  function initializeStripe() {
    const stripeKeyElement = $("#stripe-key");
    if (stripeKeyElement.length === 0) {
      console.error("Elemento stripe-key não encontrado");
      return;
    }
    const publishKey = stripeKeyElement.data("publishKey");
    if (!publishKey) {
      console.error("Chave pública do Stripe não encontrada");
      return;
    }
    const stripe = Stripe(publishKey);
    let elements,
      cardElement,
      clientSecret = null;
    function initialize() {
      $.ajax({
        url: "/create-payment-intent",
        method: "POST",
        contentType: "application/json",
        headers: {
          "X-CSRFToken": getCookie("csrftoken"),
        },
        data: JSON.stringify({ items: [{ id: "xl-tshirt", price: 2000 }] }),
        success: function (data) {
          if (data.error) {
            console.error("Falha ao criar o intent de pagamento:", data.error);
            return;
          }
          clientSecret = data.clientSecret;

          elements = stripe.elements();
          cardElement = elements.create("card");
          cardElement.mount("#payment-element");
          console.log("Elemento do cartão montado");
        },
        error: function (xhr, status, error) {
          console.error("Erro ao inicializar os elementos do Stripe:", error);
        },
      });
    }
    function getCookie(name) {
      let cookieValue = null;
      if (document.cookie && document.cookie !== "") {
        const cookies = document.cookie.split(";");
        for (let i = 0; i < cookies.length; i++) { 
          const cookie = cookies[i].trim();
          if (cookie.substring(0, name.length + 1) === name + "=") { 
            cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 
            break; 
          } 
        } 
      } 
      return cookieValue; 
    } 
    const paymentForm = $("#payment-form"); 
    if (paymentForm.length > 0) {
      paymentForm.on("submit", function (event) {
        event.preventDefault();
        if (!elements || !cardElement) {
          showMessage(
            "Elemento do cartão não inicializado corretamente.",
            true
          );
          return;
        }
        setLoading(true);
        stripe
          .confirmCardPayment(clientSecret, {
            payment_method: {
              card: cardElement,
              billing_details: {
                // Inclua os detalhes de faturamento se necessário
              },
            },
          })
          .then(function (result) {
            if (result.error) {
              showMessage(result.error.message, true);
              setTimeout(function () {
                window.location.href = "/billing/payment-failed/";
              }, 3000);
            } else if (
              result.paymentIntent &&
              result.paymentIntent.status === "succeeded"
            ) {
              showMessage("Pagamento realizado com sucesso!", false);
              setTimeout(function () {
                window.location.href = "/billing/payment-success/";
              }, 3000);
            } else {
              showMessage(
                "Pagamento não foi bem-sucedido. Tente novamente.",
                true
              );
              setTimeout(function () {
                window.location.href = "/billing/payment-failed/";
              }, 3000);
            }
            setLoading(false);
          })
          .catch(function (error) {
            showMessage("Ocorreu um erro inesperado.", true);
            setTimeout(function () {
              window.location.href = "/billing/payment-failed/";
            }, 3000);
            setLoading(false);
          });
      });
    } else {
      console.error("Formulário de pagamento não encontrado");
    }
    function showMessage(messageText, isError) {
      const messageContainer = $("#payment-message");
      messageContainer.text(messageText).removeClass("hidden");
      if (isError) {
        messageContainer.addClass("error-message");
      } else {
        messageContainer.removeClass("error-message");
      }
      setTimeout(function () {
        messageContainer.addClass("hidden").text("");
      }, 4000);
    }
    function setLoading(isLoading) {
      const submitButton = $("#submit");
      submitButton.prop("disabled", isLoading);
      $("#spinner").toggleClass("hidden", !isLoading);
      $("#button-text").toggleClass("hidden", isLoading);
    }
    initialize();
  }
  // Inicializa o Stripe diretamente se o elemento estiver presente
  const stripeKeyElement = $("#stripe-key");
  if (stripeKeyElement.length > 0) {
    initializeStripe();
  }
});


Mudanças

  1. Adição do parâmetro isError na função showMessage para distinguir entre mensagens de sucesso e erro.
  2. Atualização das chamadas para showMessage para incluir o novo parâmetro false,showMessage("Pagamento realizado com sucesso!", false);, indicando que esta é uma mensagem de sucesso e não um erro.
  3. Simplificação do redirecionamento pós-pagamento para URLs fixas e claras, com uma redução no tempo de espera.
  4. Implementação de redirecionamento para a página de falha de pagamento em caso de erro durante a confirmação do pagamento.

Isso melhora a clareza, usabilidade e feedback visual para o usuário, bem como simplifica a lógica do código.

Templates de Sucesso e Falha de Pagamento

Crie os arquivos de templates para as páginas de sucesso e falha de pagamento.

Template de Sucesso (billing/templates/billing/payment-success.html):

billing/templates/billing/payment-success.html


<!-- Começo do template -->
{% extends 'base.html' %}
{% block content %}
<div class="container">
    <h1>Pagamento realizado com sucesso!</h1>
    <p>Seu pedido foi processado com sucesso. Obrigado por sua compra!</p>
    <a href="{% url 'home' %}" class="btn btn-primary">Voltar para a página inicial</a>
</div>
{% endblock %}
<!-- Fim do template -->

Template de Falha (billing/templates/billing/payment-failed.html):

billing/templates/billing/payment-failed.html


<!-- Começo do template -->
{% extends 'base.html' %}
{% block content %}
<div class="container">
    <h1>Falha no pagamento</h1>
    <p>Ocorreu um problema ao processar seu pagamento. Por favor, tente novamente.</p>
    <a href="{% url 'billing-payment-method' %}" class="btn btn-primary">Tentar novamente</a>
</div>
{% endblock %}
<!-- Fim do template -->

Testando

Suba o servidor

python manage.py runserver

Acesse: 127.0.0.1:8000/billing/payment-method

Nesta aula, implementamos a lógica de confirmação e processamento de pagamento no nosso projeto de e-commerce usando Django e Stripe.

Adicionamos views para sucesso e falha de pagamento, ajustamos as URLs e atualizamos o JavaScript para tratar essas situações.

Com isso, agora seu sistema de pagamento está completo e você pode testar o fluxo de pagamento no seu ambiente de desenvolvimento.

Na próxima aula, vamos aprimorar nosso sistema de pagamento implementando a lógica para calcular o valor total do pedido com base nos itens do carrinho.

Além disso, vamos criar uma API para obter os itens do carrinho em tempo real e integrar essa funcionalidade ao frontend.

Isso permitirá que o valor do pedido seja calculado dinamicamente, oferecendo uma experiência mais precisa e eficiente para os usuários.

Nos vemos na próxima aula!
Bons estudos!

Voltar para página principal do blog

Todas as aulas desse curso

Aula 93                                   Aula 95

Nos vemos na próxima aula!

Bons estudos!

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>