We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Prefill customer_email in stripe checkout page
Self explainable.

Parent issue: #8146 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `app/api/helpers/payment.py`
Content:
```
1 import json
2 
3 import omise
4 import paypalrestsdk
5 import requests
6 import stripe
7 from forex_python.converter import CurrencyRates
8 
9 from app.api.helpers import checksum
10 from app.api.helpers.cache import cache
11 from app.api.helpers.db import safe_query, save_to_db
12 from app.api.helpers.errors import ConflictError, ForbiddenError
13 from app.api.helpers.utilities import represents_int, round_money
14 from app.models.order import Order
15 from app.models.stripe_authorization import StripeAuthorization
16 from app.settings import Environment, get_settings
17 
18 
19 @cache.memoize(5)
20 def forex(from_currency, to_currency, amount):
21     try:
22         currency_rates = CurrencyRates()
23         return currency_rates.convert(from_currency, to_currency, amount)
24     except:
25         return amount
26 
27 
28 class StripePaymentsManager:
29     """
30     Class to manage payments through Stripe.
31     """
32 
33     @staticmethod
34     def get_credentials(event=None):
35         """
36         If the event parameter is None, It returns the secret and publishable key of the Admin's Stripe account.
37         Else, it returns the corresponding values for the event organizer's account.
38         :param event:
39         :return: Stripe secret and publishable keys.
40         """
41         if not event:
42             settings = get_settings()
43             if (
44                 settings['app_environment'] == 'development'
45                 and settings['stripe_test_secret_key']
46                 and settings['stripe_test_publishable_key']
47             ):
48                 return {
49                     'SECRET_KEY': settings['stripe_test_secret_key'],
50                     'PUBLISHABLE_KEY': settings["stripe_test_publishable_key"],
51                 }
52             if settings['stripe_secret_key'] and settings["stripe_publishable_key"]:
53                 return {
54                     'SECRET_KEY': settings['stripe_secret_key'],
55                     'PUBLISHABLE_KEY': settings["stripe_publishable_key"],
56                 }
57             return None
58         if represents_int(event):
59             authorization = StripeAuthorization.query.filter_by(event_id=event).first()
60         else:
61             authorization = event.stripe_authorization
62         if authorization:
63             return {
64                 'SECRET_KEY': authorization.stripe_secret_key,
65                 'PUBLISHABLE_KEY': authorization.stripe_publishable_key,
66             }
67         return None
68 
69     @staticmethod
70     def get_event_organizer_credentials_from_stripe(stripe_auth_code):
71         """
72         Uses the stripe_auth_code to get the other credentials for the event organizer's stripe account
73         :param stripe_auth_code: stripe authorization code
74         :return: response from stripe
75         """
76         credentials = StripePaymentsManager.get_credentials()
77 
78         if not credentials:
79             raise ForbiddenError(
80                 {'pointer': ''},
81                 "Stripe payment isn't configured properly for the Platform",
82             )
83 
84         data = {
85             'client_secret': credentials['SECRET_KEY'],
86             'code': stripe_auth_code,
87             'grant_type': 'authorization_code',
88         }
89 
90         response = requests.post('https://connect.stripe.com/oauth/token', data=data)
91         return json.loads(response.text)
92 
93     @staticmethod
94     def capture_payment(order_invoice, currency=None, credentials=None):
95         """
96         Capture payments through stripe.
97         :param order_invoice: Order to be charged for
98         :param currency: Currency of the order amount.
99         :param credentials: Stripe credentials.
100         :return: charge/None depending on success/failure.
101         """
102         if not credentials:
103             credentials = StripePaymentsManager.get_credentials(order_invoice.event)
104 
105         if not credentials:
106             raise ConflictError(
107                 {'pointer': ''}, 'Stripe credentials not found for the event.'
108             )
109         stripe.api_key = credentials['SECRET_KEY']
110         if not currency:
111             currency = order_invoice.event.payment_currency
112 
113         if not currency or currency == "":
114             currency = "USD"
115 
116         frontend_url = get_settings()['frontend_url']
117 
118         try:
119             # payment_method_types = ['card', 'klarna']
120             payment_method_types = ['card']
121             # if currency.lower() == 'eur':
122             #     payment_method_types.append('sepa_debit')
123 
124             session = stripe.checkout.Session.create(
125                 payment_method_types= payment_method_types,
126                 line_items=[{
127                     'price_data': {
128                         'currency': currency.lower(),
129                         'product_data': {
130                             'name': order_invoice.event.name,
131                         },
132                         'unit_amount': int(order_invoice.amount * 100),
133                     },
134                     'quantity': 1,
135                 }],
136                 mode='payment',
137                 success_url=f"{frontend_url}/orders/{order_invoice.identifier}/view",
138                 cancel_url=f"{frontend_url}/orders/{order_invoice.identifier}/view",
139             )
140 
141             return session
142 
143         except Exception as e:
144             raise ConflictError({'pointer': ''}, str(e))
145 
146     @staticmethod
147     def retrieve_session(event_id, stripe_session_id):
148         credentials = StripePaymentsManager.get_credentials(event_id)
149 
150         if not credentials:
151             raise ConflictError(
152                 {'pointer': ''}, 'Stripe credentials not found for the event.'
153             )
154         stripe.api_key = credentials['SECRET_KEY']
155         session = stripe.checkout.Session.retrieve(stripe_session_id)
156 
157         return session
158 
159     @staticmethod
160     def retrieve_payment_intent(event_id, payment_intent_id):
161         credentials = StripePaymentsManager.get_credentials(event_id)
162 
163         if not credentials:
164             raise ConflictError(
165                 {'pointer': ''}, 'Stripe credentials not found for the event.'
166             )
167         stripe.api_key = credentials['SECRET_KEY']
168         payment_intent = stripe.PaymentIntent.retrieve(payment_intent_id)
169 
170         return payment_intent
171 
172 
173 class PayPalPaymentsManager:
174     """
175     Class to manage payment through Paypal REST API.
176     """
177 
178     @staticmethod
179     def configure_paypal():
180         """
181         Configure the paypal sdk
182         :return: Credentials
183         """
184         settings = get_settings()
185         # Use Sandbox by default.
186         paypal_mode = settings.get(
187             'paypal_mode',
188             'live'
189             if (settings['app_environment'] == Environment.PRODUCTION)
190             else 'sandbox',
191         )
192         paypal_key = None
193         if paypal_mode == 'sandbox':
194             paypal_key = 'paypal_sandbox'
195         elif paypal_mode == 'live':
196             paypal_key = 'paypal'
197 
198         if not paypal_key:
199             raise ConflictError(
200                 {'pointer': ''}, "Paypal Mode must be 'live' or 'sandbox'"
201             )
202 
203         paypal_client = settings.get(f'{paypal_key}_client', None)
204         paypal_secret = settings.get(f'{paypal_key}_secret', None)
205 
206         if not paypal_client or not paypal_secret:
207             raise ConflictError(
208                 {'pointer': ''},
209                 "Payments through Paypal have not been configured on the platform",
210             )
211         return paypalrestsdk.configure(
212             {
213                 "mode": paypal_mode,
214                 "client_id": paypal_client,
215                 "client_secret": paypal_secret,
216             }
217         )
218 
219     @staticmethod
220     def create_payment(order, return_url, cancel_url, payee_email=None):
221         """
222         Create payment for an order
223         :param order: Order to create payment for.
224         :param return_url: return url for the payment.
225         :param cancel_url: cancel_url for the payment.
226         :param payee_email: email of the payee. Default to event paypal email if not set
227         :return: request_id or the error message along with an indicator.
228         """
229         payee_email = payee_email or order.event.paypal_email
230         if not payee_email:
231             raise ConflictError(
232                 {'pointer': ''},
233                 "Payments through Paypal hasn't been configured for the billing",
234             )
235 
236         PayPalPaymentsManager.configure_paypal()
237 
238         payment = paypalrestsdk.Payment(
239             {
240                 "intent": "sale",
241                 "payer": {"payment_method": "paypal"},
242                 "redirect_urls": {"return_url": return_url, "cancel_url": cancel_url},
243                 "transactions": [
244                     {
245                         "amount": {
246                             "total": float(round_money(order.amount)),
247                             "currency": order.event.payment_currency,
248                         },
249                         "payee": {"email": payee_email},
250                     }
251                 ],
252             }
253         )
254 
255         if payment.create():
256             return True, payment.id
257         return False, payment.error
258 
259     @staticmethod
260     def verify_payment(payment_id, order):
261         """
262         Verify Paypal payment one more time for paying with Paypal in mobile client
263         """
264         PayPalPaymentsManager.configure_paypal()
265         try:
266             payment_server = paypalrestsdk.Payment.find(payment_id)
267             if payment_server.state != 'approved':
268                 return (
269                     False,
270                     'Payment has not been approved yet. Status is '
271                     + payment_server.state
272                     + '.',
273                 )
274 
275             # Get the most recent transaction
276             transaction = payment_server.transactions[0]
277             amount_server = transaction.amount.total
278             currency_server = transaction.amount.currency
279             sale_state = transaction.related_resources[0].sale.state
280 
281             if float(amount_server) != order.amount:
282                 return False, 'Payment amount does not match order'
283             if currency_server != order.event.payment_currency:
284                 return False, 'Payment currency does not match order'
285             if sale_state != 'completed':
286                 return False, 'Sale not completed'
287             if PayPalPaymentsManager.used_payment(payment_id, order):
288                 return False, 'Payment already been verified'
289             return True, None
290         except paypalrestsdk.ResourceNotFound:
291             return False, 'Payment Not Found'
292 
293     @staticmethod
294     def used_payment(payment_id, order):
295         """
296         Function to check for recycling of payment IDs
297         """
298         if Order.query.filter(Order.paypal_token == payment_id).first() is None:
299             order.paypal_token = payment_id
300             save_to_db(order)
301             return False
302         return True
303 
304     @staticmethod
305     def execute_payment(paypal_payer_id, paypal_payment_id):
306         """
307         Execute payemnt and charge the user.
308         :param paypal_payment_id: payment_id
309         :param paypal_payer_id: payer_id
310         :return: Result of the transaction.
311         """
312         PayPalPaymentsManager.configure_paypal()
313         payment = paypalrestsdk.Payment.find(paypal_payment_id)
314 
315         if payment.execute({"payer_id": paypal_payer_id}):
316             return True, 'Successfully Executed'
317         return False, payment.error
318 
319 
320 class AliPayPaymentsManager:
321     """
322     Class to manage AliPay Payments
323     """
324 
325     @staticmethod
326     def create_source(amount, currency, redirect_return_uri):
327         stripe.api_key = get_settings()['alipay_publishable_key']
328         response = stripe.Source.create(
329             type='alipay',
330             currency=currency,
331             amount=amount,
332             redirect={'return_url': redirect_return_uri},
333         )
334         return response
335 
336     @staticmethod
337     def charge_source(order_identifier):
338         order = safe_query(Order, 'identifier', order_identifier, 'identifier')
339         stripe.api_key = get_settings()['alipay_secret_key']
340         charge = stripe.Charge.create(
341             amount=int(order.amount),
342             currency=order.event.payment_currency,
343             source=order.order_notes,
344         )
345         return charge
346 
347 
348 class OmisePaymentsManager:
349     """
350     Class to manage Omise Payments
351     """
352 
353     @staticmethod
354     def charge_payment(order_identifier, token):
355         if get_settings()['app_environment'] == Environment.PRODUCTION:
356             omise.api_secret = get_settings()['omise_test_secret']
357             omise.api_public = get_settings()['omise_test_public']
358         else:
359             omise.api_secret = get_settings()['omise_test_secret']
360             omise.api_public = get_settings()['omise_test_public']
361         order = safe_query(Order, 'identifier', order_identifier, 'identifier')
362         charge = omise.Charge.create(
363             amount=int(round(order.amount)),
364             currency=order.event.payment_currency,
365             card=token,
366             metadata={"order_id": str(order_identifier), "status": True},
367         )
368         return charge
369 
370 
371 class PaytmPaymentsManager:
372     """
373     Class to manage PayTM payments
374     """
375 
376     @property
377     def paytm_endpoint(self):
378         if get_settings()['paytm_mode'] == 'test':
379             url = "https://securegw-stage.paytm.in/theia/api/v1/"
380         else:
381             url = "https://securegw.paytm.in/theia/api/v1/"
382         return url
383 
384     @staticmethod
385     def generate_checksum(paytm_params):
386         if get_settings()['paytm_mode'] == 'test':
387             merchant_key = get_settings()['paytm_sandbox_secret']
388         else:
389             merchant_key = get_settings()['paytm_live_secret']
390         return checksum.generate_checksum_by_str(
391             json.dumps(paytm_params["body"]), merchant_key
392         )
393 
394     @staticmethod
395     def hit_paytm_endpoint(url, head, body=None):
396         paytm_params = {}
397         paytm_params["body"] = body
398         paytm_params["head"] = head
399         post_data = json.dumps(paytm_params)
400         response = requests.post(
401             url, data=post_data, headers={"Content-type": "application/json"}
402         ).json()
403         return response
404
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/app/api/helpers/payment.py b/app/api/helpers/payment.py
--- a/app/api/helpers/payment.py
+++ b/app/api/helpers/payment.py
@@ -122,17 +122,20 @@
             #     payment_method_types.append('sepa_debit')
 
             session = stripe.checkout.Session.create(
-                payment_method_types= payment_method_types,
-                line_items=[{
-                    'price_data': {
-                        'currency': currency.lower(),
-                        'product_data': {
-                            'name': order_invoice.event.name,
+                customer_email=order_invoice.user.email,
+                payment_method_types=payment_method_types,
+                line_items=[
+                    {
+                        'price_data': {
+                            'currency': currency.lower(),
+                            'product_data': {
+                                'name': order_invoice.event.name,
+                            },
+                            'unit_amount': int(order_invoice.amount * 100),
                         },
-                        'unit_amount': int(order_invoice.amount * 100),
-                    },
-                    'quantity': 1,
-                }],
+                        'quantity': 1,
+                    }
+                ],
                 mode='payment',
                 success_url=f"{frontend_url}/orders/{order_invoice.identifier}/view",
                 cancel_url=f"{frontend_url}/orders/{order_invoice.identifier}/view",

{"golden_diff": "diff --git a/app/api/helpers/payment.py b/app/api/helpers/payment.py\n--- a/app/api/helpers/payment.py\n+++ b/app/api/helpers/payment.py\n@@ -122,17 +122,20 @@\n             #     payment_method_types.append('sepa_debit')\n \n             session = stripe.checkout.Session.create(\n-                payment_method_types= payment_method_types,\n-                line_items=[{\n-                    'price_data': {\n-                        'currency': currency.lower(),\n-                        'product_data': {\n-                            'name': order_invoice.event.name,\n+                customer_email=order_invoice.user.email,\n+                payment_method_types=payment_method_types,\n+                line_items=[\n+                    {\n+                        'price_data': {\n+                            'currency': currency.lower(),\n+                            'product_data': {\n+                                'name': order_invoice.event.name,\n+                            },\n+                            'unit_amount': int(order_invoice.amount * 100),\n                         },\n-                        'unit_amount': int(order_invoice.amount * 100),\n-                    },\n-                    'quantity': 1,\n-                }],\n+                        'quantity': 1,\n+                    }\n+                ],\n                 mode='payment',\n                 success_url=f\"{frontend_url}/orders/{order_invoice.identifier}/view\",\n                 cancel_url=f\"{frontend_url}/orders/{order_invoice.identifier}/view\",\n", "issue": "Prefill customer_email in stripe checkout page\nSelf explainable.\r\n\r\nParent issue: #8146 \n", "before_files": [{"content": "import json\n\nimport omise\nimport paypalrestsdk\nimport requests\nimport stripe\nfrom forex_python.converter import CurrencyRates\n\nfrom app.api.helpers import checksum\nfrom app.api.helpers.cache import cache\nfrom app.api.helpers.db import safe_query, save_to_db\nfrom app.api.helpers.errors import ConflictError, ForbiddenError\nfrom app.api.helpers.utilities import represents_int, round_money\nfrom app.models.order import Order\nfrom app.models.stripe_authorization import StripeAuthorization\nfrom app.settings import Environment, get_settings\n\n\n@cache.memoize(5)\ndef forex(from_currency, to_currency, amount):\n    try:\n        currency_rates = CurrencyRates()\n        return currency_rates.convert(from_currency, to_currency, amount)\n    except:\n        return amount\n\n\nclass StripePaymentsManager:\n    \"\"\"\n    Class to manage payments through Stripe.\n    \"\"\"\n\n    @staticmethod\n    def get_credentials(event=None):\n        \"\"\"\n        If the event parameter is None, It returns the secret and publishable key of the Admin's Stripe account.\n        Else, it returns the corresponding values for the event organizer's account.\n        :param event:\n        :return: Stripe secret and publishable keys.\n        \"\"\"\n        if not event:\n            settings = get_settings()\n            if (\n                settings['app_environment'] == 'development'\n                and settings['stripe_test_secret_key']\n                and settings['stripe_test_publishable_key']\n            ):\n                return {\n                    'SECRET_KEY': settings['stripe_test_secret_key'],\n                    'PUBLISHABLE_KEY': settings[\"stripe_test_publishable_key\"],\n                }\n            if settings['stripe_secret_key'] and settings[\"stripe_publishable_key\"]:\n                return {\n                    'SECRET_KEY': settings['stripe_secret_key'],\n                    'PUBLISHABLE_KEY': settings[\"stripe_publishable_key\"],\n                }\n            return None\n        if represents_int(event):\n            authorization = StripeAuthorization.query.filter_by(event_id=event).first()\n        else:\n            authorization = event.stripe_authorization\n        if authorization:\n            return {\n                'SECRET_KEY': authorization.stripe_secret_key,\n                'PUBLISHABLE_KEY': authorization.stripe_publishable_key,\n            }\n        return None\n\n    @staticmethod\n    def get_event_organizer_credentials_from_stripe(stripe_auth_code):\n        \"\"\"\n        Uses the stripe_auth_code to get the other credentials for the event organizer's stripe account\n        :param stripe_auth_code: stripe authorization code\n        :return: response from stripe\n        \"\"\"\n        credentials = StripePaymentsManager.get_credentials()\n\n        if not credentials:\n            raise ForbiddenError(\n                {'pointer': ''},\n                \"Stripe payment isn't configured properly for the Platform\",\n            )\n\n        data = {\n            'client_secret': credentials['SECRET_KEY'],\n            'code': stripe_auth_code,\n            'grant_type': 'authorization_code',\n        }\n\n        response = requests.post('https://connect.stripe.com/oauth/token', data=data)\n        return json.loads(response.text)\n\n    @staticmethod\n    def capture_payment(order_invoice, currency=None, credentials=None):\n        \"\"\"\n        Capture payments through stripe.\n        :param order_invoice: Order to be charged for\n        :param currency: Currency of the order amount.\n        :param credentials: Stripe credentials.\n        :return: charge/None depending on success/failure.\n        \"\"\"\n        if not credentials:\n            credentials = StripePaymentsManager.get_credentials(order_invoice.event)\n\n        if not credentials:\n            raise ConflictError(\n                {'pointer': ''}, 'Stripe credentials not found for the event.'\n            )\n        stripe.api_key = credentials['SECRET_KEY']\n        if not currency:\n            currency = order_invoice.event.payment_currency\n\n        if not currency or currency == \"\":\n            currency = \"USD\"\n\n        frontend_url = get_settings()['frontend_url']\n\n        try:\n            # payment_method_types = ['card', 'klarna']\n            payment_method_types = ['card']\n            # if currency.lower() == 'eur':\n            #     payment_method_types.append('sepa_debit')\n\n            session = stripe.checkout.Session.create(\n                payment_method_types= payment_method_types,\n                line_items=[{\n                    'price_data': {\n                        'currency': currency.lower(),\n                        'product_data': {\n                            'name': order_invoice.event.name,\n                        },\n                        'unit_amount': int(order_invoice.amount * 100),\n                    },\n                    'quantity': 1,\n                }],\n                mode='payment',\n                success_url=f\"{frontend_url}/orders/{order_invoice.identifier}/view\",\n                cancel_url=f\"{frontend_url}/orders/{order_invoice.identifier}/view\",\n            )\n\n            return session\n\n        except Exception as e:\n            raise ConflictError({'pointer': ''}, str(e))\n\n    @staticmethod\n    def retrieve_session(event_id, stripe_session_id):\n        credentials = StripePaymentsManager.get_credentials(event_id)\n\n        if not credentials:\n            raise ConflictError(\n                {'pointer': ''}, 'Stripe credentials not found for the event.'\n            )\n        stripe.api_key = credentials['SECRET_KEY']\n        session = stripe.checkout.Session.retrieve(stripe_session_id)\n\n        return session\n\n    @staticmethod\n    def retrieve_payment_intent(event_id, payment_intent_id):\n        credentials = StripePaymentsManager.get_credentials(event_id)\n\n        if not credentials:\n            raise ConflictError(\n                {'pointer': ''}, 'Stripe credentials not found for the event.'\n            )\n        stripe.api_key = credentials['SECRET_KEY']\n        payment_intent = stripe.PaymentIntent.retrieve(payment_intent_id)\n\n        return payment_intent\n\n\nclass PayPalPaymentsManager:\n    \"\"\"\n    Class to manage payment through Paypal REST API.\n    \"\"\"\n\n    @staticmethod\n    def configure_paypal():\n        \"\"\"\n        Configure the paypal sdk\n        :return: Credentials\n        \"\"\"\n        settings = get_settings()\n        # Use Sandbox by default.\n        paypal_mode = settings.get(\n            'paypal_mode',\n            'live'\n            if (settings['app_environment'] == Environment.PRODUCTION)\n            else 'sandbox',\n        )\n        paypal_key = None\n        if paypal_mode == 'sandbox':\n            paypal_key = 'paypal_sandbox'\n        elif paypal_mode == 'live':\n            paypal_key = 'paypal'\n\n        if not paypal_key:\n            raise ConflictError(\n                {'pointer': ''}, \"Paypal Mode must be 'live' or 'sandbox'\"\n            )\n\n        paypal_client = settings.get(f'{paypal_key}_client', None)\n        paypal_secret = settings.get(f'{paypal_key}_secret', None)\n\n        if not paypal_client or not paypal_secret:\n            raise ConflictError(\n                {'pointer': ''},\n                \"Payments through Paypal have not been configured on the platform\",\n            )\n        return paypalrestsdk.configure(\n            {\n                \"mode\": paypal_mode,\n                \"client_id\": paypal_client,\n                \"client_secret\": paypal_secret,\n            }\n        )\n\n    @staticmethod\n    def create_payment(order, return_url, cancel_url, payee_email=None):\n        \"\"\"\n        Create payment for an order\n        :param order: Order to create payment for.\n        :param return_url: return url for the payment.\n        :param cancel_url: cancel_url for the payment.\n        :param payee_email: email of the payee. Default to event paypal email if not set\n        :return: request_id or the error message along with an indicator.\n        \"\"\"\n        payee_email = payee_email or order.event.paypal_email\n        if not payee_email:\n            raise ConflictError(\n                {'pointer': ''},\n                \"Payments through Paypal hasn't been configured for the billing\",\n            )\n\n        PayPalPaymentsManager.configure_paypal()\n\n        payment = paypalrestsdk.Payment(\n            {\n                \"intent\": \"sale\",\n                \"payer\": {\"payment_method\": \"paypal\"},\n                \"redirect_urls\": {\"return_url\": return_url, \"cancel_url\": cancel_url},\n                \"transactions\": [\n                    {\n                        \"amount\": {\n                            \"total\": float(round_money(order.amount)),\n                            \"currency\": order.event.payment_currency,\n                        },\n                        \"payee\": {\"email\": payee_email},\n                    }\n                ],\n            }\n        )\n\n        if payment.create():\n            return True, payment.id\n        return False, payment.error\n\n    @staticmethod\n    def verify_payment(payment_id, order):\n        \"\"\"\n        Verify Paypal payment one more time for paying with Paypal in mobile client\n        \"\"\"\n        PayPalPaymentsManager.configure_paypal()\n        try:\n            payment_server = paypalrestsdk.Payment.find(payment_id)\n            if payment_server.state != 'approved':\n                return (\n                    False,\n                    'Payment has not been approved yet. Status is '\n                    + payment_server.state\n                    + '.',\n                )\n\n            # Get the most recent transaction\n            transaction = payment_server.transactions[0]\n            amount_server = transaction.amount.total\n            currency_server = transaction.amount.currency\n            sale_state = transaction.related_resources[0].sale.state\n\n            if float(amount_server) != order.amount:\n                return False, 'Payment amount does not match order'\n            if currency_server != order.event.payment_currency:\n                return False, 'Payment currency does not match order'\n            if sale_state != 'completed':\n                return False, 'Sale not completed'\n            if PayPalPaymentsManager.used_payment(payment_id, order):\n                return False, 'Payment already been verified'\n            return True, None\n        except paypalrestsdk.ResourceNotFound:\n            return False, 'Payment Not Found'\n\n    @staticmethod\n    def used_payment(payment_id, order):\n        \"\"\"\n        Function to check for recycling of payment IDs\n        \"\"\"\n        if Order.query.filter(Order.paypal_token == payment_id).first() is None:\n            order.paypal_token = payment_id\n            save_to_db(order)\n            return False\n        return True\n\n    @staticmethod\n    def execute_payment(paypal_payer_id, paypal_payment_id):\n        \"\"\"\n        Execute payemnt and charge the user.\n        :param paypal_payment_id: payment_id\n        :param paypal_payer_id: payer_id\n        :return: Result of the transaction.\n        \"\"\"\n        PayPalPaymentsManager.configure_paypal()\n        payment = paypalrestsdk.Payment.find(paypal_payment_id)\n\n        if payment.execute({\"payer_id\": paypal_payer_id}):\n            return True, 'Successfully Executed'\n        return False, payment.error\n\n\nclass AliPayPaymentsManager:\n    \"\"\"\n    Class to manage AliPay Payments\n    \"\"\"\n\n    @staticmethod\n    def create_source(amount, currency, redirect_return_uri):\n        stripe.api_key = get_settings()['alipay_publishable_key']\n        response = stripe.Source.create(\n            type='alipay',\n            currency=currency,\n            amount=amount,\n            redirect={'return_url': redirect_return_uri},\n        )\n        return response\n\n    @staticmethod\n    def charge_source(order_identifier):\n        order = safe_query(Order, 'identifier', order_identifier, 'identifier')\n        stripe.api_key = get_settings()['alipay_secret_key']\n        charge = stripe.Charge.create(\n            amount=int(order.amount),\n            currency=order.event.payment_currency,\n            source=order.order_notes,\n        )\n        return charge\n\n\nclass OmisePaymentsManager:\n    \"\"\"\n    Class to manage Omise Payments\n    \"\"\"\n\n    @staticmethod\n    def charge_payment(order_identifier, token):\n        if get_settings()['app_environment'] == Environment.PRODUCTION:\n            omise.api_secret = get_settings()['omise_test_secret']\n            omise.api_public = get_settings()['omise_test_public']\n        else:\n            omise.api_secret = get_settings()['omise_test_secret']\n            omise.api_public = get_settings()['omise_test_public']\n        order = safe_query(Order, 'identifier', order_identifier, 'identifier')\n        charge = omise.Charge.create(\n            amount=int(round(order.amount)),\n            currency=order.event.payment_currency,\n            card=token,\n            metadata={\"order_id\": str(order_identifier), \"status\": True},\n        )\n        return charge\n\n\nclass PaytmPaymentsManager:\n    \"\"\"\n    Class to manage PayTM payments\n    \"\"\"\n\n    @property\n    def paytm_endpoint(self):\n        if get_settings()['paytm_mode'] == 'test':\n            url = \"https://securegw-stage.paytm.in/theia/api/v1/\"\n        else:\n            url = \"https://securegw.paytm.in/theia/api/v1/\"\n        return url\n\n    @staticmethod\n    def generate_checksum(paytm_params):\n        if get_settings()['paytm_mode'] == 'test':\n            merchant_key = get_settings()['paytm_sandbox_secret']\n        else:\n            merchant_key = get_settings()['paytm_live_secret']\n        return checksum.generate_checksum_by_str(\n            json.dumps(paytm_params[\"body\"]), merchant_key\n        )\n\n    @staticmethod\n    def hit_paytm_endpoint(url, head, body=None):\n        paytm_params = {}\n        paytm_params[\"body\"] = body\n        paytm_params[\"head\"] = head\n        post_data = json.dumps(paytm_params)\n        response = requests.post(\n            url, data=post_data, headers={\"Content-type\": \"application/json\"}\n        ).json()\n        return response\n", "path": "app/api/helpers/payment.py"}], "after_files": [{"content": "import json\n\nimport omise\nimport paypalrestsdk\nimport requests\nimport stripe\nfrom forex_python.converter import CurrencyRates\n\nfrom app.api.helpers import checksum\nfrom app.api.helpers.cache import cache\nfrom app.api.helpers.db import safe_query, save_to_db\nfrom app.api.helpers.errors import ConflictError, ForbiddenError\nfrom app.api.helpers.utilities import represents_int, round_money\nfrom app.models.order import Order\nfrom app.models.stripe_authorization import StripeAuthorization\nfrom app.settings import Environment, get_settings\n\n\n@cache.memoize(5)\ndef forex(from_currency, to_currency, amount):\n    try:\n        currency_rates = CurrencyRates()\n        return currency_rates.convert(from_currency, to_currency, amount)\n    except:\n        return amount\n\n\nclass StripePaymentsManager:\n    \"\"\"\n    Class to manage payments through Stripe.\n    \"\"\"\n\n    @staticmethod\n    def get_credentials(event=None):\n        \"\"\"\n        If the event parameter is None, It returns the secret and publishable key of the Admin's Stripe account.\n        Else, it returns the corresponding values for the event organizer's account.\n        :param event:\n        :return: Stripe secret and publishable keys.\n        \"\"\"\n        if not event:\n            settings = get_settings()\n            if (\n                settings['app_environment'] == 'development'\n                and settings['stripe_test_secret_key']\n                and settings['stripe_test_publishable_key']\n            ):\n                return {\n                    'SECRET_KEY': settings['stripe_test_secret_key'],\n                    'PUBLISHABLE_KEY': settings[\"stripe_test_publishable_key\"],\n                }\n            if settings['stripe_secret_key'] and settings[\"stripe_publishable_key\"]:\n                return {\n                    'SECRET_KEY': settings['stripe_secret_key'],\n                    'PUBLISHABLE_KEY': settings[\"stripe_publishable_key\"],\n                }\n            return None\n        if represents_int(event):\n            authorization = StripeAuthorization.query.filter_by(event_id=event).first()\n        else:\n            authorization = event.stripe_authorization\n        if authorization:\n            return {\n                'SECRET_KEY': authorization.stripe_secret_key,\n                'PUBLISHABLE_KEY': authorization.stripe_publishable_key,\n            }\n        return None\n\n    @staticmethod\n    def get_event_organizer_credentials_from_stripe(stripe_auth_code):\n        \"\"\"\n        Uses the stripe_auth_code to get the other credentials for the event organizer's stripe account\n        :param stripe_auth_code: stripe authorization code\n        :return: response from stripe\n        \"\"\"\n        credentials = StripePaymentsManager.get_credentials()\n\n        if not credentials:\n            raise ForbiddenError(\n                {'pointer': ''},\n                \"Stripe payment isn't configured properly for the Platform\",\n            )\n\n        data = {\n            'client_secret': credentials['SECRET_KEY'],\n            'code': stripe_auth_code,\n            'grant_type': 'authorization_code',\n        }\n\n        response = requests.post('https://connect.stripe.com/oauth/token', data=data)\n        return json.loads(response.text)\n\n    @staticmethod\n    def capture_payment(order_invoice, currency=None, credentials=None):\n        \"\"\"\n        Capture payments through stripe.\n        :param order_invoice: Order to be charged for\n        :param currency: Currency of the order amount.\n        :param credentials: Stripe credentials.\n        :return: charge/None depending on success/failure.\n        \"\"\"\n        if not credentials:\n            credentials = StripePaymentsManager.get_credentials(order_invoice.event)\n\n        if not credentials:\n            raise ConflictError(\n                {'pointer': ''}, 'Stripe credentials not found for the event.'\n            )\n        stripe.api_key = credentials['SECRET_KEY']\n        if not currency:\n            currency = order_invoice.event.payment_currency\n\n        if not currency or currency == \"\":\n            currency = \"USD\"\n\n        frontend_url = get_settings()['frontend_url']\n\n        try:\n            # payment_method_types = ['card', 'klarna']\n            payment_method_types = ['card']\n            # if currency.lower() == 'eur':\n            #     payment_method_types.append('sepa_debit')\n\n            session = stripe.checkout.Session.create(\n                customer_email=order_invoice.user.email,\n                payment_method_types=payment_method_types,\n                line_items=[\n                    {\n                        'price_data': {\n                            'currency': currency.lower(),\n                            'product_data': {\n                                'name': order_invoice.event.name,\n                            },\n                            'unit_amount': int(order_invoice.amount * 100),\n                        },\n                        'quantity': 1,\n                    }\n                ],\n                mode='payment',\n                success_url=f\"{frontend_url}/orders/{order_invoice.identifier}/view\",\n                cancel_url=f\"{frontend_url}/orders/{order_invoice.identifier}/view\",\n            )\n\n            return session\n\n        except Exception as e:\n            raise ConflictError({'pointer': ''}, str(e))\n\n    @staticmethod\n    def retrieve_session(event_id, stripe_session_id):\n        credentials = StripePaymentsManager.get_credentials(event_id)\n\n        if not credentials:\n            raise ConflictError(\n                {'pointer': ''}, 'Stripe credentials not found for the event.'\n            )\n        stripe.api_key = credentials['SECRET_KEY']\n        session = stripe.checkout.Session.retrieve(stripe_session_id)\n\n        return session\n\n    @staticmethod\n    def retrieve_payment_intent(event_id, payment_intent_id):\n        credentials = StripePaymentsManager.get_credentials(event_id)\n\n        if not credentials:\n            raise ConflictError(\n                {'pointer': ''}, 'Stripe credentials not found for the event.'\n            )\n        stripe.api_key = credentials['SECRET_KEY']\n        payment_intent = stripe.PaymentIntent.retrieve(payment_intent_id)\n\n        return payment_intent\n\n\nclass PayPalPaymentsManager:\n    \"\"\"\n    Class to manage payment through Paypal REST API.\n    \"\"\"\n\n    @staticmethod\n    def configure_paypal():\n        \"\"\"\n        Configure the paypal sdk\n        :return: Credentials\n        \"\"\"\n        settings = get_settings()\n        # Use Sandbox by default.\n        paypal_mode = settings.get(\n            'paypal_mode',\n            'live'\n            if (settings['app_environment'] == Environment.PRODUCTION)\n            else 'sandbox',\n        )\n        paypal_key = None\n        if paypal_mode == 'sandbox':\n            paypal_key = 'paypal_sandbox'\n        elif paypal_mode == 'live':\n            paypal_key = 'paypal'\n\n        if not paypal_key:\n            raise ConflictError(\n                {'pointer': ''}, \"Paypal Mode must be 'live' or 'sandbox'\"\n            )\n\n        paypal_client = settings.get(f'{paypal_key}_client', None)\n        paypal_secret = settings.get(f'{paypal_key}_secret', None)\n\n        if not paypal_client or not paypal_secret:\n            raise ConflictError(\n                {'pointer': ''},\n                \"Payments through Paypal have not been configured on the platform\",\n            )\n        return paypalrestsdk.configure(\n            {\n                \"mode\": paypal_mode,\n                \"client_id\": paypal_client,\n                \"client_secret\": paypal_secret,\n            }\n        )\n\n    @staticmethod\n    def create_payment(order, return_url, cancel_url, payee_email=None):\n        \"\"\"\n        Create payment for an order\n        :param order: Order to create payment for.\n        :param return_url: return url for the payment.\n        :param cancel_url: cancel_url for the payment.\n        :param payee_email: email of the payee. Default to event paypal email if not set\n        :return: request_id or the error message along with an indicator.\n        \"\"\"\n        payee_email = payee_email or order.event.paypal_email\n        if not payee_email:\n            raise ConflictError(\n                {'pointer': ''},\n                \"Payments through Paypal hasn't been configured for the billing\",\n            )\n\n        PayPalPaymentsManager.configure_paypal()\n\n        payment = paypalrestsdk.Payment(\n            {\n                \"intent\": \"sale\",\n                \"payer\": {\"payment_method\": \"paypal\"},\n                \"redirect_urls\": {\"return_url\": return_url, \"cancel_url\": cancel_url},\n                \"transactions\": [\n                    {\n                        \"amount\": {\n                            \"total\": float(round_money(order.amount)),\n                            \"currency\": order.event.payment_currency,\n                        },\n                        \"payee\": {\"email\": payee_email},\n                    }\n                ],\n            }\n        )\n\n        if payment.create():\n            return True, payment.id\n        return False, payment.error\n\n    @staticmethod\n    def verify_payment(payment_id, order):\n        \"\"\"\n        Verify Paypal payment one more time for paying with Paypal in mobile client\n        \"\"\"\n        PayPalPaymentsManager.configure_paypal()\n        try:\n            payment_server = paypalrestsdk.Payment.find(payment_id)\n            if payment_server.state != 'approved':\n                return (\n                    False,\n                    'Payment has not been approved yet. Status is '\n                    + payment_server.state\n                    + '.',\n                )\n\n            # Get the most recent transaction\n            transaction = payment_server.transactions[0]\n            amount_server = transaction.amount.total\n            currency_server = transaction.amount.currency\n            sale_state = transaction.related_resources[0].sale.state\n\n            if float(amount_server) != order.amount:\n                return False, 'Payment amount does not match order'\n            if currency_server != order.event.payment_currency:\n                return False, 'Payment currency does not match order'\n            if sale_state != 'completed':\n                return False, 'Sale not completed'\n            if PayPalPaymentsManager.used_payment(payment_id, order):\n                return False, 'Payment already been verified'\n            return True, None\n        except paypalrestsdk.ResourceNotFound:\n            return False, 'Payment Not Found'\n\n    @staticmethod\n    def used_payment(payment_id, order):\n        \"\"\"\n        Function to check for recycling of payment IDs\n        \"\"\"\n        if Order.query.filter(Order.paypal_token == payment_id).first() is None:\n            order.paypal_token = payment_id\n            save_to_db(order)\n            return False\n        return True\n\n    @staticmethod\n    def execute_payment(paypal_payer_id, paypal_payment_id):\n        \"\"\"\n        Execute payemnt and charge the user.\n        :param paypal_payment_id: payment_id\n        :param paypal_payer_id: payer_id\n        :return: Result of the transaction.\n        \"\"\"\n        PayPalPaymentsManager.configure_paypal()\n        payment = paypalrestsdk.Payment.find(paypal_payment_id)\n\n        if payment.execute({\"payer_id\": paypal_payer_id}):\n            return True, 'Successfully Executed'\n        return False, payment.error\n\n\nclass AliPayPaymentsManager:\n    \"\"\"\n    Class to manage AliPay Payments\n    \"\"\"\n\n    @staticmethod\n    def create_source(amount, currency, redirect_return_uri):\n        stripe.api_key = get_settings()['alipay_publishable_key']\n        response = stripe.Source.create(\n            type='alipay',\n            currency=currency,\n            amount=amount,\n            redirect={'return_url': redirect_return_uri},\n        )\n        return response\n\n    @staticmethod\n    def charge_source(order_identifier):\n        order = safe_query(Order, 'identifier', order_identifier, 'identifier')\n        stripe.api_key = get_settings()['alipay_secret_key']\n        charge = stripe.Charge.create(\n            amount=int(order.amount),\n            currency=order.event.payment_currency,\n            source=order.order_notes,\n        )\n        return charge\n\n\nclass OmisePaymentsManager:\n    \"\"\"\n    Class to manage Omise Payments\n    \"\"\"\n\n    @staticmethod\n    def charge_payment(order_identifier, token):\n        if get_settings()['app_environment'] == Environment.PRODUCTION:\n            omise.api_secret = get_settings()['omise_test_secret']\n            omise.api_public = get_settings()['omise_test_public']\n        else:\n            omise.api_secret = get_settings()['omise_test_secret']\n            omise.api_public = get_settings()['omise_test_public']\n        order = safe_query(Order, 'identifier', order_identifier, 'identifier')\n        charge = omise.Charge.create(\n            amount=int(round(order.amount)),\n            currency=order.event.payment_currency,\n            card=token,\n            metadata={\"order_id\": str(order_identifier), \"status\": True},\n        )\n        return charge\n\n\nclass PaytmPaymentsManager:\n    \"\"\"\n    Class to manage PayTM payments\n    \"\"\"\n\n    @property\n    def paytm_endpoint(self):\n        if get_settings()['paytm_mode'] == 'test':\n            url = \"https://securegw-stage.paytm.in/theia/api/v1/\"\n        else:\n            url = \"https://securegw.paytm.in/theia/api/v1/\"\n        return url\n\n    @staticmethod\n    def generate_checksum(paytm_params):\n        if get_settings()['paytm_mode'] == 'test':\n            merchant_key = get_settings()['paytm_sandbox_secret']\n        else:\n            merchant_key = get_settings()['paytm_live_secret']\n        return checksum.generate_checksum_by_str(\n            json.dumps(paytm_params[\"body\"]), merchant_key\n        )\n\n    @staticmethod\n    def hit_paytm_endpoint(url, head, body=None):\n        paytm_params = {}\n        paytm_params[\"body\"] = body\n        paytm_params[\"head\"] = head\n        post_data = json.dumps(paytm_params)\n        response = requests.post(\n            url, data=post_data, headers={\"Content-type\": \"application/json\"}\n        ).json()\n        return response\n", "path": "app/api/helpers/payment.py"}]}