comparison env/lib/python3.9/site-packages/boto/fps/connection.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 # Copyright (c) 2012 Andy Davidoff http://www.disruptek.com/
2 # Copyright (c) 2010 Jason R. Coombs http://www.jaraco.com/
3 # Copyright (c) 2008 Chris Moyer http://coredumped.org/
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish, dis-
9 # tribute, sublicense, and/or sell copies of the Software, and to permit
10 # persons to whom the Software is furnished to do so, subject to the fol-
11 # lowing conditions:
12 #
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
18 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 # IN THE SOFTWARE.
23
24 import urllib
25 import uuid
26 from boto.connection import AWSQueryConnection
27 from boto.fps.exception import ResponseErrorFactory
28 from boto.fps.response import ResponseFactory
29 import boto.fps.response
30
31 __all__ = ['FPSConnection']
32
33 decorated_attrs = ('action', 'response')
34
35
36 def add_attrs_from(func, to):
37 for attr in decorated_attrs:
38 setattr(to, attr, getattr(func, attr, None))
39 return to
40
41
42 def complex_amounts(*fields):
43 def decorator(func):
44 def wrapper(self, *args, **kw):
45 for field in filter(kw.has_key, fields):
46 amount = kw.pop(field)
47 kw[field + '.Value'] = getattr(amount, 'Value', str(amount))
48 kw[field + '.CurrencyCode'] = getattr(amount, 'CurrencyCode',
49 self.currencycode)
50 return func(self, *args, **kw)
51 wrapper.__doc__ = "{0}\nComplex Amounts: {1}".format(func.__doc__,
52 ', '.join(fields))
53 return add_attrs_from(func, to=wrapper)
54 return decorator
55
56
57 def requires(*groups):
58
59 def decorator(func):
60
61 def wrapper(*args, **kw):
62 hasgroup = lambda x: len(x) == len(filter(kw.has_key, x))
63 if 1 != len(filter(hasgroup, groups)):
64 message = ' OR '.join(['+'.join(g) for g in groups])
65 message = "{0} requires {1} argument(s)" \
66 "".format(getattr(func, 'action', 'Method'), message)
67 raise KeyError(message)
68 return func(*args, **kw)
69 message = ' OR '.join(['+'.join(g) for g in groups])
70 wrapper.__doc__ = "{0}\nRequired: {1}".format(func.__doc__,
71 message)
72 return add_attrs_from(func, to=wrapper)
73 return decorator
74
75
76 def needs_caller_reference(func):
77
78 def wrapper(*args, **kw):
79 kw.setdefault('CallerReference', uuid.uuid4())
80 return func(*args, **kw)
81 wrapper.__doc__ = "{0}\nUses CallerReference, defaults " \
82 "to uuid.uuid4()".format(func.__doc__)
83 return add_attrs_from(func, to=wrapper)
84
85
86 def api_action(*api):
87
88 def decorator(func):
89 action = ''.join(api or map(str.capitalize, func.__name__.split('_')))
90 response = ResponseFactory(action)
91 if hasattr(boto.fps.response, action + 'Response'):
92 response = getattr(boto.fps.response, action + 'Response')
93
94 def wrapper(self, *args, **kw):
95 return func(self, action, response, *args, **kw)
96 wrapper.action, wrapper.response = action, response
97 wrapper.__doc__ = "FPS {0} API call\n{1}".format(action,
98 func.__doc__)
99 return wrapper
100 return decorator
101
102
103 class FPSConnection(AWSQueryConnection):
104
105 APIVersion = '2010-08-28'
106 ResponseError = ResponseErrorFactory
107 currencycode = 'USD'
108
109 def __init__(self, *args, **kw):
110 self.currencycode = kw.pop('CurrencyCode', self.currencycode)
111 kw.setdefault('host', 'fps.sandbox.amazonaws.com')
112 super(FPSConnection, self).__init__(*args, **kw)
113
114 def _required_auth_capability(self):
115 return ['fps']
116
117 @needs_caller_reference
118 @complex_amounts('SettlementAmount')
119 @requires(['CreditInstrumentId', 'SettlementAmount.Value',
120 'SenderTokenId', 'SettlementAmount.CurrencyCode'])
121 @api_action()
122 def settle_debt(self, action, response, **kw):
123 """
124 Allows a caller to initiate a transaction that atomically transfers
125 money from a sender's payment instrument to the recipient, while
126 decreasing corresponding debt balance.
127 """
128 return self.get_object(action, kw, response)
129
130 @requires(['TransactionId'])
131 @api_action()
132 def get_transaction_status(self, action, response, **kw):
133 """
134 Gets the latest status of a transaction.
135 """
136 return self.get_object(action, kw, response)
137
138 @requires(['StartDate'])
139 @api_action()
140 def get_account_activity(self, action, response, **kw):
141 """
142 Returns transactions for a given date range.
143 """
144 return self.get_object(action, kw, response)
145
146 @requires(['TransactionId'])
147 @api_action()
148 def get_transaction(self, action, response, **kw):
149 """
150 Returns all details of a transaction.
151 """
152 return self.get_object(action, kw, response)
153
154 @api_action()
155 def get_outstanding_debt_balance(self, action, response):
156 """
157 Returns the total outstanding balance for all the credit instruments
158 for the given creditor account.
159 """
160 return self.get_object(action, {}, response)
161
162 @requires(['PrepaidInstrumentId'])
163 @api_action()
164 def get_prepaid_balance(self, action, response, **kw):
165 """
166 Returns the balance available on the given prepaid instrument.
167 """
168 return self.get_object(action, kw, response)
169
170 @api_action()
171 def get_total_prepaid_liability(self, action, response):
172 """
173 Returns the total liability held by the given account corresponding to
174 all the prepaid instruments owned by the account.
175 """
176 return self.get_object(action, {}, response)
177
178 @api_action()
179 def get_account_balance(self, action, response):
180 """
181 Returns the account balance for an account in real time.
182 """
183 return self.get_object(action, {}, response)
184
185 @needs_caller_reference
186 @requires(['PaymentInstruction', 'TokenType'])
187 @api_action()
188 def install_payment_instruction(self, action, response, **kw):
189 """
190 Installs a payment instruction for caller.
191 """
192 return self.get_object(action, kw, response)
193
194 @needs_caller_reference
195 @requires(['returnURL', 'pipelineName'])
196 def cbui_url(self, **kw):
197 """
198 Generate a signed URL for the Co-Branded service API given arguments as
199 payload.
200 """
201 sandbox = 'sandbox' in self.host and 'payments-sandbox' or 'payments'
202 endpoint = 'authorize.{0}.amazon.com'.format(sandbox)
203 base = '/cobranded-ui/actions/start'
204
205 validpipelines = ('SingleUse', 'MultiUse', 'Recurring', 'Recipient',
206 'SetupPrepaid', 'SetupPostpaid', 'EditToken')
207 assert kw['pipelineName'] in validpipelines, "Invalid pipelineName"
208 kw.update({
209 'signatureMethod': 'HmacSHA256',
210 'signatureVersion': '2',
211 })
212 kw.setdefault('callerKey', self.aws_access_key_id)
213
214 safestr = lambda x: x is not None and str(x) or ''
215 safequote = lambda x: urllib.quote(safestr(x), safe='~')
216 payload = sorted([(k, safequote(v)) for k, v in kw.items()])
217
218 encoded = lambda p: '&'.join([k + '=' + v for k, v in p])
219 canonical = '\n'.join(['GET', endpoint, base, encoded(payload)])
220 signature = self._auth_handler.sign_string(canonical)
221 payload += [('signature', safequote(signature))]
222 payload.sort()
223
224 return 'https://{0}{1}?{2}'.format(endpoint, base, encoded(payload))
225
226 @needs_caller_reference
227 @complex_amounts('TransactionAmount')
228 @requires(['SenderTokenId', 'TransactionAmount.Value',
229 'TransactionAmount.CurrencyCode'])
230 @api_action()
231 def reserve(self, action, response, **kw):
232 """
233 Reserve API is part of the Reserve and Settle API conjunction that
234 serve the purpose of a pay where the authorization and settlement have
235 a timing difference.
236 """
237 return self.get_object(action, kw, response)
238
239 @needs_caller_reference
240 @complex_amounts('TransactionAmount')
241 @requires(['SenderTokenId', 'TransactionAmount.Value',
242 'TransactionAmount.CurrencyCode'])
243 @api_action()
244 def pay(self, action, response, **kw):
245 """
246 Allows calling applications to move money from a sender to a recipient.
247 """
248 return self.get_object(action, kw, response)
249
250 @requires(['TransactionId'])
251 @api_action()
252 def cancel(self, action, response, **kw):
253 """
254 Cancels an ongoing transaction and puts it in cancelled state.
255 """
256 return self.get_object(action, kw, response)
257
258 @complex_amounts('TransactionAmount')
259 @requires(['ReserveTransactionId', 'TransactionAmount.Value',
260 'TransactionAmount.CurrencyCode'])
261 @api_action()
262 def settle(self, action, response, **kw):
263 """
264 The Settle API is used in conjunction with the Reserve API and is used
265 to settle previously reserved transaction.
266 """
267 return self.get_object(action, kw, response)
268
269 @complex_amounts('RefundAmount')
270 @requires(['TransactionId', 'RefundAmount.Value',
271 'CallerReference', 'RefundAmount.CurrencyCode'])
272 @api_action()
273 def refund(self, action, response, **kw):
274 """
275 Refunds a previously completed transaction.
276 """
277 return self.get_object(action, kw, response)
278
279 @requires(['RecipientTokenId'])
280 @api_action()
281 def get_recipient_verification_status(self, action, response, **kw):
282 """
283 Returns the recipient status.
284 """
285 return self.get_object(action, kw, response)
286
287 @requires(['CallerReference'], ['TokenId'])
288 @api_action()
289 def get_token_by_caller(self, action, response, **kw):
290 """
291 Returns the details of a particular token installed by this calling
292 application using the subway co-branded UI.
293 """
294 return self.get_object(action, kw, response)
295
296 @requires(['UrlEndPoint', 'HttpParameters'])
297 @api_action()
298 def verify_signature(self, action, response, **kw):
299 """
300 Verify the signature that FPS sent in IPN or callback urls.
301 """
302 return self.get_object(action, kw, response)
303
304 @api_action()
305 def get_tokens(self, action, response, **kw):
306 """
307 Returns a list of tokens installed on the given account.
308 """
309 return self.get_object(action, kw, response)
310
311 @requires(['TokenId'])
312 @api_action()
313 def get_token_usage(self, action, response, **kw):
314 """
315 Returns the usage of a token.
316 """
317 return self.get_object(action, kw, response)
318
319 @requires(['TokenId'])
320 @api_action()
321 def cancel_token(self, action, response, **kw):
322 """
323 Cancels any token installed by the calling application on its own
324 account.
325 """
326 return self.get_object(action, kw, response)
327
328 @needs_caller_reference
329 @complex_amounts('FundingAmount')
330 @requires(['PrepaidInstrumentId', 'FundingAmount.Value',
331 'SenderTokenId', 'FundingAmount.CurrencyCode'])
332 @api_action()
333 def fund_prepaid(self, action, response, **kw):
334 """
335 Funds the prepaid balance on the given prepaid instrument.
336 """
337 return self.get_object(action, kw, response)
338
339 @requires(['CreditInstrumentId'])
340 @api_action()
341 def get_debt_balance(self, action, response, **kw):
342 """
343 Returns the balance corresponding to the given credit instrument.
344 """
345 return self.get_object(action, kw, response)
346
347 @needs_caller_reference
348 @complex_amounts('AdjustmentAmount')
349 @requires(['CreditInstrumentId', 'AdjustmentAmount.Value',
350 'AdjustmentAmount.CurrencyCode'])
351 @api_action()
352 def write_off_debt(self, action, response, **kw):
353 """
354 Allows a creditor to write off the debt balance accumulated partially
355 or fully at any time.
356 """
357 return self.get_object(action, kw, response)
358
359 @requires(['SubscriptionId'])
360 @api_action()
361 def get_transactions_for_subscription(self, action, response, **kw):
362 """
363 Returns the transactions for a given subscriptionID.
364 """
365 return self.get_object(action, kw, response)
366
367 @requires(['SubscriptionId'])
368 @api_action()
369 def get_subscription_details(self, action, response, **kw):
370 """
371 Returns the details of Subscription for a given subscriptionID.
372 """
373 return self.get_object(action, kw, response)
374
375 @needs_caller_reference
376 @complex_amounts('RefundAmount')
377 @requires(['SubscriptionId'])
378 @api_action()
379 def cancel_subscription_and_refund(self, action, response, **kw):
380 """
381 Cancels a subscription.
382 """
383 message = "If you specify a RefundAmount, " \
384 "you must specify CallerReference."
385 assert not 'RefundAmount.Value' in kw \
386 or 'CallerReference' in kw, message
387 return self.get_object(action, kw, response)
388
389 @requires(['TokenId'])
390 @api_action()
391 def get_payment_instruction(self, action, response, **kw):
392 """
393 Gets the payment instruction of a token.
394 """
395 return self.get_object(action, kw, response)