From f19a7e1bca7c342096209c1a35547386640fd98a Mon Sep 17 00:00:00 2001
From: Son NK <>
Date: Mon, 14 Dec 2020 11:33:39 +0100
Subject: [PATCH 17/21] Add COINBASE_API_KEY and COINBASE_YEARLY_PRICE config
---
app/config.py | 5 +++++
example.env | 4 +++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/app/config.py b/app/config.py
index 56bb6e4b..498a6210 100644
--- a/app/config.py
+++ b/app/config.py
@@ -361,3 +361,8 @@ NOREPLY = os.environ.get("NOREPLY", f"noreply@{EMAIL_DOMAIN}")
COINBASE_WEBHOOK_SECRET = os.environ.get("COINBASE_WEBHOOK_SECRET")
COINBASE_CHECKOUT_ID = os.environ.get("COINBASE_CHECKOUT_ID")
+COINBASE_API_KEY = os.environ.get("COINBASE_API_KEY")
+try:
+ COINBASE_YEARLY_PRICE = float(os.environ["COINBASE_YEARLY_PRICE"])
+except Exception:
+ COINBASE_YEARLY_PRICE = 30.00
diff --git a/example.env b/example.env
index 30a196a1..8a17e693 100644
--- a/example.env
+++ b/example.env
@@ -169,4 +169,6 @@ DISABLE_ONBOARDING=true
# Coinbase
# COINBASE_WEBHOOK_SECRET=to_fill
-# COINBASE_CHECKOUT_ID=to_fill
\ No newline at end of file
+# COINBASE_CHECKOUT_ID=to_fill
+# COINBASE_API_KEY=to_fill
+# COINBASE_YEARLY_PRICE=30.00
\ No newline at end of file
From 3dd8ed7840104960cac23f8f126aa98a0e0f57f0 Mon Sep 17 00:00:00 2001
From: Son NK <>
Date: Mon, 14 Dec 2020 11:34:59 +0100
Subject: [PATCH 18/21] Create /dashboard/coinbase_checkout, remove
extend_subscription route
---
app/dashboard/__init__.py | 1 -
.../templates/dashboard/pricing.html | 16 +++++--------
.../templates/dashboard/setting.html | 2 +-
app/dashboard/views/extend_subscription.py | 24 -------------------
app/dashboard/views/pricing.py | 24 +++++++++++++++----
cron.py | 2 +-
6 files changed, 28 insertions(+), 41 deletions(-)
delete mode 100644 app/dashboard/views/extend_subscription.py
diff --git a/app/dashboard/__init__.py b/app/dashboard/__init__.py
index ec7db995..8363aa5d 100644
--- a/app/dashboard/__init__.py
+++ b/app/dashboard/__init__.py
@@ -25,5 +25,4 @@ from .views import (
contact_detail,
setup_done,
batch_import,
- extend_subscription,
)
diff --git a/app/dashboard/templates/dashboard/pricing.html b/app/dashboard/templates/dashboard/pricing.html
index 21c64045..a8366939 100644
--- a/app/dashboard/templates/dashboard/pricing.html
+++ b/app/dashboard/templates/dashboard/pricing.html
@@ -65,7 +65,7 @@
@@ -100,16 +100,12 @@
Coinbase Commerce
- Only the yearly plan is supported.
+ Only the yearly plan is supported.
-
+
+ $30/year - Crypto
+
{% endif %}
diff --git a/app/dashboard/templates/dashboard/setting.html b/app/dashboard/templates/dashboard/setting.html
index 8d33608f..62850daa 100644
--- a/app/dashboard/templates/dashboard/setting.html
+++ b/app/dashboard/templates/dashboard/setting.html
@@ -53,7 +53,7 @@
({{ coinbase_sub.end_at.format("YYYY-MM-DD") }}).
You can extend your subscription on
-
+
Extend Subscription
diff --git a/app/dashboard/views/extend_subscription.py b/app/dashboard/views/extend_subscription.py
deleted file mode 100644
index e10920aa..00000000
--- a/app/dashboard/views/extend_subscription.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from flask import render_template, flash, redirect, url_for
-from flask_login import login_required, current_user
-
-from app.config import COINBASE_CHECKOUT_ID
-from app.dashboard.base import dashboard_bp
-from app.models import CoinbaseSubscription
-
-
-@dashboard_bp.route("/extend_subscription", methods=["GET", "POST"])
-@login_required
-def extend_subscription_route():
- coinbase_subscription = CoinbaseSubscription.get_by(user_id=current_user.id)
- # this page is only for user who has an active coinbase subscription
- if not coinbase_subscription or not coinbase_subscription.is_active():
- flash("Unknown error, redirect to home page", "error")
- return redirect(url_for("dashboard.index"))
-
- coinbase_url = "https://commerce.coinbase.com/checkout/" + COINBASE_CHECKOUT_ID
-
- return render_template(
- "dashboard/extend_subscription.html",
- coinbase_subscription=coinbase_subscription,
- coinbase_url=coinbase_url,
- )
diff --git a/app/dashboard/views/pricing.py b/app/dashboard/views/pricing.py
index b99353fc..5cc6e98c 100644
--- a/app/dashboard/views/pricing.py
+++ b/app/dashboard/views/pricing.py
@@ -1,3 +1,4 @@
+from coinbase_commerce import Client
from flask import render_template, flash, redirect, url_for
from flask_login import login_required, current_user
@@ -6,9 +7,11 @@ from app.config import (
PADDLE_MONTHLY_PRODUCT_ID,
PADDLE_YEARLY_PRODUCT_ID,
URL,
- COINBASE_CHECKOUT_ID,
+ COINBASE_YEARLY_PRICE,
+ COINBASE_API_KEY,
)
from app.dashboard.base import dashboard_bp
+from app.log import LOG
@dashboard_bp.route("/pricing", methods=["GET", "POST"])
@@ -18,15 +21,12 @@ def pricing():
flash("You are already a premium user", "warning")
return redirect(url_for("dashboard.index"))
- coinbase_url = "https://commerce.coinbase.com/checkout/" + COINBASE_CHECKOUT_ID
-
return render_template(
"dashboard/pricing.html",
PADDLE_VENDOR_ID=PADDLE_VENDOR_ID,
PADDLE_MONTHLY_PRODUCT_ID=PADDLE_MONTHLY_PRODUCT_ID,
PADDLE_YEARLY_PRODUCT_ID=PADDLE_YEARLY_PRODUCT_ID,
success_url=URL + "/dashboard/subscription_success",
- coinbase_url=coinbase_url,
)
@@ -35,3 +35,19 @@ def pricing():
def subscription_success():
flash("Thanks so much for supporting SimpleLogin!", "success")
return redirect(url_for("dashboard.index"))
+
+
+@dashboard_bp.route("/coinbase_checkout")
+@login_required
+def coinbase_checkout_route():
+ client = Client(api_key=COINBASE_API_KEY)
+ charge = client.charge.create(
+ name="1 Year Premium Subscription",
+ local_price={"amount": str(COINBASE_YEARLY_PRICE), "currency": "USD"},
+ pricing_type="fixed_price",
+ metadata={"user_id": current_user.id},
+ )
+
+ LOG.d("Create coinbase charge %s", charge)
+
+ return redirect(charge["hosted_url"])
diff --git a/cron.py b/cron.py
index 3f3c045b..d7e99469 100644
--- a/cron.py
+++ b/cron.py
@@ -130,7 +130,7 @@ def notify_manual_sub_end():
),
)
- extend_subscription_url = URL + "/dashboard/extend_subscription"
+ extend_subscription_url = URL + "/dashboard/coinbase_checkout"
for coinbase_subscription in CoinbaseSubscription.query.all():
need_reminder = False
if (
From 6eaeb1fcf66e6fbbc4f37132611207c5f8984bc5 Mon Sep 17 00:00:00 2001
From: Son NK <>
Date: Mon, 14 Dec 2020 11:36:34 +0100
Subject: [PATCH 19/21] update coinbase webhook
---
server.py | 2 +-
tests/test_server.py | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/server.py b/server.py
index 0669f882..99725d51 100644
--- a/server.py
+++ b/server.py
@@ -671,7 +671,7 @@ def setup_coinbase_commerce(app):
def handle_coinbase_event(event) -> bool:
- user_id = int(event["data"]["metadata"]["custom"])
+ user_id = int(event["data"]["metadata"]["user_id"])
code = event["data"]["code"]
user = User.get(user_id)
if not user:
diff --git a/tests/test_server.py b/tests/test_server.py
index 46ceaac8..ed362342 100644
--- a/tests/test_server.py
+++ b/tests/test_server.py
@@ -27,7 +27,7 @@ def test_handle_coinbase_event_new_subscription(flask_client):
commit=True,
)
handle_coinbase_event(
- {"data": {"code": "AAAAAA", "metadata": {"custom": str(user.id)}}}
+ {"data": {"code": "AAAAAA", "metadata": {"user_id": str(user.id)}}}
)
assert user.is_paid()
@@ -55,7 +55,7 @@ def test_handle_coinbase_event_extend_subscription(flask_client):
assert not user.is_premium()
handle_coinbase_event(
- {"data": {"code": "AAAAAA", "metadata": {"custom": str(user.id)}}}
+ {"data": {"code": "AAAAAA", "metadata": {"user_id": str(user.id)}}}
)
assert user.is_paid()
From b9dba9c2c3bb172ce43550aa77c1a913546719d0 Mon Sep 17 00:00:00 2001
From: Son NK <>
Date: Mon, 14 Dec 2020 11:48:08 +0100
Subject: [PATCH 20/21] improve wording
---
app/dashboard/templates/dashboard/setting.html | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/dashboard/templates/dashboard/setting.html b/app/dashboard/templates/dashboard/setting.html
index 62850daa..173572f8 100644
--- a/app/dashboard/templates/dashboard/setting.html
+++ b/app/dashboard/templates/dashboard/setting.html
@@ -52,9 +52,9 @@
You are on the Premium plan which expires {{ coinbase_sub.end_at | dt }}
({{ coinbase_sub.end_at.format("YYYY-MM-DD") }}).
- You can extend your subscription on
-
- Extend Subscription
+
+ Extend Subscription
{% elif current_user.in_trial() %}
From 830331d9b30086b662463f0f805ae4d142a1c61b Mon Sep 17 00:00:00 2001
From: Son NK <>
Date: Mon, 14 Dec 2020 11:52:35 +0100
Subject: [PATCH 21/21] improve wording
---
app/dashboard/views/pricing.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/dashboard/views/pricing.py b/app/dashboard/views/pricing.py
index 5cc6e98c..7378d18d 100644
--- a/app/dashboard/views/pricing.py
+++ b/app/dashboard/views/pricing.py
@@ -42,7 +42,7 @@ def subscription_success():
def coinbase_checkout_route():
client = Client(api_key=COINBASE_API_KEY)
charge = client.charge.create(
- name="1 Year Premium Subscription",
+ name="1 Year SimpleLogin Premium Subscription",
local_price={"amount": str(COINBASE_YEARLY_PRICE), "currency": "USD"},
pricing_type="fixed_price",
metadata={"user_id": current_user.id},