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 |
---|
85 | response = requests.post( |
---|
86 | 'https://api-m.sandbox.paypal.com/v2/checkout/orders', |
---|
87 | headers=headers, json=json_data) |
---|
88 | try: |
---|
89 | response.raise_for_status() |
---|
90 | except requests.HTTPError as err: |
---|
91 | data = err.response.json() |
---|
92 | return None, None, request_id, data |
---|
93 | data = response.json() |
---|
94 | order_id = data['id'] # order token |
---|
95 | payment_link = [x for x in data['links'] |
---|
96 | if x["rel"] == "payer-action"][0]["href"] |
---|
97 | return order_id, payment_link, request_id, data |
---|
98 | |
---|
99 | |
---|
100 | def capture_order(order_id, request_id=None): |
---|
101 | config = getUtility(IPaypalConfig) |
---|
102 | token = get_auth_token() |
---|
103 | headers = { |
---|
104 | "content-type": "application/json", |
---|
105 | "authorization": "Bearer %s" % token, |
---|
106 | "paypal-request-id": request_id |
---|
107 | } |
---|
108 | if request_id is not None: |
---|
109 | headers["paypal-request-id"] = request_id |
---|
110 | url = "%s/v2/checkout/orders/%s/capture" % ( |
---|
111 | PAYPAL_REST_URLS[config['mode']], order_id) |
---|
112 | response = requests.post(url, headers=headers) |
---|
113 | response.raise_for_status() |
---|
114 | data = response.json() |
---|
115 | return data |
---|