Skip to content

Commit f1982c3

Browse files
committed
#43 donationシステムの実装.
1 parent 320f2f5 commit f1982c3

File tree

8 files changed

+198
-109
lines changed

8 files changed

+198
-109
lines changed

custom_auth/views.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,7 @@ def group_payment(request, group_id: int):
225225
price_id = request.POST.get("checkout", None)
226226
if not price_id:
227227
return render(request, "error.html", {"text": "price_idが不正です"})
228-
session_url = payment.checkout_membership(
229-
customer_id=user_group.group.stripe_customer_id,
228+
session_url = payment.checkout(
230229
price_id=price_id,
231230
group=user_group.group,
232231
user=request.user,

dsbd/payment.py

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
MEMBERSHIP_TAG_TYPE = f"{settings.STRIPE_MEMBERSHIP_TAG_NAME}"
1111
DONATE_TAG_TYPE = f"{settings.STRIPE_DONATE_TAG_NAME}"
12-
DONATE_MEMBERSHIP_TAG_TYPE = f"{settings.STRIPE_DONATE_MEMBERSHIP_TAG_NAME}"
1312

1413

1514
def check_expired(expired_at):
@@ -19,23 +18,40 @@ def check_expired(expired_at):
1918

2019

2120
class Payment:
22-
def __init__(self):
21+
def __init__(self, is_membership: bool = True):
2322
self.stripe = stripe
2423
self.stripe.api_key = settings.STRIPE_SECRET_KEY
24+
self.is_membership = is_membership
25+
26+
def create_donate_customer(self, user: User):
27+
name = f"[USER(DONATE)] {user.id}: {user.username}"
28+
if user.stripe_donate_customer_id:
29+
return None
30+
customer = self.stripe.Customer.create(
31+
name=name,
32+
description="dsbd-system",
33+
metadata={
34+
"user_id": user.id,
35+
"is_donate": True,
36+
"dsbd_payment_system": "v2",
37+
},
38+
)
39+
user.stripe_donate_customer_id = customer.id
40+
user.save()
41+
return customer.id
2542

2643
def create_customer(self, group_id: int, user_id: int):
2744
group = Group.objects.get(id=group_id)
2845
name = f"[GROUP] {group.id}: {group.name}"
29-
if not group.stripe_customer_id:
46+
if group.stripe_customer_id:
3047
return None
3148
customer = self.stripe.Customer.create(
3249
name=name,
33-
description="doornoc_service", # TODO: change description
50+
description="dsbd-system", # TODO: change description
3451
metadata={
35-
"id": "doornoc_service", # TODO: change description
3652
"user_id": user_id,
3753
"group_id": group.id,
38-
"version": 2,
54+
"dsbd_payment_system": "v2",
3955
},
4056
)
4157
group.stripe_customer_id = customer.id
@@ -46,36 +62,46 @@ def get_billing_portal(self, customer_id: str, group_id: int = 0):
4662
return_url = f"{settings.DOMAIN_URL}/group"
4763
if group_id != 0:
4864
return_url += f"/{group_id}/payment"
65+
if not self.is_membership:
66+
return_url = f"{settings.DOMAIN_URL}/donate"
4967
session = self.stripe.billing_portal.Session.create(customer=customer_id, return_url=return_url)
5068
return session.url
5169

52-
def checkout_membership(self, customer_id: str, price_id: str, group: Group, user: User):
53-
payment_return_url = f"{settings.DOMAIN_URL}/group/{group.id}/payment"
54-
session = self.stripe.checkout.Session.create(
55-
mode="subscription",
56-
line_items=[
70+
def checkout(self, price_id: str, group: Group or None, user: User, is_subscription: bool = True):
71+
return_url = f"{settings.DOMAIN_URL}/donate"
72+
if self.is_membership:
73+
return_url = f"{settings.DOMAIN_URL}/group/{group.id}/payment"
74+
customer_id = user.stripe_donate_customer_id if not group else group.stripe_customer_id
75+
log = f"[USER] {user.id}: {user.username}" if not group else f"[{group.id}] {group.name}"
76+
session_data = {
77+
"mode": "subscription" if is_subscription else "payment",
78+
"line_items": [
5779
{
5880
"price": price_id,
5981
"quantity": 1,
6082
},
6183
],
62-
customer=customer_id,
63-
success_url=payment_return_url,
64-
cancel_url=payment_return_url,
65-
expires_at=int(default_time.time() + (60 * 30)),
66-
subscription_data={
67-
"metadata": {
68-
"type": "membership",
69-
"user_id": user.id,
70-
"group_id": group.id,
71-
"log": f"[{group.id}] {group.name}",
72-
}
73-
},
74-
)
84+
"customer": customer_id,
85+
"success_url": return_url,
86+
"cancel_url": return_url,
87+
"expires_at": int(default_time.time() + (60 * 30)),
88+
}
89+
metadata = {
90+
"service_type": "donate" if not group else "membership",
91+
"user_id": user.id,
92+
"group_id": None if not group else group.id,
93+
"log": log,
94+
"dsbd_payment_system": "v2",
95+
}
96+
if is_subscription:
97+
session_data["subscription_data"] = {"metadata": metadata}
98+
else:
99+
session_data["payment_intent_data"] = {"metadata": metadata}
100+
session = self.stripe.checkout.Session.create(**session_data)
75101
return session.url
76102

77103
def get_product(self, stripe_type: str):
78-
products = self.stripe.Product.search(query=f"metadata['service_id']:'{stripe_type}'")
104+
products = self.stripe.Product.search(query=f"metadata['service_type']:'{stripe_type}'")
79105
if not products["data"]:
80106
raise ValueError("Products not found")
81107
return products.data[0]

dsbd/settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ def _import_ldap_group_type(group_type_name):
209209
STRIPE_SECRET_KEY = os.environ.get("STRIPE_SECRET_KEY", "")
210210
STRIPE_WEBHOOK_SECRET_KEY = os.environ.get("STRIPE_WEBHOOK_SECRET_KEY", "")
211211
STRIPE_MEMBERSHIP_TAG_NAME = os.environ.get("STRIPE_MEMBERSHIP_TAG_NAME", "membership")
212-
STRIPE_DONATE_MEMBERSHIP_TAG_NAME = os.environ.get("STRIPE_DONATE_MEMBERSHIP_TAG_NAME", "donate_membership")
213212
STRIPE_DONATE_TAG_NAME = os.environ.get("STRIPE_DONATE_TAG_NAME", "donate")
214213

215214
# Slack

dsbd/templates/home.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,7 @@ <h2>Information</h2>
233233
<div class="card">
234234
<div class="card-body">
235235
<h5 class="card-title">会員情報</h5>
236-
<p class="card-text">This card has supporting text below
237-
as a natural lead-in to
238-
additional
239-
content.</p>
236+
{# <p class="card-text">{{ group.get_membership_type_display }}#}
240237
<p class="card-text"><small class="text-body-secondary">Last
241238
updated 3 mins ago</small>
242239
</p>

dsbd/templates/navbar2.html

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,15 @@
102102
Services
103103
</a>
104104
</li>
105-
{# <li>#}
106-
{# <a href="#" class="nav-link text-white">#}
107-
{# <svg class="bi me-2" width="16" height="16">#}
108-
{# <use xlink:href="#people-circle"></use>#}
109-
{# </svg>#}
110-
{# Customers#}
111-
{# </a>#}
112-
{# </li>#}
105+
<li>
106+
{#TODO: href弄る#}
107+
<a href="{% url 'donate' %}" class="nav-link text-white">
108+
<svg class="bi me-2" width="16" height="16">
109+
<use xlink:href="#wallet"></use>
110+
</svg>
111+
Donate
112+
</a>
113+
</li>
113114
<li class="nav-item">
114115
<a href="{% url 'ticket:index' %}" class="nav-link text-white"
115116
aria-current="page">

dsbd/templates/payment/donate.html

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
{% extends 'base2.html' %}
2+
{% block content %}
3+
<div class="container">
4+
<div class="row">
5+
<div class="container py-4 mb-auto">
6+
<div class="h-900 p-2 rounded-3">
7+
<h2 class="card-title">Donation System</h2>
8+
<br/>
9+
<h3><b>こちらは寄付システムです。</b></h3>
10+
<p><b>会費の支払いシステムとは異なりますのでご注意ください。「グループ一覧」ボタンから「支払い情報」でご確認いただけます。</b></p>
11+
<a href="{% url 'custom_auth_group:index' %}" type="button"
12+
class="btn btn-sm btn-primary">グループ一覧</a>
13+
<br/>
14+
<br/>
15+
<div class="card">
16+
<div class="card-body">
17+
<h3 class="card-title">寄附一覧(One-time)</h3>
18+
<br/>
19+
<form method="post">
20+
{% csrf_token %}
21+
<input type="text" value="False" name="is_subscription" hidden>
22+
<div class="row mb-3 text-center">
23+
{% for price in prices %}
24+
{% if not price.recurring.interval %}
25+
<div class="col-sm-4 mb-2 mb-sm-0">
26+
<div class="card mb-4 rounded-3 shadow-sm">
27+
<div class="card-header py-3">
28+
<h4 class="my-0 fw-normal">one-time</h4>
29+
</div>
30+
<div class="card-body">
31+
<h1 class="card-title pricing-card-title">{{ price.unit_amount }} {{ price.currency }}<small
32+
class="text-muted fw-light">/one-time</small>
33+
</h1>
34+
<button type="submit"
35+
name="checkout"
36+
value="{{ price.id }}"
37+
class="w-100 btn btn-lg btn-outline-primary">
38+
会費支払い
39+
</button>
40+
</div>
41+
</div>
42+
</div>
43+
{% endif %}
44+
{% endfor %}
45+
</div>
46+
</form>
47+
</div>
48+
</div>
49+
<br/>
50+
<div class="card">
51+
<div class="card-body">
52+
<h3 class="card-title">寄附一覧(定期払い)</h3>
53+
<p>
54+
<b>寄附の定期支払いをキャンセルする場合は、「支払い履歴・情報・プラン変更」より可能です。</b>
55+
</p>
56+
<br/>
57+
<form method="post">
58+
{% csrf_token %}
59+
<div class="row mb-3 text-center">
60+
{% for price in prices %}
61+
{% if price.recurring.interval %}
62+
<div class="col-sm-4 mb-2 mb-sm-0">
63+
<div class="card mb-4 rounded-3 shadow-sm">
64+
<div class="card-header py-3">
65+
<h4 class="my-0 fw-normal">{{ price.recurring.interval }}</h4>
66+
</div>
67+
<div class="card-body">
68+
<h1 class="card-title pricing-card-title">{{ price.unit_amount }} {{ price.currency }}<small
69+
class="text-muted fw-light">/{{ price.recurring.interval }}</small>
70+
</h1>
71+
<button type="submit"
72+
name="checkout"
73+
value="{{ price.id }}"
74+
class="w-100 btn btn-lg btn-outline-primary">
75+
会費支払い{% if price.recurring.interval %}
76+
(定期払){% endif %}
77+
</button>
78+
</div>
79+
</div>
80+
</div>
81+
{% endif %}
82+
{% endfor %}
83+
</div>
84+
</form>
85+
</div>
86+
</div>
87+
<br/>
88+
<form method="post">
89+
{% csrf_token %}
90+
<p><b>支払い履歴やプラン変更などはこちらから確認可能です</b></p>
91+
<button type="submit" class="btn btn-primary btn-sm"
92+
name="billing_portal">支払い履歴・情報・プラン変更
93+
</button>
94+
<p>履歴はサブスクリプション情報のみとなります。(stripeの仕様のため)</p>
95+
</form>
96+
<br/>
97+
<p>
98+
ご不明な場合などがありましたら、Supportチャットにてご連絡のほどお願いいたします。</p>
99+
<br/>
100+
<br/>
101+
<a class="btn btn-primary"
102+
href="{% url 'custom_auth_group:index' %}" role="button"
103+
aria-expanded="false">ホームへ戻る</a>
104+
</div>
105+
</div>
106+
</div>
107+
</div>
108+
{% endblock content %}

dsbd/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
path("group/", include("custom_auth.group_urls")),
3636
path("group/<int:group_id>/jpnic/", include("ip.jpnic_urls")),
3737
path("group/<int:group_id>/service/", include("service.group_urls")),
38+
path("donate/", views.donate, name="donate"),
3839
path("services/", include("service.urls")),
3940
path("profile/", include("custom_auth.urls")),
4041
path("ticket/", include("ticket.urls")),

0 commit comments

Comments
 (0)