↓↓クリックして頂けると励みになります。
【21 | 電話番号更新】 << 【ホーム】 >> 【23 | クレジットカード登録】
まずは以下の手順でStripeのアカウントを取得してください。
mrradiology.hatenablog.jp
ダッシュボードで「公開可能キー」と「シークレットキー」をコピーします。
「crowdsource/settings.py」ファイルに記述を追加します。
記述追加 【Desktop/crowdsource/crowdsource/settings.py】164行目(末尾)
STRIPE_API_PUBLIC_KEY = "ご自分の公開可能キーを入れてください。" STRIPE_API_SECRET_KEY = "ご自分のシークレットキーを入れてください。"
モデルを作成します。
「core/models.py」ファイルを以下のように編集します。
記述編集 【Desktop/crowdsource/core/models.py】
from django.db import models from django.contrib.auth.models import User # Create your models here. class Customer(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) avatar = models.ImageField(upload_to='customer/avatars/', blank=True, null=True) phone_number = models.CharField(max_length=50, blank=True) stripe_customer_id = models.CharField(max_length=255, blank=True) stripe_payment_method_id = models.CharField(max_length=255, blank=True) stripe_card_last4 = models.CharField(max_length=255, blank=True) def __str__(self): return self.user.get_full_name()
マイグレーションファイルを作成します。
コマンド
python manage.py makemigrations
マイグレーションを適用します。
コマンド
python manage.py migrate
「crowdsource/urls.py」ファイルに記述を追加します。
記述追加 【Desktop/crowdsource/crowdsource/urls.py】15行目
from django.contrib import admin from django.urls import path, include from django.contrib.auth import views as auth_views from django.conf import settings from django.conf.urls.static import static from core import views from core.customer import views as customer_views from core.courier import views as courier_views customer_urlpatters = [ path('', customer_views.home, name="home"), path('profile/', customer_views.profile_page, name="profile"), path('payment_method/', customer_views.payment_method_page, name="payment_method"), ] courier_urlpatters = [ path('', courier_views.home, name="home"), ] urlpatterns = [ path('admin/', admin.site.urls), path('oauth/', include('social_django.urls', namespace='social')), path('', views.home), path('sign-in/', auth_views.LoginView.as_view(template_name="sign_in.html")), path('sign-out/', auth_views.LogoutView.as_view(next_page="/")), path('sign-up/', views.sign_up), path('customer/', include((customer_urlpatters, 'customer'))), path('courier/', include((courier_urlpatters, 'courier'))), ] if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
「core/customer/views.py」ファイルを編集します。
記述追加 【Desktop/crowdsource/core/customer/views.py】65行目
import firebase_admin from firebase_admin import credentials, auth from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from django.urls import reverse from core.customer import forms from django.contrib import messages from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth import update_session_auth_hash from django.conf import settings cred = credentials.Certificate(settings.FIREBASE_ADMIN_CREDENTIAL) firebase_admin.initialize_app(cred) @login_required() def home(request): return redirect(reverse('customer:profile')) @login_required(login_url="/sign-in/?next=/customer/") def profile_page(request): user_form = forms.BasicUserForm(instance=request.user) customer_form = forms.BasicCustomerForm(instance=request.user.customer) password_form = PasswordChangeForm(request.user) if request.method == "POST": if request.POST.get('action') == 'update_profile': user_form = forms.BasicUserForm(request.POST, instance=request.user) customer_form = forms.BasicCustomerForm(request.POST, request.FILES, instance=request.user.customer) if user_form.is_valid() and customer_form.is_valid(): user_form.save() customer_form.save() messages.success(request, 'プロフィールが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_password': password_form = PasswordChangeForm(request.user, request.POST) if password_form.is_valid(): user = password_form.save() update_session_auth_hash(request, user) messages.success(request, 'パスワードが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_phone': # Get Firebase user data firebase_user = auth.verify_id_token(request.POST.get('id_token')) request.user.customer.phone_number = firebase_user['phone_number'] request.user.customer.save() messages.success(request, '電話番号が更新されました。') return redirect(reverse('customer:profile')) return render(request, 'customer/profile.html', { "user_form": user_form, "customer_form": customer_form, "password_form": password_form, }) @login_required(login_url="/sign-in/?next=/customer/") def payment_method_page(request): return render(request, 'customer/payment_method.html')
「core/templates/customer」フォルダに「payment_method.html」ファイルを新規作成します。
新規作成 【Desktop/crowdsource/core/templates/customer/payment_method.html】
{% extends 'customer/base.html' %} {% load bootstrap4 %} {% block main %} <b class="text-secondary">クレジットカード登録</b> <div class="card bg-white mt-2 mb-5"> <div class="card-body"> </div> </div> {% endblock %}
ブラウザを確認します。
http://127.0.0.1:8000/customer/payment_method/
Stripeをインストールします。
コマンド
pip install stripe==2.55.1
バージョン確認します。
コマンド
pip freeze > requirements.txt
内容確認 【Desktop/crowdsource/requirements.txt】
asgiref==3.7.2 beautifulsoup4==4.12.2 CacheControl==0.13.1 cachetools==5.3.1 certifi==2023.7.22 cffi==1.15.1 charset-normalizer==3.2.0 cryptography==41.0.3 defusedxml==0.7.1 Django==3.2.20 django-bootstrap4==2.3.1 firebase-admin==4.4.0 google-api-core==1.34.0 google-api-python-client==2.97.0 google-auth==2.22.0 google-auth-httplib2==0.1.0 google-cloud-core==2.3.3 google-cloud-firestore==2.11.1 google-cloud-storage==2.10.0 google-crc32c==1.5.0 google-resumable-media==2.5.0 googleapis-common-protos==1.60.0 grpcio==1.57.0 grpcio-status==1.48.2 httplib2==0.22.0 idna==3.4 msgpack==1.0.5 oauthlib==3.2.2 Pillow==10.0.0 proto-plus==1.22.3 protobuf==3.20.3 pyasn1==0.5.0 pyasn1-modules==0.3.0 pycparser==2.21 PyJWT==2.8.0 pyparsing==3.1.1 python3-openid==3.2.0 pytz==2023.3 requests==2.31.0 requests-oauthlib==1.3.1 rsa==4.9 six==1.16.0 social-auth-app-django==4.0.0 social-auth-core==4.4.2 soupsieve==2.5 sqlparse==0.4.4 stripe==2.55.1 typing_extensions==4.7.1 uritemplate==4.1.1 urllib3==1.26.16
「core/customer/views.py」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/customer/views.py】
import firebase_admin from firebase_admin import credentials, auth import stripe from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required from django.urls import reverse from core.customer import forms from django.contrib import messages from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth import update_session_auth_hash from django.conf import settings cred = credentials.Certificate(settings.FIREBASE_ADMIN_CREDENTIAL) firebase_admin.initialize_app(cred) stripe.api_key = settings.STRIPE_API_SECRET_KEY @login_required() def home(request): return redirect(reverse('customer:profile')) @login_required(login_url="/sign-in/?next=/customer/") def profile_page(request): user_form = forms.BasicUserForm(instance=request.user) customer_form = forms.BasicCustomerForm(instance=request.user.customer) password_form = PasswordChangeForm(request.user) if request.method == "POST": if request.POST.get('action') == 'update_profile': user_form = forms.BasicUserForm(request.POST, instance=request.user) customer_form = forms.BasicCustomerForm(request.POST, request.FILES, instance=request.user.customer) if user_form.is_valid() and customer_form.is_valid(): user_form.save() customer_form.save() messages.success(request, 'プロフィールが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_password': password_form = PasswordChangeForm(request.user, request.POST) if password_form.is_valid(): user = password_form.save() update_session_auth_hash(request, user) messages.success(request, 'パスワードが更新されました。') return redirect(reverse('customer:profile')) elif request.POST.get('action') == 'update_phone': # Get Firebase user data firebase_user = auth.verify_id_token(request.POST.get('id_token')) request.user.customer.phone_number = firebase_user['phone_number'] request.user.customer.save() messages.success(request, '電話番号が更新されました。') return redirect(reverse('customer:profile')) return render(request, 'customer/profile.html', { "user_form": user_form, "customer_form": customer_form, "password_form": password_form, }) @login_required(login_url="/sign-in/?next=/customer/") def payment_method_page(request): current_customer = request.user.customer # Save stripe customer infor if not current_customer.stripe_customer_id: customer = stripe.Customer.create() current_customer.stripe_customer_id = customer['id'] current_customer.save() intent = stripe.SetupIntent.create( customer = current_customer.stripe_customer_id ) return render(request, 'customer/payment_method.html', { "client_secret": intent.client_secret, "STRIPE_API_PUBLIC_KEY": settings.STRIPE_API_PUBLIC_KEY, })
「core/templates/customer/payment_method.html」ファイルを編集します。
記述編集 【Desktop/crowdsource/core/templates/customer/payment_method.html】
{% extends 'customer/base.html' %} {% load bootstrap4 %} {% block head %} <script src="https://js.stripe.com/v3/"></script> <style> .StripeElement { height: 40px; padding: 10px 12px; width: 100%; color: #32325d; background-color: white; /* border: 1px solid transparent; */ border: 1px solid #ced4da; border-radius: 4px; /* box-shadow: 0 1px 3px 0 #e6ebf1; -webkit-transition: box-shadow 150ms ease; transition: box-shadow 150ms ease; */ } .StripeElement--focus { border-color: #80bdff; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, .25); } .StripeElement--invalid { border-color: #fa755a; } .StripeElement--webkit-autofill { background-color: #fefde5 !important; } </style> {% endblock %} {% block main %} <b class="text-secondary">クレジットカード登録</b> <div class="card bg-white mt-2 mb-5"> <div class="card-body"> {% if request.user.customer.stripe_payment_method_id %} <div id="change-card" class="input-group"> <input type="text" class="form-control" disabled value="**** **** **** {{ request.user.customer.stripe_card_last4 }}"> <div class="input-group-append"> <form method="POST"> {% csrf_token %} <button type="submit" class="btn btn-danger">Remove</button> </form> </div> </div> {% else %} <form id="setup-form" data-secret="{{ client_secret }}"> <div id="card-element"></div> <button id="card-button" class="btn btn-danger mt-3" type="button"> カード登録 </button> </form> {% endif %} </div> </div> <script> var stripe = Stripe("{{ STRIPE_API_PUBLIC_KEY }}"); var elements = stripe.elements(); var cardElement = elements.create('card'); cardElement.mount('#card-element'); </script> {% endblock %}
ブラウザを確認します。
クレジットカード登録フォームが完成しました。
まだ登録はできませんが、テストカードは「4242 4242 4242 4242」を使用してください。
http://127.0.0.1:8000/customer/payment_method/
↓↓クリックして頂けると励みになります。
【21 | 電話番号更新】 << 【ホーム】 >> 【23 | クレジットカード登録】