mirror of
https://github.com/gooba42/adventureland.git
synced 2026-10-15 10:59:29 -05:00
343 lines
13 KiB
Python
Executable File
343 lines
13 KiB
Python
Executable File
import calendar
|
|
import datetime
|
|
import platform
|
|
import time
|
|
#import urllib
|
|
#import urlparse
|
|
import warnings
|
|
|
|
import libraries.stripe
|
|
from libraries.stripe import error, http_client, version, util
|
|
from libraries.stripe.multipart_data_generator import MultipartDataGenerator
|
|
|
|
|
|
def _encode_datetime(dttime):
|
|
if dttime.tzinfo and dttime.tzinfo.utcoffset(dttime) is not None:
|
|
utc_timestamp = calendar.timegm(dttime.utctimetuple())
|
|
else:
|
|
utc_timestamp = time.mktime(dttime.timetuple())
|
|
|
|
return int(utc_timestamp)
|
|
|
|
|
|
def _encode_nested_dict(key, data, fmt='%s[%s]'):
|
|
d = {}
|
|
for subkey, subvalue in data.iteritems():
|
|
d[fmt % (key, subkey)] = subvalue
|
|
return d
|
|
|
|
|
|
def _api_encode(data):
|
|
for key, value in data.iteritems():
|
|
key = util.utf8(key)
|
|
if value is None:
|
|
continue
|
|
elif hasattr(value, 'stripe_id'):
|
|
yield (key, value.stripe_id)
|
|
elif isinstance(value, list) or isinstance(value, tuple):
|
|
for sv in value:
|
|
if isinstance(sv, dict):
|
|
subdict = _encode_nested_dict(key, sv, fmt='%s[][%s]')
|
|
for k, v in _api_encode(subdict):
|
|
yield (k, v)
|
|
else:
|
|
yield ("%s[]" % (key,), util.utf8(sv))
|
|
elif isinstance(value, dict):
|
|
subdict = _encode_nested_dict(key, value)
|
|
for subkey, subvalue in _api_encode(subdict):
|
|
yield (subkey, subvalue)
|
|
elif isinstance(value, datetime.datetime):
|
|
yield (key, _encode_datetime(value))
|
|
else:
|
|
yield (key, util.utf8(value))
|
|
|
|
|
|
def _build_api_url(url, query):
|
|
scheme, netloc, path, base_query, fragment = urlparse.urlsplit(url)
|
|
|
|
if base_query:
|
|
query = '%s&%s' % (base_query, query)
|
|
|
|
return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
|
|
|
|
|
|
class APIRequestor(object):
|
|
|
|
def __init__(self, key=None, client=None, api_base=None, account=None):
|
|
self.api_base = api_base or libraries.stripe.api_base
|
|
self.api_key = key
|
|
self.stripe_account = account
|
|
|
|
from libraries.stripe import verify_ssl_certs as verify
|
|
|
|
self._client = client or libraries.stripe.default_http_client or \
|
|
http_client.new_default_http_client(verify_ssl_certs=verify)
|
|
|
|
@classmethod
|
|
def api_url(cls, url=''):
|
|
warnings.warn(
|
|
'The `api_url` class method of APIRequestor is '
|
|
'deprecated and will be removed in version 2.0.'
|
|
'If you need public access to this function, please email us '
|
|
'at support@stripe.com.',
|
|
DeprecationWarning)
|
|
return '%s%s' % (stripe.api_base, url)
|
|
|
|
@classmethod
|
|
def _deprecated_encode(cls, stk, key, value):
|
|
warnings.warn(
|
|
'The encode_* class methods of APIRequestor are deprecated and '
|
|
'will be removed in version 2.0. '
|
|
'If you need public access to this function, please email us '
|
|
'at support@stripe.com.',
|
|
DeprecationWarning, stacklevel=2)
|
|
stk.extend(_api_encode({key: value}))
|
|
|
|
@classmethod
|
|
def encode_dict(cls, stk, key, value):
|
|
cls._deprecated_encode(stk, key, value)
|
|
|
|
@classmethod
|
|
def encode_list(cls, stk, key, value):
|
|
cls._deprecated_encode(stk, key, value)
|
|
|
|
@classmethod
|
|
def encode_datetime(cls, stk, key, value):
|
|
cls._deprecated_encode(stk, key, value)
|
|
|
|
@classmethod
|
|
def encode_none(cls, stk, key, value):
|
|
cls._deprecated_encode(stk, key, value)
|
|
|
|
@classmethod
|
|
def encode(cls, d):
|
|
"""
|
|
Internal: encode a string for url representation
|
|
"""
|
|
warnings.warn(
|
|
'The `encode` class method of APIRequestor is deprecated and '
|
|
'will be removed in version 2.0.'
|
|
'If you need public access to this function, please email us '
|
|
'at support@stripe.com.',
|
|
DeprecationWarning)
|
|
return urllib.urlencode(list(_api_encode(d)))
|
|
|
|
@classmethod
|
|
def build_url(cls, url, params):
|
|
warnings.warn(
|
|
'The `build_url` class method of APIRequestor is deprecated and '
|
|
'will be removed in version 2.0.'
|
|
'If you need public access to this function, please email us '
|
|
'at support@stripe.com.',
|
|
DeprecationWarning)
|
|
return _build_api_url(url, cls.encode(params))
|
|
|
|
def request(self, method, url, params=None, headers=None):
|
|
rbody, rcode, rheaders, my_api_key = self.request_raw(
|
|
method.lower(), url, params, headers)
|
|
resp = self.interpret_response(rbody, rcode, rheaders)
|
|
return resp, my_api_key
|
|
|
|
def handle_api_error(self, rbody, rcode, resp, rheaders):
|
|
try:
|
|
err = resp['error']
|
|
except (KeyError, TypeError):
|
|
raise error.APIError(
|
|
"Invalid response object from API: %r (HTTP response code "
|
|
"was %d)" % (rbody, rcode),
|
|
rbody, rcode, resp)
|
|
|
|
# Rate limits were previously coded as 400's with code 'rate_limit'
|
|
if rcode == 429 or (rcode == 400 and err.get('code') == 'rate_limit'):
|
|
raise error.RateLimitError(
|
|
err.get('message'), rbody, rcode, resp, rheaders)
|
|
elif rcode in [400, 404]:
|
|
raise error.InvalidRequestError(
|
|
err.get('message'), err.get('param'),
|
|
rbody, rcode, resp, rheaders)
|
|
elif rcode == 401:
|
|
raise error.AuthenticationError(
|
|
err.get('message'), rbody, rcode, resp,
|
|
rheaders)
|
|
elif rcode == 402:
|
|
raise error.CardError(err.get('message'), err.get('param'),
|
|
err.get('code'), rbody, rcode, resp,
|
|
rheaders)
|
|
else:
|
|
raise error.APIError(err.get('message'), rbody, rcode, resp,
|
|
rheaders)
|
|
|
|
def request_raw(self, method, url, params=None, supplied_headers=None):
|
|
"""
|
|
Mechanism for issuing an API call
|
|
"""
|
|
from libraries.stripe import api_version
|
|
|
|
if self.api_key:
|
|
my_api_key = self.api_key
|
|
else:
|
|
from libraries.stripe import api_key
|
|
my_api_key = api_key
|
|
|
|
if my_api_key is None:
|
|
raise error.AuthenticationError(
|
|
'No API key provided. (HINT: set your API key using '
|
|
'"stripe.api_key = <API-KEY>"). You can generate API keys '
|
|
'from the Stripe web interface. See https://stripe.com/api '
|
|
'for details, or email support@stripe.com if you have any '
|
|
'questions.')
|
|
|
|
abs_url = '%s%s' % (self.api_base, url)
|
|
|
|
encoded_params = urllib.urlencode(list(_api_encode(params or {})))
|
|
|
|
if method == 'get' or method == 'delete':
|
|
if params:
|
|
abs_url = _build_api_url(abs_url, encoded_params)
|
|
post_data = None
|
|
elif method == 'post':
|
|
if supplied_headers is not None and \
|
|
supplied_headers.get("Content-Type") == \
|
|
"multipart/form-data":
|
|
generator = MultipartDataGenerator()
|
|
generator.add_params(params or {})
|
|
post_data = generator.get_post_data()
|
|
supplied_headers["Content-Type"] = \
|
|
"multipart/form-data; boundary=%s" % (generator.boundary,)
|
|
else:
|
|
post_data = encoded_params
|
|
else:
|
|
raise error.APIConnectionError(
|
|
'Unrecognized HTTP method %r. This may indicate a bug in the '
|
|
'Stripe bindings. Please contact support@stripe.com for '
|
|
'assistance.' % (method,))
|
|
|
|
ua = {
|
|
'bindings_version': version.VERSION,
|
|
'lang': 'python',
|
|
'publisher': 'stripe',
|
|
'httplib': self._client.name,
|
|
}
|
|
for attr, func in [['lang_version', platform.python_version],
|
|
['platform', platform.platform],
|
|
['uname', lambda: ' '.join(platform.uname())]]:
|
|
try:
|
|
val = func()
|
|
except Exception as e:
|
|
val = "!! %s" % (e,)
|
|
ua[attr] = val
|
|
|
|
headers = {
|
|
'X-Stripe-Client-User-Agent': util.json.dumps(ua),
|
|
'User-Agent': 'Stripe/v1 PythonBindings/%s' % (version.VERSION,),
|
|
'Authorization': 'Bearer %s' % (my_api_key,)
|
|
}
|
|
|
|
if self.stripe_account:
|
|
headers['Stripe-Account'] = self.stripe_account
|
|
|
|
if method == 'post':
|
|
headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
|
|
if api_version is not None:
|
|
headers['Stripe-Version'] = api_version
|
|
|
|
if supplied_headers is not None:
|
|
for key, value in supplied_headers.items():
|
|
headers[key] = value
|
|
|
|
rbody, rcode, rheaders = self._client.request(
|
|
method, abs_url, headers, post_data)
|
|
|
|
util.logger.info('%s %s %d', method.upper(), abs_url, rcode)
|
|
util.logger.debug(
|
|
'API request to %s returned (response code, response body) of '
|
|
'(%d, %r)',
|
|
abs_url, rcode, rbody)
|
|
return rbody, rcode, rheaders, my_api_key
|
|
|
|
def interpret_response(self, rbody, rcode, rheaders):
|
|
try:
|
|
if hasattr(rbody, 'decode'):
|
|
rbody = rbody.decode('utf-8')
|
|
resp = util.json.loads(rbody)
|
|
except Exception:
|
|
raise error.APIError(
|
|
"Invalid response body from API: %s "
|
|
"(HTTP response code was %d)" % (rbody, rcode),
|
|
rbody, rcode, rheaders)
|
|
if not (200 <= rcode < 300):
|
|
self.handle_api_error(rbody, rcode, resp, rheaders)
|
|
return resp
|
|
|
|
# Deprecated request handling. Will all be removed in 2.0
|
|
def _deprecated_request(self, impl, method, url, headers, params):
|
|
warnings.warn(
|
|
'The *_request functions of APIRequestor are deprecated and '
|
|
'will be removed in version 2.0. Please use the client classes '
|
|
' in `stripe.http_client` instead',
|
|
DeprecationWarning, stacklevel=2)
|
|
|
|
method = method.lower()
|
|
|
|
if method == 'get' or method == 'delete':
|
|
if params:
|
|
url = self.build_url(url, params)
|
|
post_data = None
|
|
elif method == 'post':
|
|
post_data = self.encode(params)
|
|
else:
|
|
raise error.APIConnectionError(
|
|
'Unrecognized HTTP method %r. This may indicate a bug in the '
|
|
'Stripe bindings. Please contact support@stripe.com for '
|
|
'assistance.' % (method,))
|
|
|
|
client = impl(verify_ssl_certs=self._client._verify_ssl_certs)
|
|
return client.request(method, url, headers, post_data)
|
|
|
|
def _deprecated_handle_error(self, impl, *args):
|
|
warnings.warn(
|
|
'The handle_*_error functions of APIRequestor are deprecated and '
|
|
'will be removed in version 2.0. Please use the client classes '
|
|
' in `stripe.http_client` instead',
|
|
DeprecationWarning, stacklevel=2)
|
|
|
|
client = impl(verify_ssl_certs=self._client._verify_ssl_certs)
|
|
return client._handle_request_error(*args)
|
|
|
|
def requests_request(self, meth, abs_url, headers, params):
|
|
from libraries.stripe.http_client import RequestsClient
|
|
return self._deprecated_request(RequestsClient, meth, abs_url,
|
|
headers, params)
|
|
|
|
def handle_requests_error(self, err):
|
|
from libraries.stripe.http_client import RequestsClient
|
|
return self._deprecated_handle_error(RequestsClient, err)
|
|
|
|
def pycurl_request(self, meth, abs_url, headers, params):
|
|
from libraries.stripe.http_client import PycurlClient
|
|
return self._deprecated_request(PycurlClient, meth, abs_url,
|
|
headers, params)
|
|
|
|
def handle_pycurl_error(self, err):
|
|
from libraries.stripe.http_client import PycurlClient
|
|
return self._deprecated_handle_error(PycurlClient, err)
|
|
|
|
def urlfetch_request(self, meth, abs_url, headers, params):
|
|
from libraries.stripe.http_client import UrlFetchClient
|
|
return self._deprecated_request(UrlFetchClient, meth, abs_url,
|
|
headers, params)
|
|
|
|
def handle_urlfetch_error(self, err, abs_url):
|
|
from libraries.stripe.http_client import UrlFetchClient
|
|
return self._deprecated_handle_error(UrlFetchClient, err, abs_url)
|
|
|
|
def urllib2_request(self, meth, abs_url, headers, params):
|
|
from libraries.stripe.http_client import Urllib2Client
|
|
return self._deprecated_request(Urllib2Client, meth, abs_url,
|
|
headers, params)
|
|
|
|
def handle_urllib2_error(self, err, abs_url):
|
|
from libraries.stripe.http_client import Urllib2Client
|
|
return self._deprecated_handle_error(Urllib2Client, err)
|