OLD | NEW |
1 # Copyright (c) 2008 Chris Moyer http://coredumped.org/ | 1 # Copyright (c) 2008 Chris Moyer http://coredumped.org/ |
2 # Copyringt (c) 2010 Jason R. Coombs http://www.jaraco.com/ | 2 # Copyringt (c) 2010 Jason R. Coombs http://www.jaraco.com/ |
3 # | 3 # |
4 # Permission is hereby granted, free of charge, to any person obtaining a | 4 # Permission is hereby granted, free of charge, to any person obtaining a |
5 # copy of this software and associated documentation files (the | 5 # copy of this software and associated documentation files (the |
6 # "Software"), to deal in the Software without restriction, including | 6 # "Software"), to deal in the Software without restriction, including |
7 # without limitation the rights to use, copy, modify, merge, publish, dis- | 7 # without limitation the rights to use, copy, modify, merge, publish, dis- |
8 # tribute, sublicense, and/or sell copies of the Software, and to permit | 8 # tribute, sublicense, and/or sell copies of the Software, and to permit |
9 # persons to whom the Software is furnished to do so, subject to the fol- | 9 # persons to whom the Software is furnished to do so, subject to the fol- |
10 # lowing conditions: | 10 # lowing conditions: |
(...skipping 24 matching lines...) Expand all Loading... |
35 | 35 |
36 class FPSConnection(AWSQueryConnection): | 36 class FPSConnection(AWSQueryConnection): |
37 | 37 |
38 APIVersion = '2007-01-08' | 38 APIVersion = '2007-01-08' |
39 | 39 |
40 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, | 40 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, |
41 is_secure=True, port=None, proxy=None, proxy_port=None, | 41 is_secure=True, port=None, proxy=None, proxy_port=None, |
42 proxy_user=None, proxy_pass=None, | 42 proxy_user=None, proxy_pass=None, |
43 host='fps.sandbox.amazonaws.com', debug=0, | 43 host='fps.sandbox.amazonaws.com', debug=0, |
44 https_connection_factory=None, path="/"): | 44 https_connection_factory=None, path="/"): |
45 AWSQueryConnection.__init__(self, aws_access_key_id, aws_secret_access_k
ey, | 45 AWSQueryConnection.__init__(self, aws_access_key_id, |
| 46 aws_secret_access_key, |
46 is_secure, port, proxy, proxy_port, | 47 is_secure, port, proxy, proxy_port, |
47 proxy_user, proxy_pass, host, debug, | 48 proxy_user, proxy_pass, host, debug, |
48 https_connection_factory, path) | 49 https_connection_factory, path) |
49 | 50 |
50 def _required_auth_capability(self): | 51 def _required_auth_capability(self): |
51 return ['fps'] | 52 return ['fps'] |
52 | 53 |
53 def install_payment_instruction(self, instruction, token_type="Unrestricted"
, transaction_id=None): | 54 def install_payment_instruction(self, instruction, |
| 55 token_type="Unrestricted", |
| 56 transaction_id=None): |
54 """ | 57 """ |
55 InstallPaymentInstruction | 58 InstallPaymentInstruction |
56 instruction: The PaymentInstruction to send, for example: | 59 instruction: The PaymentInstruction to send, for example: |
57 | 60 |
58 MyRole=='Caller' orSay 'Roles do not match'; | 61 MyRole=='Caller' orSay 'Roles do not match'; |
59 | 62 |
60 token_type: Defaults to "Unrestricted" | 63 token_type: Defaults to "Unrestricted" |
61 transaction_id: Defaults to a new ID | 64 transaction_id: Defaults to a new ID |
62 """ | 65 """ |
63 | 66 |
64 if(transaction_id == None): | 67 if(transaction_id == None): |
65 transaction_id = uuid.uuid4() | 68 transaction_id = uuid.uuid4() |
66 params = {} | 69 params = {} |
67 params['PaymentInstruction'] = instruction | 70 params['PaymentInstruction'] = instruction |
68 params['TokenType'] = token_type | 71 params['TokenType'] = token_type |
69 params['CallerReference'] = transaction_id | 72 params['CallerReference'] = transaction_id |
70 response = self.make_request("InstallPaymentInstruction", params) | 73 response = self.make_request("InstallPaymentInstruction", params) |
71 return response | 74 return response |
72 | 75 |
73 def install_caller_instruction(self, token_type="Unrestricted", transaction_
id=None): | 76 def install_caller_instruction(self, token_type="Unrestricted", |
| 77 transaction_id=None): |
74 """ | 78 """ |
75 Set us up as a caller | 79 Set us up as a caller |
76 This will install a new caller_token into the FPS section. | 80 This will install a new caller_token into the FPS section. |
77 This should really only be called to regenerate the caller token. | 81 This should really only be called to regenerate the caller token. |
78 """ | 82 """ |
79 response = self.install_payment_instruction("MyRole=='Caller';", token_t
ype=token_type, transaction_id=transaction_id) | 83 response = self.install_payment_instruction("MyRole=='Caller';", |
| 84 token_type=token_type, |
| 85 transaction_id=transaction_i
d) |
80 body = response.read() | 86 body = response.read() |
81 if(response.status == 200): | 87 if(response.status == 200): |
82 rs = ResultSet() | 88 rs = ResultSet() |
83 h = handler.XmlHandler(rs, self) | 89 h = handler.XmlHandler(rs, self) |
84 xml.sax.parseString(body, h) | 90 xml.sax.parseString(body, h) |
85 caller_token = rs.TokenId | 91 caller_token = rs.TokenId |
86 try: | 92 try: |
87 boto.config.save_system_option("FPS", "caller_token", caller_tok
en) | 93 boto.config.save_system_option("FPS", "caller_token", |
| 94 caller_token) |
88 except(IOError): | 95 except(IOError): |
89 boto.config.save_user_option("FPS", "caller_token", caller_token
) | 96 boto.config.save_user_option("FPS", "caller_token", |
| 97 caller_token) |
90 return caller_token | 98 return caller_token |
91 else: | 99 else: |
92 raise FPSResponseError(response.status, response.reason, body) | 100 raise FPSResponseError(response.status, response.reason, body) |
93 | 101 |
94 def install_recipient_instruction(self, token_type="Unrestricted", transacti
on_id=None): | 102 def install_recipient_instruction(self, token_type="Unrestricted", |
| 103 transaction_id=None): |
95 """ | 104 """ |
96 Set us up as a Recipient | 105 Set us up as a Recipient |
97 This will install a new caller_token into the FPS section. | 106 This will install a new caller_token into the FPS section. |
98 This should really only be called to regenerate the recipient token. | 107 This should really only be called to regenerate the recipient token. |
99 """ | 108 """ |
100 response = self.install_payment_instruction("MyRole=='Recipient';", toke
n_type=token_type, transaction_id=transaction_id) | 109 response = self.install_payment_instruction("MyRole=='Recipient';", |
| 110 token_type=token_type, |
| 111 transaction_id=transaction_i
d) |
101 body = response.read() | 112 body = response.read() |
102 if(response.status == 200): | 113 if(response.status == 200): |
103 rs = ResultSet() | 114 rs = ResultSet() |
104 h = handler.XmlHandler(rs, self) | 115 h = handler.XmlHandler(rs, self) |
105 xml.sax.parseString(body, h) | 116 xml.sax.parseString(body, h) |
106 recipient_token = rs.TokenId | 117 recipient_token = rs.TokenId |
107 try: | 118 try: |
108 boto.config.save_system_option("FPS", "recipient_token", recipie
nt_token) | 119 boto.config.save_system_option("FPS", "recipient_token", |
| 120 recipient_token) |
109 except(IOError): | 121 except(IOError): |
110 boto.config.save_user_option("FPS", "recipient_token", recipient
_token) | 122 boto.config.save_user_option("FPS", "recipient_token", |
| 123 recipient_token) |
111 | 124 |
112 return recipient_token | 125 return recipient_token |
113 else: | 126 else: |
114 raise FPSResponseError(response.status, response.reason, body) | 127 raise FPSResponseError(response.status, response.reason, body) |
115 | 128 |
116 def make_url(self, returnURL, paymentReason, pipelineName, transactionAmount
, **params): | 129 def make_marketplace_registration_url(self, returnURL, pipelineName, |
| 130 maxFixedFee=0.0, maxVariableFee=0.0, |
| 131 recipientPaysFee=True, **params): |
117 """ | 132 """ |
118 Generate the URL with the signature required for a transaction | 133 Generate the URL with the signature required for signing up a recipient |
119 """ | 134 """ |
120 # use the sandbox authorization endpoint if we're using the | 135 # use the sandbox authorization endpoint if we're using the |
121 # sandbox for API calls. | 136 # sandbox for API calls. |
122 endpoint_host = 'authorize.payments.amazon.com' | 137 endpoint_host = 'authorize.payments.amazon.com' |
123 if 'sandbox' in self.host: | 138 if 'sandbox' in self.host: |
124 endpoint_host = 'authorize.payments-sandbox.amazon.com' | 139 endpoint_host = 'authorize.payments-sandbox.amazon.com' |
125 base = "/cobranded-ui/actions/start" | 140 base = "/cobranded-ui/actions/start" |
126 | 141 |
| 142 params['callerKey'] = str(self.aws_access_key_id) |
| 143 params['returnURL'] = str(returnURL) |
| 144 params['pipelineName'] = str(pipelineName) |
| 145 params['maxFixedFee'] = str(maxFixedFee) |
| 146 params['maxVariableFee'] = str(maxVariableFee) |
| 147 params['recipientPaysFee'] = str(recipientPaysFee) |
| 148 params["signatureMethod"] = 'HmacSHA256' |
| 149 params["signatureVersion"] = '2' |
| 150 |
| 151 if(not params.has_key('callerReference')): |
| 152 params['callerReference'] = str(uuid.uuid4()) |
| 153 |
| 154 parts = '' |
| 155 for k in sorted(params.keys()): |
| 156 parts += "&%s=%s" % (k, urllib.quote(params[k], '~')) |
| 157 |
| 158 canonical = '\n'.join(['GET', |
| 159 str(endpoint_host).lower(), |
| 160 base, |
| 161 parts[1:]]) |
| 162 |
| 163 signature = self._auth_handler.sign_string(canonical) |
| 164 params["signature"] = signature |
| 165 |
| 166 urlsuffix = '' |
| 167 for k in sorted(params.keys()): |
| 168 urlsuffix += "&%s=%s" % (k, urllib.quote(params[k], '~')) |
| 169 urlsuffix = urlsuffix[1:] # strip the first & |
| 170 |
| 171 fmt = "https://%(endpoint_host)s%(base)s?%(urlsuffix)s" |
| 172 final = fmt % vars() |
| 173 return final |
| 174 |
| 175 |
| 176 def make_url(self, returnURL, paymentReason, pipelineName, |
| 177 transactionAmount, **params): |
| 178 """ |
| 179 Generate the URL with the signature required for a transaction |
| 180 """ |
| 181 # use the sandbox authorization endpoint if we're using the |
| 182 # sandbox for API calls. |
| 183 endpoint_host = 'authorize.payments.amazon.com' |
| 184 if 'sandbox' in self.host: |
| 185 endpoint_host = 'authorize.payments-sandbox.amazon.com' |
| 186 base = "/cobranded-ui/actions/start" |
127 | 187 |
128 params['callerKey'] = str(self.aws_access_key_id) | 188 params['callerKey'] = str(self.aws_access_key_id) |
129 params['returnURL'] = str(returnURL) | 189 params['returnURL'] = str(returnURL) |
130 params['paymentReason'] = str(paymentReason) | 190 params['paymentReason'] = str(paymentReason) |
131 params['pipelineName'] = pipelineName | 191 params['pipelineName'] = pipelineName |
| 192 params['transactionAmount'] = transactionAmount |
132 params["signatureMethod"] = 'HmacSHA256' | 193 params["signatureMethod"] = 'HmacSHA256' |
133 params["signatureVersion"] = '2' | 194 params["signatureVersion"] = '2' |
134 params["transactionAmount"] = transactionAmount | 195 |
135 | |
136 if(not params.has_key('callerReference')): | 196 if(not params.has_key('callerReference')): |
137 params['callerReference'] = str(uuid.uuid4()) | 197 params['callerReference'] = str(uuid.uuid4()) |
138 | 198 |
139 parts = '' | 199 parts = '' |
140 for k in sorted(params.keys()): | 200 for k in sorted(params.keys()): |
141 parts += "&%s=%s" % (k, urllib.quote(params[k], '~')) | 201 parts += "&%s=%s" % (k, urllib.quote(params[k], '~')) |
142 | 202 |
143 canonical = '\n'.join(['GET', | 203 canonical = '\n'.join(['GET', |
144 str(endpoint_host).lower(), | 204 str(endpoint_host).lower(), |
145 base, | 205 base, |
146 parts[1:]]) | 206 parts[1:]]) |
147 | 207 |
148 signature = self._auth_handler.sign_string(canonical) | 208 signature = self._auth_handler.sign_string(canonical) |
149 params["signature"] = signature | 209 params["signature"] = signature |
150 | 210 |
151 urlsuffix = '' | 211 urlsuffix = '' |
152 for k in sorted(params.keys()): | 212 for k in sorted(params.keys()): |
153 urlsuffix += "&%s=%s" % (k, urllib.quote(params[k], '~')) | 213 urlsuffix += "&%s=%s" % (k, urllib.quote(params[k], '~')) |
154 urlsuffix = urlsuffix[1:] # strip the first & | 214 urlsuffix = urlsuffix[1:] # strip the first & |
155 | 215 |
156 fmt = "https://%(endpoint_host)s%(base)s?%(urlsuffix)s" | 216 fmt = "https://%(endpoint_host)s%(base)s?%(urlsuffix)s" |
157 final = fmt % vars() | 217 final = fmt % vars() |
158 return final | 218 return final |
159 | 219 |
160 def pay(self, transactionAmount, senderTokenId, | 220 def pay(self, transactionAmount, senderTokenId, |
161 recipientTokenId=None, callerTokenId=None, | 221 recipientTokenId=None, callerTokenId=None, |
162 chargeFeeTo="Recipient", | 222 chargeFeeTo="Recipient", |
163 callerReference=None, senderReference=None, recipientReference=None, | 223 callerReference=None, senderReference=None, recipientReference=None, |
164 senderDescription=None, recipientDescription=None, callerDescription
=None, | 224 senderDescription=None, recipientDescription=None, |
165 metadata=None, transactionDate=None, reserve=False): | 225 callerDescription=None, metadata=None, |
| 226 transactionDate=None, reserve=False): |
166 """ | 227 """ |
167 Make a payment transaction. You must specify the amount. | 228 Make a payment transaction. You must specify the amount. |
168 This can also perform a Reserve request if 'reserve' is set to True. | 229 This can also perform a Reserve request if 'reserve' is set to True. |
169 """ | 230 """ |
170 params = {} | 231 params = {} |
171 params['SenderTokenId'] = senderTokenId | 232 params['SenderTokenId'] = senderTokenId |
172 # this is for 2008-09-17 specification | 233 # this is for 2008-09-17 specification |
173 params['TransactionAmount.Amount'] = str(transactionAmount) | 234 params['TransactionAmount.Amount'] = str(transactionAmount) |
174 params['TransactionAmount.CurrencyCode'] = "USD" | 235 params['TransactionAmount.CurrencyCode'] = "USD" |
175 #params['TransactionAmount'] = str(transactionAmount) | 236 #params['TransactionAmount'] = str(transactionAmount) |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 response = self.make_request("Settle", params) | 323 response = self.make_request("Settle", params) |
263 body = response.read() | 324 body = response.read() |
264 if(response.status == 200): | 325 if(response.status == 200): |
265 rs = ResultSet() | 326 rs = ResultSet() |
266 h = handler.XmlHandler(rs, self) | 327 h = handler.XmlHandler(rs, self) |
267 xml.sax.parseString(body, h) | 328 xml.sax.parseString(body, h) |
268 return rs | 329 return rs |
269 else: | 330 else: |
270 raise FPSResponseError(response.status, response.reason, body) | 331 raise FPSResponseError(response.status, response.reason, body) |
271 | 332 |
272 def refund(self, callerReference, transactionId, refundAmount=None, callerDe
scription=None): | 333 def refund(self, callerReference, transactionId, refundAmount=None, |
| 334 callerDescription=None): |
273 """ | 335 """ |
274 Refund a transaction. This refunds the full amount by default unless 're
fundAmount' is specified. | 336 Refund a transaction. This refunds the full amount by default |
| 337 unless 'refundAmount' is specified. |
275 """ | 338 """ |
276 params = {} | 339 params = {} |
277 params['CallerReference'] = callerReference | 340 params['CallerReference'] = callerReference |
278 params['TransactionId'] = transactionId | 341 params['TransactionId'] = transactionId |
279 if(refundAmount != None): | 342 if(refundAmount != None): |
280 params['RefundAmount'] = refundAmount | 343 params['RefundAmount'] = refundAmount |
281 if(callerDescription != None): | 344 if(callerDescription != None): |
282 params['CallerDescription'] = callerDescription | 345 params['CallerDescription'] = callerDescription |
283 | 346 |
284 response = self.make_request("Refund", params) | 347 response = self.make_request("Refund", params) |
(...skipping 18 matching lines...) Expand all Loading... |
303 if(response.status == 200): | 366 if(response.status == 200): |
304 rs = ResultSet() | 367 rs = ResultSet() |
305 h = handler.XmlHandler(rs, self) | 368 h = handler.XmlHandler(rs, self) |
306 xml.sax.parseString(body, h) | 369 xml.sax.parseString(body, h) |
307 return rs | 370 return rs |
308 else: | 371 else: |
309 raise FPSResponseError(response.status, response.reason, body) | 372 raise FPSResponseError(response.status, response.reason, body) |
310 | 373 |
311 def get_token_by_caller_reference(self, callerReference): | 374 def get_token_by_caller_reference(self, callerReference): |
312 """ | 375 """ |
313 Returns details about the token specified by 'callerReference'. | 376 Returns details about the token specified by 'CallerReference'. |
314 """ | 377 """ |
315 params ={} | 378 params ={} |
316 params['callerReference'] = callerReference | 379 params['CallerReference'] = callerReference |
317 | 380 |
318 response = self.make_request("GetTokenByCaller", params) | 381 response = self.make_request("GetTokenByCaller", params) |
319 body = response.read() | 382 body = response.read() |
320 if(response.status == 200): | 383 if(response.status == 200): |
321 rs = ResultSet() | 384 rs = ResultSet() |
322 h = handler.XmlHandler(rs, self) | 385 h = handler.XmlHandler(rs, self) |
323 xml.sax.parseString(body, h) | 386 xml.sax.parseString(body, h) |
324 return rs | 387 return rs |
325 else: | 388 else: |
326 raise FPSResponseError(response.status, response.reason, body) | 389 raise FPSResponseError(response.status, response.reason, body) |
| 390 |
327 def get_token_by_caller_token(self, tokenId): | 391 def get_token_by_caller_token(self, tokenId): |
328 """ | 392 """ |
329 Returns details about the token specified by 'callerReference'. | 393 Returns details about the token specified by 'TokenId'. |
330 """ | 394 """ |
331 params ={} | 395 params ={} |
332 params['TokenId'] = tokenId | 396 params['TokenId'] = tokenId |
333 | 397 |
334 response = self.make_request("GetTokenByCaller", params) | 398 response = self.make_request("GetTokenByCaller", params) |
335 body = response.read() | 399 body = response.read() |
336 if(response.status == 200): | 400 if(response.status == 200): |
337 rs = ResultSet() | 401 rs = ResultSet() |
338 h = handler.XmlHandler(rs, self) | 402 h = handler.XmlHandler(rs, self) |
339 xml.sax.parseString(body, h) | 403 xml.sax.parseString(body, h) |
340 return rs | 404 return rs |
341 else: | 405 else: |
342 raise FPSResponseError(response.status, response.reason, body) | 406 raise FPSResponseError(response.status, response.reason, body) |
343 | 407 |
344 def verify_signature(self, end_point_url, http_parameters): | 408 def verify_signature(self, end_point_url, http_parameters): |
345 params = dict( | 409 params = dict( |
346 UrlEndPoint = end_point_url, | 410 UrlEndPoint = end_point_url, |
347 HttpParameters = http_parameters, | 411 HttpParameters = http_parameters, |
348 ) | 412 ) |
349 response = self.make_request("VerifySignature", params) | 413 response = self.make_request("VerifySignature", params) |
350 body = response.read() | 414 body = response.read() |
351 if(response.status != 200): | 415 if(response.status != 200): |
352 raise FPSResponseError(response.status, response.reason, body) | 416 raise FPSResponseError(response.status, response.reason, body) |
353 rs = ResultSet() | 417 rs = ResultSet() |
354 h = handler.XmlHandler(rs, self) | 418 h = handler.XmlHandler(rs, self) |
355 xml.sax.parseString(body, h) | 419 xml.sax.parseString(body, h) |
356 return rs | 420 return rs |
OLD | NEW |