[17239] | 1 | ## $Id$ |
---|
| 2 | ## |
---|
| 3 | ## Copyright (C) 2022 Uli Fouquet & Henrik Bettermann |
---|
| 4 | ## This program is free software; you can redistribute it and/or modify |
---|
| 5 | ## it under the terms of the GNU General Public License as published by |
---|
| 6 | ## the Free Software Foundation; either version 2 of the License, or |
---|
| 7 | ## (at your option) any later version. |
---|
| 8 | ## |
---|
| 9 | ## This program is distributed in the hope that it will be useful, |
---|
| 10 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 11 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 12 | ## GNU General Public License for more details. |
---|
| 13 | ## |
---|
| 14 | ## You should have received a copy of the GNU General Public License |
---|
| 15 | ## along with this program; if not, write to the Free Software |
---|
| 16 | ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
| 17 | ## |
---|
| 18 | import json |
---|
| 19 | import requests |
---|
| 20 | import uuid |
---|
| 21 | from zope.component import getUtility, queryUtility |
---|
| 22 | from kofacustom.nigeria.paypal.interfaces import IPaypalConfig |
---|
| 23 | |
---|
| 24 | |
---|
| 25 | PAYPAL_REST_URLS = { |
---|
| 26 | 'sandbox': 'https://api-m.sandbox.paypal.com', |
---|
| 27 | 'live': 'https://api-m.paypal.com'} |
---|
| 28 | |
---|
| 29 | |
---|
| 30 | def get_auth_token(): |
---|
| 31 | """Get an authentication token from paypal |
---|
| 32 | |
---|
| 33 | Requests to paypal must provide an authorization token, which can be |
---|
| 34 | retrieved by sending REST credentials (`client_id` and `client_secret`) as |
---|
| 35 | provided in your Paypal developer account. |
---|
| 36 | |
---|
| 37 | During livespan of tokens, this call will not create new ones. |
---|
| 38 | """ |
---|
| 39 | config = getUtility(IPaypalConfig) |
---|
| 40 | url = "%s/v1/oauth2/token" % PAYPAL_REST_URLS[config['mode']] |
---|
| 41 | auth = requests.auth.HTTPBasicAuth( |
---|
| 42 | config['client_id'], config['client_secret']) |
---|
| 43 | headers = {"content-type": "application/x-www-form-urlencoded"} |
---|
| 44 | params = [("grant_type", "client_credentials"), ] |
---|
| 45 | response = requests.post(url, auth=auth, headers=headers, params=params) |
---|
| 46 | response.raise_for_status() |
---|
| 47 | result = response.json() |
---|
| 48 | return result["access_token"] |
---|
| 49 | |
---|
| 50 | |
---|
| 51 | def create_order( |
---|
| 52 | purchase_units, return_url, cancel_url, |
---|
| 53 | request_id=None, notify_url=None): |
---|
| 54 | token = get_auth_token() |
---|
| 55 | if request_id is None: |
---|
| 56 | request_id = str(uuid.uuid4()) |
---|
| 57 | headers = { |
---|
| 58 | "content-type": "application/json", |
---|
| 59 | "authorization": "Bearer %s" % token, |
---|
| 60 | "paypal-request-id": request_id |
---|
| 61 | } |
---|
| 62 | |
---|
| 63 | json_data = { |
---|
| 64 | "intent": "CAPTURE", |
---|
| 65 | "payment_source": { |
---|
| 66 | "paypal": { |
---|
| 67 | "experience_context": { |
---|
| 68 | "landing_page": "NO_PREFERENCE", |
---|
| 69 | "user_action": "CONTINUE", |
---|
| 70 | "brand_name": "WAeUP", |
---|
| 71 | "shipping_preference": "NO_SHIPPING", |
---|
| 72 | "cancel_url": cancel_url, |
---|
| 73 | "return_url": return_url} |
---|
| 74 | } |
---|
| 75 | }, |
---|
| 76 | "purchase_units": [] |
---|
| 77 | } |
---|
| 78 | units = [x.json() for x in purchase_units] |
---|
| 79 | for n, unit in enumerate(units): |
---|
| 80 | unit["reference_id"] = n |
---|
| 81 | json_data["purchase_units"].append(unit) |
---|
| 82 | if notify_url: |
---|
| 83 | json_data["payment_source"]["paypal"][ |
---|
| 84 | "experience_context"]["notify_url"] = notify_url |
---|
[17241] | 85 | config = getUtility(IPaypalConfig) |
---|
| 86 | url = "%s/v2/checkout/orders" % PAYPAL_REST_URLS[config['mode']] |
---|
| 87 | response = requests.post(url, |
---|
[17239] | 88 | headers=headers, json=json_data) |
---|
| 89 | try: |
---|
| 90 | response.raise_for_status() |
---|
| 91 | except requests.HTTPError as err: |
---|
| 92 | data = err.response.json() |
---|
| 93 | return None, None, request_id, data |
---|
| 94 | data = response.json() |
---|
| 95 | order_id = data['id'] # order token |
---|
| 96 | payment_link = [x for x in data['links'] |
---|
| 97 | if x["rel"] == "payer-action"][0]["href"] |
---|
| 98 | return order_id, payment_link, request_id, data |
---|
| 99 | |
---|
| 100 | |
---|
| 101 | def capture_order(order_id, request_id=None): |
---|
| 102 | config = getUtility(IPaypalConfig) |
---|
| 103 | token = get_auth_token() |
---|
| 104 | headers = { |
---|
| 105 | "content-type": "application/json", |
---|
| 106 | "authorization": "Bearer %s" % token, |
---|
| 107 | "paypal-request-id": request_id |
---|
| 108 | } |
---|
| 109 | if request_id is not None: |
---|
| 110 | headers["paypal-request-id"] = request_id |
---|
| 111 | url = "%s/v2/checkout/orders/%s/capture" % ( |
---|
| 112 | PAYPAL_REST_URLS[config['mode']], order_id) |
---|
| 113 | response = requests.post(url, headers=headers) |
---|
| 114 | response.raise_for_status() |
---|
| 115 | data = response.json() |
---|
| 116 | return data |
---|