Compare commits

..

No commits in common. "main" and "v1.0.0" have entirely different histories.
main ... v1.0.0

14 changed files with 159 additions and 309 deletions

View file

@ -1,35 +0,0 @@
name: Check / auto apply Black
on:
push:
branches:
- main
jobs:
black:
name: Check / auto apply black
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check files using the black formatter
uses: psf/black@stable
id: black
with:
options: "."
continue-on-error: true
- shell: pwsh
id: check_files_changed
run: |
# Diff HEAD with the previous commit
$diff = git diff
$HasDiff = $diff.Length -gt 0
Write-Host "::set-output name=files_changed::$HasDiff"
- name: Create Pull Request
if: steps.check_files_changed.outputs.files_changed == 'true'
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: "Format Python code with Black"
commit-message: ":art: Format Python code with Black"
body: |
This pull request uses the [psf/black](https://github.com/psf/black) formatter.
base: ${{ github.head_ref }} # Creates pull request onto pull request or commit branch
branch: actions/black

3
.gitignore vendored
View file

@ -127,6 +127,3 @@ dmypy.json
# Pyre type checker # Pyre type checker
.pyre/ .pyre/
# Config file
settings.py

View file

@ -8,23 +8,22 @@ The demo is running in test mode -- use `4242424242424242` as a test card number
Use the `4000002500003155` test card number to trigger a 3D Secure challenge flow. Use the `4000002500003155` test card number to trigger a 3D Secure challenge flow.
Read more about testing on Stripe at <https://stripe.com/docs/testing>. Read more about testing on Stripe at https://stripe.com/docs/testing.
## How to run locally ## How to run locally
Follow the steps below to run locally. Follow the steps below to run locally.
```bash ```
git clone https://github.com/YunoHost/pepettes git clone https://github.com/yunohost/donate
cd pepettes cd donate
python3 -m venv venv python3 -m venv venv
source venv/bin/activate source venv/bin/activate
python3 -m pip install -r requirements.txt pip3 install requirements.txt
``` ```
Create a settings.py file with : Create a settings.py file with :
```
```python
ENV = 'development' ENV = 'development'
PORT = 8000 PORT = 8000
DOMAIN = 'http://localhost:8000' DOMAIN = 'http://localhost:8000'
@ -56,15 +55,7 @@ DONATION['recuring']['EUR'] = 'price_1IKumjE7vOmTpJBikyqS2NqD'
DONATION['recuring']['USD'] = 'price_1IKumAE7vOmTpJBiO4CEfa3Q' DONATION['recuring']['USD'] = 'price_1IKumAE7vOmTpJBiO4CEfa3Q'
``` ```
```bash ```
export FLASK_APP=server.py export FLASK_APP=server.py
python3 -m flask run --port=8000 python3 -m flask run --port=8000
``` ```
```bash
# extract new strings or update existing strings
pybabel extract -F babel.cfg -o messages.pot *.py assets/*.html
# then update the locale files, please translate into french any new string
pybabel update -i messages.pot -d locales
```

View file

@ -1,32 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ lang }}"> <html>
<head>
<head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ _('Donate to %(name)s', name=name) }}</title> <title>{{ _('Donate to %(name)s', name=name) }}</title>
<link rel="icon" href="{{ favicon }}" type="image/x-icon" /> <link rel="icon" href="{{ favicon }}" type="image/x-icon" />
<link href="./css/bootstrap-5.3.3.min.css" rel="stylesheet" <link href="./css/bootstrap-5.0.0-beta2.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" />
<link href="./css/global.css" rel="stylesheet" /> <link href="./css/global.css" rel="stylesheet" />
<script src="./darkmode.js" defer></script> </head>
</head>
<body class="text-center"> <body class="text-center">
<main class="form-donate"> <main class="form-donate">
<div> <div>
<img src="{{ logo }}" class="mb-4" alt="{{ _('%(name)s Logo', name=name) }}" /> <img src="{{ logo }}" class="mb-4" alt="" width="74" height="74"/>
<h1 class="h3 mb-3 fw-normal">{{ _('Your payment was canceled') }}</h1> <h1 class="h3 mb-3 fw-normal">{{ _('Your payment was canceled') }}</h1>
<button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary"> <button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary">{{ _('Go back to the donate form') }}</button>
{{ _('Go back to the donate form') }}
</button>
</div> </div>
</main> </main>
</body> </body>
</html> </html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -8,16 +8,7 @@ body {
align-items: center; align-items: center;
padding-top: 40px; padding-top: 40px;
padding-bottom: 40px; padding-bottom: 40px;
} background-color: #f5f5f5;
@media (prefers-color-scheme: dark) {
img {
filter: invert(100%);
}
}
img {
max-width: 13em
} }
.form-donate { .form-donate {
@ -26,11 +17,9 @@ img {
padding: 15px; padding: 15px;
margin: auto; margin: auto;
} }
.form-donate .checkbox { .form-donate .checkbox {
font-weight: 400; font-weight: 400;
} }
.form-donate .form-control { .form-donate .form-control {
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
@ -38,19 +27,17 @@ img {
padding: 10px; padding: 10px;
font-size: 16px; font-size: 16px;
} }
.form-donate .form-control:focus { .form-donate .form-control:focus {
z-index: 2; z-index: 2;
} }
.form-donate input[type="email"] { .form-donate input[type="email"] {
margin-bottom: -1px; margin-bottom: -1px;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
} }
.form-donate input[type="password"] { .form-donate input[type="password"] {
margin-bottom: 10px; margin-bottom: 10px;
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
} }

View file

@ -1,13 +0,0 @@
// Set theme to the user's preferred color scheme
function updateTheme() {
const colorMode = window.matchMedia("(prefers-color-scheme: dark)").matches ?
"dark" :
"light";
document.querySelector("html").setAttribute("data-bs-theme", colorMode);
}
// Set theme on load
updateTheme()
// Update theme when the preferred scheme changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateTheme)

View file

@ -1,55 +1,42 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ lang }}"> <html>
<head>
<head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ _('Donate to %(name)s', name=name) }}</title> <title>{{ _('Donate to %(name)s', name=name) }}</title>
<link rel="icon" href="{{ favicon }}" type="image/x-icon" /> <link rel="icon" href="{{ favicon }}" type="image/x-icon" />
<link href="./css/bootstrap-5.3.3.min.css" rel="stylesheet" <link href="./css/bootstrap-5.0.0-beta2.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" />
<link href="./css/global.css" rel="stylesheet" /> <link href="./css/global.css" rel="stylesheet" />
<script src="https://js.stripe.com/v3/"></script> <script src="https://js.stripe.com/v3/"></script>
<script src="./index.js" defer></script> <script src="./index.js" defer></script>
<script src="./darkmode.js" defer></script> </head>
</head>
<body class="text-center"> <body class="text-center">
<main class="form-donate"> <main class="form-donate">
<div> <div>
<img src="{{ logo }}" class="mb-4" alt="{{ _('%(name)s Logo', name=name) }}" /> <img src="{{ logo }}" class="mb-4" alt="" width="74" height="74"/>
<h1 class="h3 mb-3 fw-normal">{{ _('I want to give to %(name)s', name=name) }}</h1> <h1 class="h3 mb-3 fw-normal">{{ _('I want to give to %(name)s', name=name) }}</h1>
<div class="input-group mb-3"> <div class="input-group mb-3">
<input type="hidden" id="csrf" value="{{ csrf }}" /> <input type="hidden" id="csrf" value="{{ csrf }}" />
<input type="hidden" id="public_key" value="{{ stripe_publishable_key }}" /> <input type="hidden" id="public_key" value="{{ stripe_publishable_key }}" />
<input type="number" min="0" max="9999" class="form-control" id="quantity" value="10" aria-label="Amount">
<input type="number" min="0" max="9999" class="form-control" id="quantity" value="10" <select class="form-control" id="currency" style="width:40px">
aria-label="{{ _('Amount') }}">
<select class="form-select" id="currency" style="width:40px" aria-label="{{ _('Currency') }}">
{% for iso, symbol in currencies %} {% for iso, symbol in currencies %}
<option value="{{ iso }}">{{ symbol }} </option> <option value="{{ iso }}">{{ symbol }}
{% endfor %} {% endfor %}
</select> </select>
<select class="form-control" id="frequency">
<select class="form-select" id="frequency" aria-label="{{ _('Frequency') }}"> <option value="recuring"> {{ _('/ month') }}
<option value="recuring"> {{ _('/ month') }} </option> <option value="one_time"> {{ _('one time') }}
<option value="one_time"> {{ _('one time') }} </option>
</select> </select>
</div> </div>
<button id="submit" class="w-100 btn btn-lg btn-primary"> <button id="submit" class="w-100 btn btn-lg btn-primary">{{ _('Donate') }}</button>
{{ _('Donate') }} <p><a href="{{ contact_url }}">{{ _('If you want to stop a monthly donation contact us') }}</a></p>
</button>
<p><a href="{{ contact_url }}">{{ _('If you want to cancel a monthly donation, please contact us') }}</a></p>
<div id="error-message"></div> <div id="error-message"></div>
</div> </div>
</main> </main>
</body> </body>
</html> </html>

View file

@ -1,32 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ lang }}"> <html>
<head>
<head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{{ _('Donate to %(name)s', name=name) }}</title> <title>{{ _('Donate to %(name)s', name=name) }}</title>
<link rel="icon" href="{{ favicon }}" type="image/x-icon" /> <link rel="icon" href="{{ favicon }}" type="image/x-icon" />
<link href="./css/bootstrap-5.3.3.min.css" rel="stylesheet" <link href="./css/bootstrap-5.0.0-beta2.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" />
<link href="./css/global.css" rel="stylesheet" /> <link href="./css/global.css" rel="stylesheet" />
<script src="./darkmode.js" defer></script> </head>
</head>
<body class="text-center"> <body class="text-center">
<main class="form-donate"> <main class="form-donate">
<div> <div>
<img src="{{ logo }}" class="mb-4" alt="{{ _('%(name)s Logo', name=name) }}" /> <img src="{{ logo }}" class="mb-4" alt="" width="74" height="74"/>
<h1 class="h3 mb-3 fw-normal">{{ _('Thanks for your donation 🙂') }}</h1> <h1 class="h3 mb-3 fw-normal">{{ _('Thanks for your donation 🙂') }}</h1>
<button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary"> <button onclick="window.location.href = '/';" class="w-100 btn btn-lg btn-primary">{{ _('Go back to the donate form') }}</button>
{{ _('Go back to the donate form') }}
</button>
</div> </div>
</main> </main>
</body> </body>
</html> </html>

View file

@ -7,69 +7,48 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-05-22 04:43+0200\n" "POT-Creation-Date: 2021-02-18 23:32+0100\n"
"PO-Revision-Date: 2021-02-18 23:33+0100\n" "PO-Revision-Date: 2021-02-18 23:33+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n" "Language: en\n"
"Language-Team: en <LL@li.org>\n" "Language-Team: en <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.15.0\n" "Generated-By: Babel 2.9.0\n"
#: assets/canceled.html:8 assets/index.html:8 assets/success.html:8 #: assets/canceled.html:7 assets/index.html:7 assets/success.html:7
#, python-format #, python-format
msgid "Donate to %(name)s" msgid "Donate to %(name)s"
msgstr "" msgstr ""
#: assets/canceled.html:20 assets/index.html:22 assets/success.html:20 #: assets/canceled.html:18
#, python-format
msgid "%(name)s Logo"
msgstr ""
#: assets/canceled.html:22
msgid "Your payment was canceled" msgid "Your payment was canceled"
msgstr "" msgstr ""
#: assets/canceled.html:25 assets/success.html:25 #: assets/canceled.html:20 assets/success.html:20
msgid "Go back to the donate form" msgid "Go back to the donate form"
msgstr "" msgstr ""
#: assets/index.html:23 #: assets/index.html:20
#, python-format #, python-format
msgid "I want to give to %(name)s" msgid "I want to give to %(name)s"
msgstr "" msgstr ""
#: assets/index.html:30 #: assets/index.html:31
msgid "Amount"
msgstr ""
#: assets/index.html:32
msgid "Currency"
msgstr ""
#: assets/index.html:38
msgid "Frequency"
msgstr ""
#: assets/index.html:39
msgid "/ month" msgid "/ month"
msgstr "" msgstr ""
#: assets/index.html:40 #: assets/index.html:32
msgid "one time" msgid "one time"
msgstr "" msgstr ""
#: assets/index.html:45 #: assets/index.html:36
msgid "Donate" msgid "Donate"
msgstr "" msgstr ""
#: assets/index.html:48 #: assets/success.html:18
msgid "If you want to cancel a monthly donation, please contact us"
msgstr ""
#: assets/success.html:22
msgid "Thanks for your donation 🙂" msgid "Thanks for your donation 🙂"
msgstr "" msgstr ""

View file

@ -7,72 +7,48 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-05-22 04:43+0200\n" "POT-Creation-Date: 2021-02-18 23:32+0100\n"
"PO-Revision-Date: 2021-02-18 23:33+0100\n" "PO-Revision-Date: 2021-02-18 23:33+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: fr\n" "Language: fr\n"
"Language-Team: fr <LL@li.org>\n" "Language-Team: fr <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.15.0\n" "Generated-By: Babel 2.9.0\n"
#: assets/canceled.html:8 assets/index.html:8 assets/success.html:8 #: assets/canceled.html:7 assets/index.html:7 assets/success.html:7
#, python-format #, python-format
msgid "Donate to %(name)s" msgid "Donate to %(name)s"
msgstr "Donner à %(name)s" msgstr "Donner à %(name)s"
#: assets/canceled.html:20 assets/index.html:22 assets/success.html:20 #: assets/canceled.html:18
#, python-format
msgid "%(name)s Logo"
msgstr "Logo de %(name)s"
#: assets/canceled.html:22
msgid "Your payment was canceled" msgid "Your payment was canceled"
msgstr "Votre paiement a été annulé" msgstr "Votre paiement a été annulé"
#: assets/canceled.html:25 assets/success.html:25 #: assets/canceled.html:20 assets/success.html:20
msgid "Go back to the donate form" msgid "Go back to the donate form"
msgstr "Retourner au formulaire de don" msgstr "Retourner au formulaire de don"
#: assets/index.html:23 #: assets/index.html:20
#, python-format #, python-format
msgid "I want to give to %(name)s" msgid "I want to give to %(name)s"
msgstr "Je veux donner à %(name)s" msgstr "Je veux donner à %(name)s"
#: assets/index.html:30 #: assets/index.html:31
#, fuzzy
msgid "Amount"
msgstr "Montant"
#: assets/index.html:32
msgid "Currency"
msgstr "Devise"
#: assets/index.html:38
msgid "Frequency"
msgstr "Fréquence"
#: assets/index.html:39
msgid "/ month" msgid "/ month"
msgstr "/ mois" msgstr "/ mois"
#: assets/index.html:40 #: assets/index.html:32
msgid "one time" msgid "one time"
msgstr "une fois" msgstr "une fois"
#: assets/index.html:45 #: assets/index.html:36
msgid "Donate" msgid "Donate"
msgstr "Donner" msgstr "Donner"
#: assets/index.html:48 #: assets/success.html:18
msgid "If you want to cancel a monthly donation, please contact us"
msgstr ""
"Si vous souhaitez mettre fin à votre don mensuel, contactez-nous s'il "
"vous plaît"
#: assets/success.html:22
msgid "Thanks for your donation 🙂" msgid "Thanks for your donation 🙂"
msgstr "Merci pour votre don 🙂" msgstr "Merci pour votre don 🙂"

View file

@ -13,4 +13,3 @@ toml==0.9.6
urllib3==1.25.3 urllib3==1.25.3
flask-simple-csrf flask-simple-csrf
flask-babel flask-babel
Werkzeug==0.16.0

View file

@ -12,89 +12,84 @@ import os
import random import random
import string import string
from flask import Flask, render_template, jsonify, request, session from flask import Flask, render_template, jsonify, request, send_from_directory, session
from flask_babel import Babel from flask_babel import Babel, _
from flask_simple_csrf import CSRF from flask_simple_csrf import CSRF
static_dir = str(os.path.abspath(os.path.join(__file__, "..", "assets"))) static_dir = str(os.path.abspath(os.path.join(
app = Flask( __file__, "..", 'assets')))
__name__, static_folder=static_dir, static_url_path="", template_folder=static_dir app = Flask(__name__, static_folder=static_dir,
) static_url_path="", template_folder=static_dir)
app.config.from_pyfile("settings.py") app.config.from_pyfile('settings.py')
stripe.api_key = app.config["STRIPE_SECRET_KEY"] stripe.api_key = app.config['STRIPE_SECRET_KEY']
CSRF = CSRF(config={"SECRET_CSRF_KEY": app.config["SECRET_CSRF_KEY"]}) CSRF = CSRF(config={
'SECRET_CSRF_KEY': app.config['SECRET_CSRF_KEY']
})
app = CSRF.init_app(app) app = CSRF.init_app(app)
babel = Babel(app) babel = Babel(app)
@app.before_request @app.before_request
def before_request(): def before_request():
if "CSRF_TOKEN" not in session or "USER_CSRF" not in session: if 'CSRF_TOKEN' not in session or 'USER_CSRF' not in session:
session["USER_CSRF"] = "".join( session['USER_CSRF'] = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(64))
random.SystemRandom().choice(string.ascii_uppercase + string.digits) session['CSRF_TOKEN'] = CSRF.create(session['USER_CSRF'])
for _ in range(64)
)
session["CSRF_TOKEN"] = CSRF.create(session["USER_CSRF"])
@babel.localeselector @babel.localeselector
def get_locale(): def get_locale():
return request.accept_languages.best_match(app.config["LANGUAGES"]) return 'fr' #request.accept_languages.best_match(app.config['LANGUAGES'])
@app.route('/', methods=['GET'])
@app.context_processor
def utility_processor():
return dict(lang=babel.locale_selector_func())
@app.route("/", methods=["GET"])
def get_index(): def get_index():
return render_template( return render_template('index.html', **app.config['CUSTOM'],
"index.html", **app.config["CUSTOM"], csrf=session["USER_CSRF"] csrf=session['USER_CSRF'])
)
@app.route("/success", methods=["GET"]) @app.route('/success', methods=['GET'])
def get_success(): def get_success():
return render_template("success.html", **app.config["CUSTOM"]) return render_template('success.html', **app.config['CUSTOM'])
@app.route("/canceled", methods=["GET"]) @app.route('/canceled', methods=['GET'])
def get_canceled(): def get_canceled():
return render_template("canceled.html", **app.config["CUSTOM"]) return render_template('canceled.html', **app.config['CUSTOM'])
@app.route("/create-checkout-session", methods=["POST"]) @app.route('/create-checkout-session', methods=['POST'])
def create_checkout_session(): def create_checkout_session():
data = json.loads(request.data) data = json.loads(request.data)
domain_url = app.config["DOMAIN"] domain_url = app.config['DOMAIN']
try: try:
donation = app.config["DONATION"] donation = app.config['DONATION']
currencies = [iso for iso, symbol in app.config["CUSTOM"]["currencies"]] currencies = [iso for iso, symbol in app.config['CUSTOM']['currencies']]
if ( if CSRF.verify(data['user_csrf'], session['CSRF_TOKEN']) is False or \
CSRF.verify(data["user_csrf"], session["CSRF_TOKEN"]) is False data['frequency'] not in ['recuring', 'one_time'] or \
or data["frequency"] not in ["recuring", "one_time"] data['currency'] not in currencies or \
or data["currency"] not in currencies int(data['quantity']) <= 0:
or int(data["quantity"]) <= 0
):
return jsonify(error="Bad value"), 400 return jsonify(error="Bad value"), 400
# Create new Checkout Session for the order # Create new Checkout Session for the order
price = donation[data["frequency"]][data["currency"]] price = donation[data['frequency']][data['currency']]
mode = "payment" if data["frequency"] == "one_time" else "subscription" mode = "payment" if data['frequency'] == 'one_time' else "subscription"
checkout_session = stripe.checkout.Session.create( checkout_session = stripe.checkout.Session.create(
success_url=domain_url + "/success?session_id={CHECKOUT_SESSION_ID}", success_url=domain_url +
"/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url=domain_url + "/canceled", cancel_url=domain_url + "/canceled",
payment_method_types=["card"], payment_method_types= ["card"],
mode=mode, mode=mode,
line_items=[{"price": price, "quantity": data["quantity"]}], line_items=[
{
"price": price,
"quantity": data['quantity']
}
]
) )
return jsonify({"sessionId": checkout_session["id"]}) return jsonify({'sessionId': checkout_session['id']})
except Exception as e: except Exception as e:
return jsonify(error=str(e)), 403 return jsonify(error=str(e)), 403
if __name__ == "__main__":
app.run(port=app.config["PORT"], debug=app.debug) if __name__ == '__main__':
app.run(port=app.config['PORT'], debug=app.debug)