We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Paypal email is not verified. Although I verified it.
I see you added Paypal as a payment option which is great. However when I add my paypal email - which is different from liberapay email - it still says it is not verified although I received an email and clicked "verify". Is this a bug?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `liberapay/payin/paypal.py`
Content:
```
1 from __future__ import absolute_import, division, print_function, unicode_literals
2 
3 import logging
4 
5 import requests
6 
7 from ..exceptions import PaymentError
8 from ..utils.currencies import Money
9 from ..website import website
10 from .common import update_payin, update_payin_transfer
11 
12 
13 PAYMENT_STATES_MAP = {
14     'approved': 'succeeded',
15     'created': 'pending',
16     'failed': 'failed',
17 }
18 SALE_STATES_MAP = {
19     'completed': 'succeeded',
20     'denied': 'failed',
21     'pending': 'pending',
22 }
23 
24 logger = logging.Logger('paypal')
25 
26 session = requests.Session()
27 
28 
29 def _init_session():
30     # TODO switch to bearer tokens to reduce the risk of exposing the long-lived secret
31     if 'Authentication' in session.headers:
32         return session
33     from base64 import b64encode
34     session.headers.update({
35         'Authorization': 'Basic ' + b64encode((
36             '%s:%s' % (website.app_conf.paypal_id, website.app_conf.paypal_secret)
37         ).encode('ascii')).decode('ascii'),
38     })
39     return session
40 
41 
42 def create_payment(db, payin, payer, return_url, state):
43     """Create a Payment.
44 
45     Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_create
46 
47     Note: even though the API expects a list of transactions it rejects the
48     request if the list contains more than one transaction.
49     """
50     transfers = db.all("""
51         SELECT pt.*
52              , recipient.username AS recipient_username
53              , team.username AS team_name
54              , a.id AS merchant_id
55           FROM payin_transfers pt
56           JOIN participants recipient ON recipient.id = pt.recipient
57      LEFT JOIN participants team ON team.id = pt.team
58           JOIN payment_accounts a ON a.pk = pt.destination
59          WHERE pt.payin = %s
60       ORDER BY pt.id
61     """, (payin.id,))
62     assert transfers
63     locale, _ = state['locale'], state['_']
64     data = {
65         "intent": "sale",
66         "application_context": {
67             "brand_name": "Liberapay",
68             "locale": locale.language,
69             "landing_page": "Login",
70             "shipping_preference": "NO_SHIPPING",
71             "user_action": "commit",
72         },
73         "payer": {
74             "payment_method": "paypal"
75         },
76         "transactions": [{
77             "amount": {
78                 "total": str(pt.amount.amount),
79                 "currency": pt.amount.currency
80             },
81             "description": (
82                 _("donation to {0} for their role in the {1} team",
83                   pt.recipient_username, pt.team_name)
84                 if pt.team_name else
85                 _("donation to {0}", pt.recipient_username)
86             ),
87             "invoice_number": str(pt.id),
88             "note_to_payee": (
89                 "donation via Liberapay for your role in the %s team" % pt.team_name
90                 if pt.team_name else
91                 "donation via Liberapay"
92             ),
93             "payee": {
94                 "email": pt.merchant_id,
95             },
96             "payment_options": {
97                 "allowed_payment_method": "UNRESTRICTED"
98             },
99             "soft_descriptor": "Liberapay",
100             "item_list": {
101                 "items": [{
102                     "name":
103                         _("One week of the donation") if pt.period == 'weekly' else
104                         _("One month of the donation") if pt.period == 'monthly' else
105                         _("One year of the donation"),
106                     "quantity": pt.n_units,
107                     "price": str(pt.unit_amount.amount),
108                     "currency": pt.unit_amount.currency
109                 }]
110             }
111         } for pt in transfers],
112         "redirect_urls": {
113             "return_url": return_url,
114             "cancel_url": return_url
115         }
116     }
117     url = 'https://api.%s/v1/payments/payment' % website.app_conf.paypal_domain
118     headers = {
119         'PayPal-Request-Id': 'payin_%i' % payin.id
120     }
121     response = _init_session().post(url, json=data, headers=headers)
122     if response.status_code != 201:
123         error = response.text  # for Sentry
124         logger.debug(error)
125         raise PaymentError('PayPal', error)
126     payment = response.json()
127     status = PAYMENT_STATES_MAP[payment['state']]
128     error = payment.get('failure_reason')
129     payin = update_payin(db, payin.id, payment['id'], status, error)
130     if payin.status == 'pending':
131         redirect_url = [l['href'] for l in payment['links'] if l['rel'] == 'approval_url'][0]
132         raise state['response'].redirect(redirect_url)
133     return payin
134 
135 
136 def execute_payment(db, payin, payer_id):
137     """Execute a previously approved payment.
138 
139     Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_execute
140     """
141     url = 'https://api.%s/v1/payments/payment/%s/execute' % (
142         website.app_conf.paypal_domain, payin.remote_id
143     )
144     headers = {'PayPal-Request-Id': 'payin_execute_%i' % payin.id}
145     data = {"payer_id": payer_id}
146     response = _init_session().post(url, json=data, headers=headers)
147     if response.status_code != 200:
148         error = response.text  # for Sentry
149         logger.debug(error)
150         raise PaymentError('PayPal')
151     payment = response.json()
152 
153     # Update the payin
154     status = PAYMENT_STATES_MAP[payment['state']]
155     error = payment.get('failure_reason')
156     payin = update_payin(db, payin.id, payment['id'], status, error)
157 
158     # Update the payin transfers
159     for tr in payment['transactions']:
160         sale = tr.get('related_resources', [{}])[0].get('sale')
161         if sale:
162             pt_id = tr['invoice_number']
163             pt_remote_id = sale['id']
164             pt_status = SALE_STATES_MAP[sale['state']]
165             pt_error = sale.get('reason_code')
166             pt_fee = Money(sale['transaction_fee']['value'], sale['transaction_fee']['currency'])
167             charge_amount = Money(sale['amount']['total'], sale['amount']['currency'])
168             net_amount = charge_amount - pt_fee
169             update_payin_transfer(
170                 db, pt_id, pt_remote_id, pt_status, pt_error,
171                 amount=net_amount, fee=pt_fee
172             )
173 
174     return payin
175 
176 
177 def sync_payment(db, payin):
178     """Fetch the payment's data and update our database.
179 
180     Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_get
181     """
182     url = 'https://api.%s/v1/payments/payment/%s' % (
183         website.app_conf.paypal_domain, payin.remote_id
184     )
185     response = _init_session().get(url)
186     if response.status_code != 200:
187         error = response.text  # for Sentry
188         logger.debug(error)
189         raise PaymentError('PayPal')
190     payment = response.json()
191     status = PAYMENT_STATES_MAP[payment['state']]
192     error = payment.get('failure_reason')
193     return update_payin(db, payin.id, payment['id'], status, error)
194
```
--- 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/liberapay/payin/paypal.py b/liberapay/payin/paypal.py
--- a/liberapay/payin/paypal.py
+++ b/liberapay/payin/paypal.py
@@ -107,7 +107,7 @@
                     "price": str(pt.unit_amount.amount),
                     "currency": pt.unit_amount.currency
                 }]
-            }
+            } if pt.n_units >= 1 else {}
         } for pt in transfers],
         "redirect_urls": {
             "return_url": return_url,
@@ -163,9 +163,11 @@
             pt_remote_id = sale['id']
             pt_status = SALE_STATES_MAP[sale['state']]
             pt_error = sale.get('reason_code')
-            pt_fee = Money(sale['transaction_fee']['value'], sale['transaction_fee']['currency'])
+            pt_fee = sale.get('transaction_fee')
+            if pt_fee:
+                pt_fee = Money(pt_fee['value'], pt_fee['currency'])
             charge_amount = Money(sale['amount']['total'], sale['amount']['currency'])
-            net_amount = charge_amount - pt_fee
+            net_amount = charge_amount - (pt_fee or 0)
             update_payin_transfer(
                 db, pt_id, pt_remote_id, pt_status, pt_error,
                 amount=net_amount, fee=pt_fee

{"golden_diff": "diff --git a/liberapay/payin/paypal.py b/liberapay/payin/paypal.py\n--- a/liberapay/payin/paypal.py\n+++ b/liberapay/payin/paypal.py\n@@ -107,7 +107,7 @@\n                     \"price\": str(pt.unit_amount.amount),\n                     \"currency\": pt.unit_amount.currency\n                 }]\n-            }\n+            } if pt.n_units >= 1 else {}\n         } for pt in transfers],\n         \"redirect_urls\": {\n             \"return_url\": return_url,\n@@ -163,9 +163,11 @@\n             pt_remote_id = sale['id']\n             pt_status = SALE_STATES_MAP[sale['state']]\n             pt_error = sale.get('reason_code')\n-            pt_fee = Money(sale['transaction_fee']['value'], sale['transaction_fee']['currency'])\n+            pt_fee = sale.get('transaction_fee')\n+            if pt_fee:\n+                pt_fee = Money(pt_fee['value'], pt_fee['currency'])\n             charge_amount = Money(sale['amount']['total'], sale['amount']['currency'])\n-            net_amount = charge_amount - pt_fee\n+            net_amount = charge_amount - (pt_fee or 0)\n             update_payin_transfer(\n                 db, pt_id, pt_remote_id, pt_status, pt_error,\n                 amount=net_amount, fee=pt_fee\n", "issue": "Paypal email is not verified. Although I verified it.\nI see you added Paypal as a payment option which is great. However when I add my paypal email - which is different from liberapay email - it still says it is not verified although I received an email and clicked \"verify\". Is this a bug?\n", "before_files": [{"content": "from __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\n\nimport requests\n\nfrom ..exceptions import PaymentError\nfrom ..utils.currencies import Money\nfrom ..website import website\nfrom .common import update_payin, update_payin_transfer\n\n\nPAYMENT_STATES_MAP = {\n    'approved': 'succeeded',\n    'created': 'pending',\n    'failed': 'failed',\n}\nSALE_STATES_MAP = {\n    'completed': 'succeeded',\n    'denied': 'failed',\n    'pending': 'pending',\n}\n\nlogger = logging.Logger('paypal')\n\nsession = requests.Session()\n\n\ndef _init_session():\n    # TODO switch to bearer tokens to reduce the risk of exposing the long-lived secret\n    if 'Authentication' in session.headers:\n        return session\n    from base64 import b64encode\n    session.headers.update({\n        'Authorization': 'Basic ' + b64encode((\n            '%s:%s' % (website.app_conf.paypal_id, website.app_conf.paypal_secret)\n        ).encode('ascii')).decode('ascii'),\n    })\n    return session\n\n\ndef create_payment(db, payin, payer, return_url, state):\n    \"\"\"Create a Payment.\n\n    Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_create\n\n    Note: even though the API expects a list of transactions it rejects the\n    request if the list contains more than one transaction.\n    \"\"\"\n    transfers = db.all(\"\"\"\n        SELECT pt.*\n             , recipient.username AS recipient_username\n             , team.username AS team_name\n             , a.id AS merchant_id\n          FROM payin_transfers pt\n          JOIN participants recipient ON recipient.id = pt.recipient\n     LEFT JOIN participants team ON team.id = pt.team\n          JOIN payment_accounts a ON a.pk = pt.destination\n         WHERE pt.payin = %s\n      ORDER BY pt.id\n    \"\"\", (payin.id,))\n    assert transfers\n    locale, _ = state['locale'], state['_']\n    data = {\n        \"intent\": \"sale\",\n        \"application_context\": {\n            \"brand_name\": \"Liberapay\",\n            \"locale\": locale.language,\n            \"landing_page\": \"Login\",\n            \"shipping_preference\": \"NO_SHIPPING\",\n            \"user_action\": \"commit\",\n        },\n        \"payer\": {\n            \"payment_method\": \"paypal\"\n        },\n        \"transactions\": [{\n            \"amount\": {\n                \"total\": str(pt.amount.amount),\n                \"currency\": pt.amount.currency\n            },\n            \"description\": (\n                _(\"donation to {0} for their role in the {1} team\",\n                  pt.recipient_username, pt.team_name)\n                if pt.team_name else\n                _(\"donation to {0}\", pt.recipient_username)\n            ),\n            \"invoice_number\": str(pt.id),\n            \"note_to_payee\": (\n                \"donation via Liberapay for your role in the %s team\" % pt.team_name\n                if pt.team_name else\n                \"donation via Liberapay\"\n            ),\n            \"payee\": {\n                \"email\": pt.merchant_id,\n            },\n            \"payment_options\": {\n                \"allowed_payment_method\": \"UNRESTRICTED\"\n            },\n            \"soft_descriptor\": \"Liberapay\",\n            \"item_list\": {\n                \"items\": [{\n                    \"name\":\n                        _(\"One week of the donation\") if pt.period == 'weekly' else\n                        _(\"One month of the donation\") if pt.period == 'monthly' else\n                        _(\"One year of the donation\"),\n                    \"quantity\": pt.n_units,\n                    \"price\": str(pt.unit_amount.amount),\n                    \"currency\": pt.unit_amount.currency\n                }]\n            }\n        } for pt in transfers],\n        \"redirect_urls\": {\n            \"return_url\": return_url,\n            \"cancel_url\": return_url\n        }\n    }\n    url = 'https://api.%s/v1/payments/payment' % website.app_conf.paypal_domain\n    headers = {\n        'PayPal-Request-Id': 'payin_%i' % payin.id\n    }\n    response = _init_session().post(url, json=data, headers=headers)\n    if response.status_code != 201:\n        error = response.text  # for Sentry\n        logger.debug(error)\n        raise PaymentError('PayPal', error)\n    payment = response.json()\n    status = PAYMENT_STATES_MAP[payment['state']]\n    error = payment.get('failure_reason')\n    payin = update_payin(db, payin.id, payment['id'], status, error)\n    if payin.status == 'pending':\n        redirect_url = [l['href'] for l in payment['links'] if l['rel'] == 'approval_url'][0]\n        raise state['response'].redirect(redirect_url)\n    return payin\n\n\ndef execute_payment(db, payin, payer_id):\n    \"\"\"Execute a previously approved payment.\n\n    Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_execute\n    \"\"\"\n    url = 'https://api.%s/v1/payments/payment/%s/execute' % (\n        website.app_conf.paypal_domain, payin.remote_id\n    )\n    headers = {'PayPal-Request-Id': 'payin_execute_%i' % payin.id}\n    data = {\"payer_id\": payer_id}\n    response = _init_session().post(url, json=data, headers=headers)\n    if response.status_code != 200:\n        error = response.text  # for Sentry\n        logger.debug(error)\n        raise PaymentError('PayPal')\n    payment = response.json()\n\n    # Update the payin\n    status = PAYMENT_STATES_MAP[payment['state']]\n    error = payment.get('failure_reason')\n    payin = update_payin(db, payin.id, payment['id'], status, error)\n\n    # Update the payin transfers\n    for tr in payment['transactions']:\n        sale = tr.get('related_resources', [{}])[0].get('sale')\n        if sale:\n            pt_id = tr['invoice_number']\n            pt_remote_id = sale['id']\n            pt_status = SALE_STATES_MAP[sale['state']]\n            pt_error = sale.get('reason_code')\n            pt_fee = Money(sale['transaction_fee']['value'], sale['transaction_fee']['currency'])\n            charge_amount = Money(sale['amount']['total'], sale['amount']['currency'])\n            net_amount = charge_amount - pt_fee\n            update_payin_transfer(\n                db, pt_id, pt_remote_id, pt_status, pt_error,\n                amount=net_amount, fee=pt_fee\n            )\n\n    return payin\n\n\ndef sync_payment(db, payin):\n    \"\"\"Fetch the payment's data and update our database.\n\n    Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_get\n    \"\"\"\n    url = 'https://api.%s/v1/payments/payment/%s' % (\n        website.app_conf.paypal_domain, payin.remote_id\n    )\n    response = _init_session().get(url)\n    if response.status_code != 200:\n        error = response.text  # for Sentry\n        logger.debug(error)\n        raise PaymentError('PayPal')\n    payment = response.json()\n    status = PAYMENT_STATES_MAP[payment['state']]\n    error = payment.get('failure_reason')\n    return update_payin(db, payin.id, payment['id'], status, error)\n", "path": "liberapay/payin/paypal.py"}], "after_files": [{"content": "from __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\n\nimport requests\n\nfrom ..exceptions import PaymentError\nfrom ..utils.currencies import Money\nfrom ..website import website\nfrom .common import update_payin, update_payin_transfer\n\n\nPAYMENT_STATES_MAP = {\n    'approved': 'succeeded',\n    'created': 'pending',\n    'failed': 'failed',\n}\nSALE_STATES_MAP = {\n    'completed': 'succeeded',\n    'denied': 'failed',\n    'pending': 'pending',\n}\n\nlogger = logging.Logger('paypal')\n\nsession = requests.Session()\n\n\ndef _init_session():\n    # TODO switch to bearer tokens to reduce the risk of exposing the long-lived secret\n    if 'Authentication' in session.headers:\n        return session\n    from base64 import b64encode\n    session.headers.update({\n        'Authorization': 'Basic ' + b64encode((\n            '%s:%s' % (website.app_conf.paypal_id, website.app_conf.paypal_secret)\n        ).encode('ascii')).decode('ascii'),\n    })\n    return session\n\n\ndef create_payment(db, payin, payer, return_url, state):\n    \"\"\"Create a Payment.\n\n    Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_create\n\n    Note: even though the API expects a list of transactions it rejects the\n    request if the list contains more than one transaction.\n    \"\"\"\n    transfers = db.all(\"\"\"\n        SELECT pt.*\n             , recipient.username AS recipient_username\n             , team.username AS team_name\n             , a.id AS merchant_id\n          FROM payin_transfers pt\n          JOIN participants recipient ON recipient.id = pt.recipient\n     LEFT JOIN participants team ON team.id = pt.team\n          JOIN payment_accounts a ON a.pk = pt.destination\n         WHERE pt.payin = %s\n      ORDER BY pt.id\n    \"\"\", (payin.id,))\n    assert transfers\n    locale, _ = state['locale'], state['_']\n    data = {\n        \"intent\": \"sale\",\n        \"application_context\": {\n            \"brand_name\": \"Liberapay\",\n            \"locale\": locale.language,\n            \"landing_page\": \"Login\",\n            \"shipping_preference\": \"NO_SHIPPING\",\n            \"user_action\": \"commit\",\n        },\n        \"payer\": {\n            \"payment_method\": \"paypal\"\n        },\n        \"transactions\": [{\n            \"amount\": {\n                \"total\": str(pt.amount.amount),\n                \"currency\": pt.amount.currency\n            },\n            \"description\": (\n                _(\"donation to {0} for their role in the {1} team\",\n                  pt.recipient_username, pt.team_name)\n                if pt.team_name else\n                _(\"donation to {0}\", pt.recipient_username)\n            ),\n            \"invoice_number\": str(pt.id),\n            \"note_to_payee\": (\n                \"donation via Liberapay for your role in the %s team\" % pt.team_name\n                if pt.team_name else\n                \"donation via Liberapay\"\n            ),\n            \"payee\": {\n                \"email\": pt.merchant_id,\n            },\n            \"payment_options\": {\n                \"allowed_payment_method\": \"UNRESTRICTED\"\n            },\n            \"soft_descriptor\": \"Liberapay\",\n            \"item_list\": {\n                \"items\": [{\n                    \"name\":\n                        _(\"One week of the donation\") if pt.period == 'weekly' else\n                        _(\"One month of the donation\") if pt.period == 'monthly' else\n                        _(\"One year of the donation\"),\n                    \"quantity\": pt.n_units,\n                    \"price\": str(pt.unit_amount.amount),\n                    \"currency\": pt.unit_amount.currency\n                }]\n            } if pt.n_units >= 1 else {}\n        } for pt in transfers],\n        \"redirect_urls\": {\n            \"return_url\": return_url,\n            \"cancel_url\": return_url\n        }\n    }\n    url = 'https://api.%s/v1/payments/payment' % website.app_conf.paypal_domain\n    headers = {\n        'PayPal-Request-Id': 'payin_%i' % payin.id\n    }\n    response = _init_session().post(url, json=data, headers=headers)\n    if response.status_code != 201:\n        error = response.text  # for Sentry\n        logger.debug(error)\n        raise PaymentError('PayPal', error)\n    payment = response.json()\n    status = PAYMENT_STATES_MAP[payment['state']]\n    error = payment.get('failure_reason')\n    payin = update_payin(db, payin.id, payment['id'], status, error)\n    if payin.status == 'pending':\n        redirect_url = [l['href'] for l in payment['links'] if l['rel'] == 'approval_url'][0]\n        raise state['response'].redirect(redirect_url)\n    return payin\n\n\ndef execute_payment(db, payin, payer_id):\n    \"\"\"Execute a previously approved payment.\n\n    Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_execute\n    \"\"\"\n    url = 'https://api.%s/v1/payments/payment/%s/execute' % (\n        website.app_conf.paypal_domain, payin.remote_id\n    )\n    headers = {'PayPal-Request-Id': 'payin_execute_%i' % payin.id}\n    data = {\"payer_id\": payer_id}\n    response = _init_session().post(url, json=data, headers=headers)\n    if response.status_code != 200:\n        error = response.text  # for Sentry\n        logger.debug(error)\n        raise PaymentError('PayPal')\n    payment = response.json()\n\n    # Update the payin\n    status = PAYMENT_STATES_MAP[payment['state']]\n    error = payment.get('failure_reason')\n    payin = update_payin(db, payin.id, payment['id'], status, error)\n\n    # Update the payin transfers\n    for tr in payment['transactions']:\n        sale = tr.get('related_resources', [{}])[0].get('sale')\n        if sale:\n            pt_id = tr['invoice_number']\n            pt_remote_id = sale['id']\n            pt_status = SALE_STATES_MAP[sale['state']]\n            pt_error = sale.get('reason_code')\n            pt_fee = sale.get('transaction_fee')\n            if pt_fee:\n                pt_fee = Money(pt_fee['value'], pt_fee['currency'])\n            charge_amount = Money(sale['amount']['total'], sale['amount']['currency'])\n            net_amount = charge_amount - (pt_fee or 0)\n            update_payin_transfer(\n                db, pt_id, pt_remote_id, pt_status, pt_error,\n                amount=net_amount, fee=pt_fee\n            )\n\n    return payin\n\n\ndef sync_payment(db, payin):\n    \"\"\"Fetch the payment's data and update our database.\n\n    Doc: https://developer.paypal.com/docs/api/payments/v1/#payment_get\n    \"\"\"\n    url = 'https://api.%s/v1/payments/payment/%s' % (\n        website.app_conf.paypal_domain, payin.remote_id\n    )\n    response = _init_session().get(url)\n    if response.status_code != 200:\n        error = response.text  # for Sentry\n        logger.debug(error)\n        raise PaymentError('PayPal')\n    payment = response.json()\n    status = PAYMENT_STATES_MAP[payment['state']]\n    error = payment.get('failure_reason')\n    return update_payin(db, payin.id, payment['id'], status, error)\n", "path": "liberapay/payin/paypal.py"}]}