mirror of
https://github.com/gooba42/adventureland.git
synced 2026-10-14 18:39:27 -05:00
Open source
This commit is contained in:
Executable
+342
@@ -0,0 +1,342 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user