Giter Club home page Giter Club logo

stripe-python's Introduction

Stripe Python Library

pypi Build Status Coverage Status

The Stripe Python library provides convenient access to the Stripe API from applications written in the Python language. It includes a pre-defined set of classes for API resources that initialize themselves dynamically from API responses which makes it compatible with a wide range of versions of the Stripe API.

Documentation

See the Python API docs.

See video demonstrations covering how to use the library.

Installation

You don't need this source code unless you want to modify the package. If you just want to use the package, just run:

pip install --upgrade stripe

Install from source with:

python setup.py install

Requirements

  • Python 3.6+ (PyPy supported)

Python 2.7 deprecation

The Python Software Foundation (PSF) community announced the end of support of Python 2 on 01 January 2020. Starting with version 6.0.0 Stripe SDK Python packages will no longer support Python 2.7. To continue to get new features and security updates, please make sure to update your Python runtime to Python 3.6+.

The last version of the Stripe SDK that supports Python 2.7 is 5.5.0.

Usage

The library needs to be configured with your account's secret key which is available in your Stripe Dashboard. Set stripe.api_key to its value:

from stripe import StripeClient

client = StripeClient("sk_test_...")

# list customers
customers = client.customers.list()

# print the first customer's email
print(customers.data[0].email)

# retrieve specific Customer
customer = client.customers.retrieve("cus_123456789")

# print that customer's email
print(customer.email)

Handling exceptions

Unsuccessful requests raise exceptions. The class of the exception will reflect the sort of error that occurred. Please see the Api Reference for a description of the error classes you should handle, and for information on how to inspect these errors.

Per-request Configuration

Configure individual requests with the options argument. For example, you can make requests with a specific Stripe Version or as a connected account:

from stripe import StripeClient

client = StripeClient("sk_test_...")

# list customers
client.customers.list(
    options={
        "api_key": "sk_test_...",
        "stripe_account": "acct_...",
        "stripe_version": "2019-02-19",
    }
)

# retrieve single customer
client.customers.retrieve(
    "cus_123456789",
    options={
        "api_key": "sk_test_...",
        "stripe_account": "acct_...",
        "stripe_version": "2019-02-19",
    }
)

Configuring an HTTP Client

You can configure your StripeClient to use urlfetch, requests, pycurl, or urllib2 with the http_client option:

client = StripeClient("sk_test_...", http_client=stripe.UrlFetchClient())
client = StripeClient("sk_test_...", http_client=stripe.RequestsClient())
client = StripeClient("sk_test_...", http_client=stripe.PycurlClient())
client = StripeClient("sk_test_...", http_client=stripe.Urllib2Client())

Without a configured client, by default the library will attempt to load libraries in the order above (i.e. urlfetch is preferred with urllib2 used as a last resort). We usually recommend that people use requests.

Configuring a Proxy

A proxy can be configured with the proxy client option:

client = StripeClient("sk_test_...", proxy="https://user:[email protected]:1234")

Configuring Automatic Retries

You can enable automatic retries on requests that fail due to a transient problem by configuring the maximum number of retries:

client = StripeClient("sk_test_...", max_network_retries=2)

Various errors can trigger a retry, like a connection error or a timeout, and also certain API responses like HTTP status 409 Conflict.

Idempotency keys are automatically generated and added to requests, when not given, to guarantee that retries are safe.

Logging

The library can be configured to emit logging that will give you better insight into what it's doing. The info logging level is usually most appropriate for production use, but debug is also available for more verbosity.

There are a few options for enabling it:

  1. Set the environment variable STRIPE_LOG to the value debug or info

    $ export STRIPE_LOG=debug
  2. Set stripe.log:

    import stripe
    stripe.log = 'debug'
  3. Enable it through Python's logging module:

    import logging
    logging.basicConfig()
    logging.getLogger('stripe').setLevel(logging.DEBUG)

Accessing response code and headers

You can access the HTTP response code and headers using the last_response property of the returned resource.

customer = client.customers.retrieve(
    "cus_123456789"
)

print(customer.last_response.code)
print(customer.last_response.headers)

Writing a Plugin

If you're writing a plugin that uses the library, we'd appreciate it if you identified using stripe.set_app_info():

stripe.set_app_info("MyAwesomePlugin", version="1.2.34", url="https://myawesomeplugin.info")

This information is passed along when the library makes calls to the Stripe API.

Telemetry

By default, the library sends telemetry to Stripe regarding request latency and feature usage. These numbers help Stripe improve the overall latency of its API for all users, and improve popular features.

You can disable this behavior if you prefer:

stripe.enable_telemetry = False

Types

In v7.1.0 and newer, the library includes type annotations. See the wiki for a detailed guide.

Please note that some annotations use features that were only fairly recently accepted, such as Unpack[TypedDict] that was accepted in January 2023. We have tested that these types are recognized properly by Pyright. Support for Unpack in MyPy is still experimental, but appears to degrade gracefully. Please report an issue if there is anything we can do to improve the types for your type checker of choice.

Types and the Versioning Policy

We release type changes in minor releases. While stripe-python follows semantic versioning, our semantic versions describe the runtime behavior of the library alone. Our type annotations are not reflected in the semantic version. That is, upgrading to a new minor version of stripe-python might result in your type checker producing a type error that it didn't before. You can use a ~=x.x or x.x.* version specifier in your requirements.txt to constrain pip to a certain minor range of stripe-python.

Types and API Versions

The types describe the Stripe API version that was the latest at the time of release. This is the version that your library sends by default. If you are overriding stripe.api_version / stripe_version on the StripeClient, or using a webhook endpoint tied to an older version, be aware that the data you see at runtime may not match the types.

Beta SDKs

Stripe has features in the beta phase that can be accessed via the beta version of this package. We would love for you to try these and share feedback with us before these features reach the stable phase. To install a beta version use pip install with the exact version you'd like to use:

pip install --pre stripe

Note There can be breaking changes between beta versions. Therefore we recommend pinning the package version to a specific beta version in your requirements file or setup.py. This way you can install the same version each time without breaking changes unless you are intentionally looking for the latest beta version.

We highly recommend keeping an eye on when the beta feature you are interested in goes from beta to stable so that you can move from using a beta version of the SDK to the stable version.

If your beta feature requires a Stripe-Version header to be sent, set the stripe.api_version field using the stripe.add_beta_version function:

stripe.add_beta_version("feature_beta", "v3")

Async

Asynchronous versions of request-making methods are available by suffixing the method name with _async.

# With StripeClient
client = StripeClient("sk_test_...")
customer = await client.customers.retrieve_async("cus_xyz")

# With global client
stripe.api_key = "sk_test_..."
customer = await stripe.Customer.retrieve_async("cus_xyz")

# .auto_paging_iter() implements both AsyncIterable and Iterable
async for c in await stripe.Customer.list_async().auto_paging_iter():
  ...

There is no .save_async as .save is deprecated since stripe-python v5. Please migrate to .modify_async.

The default HTTP client uses requests for making synchronous requests but httpx for making async requests. If you're migrating to async, we recommend you to explicitly initialize your own http client and pass it to StripeClient or set it as the global default.

# By default, an explicitly initialized HTTPXClient will raise an exception if you
# attempt to call a sync method. If you intend to only use async, this is useful to
# make sure you don't unintentionally make a synchronous request.
my_http_client = stripe.HTTPXClient()

# If you want to use httpx to make sync requests, you can disable this
# behavior.
my_http_client = stripe.HTTPXClient(allow_sync_methods=True)

# aiohttp is also available (does not support sync requests)
my_http_client = stripe.AIOHTTPClient()

# With StripeClient
client = StripeClient("sk_test_...", http_client=my_http_client)

# With the global client
stripe.default_http_client = my_http_client

You can also subclass stripe.HTTPClient and provide your own instance.

Support

New features and bug fixes are released on the latest major version of the Stripe Python library. If you are on an older major version, we recommend that you upgrade to the latest in order to use the new features and bug fixes including those for security vulnerabilities. Older major versions of the package will continue to be available for use, but will not be receiving any updates.

Development

The test suite depends on stripe-mock, so make sure to fetch and run it from a background terminal (stripe-mock's README also contains instructions for installing via Homebrew and other methods):

go install github.com/stripe/stripe-mock@latest
stripe-mock

Run the following command to set up the development virtualenv:

make

Run all tests on all supported Python versions:

make test

Run all tests for a specific Python version (modify -e according to your Python target):

TOX_ARGS="-e py37" make test

Run all tests in a single file:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py" make test

Run a single test suite:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py::TestUpdateableAPIResource" make test

Run a single test:

TOX_ARGS="-e py37 -- tests/api_resources/abstract/test_updateable_api_resource.py::TestUpdateableAPIResource::test_save" make test

Run the linter with:

make lint

The library uses Ruff for code formatting. Code must be formatted with Black before PRs are submitted, otherwise CI will fail. Run the formatter with:

make fmt

stripe-python's People

Contributors

amber-stripe avatar andrew-stripe avatar anniel-stripe avatar anurag avatar boucher avatar brandur avatar brandur-stripe avatar dcr-stripe avatar evan-stripe avatar gdb avatar jameshageman-stripe avatar jim-stripe avatar kamil-stripe avatar kiran-stripe avatar kjc-stripe avatar kyleconroy avatar metcalf avatar mickjermsurawong-stripe avatar mikez avatar ob-stripe avatar ofek avatar pakrym-stripe avatar ramya-stripe avatar rattrayalex-stripe avatar remi-stripe avatar richardm-stripe avatar richo avatar spakanati avatar stripe-openapi[bot] avatar wangjohn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stripe-python's Issues

API Docs Issue

Per the API docs, the proper way to create a refund is as follows:
screen shot 2014-08-11 at 12 27 05 am

But this doesn't work. You get AttributeError: 'list' object has no attribute 'create'.

This is because the correct way to create a refund (as described in #5) is ch.refund(amount=whatever).

Inconsistent card object

Docs suggests card retrieval returns name value as None or card holder name . In practice card doesn't have attribute name.

In [21]: cus.cards.retrieve("card_placeholder")
Out[21]:
<Card card id=card_placeholder at 0x4f08a40> JSON: {
  "address_city": null,
  "country": "US",
  "customer": "cus_placeholder",
  "cvc_check": "pass",
  "exp_month": 11,
  "exp_year": 2015,
  "fingerprint": "fingerprint",
  "id": "card_placeholder",
  "last4": "3214",
  "object": "card",
  "type": "Visa"
}

In [22]: card = cus.cards.retrieve("card_placeholder")

In [24]: hasattr(card, 'name')
Out[24]: False

#Stripe version: 
In [25]: stripe_obj.version.VERSION
Out[25]: '1.11.0'

resp.keys()

Using your example.py I try and do resp.keys(). It spits back the entire object description. I look at the code, and I see the keys definition which references self._values. I was hoping to not using the _values attribute, since its designated as private, though resp.keys() fails because _values is a set, and not a dict. Is keys() supposed to be removed? or it was missed in some refactor? Thanks!

Unable to unset bank account on recipient

Try to do:

import stripe
stripe.api_key = 'xxx'

rp = stripe.Recipient.retrieve('xxxxxx')
rp.bank_account = None
rp.save()

Get this:

InvalidRequestError

You passed an empty string for 'bank_account'. We assume empty values are an attempt to unset a parameter; however 'bank_account' cannot be unset. You should remove 'bank_account' from your request or supply a non-empty value

But I can't remove bank_account from the request and can't set it to "" either.

stripe not working as expected when installed via pip into a virtualenv

If I install Stripe via pip into a virtualenv and copy/paste the API doc code to create any of the classes such as Token, Charge, Customer, etc, I get:

'module' has no attribute '[classname]'

I tried this on Windows 7 and Ubuntu 11.10 and got the same result.

If you install stripe and dependencies into your system site-packages and then enable a virtualenv, you'll also get the same result.

Virtualenv support is absolutely critical for keeping versions of packages separate per project. If you guys could look into this, it would be super!

StripeObjects are unpickleable

This may be a use case you never considered (and maybe don't care about), but all objects derived from stripe.StripeObject cannot be unpickled.

The following will result in a RuntimeError:

import pickle
import stripe

obj = stripe.StripeObject(id="foo")
pickle.loads(pickle.dumps(obj))

pickle.loads triggers infinite recursion in StripeObject.__getattr__, when it tries to check for the existence of a __setstate__ method:

Stacktrace (most recent call last):

 File "pickle.py", line 1382, in loads
    return Unpickler(file).load()
  File "pickle.py", line 858, in load
    dispatch[key](self)
  File "pickle.py", line 1215, in load_build
    setstate = getattr(inst, "__setstate__", None)
  File "stripe/__init__.py", line 504, in __getattr__
    if k in self._transient_values:
  File "stripe/__init__.py", line 504, in __getattr__
    if k in self._transient_values:
  ...
  File "stripe/__init__.py", line 501, in __getattr__
    return self.__dict__[k]
  RuntimeError: maximum recursion depth exceeded

When unpickling the StripeObject, the _transient_values attribute doesn't exist, ergo the recursive call to __getattr__.

This can be fixed by either implementing a custom __getinitargs__ or __getnewargs__ method (see the Python pickle docs).

Example.py

Perhaps it's just me, but there seems to be something amiss in 'line 4' of Example.py.

'resp = stripe.Charge.execute(...' returns an error, while changing it to 'resp=stripe.Charge.create(...' as in the Stripe API documentation seems to work.

Just thought I'd pass this along.

Using OSX 10.7.1 / Python 2.7

AssertionError: No api proxy found for service "urlfetch"

We are using Google Compute engine on our project and we are also using Google SQL for our DB and Google Cloud Storage. We have to have Google App Engine installed to be able to connect to these other services. I ran into this problem when trying to run the init_plans.py command.

AssertionError: No api proxy found for service "urlfetch"

Here is the traceback.

Traceback (most recent call last):
File "/home/code/virtualenvs/_/local/lib/python2.7/site-packages/django/core/management/base.py", line 222, in run_from_argv
self.execute(_args, **options.dict)
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/django/core/management/base.py", line 255, in execute
output = self.handle(_args, _options)
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/payments/management/commands/init_customers.py", line 14, in handle
Customer.create(user=user)
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/payments/models.py", line 378, in create
email=user.email
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/stripe/init.py", line 703, in create
response, api_key = requestor.request('post', url, params)
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/stripe/init.py", line 233, in request
rbody, rcode, my_api_key = self.request_raw(meth, url, params)
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/stripe/init.py", line 292, in request_raw
rbody, rcode = self.urlfetch_request(meth, abs_url, headers, params)
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/stripe/init.py", line 432, in urlfetch_request
result = urlfetch.fetch(args)
File "/home/code/virtualenvs/
/local/lib/python2.7/site-packages/google/appengine/api/urlfetch.py", line 267, in fetch
rpc = create_rpc(deadline=deadline)
File "/home/code/virtualenvs/**__/local/lib/python2.7/site-packages/google/appengine/api/urlfetch.py", line 223, in create_rpc
return apiproxy_stub_map.UserRPC('urlfetch', deadline, callback)
File "/home/code/virtualenvs/
_/local/lib/python2.7/site-packages/google/appengine/api/apiproxy_stub_map.py", line 413, in init
self.__rpc = CreateRPC(service, stubmap)
File "/home/code/virtualenvs/
_
/local/lib/python2.7/site-packages/google/appengine/api/apiproxy_stub_map.py", line 67, in CreateRPC
assert stub, 'No api proxy found for service "%s"' % service
AssertionError: No api proxy found for service "urlfetch"

Since we have google app engine installed but are not using it there is an error thrown about api proxy.

To get around this I had to remove the following form init.py

try:
from google.appengine.api import urlfetch
_httplib = 'urlfetch'
except ImportError:
pass

Not sure what the appropriate fix for this should be going forward. I know my use case is probably rare, but figured you might want to know.

Stripe is still not working on google app engine development server

okay, so this issue is killing me, it is directly related to, if not the same as issues #75, and #74.

I've detailed a lot of my problems in issue #75, I understand that the workaround should be:

stripe.verify_ssl_certs = False

However, I've got this set, and a debug log shows it is set to false, just before my call to create a customer, however when I try to create the customer , I'm still getting the SSL error:

  File "/home/john/PycharmProjects/flask-peachy-new/server/lib/stripe/api_requestor.py", line 257, in _check_ssl_cert
    raise error.APIConnectionError(e)
APIConnectionError: [Errno 13] Permission denied

Documentation

stripe.Charge.create() says that you need to either provide a customer id or a credit card token. This does not mention how one would charge a specific card stored under a customer (rather than always the default card).

Looks like passing the card id to 'card' with the customer id works, but is not documented.

PycURL doesn't seem to work on Windows

When using PycURL on Windows, we end up with POST submissions like this:

   {
     "C:\\Python27\\lib\\email\\mime\\nonmultipart%2Epy%00n": ""
   }

We should either track down and squash the bug, or (easier) don't use PycURL on Windows (fall back on another library)

Storage objects

Is there a reason StripeObject is extending dict and additionally overriding __setattr__ in StripeObject? I see the value provided (accessing as dict or obj) however it seems like this repeats a lot of code and that a preferable alternative would be to follow the model of webpy's Storage object:

https://github.com/webpy/webpy/blob/master/web/utils.py, line 52:

class Storage(dict):
    """
    A Storage object is like a dictionary except `obj.foo` can be used
    in addition to `obj['foo']`.

        >>> o = storage(a=1)
        >>> o.a
        1
        >>> o['a']
        1
        >>> o.a = 2
        >>> o['a']
        2
        >>> del o.a
        >>> o.a
        Traceback (most recent call last):
            ...
        AttributeError: 'a'

    """
    def __getattr__(self, key): 
        try:
            return self[key]
        except KeyError, k:
            raise AttributeError, k

    def __setattr__(self, key, value): 
        self[key] = value

    def __delattr__(self, key):
        try:
            del self[key]
        except KeyError, k:
            raise AttributeError, k

    def __repr__(self):     
        return '<Storage ' + dict.__repr__(self) + '>'

Thus, instantiation would be simplified to StripeObject(Storage)

Customer.update_subscription() resets account_balance

We're on API version 2013-07-05 with stripe 1.18.0. Here's what we can do to reproduce. This example customer has a non-zero account_balance going into this:

    customer = stripe.Customer.retrieve(
        subscription_id,
        api_key=self._api_key,
    )

    # Make the changes. The response we get back from this is missing quite
    # a bit of data, so discard it.
    customer.update_subscription(plan=plan_id, card=credit_card)

    # Re-query the customer so we can get the full, up-to-date values.
    customer = stripe.Customer.retrieve(
        subscription_id,
        api_key=self._api_key,
        expand=['default_card'],
    )

At the end of this, we end up with an account balance of 0 again. This is obviously a pretty big disruption for us. Our tests started failing within the last week, so this appears to be a recent API breakage.

verify_ssl_certs flag not implemented for requests.request

It would be useful to me to be able to set stripe so that it ignores verifying ssl certificates. In requests, this is through the 'verify' kwargs.

Likewise, it might be useful for someone to set the .crt to use via the CA_BUNDLE variable, rather than automatically verifying against the stripe-supplied "data/ca-certificates.crt".

Thanks!

`deleted` on Customer not present when object is live

When checking to see if a customer is still active, you must do something like:

if getattr(customer, 'deleted', False):
do_something()

in order to avoid an AttributeError from deletednot being present on live objects.

This is incredibly minor, but it would nicer to be able to just do:

if customer.deleted:
do_something()

by defaulting it to False.

Fatal Python error: pycurl: libcurl link-time version is older than compile-time version

When I try to install the Stripe python package (http://pypi.python.org/pypi/stripe) on Ubuntu 10.10, I'm getting the following error:

Fatal Python error: pycurl: libcurl link-time version is older than compile-time version

According to these pages, it appears that there are some version differences:
http://kmaiti.blogspot.com/2011/02/fatal-python-error-pycurl-libcurl-lin...
http://ubuntuforums.org/showthread.php?t=1038856

Should I try updating libcurl or pycurl?

See the full traceback here:

  Downloading from URL http://pypi.python.org/packages/source/s/stripe/stripe-1.5.29.tar.gz#md5... (from http://pypi.python.org/simple/stripe/)
  Running setup.py egg_info for package stripe
    Fatal Python error: pycurl: libcurl link-time version is older than compile-time version
    Complete output from command python setup.py egg_info:
    Fatal Python error: pycurl: libcurl link-time version is older than compile-time version
----------------------------------------
Command python setup.py egg_info failed with error code -6
Exception information:
Traceback (most recent call last):
  File "/opt/ActivePython-2.7/lib/python2.7/site-packages/pip/basecommand.py", line 126, in main
    self.run(options, args)
  File "/opt/ActivePython-2.7/lib/python2.7/site-packages/pip/commands/install.py", line 223, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File "/opt/ActivePython-2.7/lib/python2.7/site-packages/pip/req.py", line 986, in prepare_files
    req_to_install.run_egg_info()
  File "/opt/ActivePython-2.7/lib/python2.7/site-packages/pip/req.py", line 222, in run_egg_info
    command_desc='python setup.py egg_info')
  File "/opt/ActivePython-2.7/lib/python2.7/site-packages/pip/__init__.py", line 255, in call_subprocess
    % (command_desc, proc.returncode))
InstallationError: Command python setup.py egg_info failed with error code -6

'module' object has no attribute 'Token'

Hi again, still having problems on Windows. I installed stripe-python from source, and I can import stripe, however when doing:

stripe.Token.create()

I get: 'module' object has no attribute 'Token'

Can someone please try this with Python 2.7.2 on Windows 7 and see if they get the same error?

Thanks!

Stripe Python API library broken for use on Google AppEngine

I've just updated Stripe API library to the latest version and it stopped working on Google AppEngine due to fact that GAE is blocking imports of some packages such as sockets and SSL.

ERROR    2014-05-10 09:55:16,576 base.py:215] Internal Server Error: /api/billing/subscribe_to_paid_plan/stripe
    Traceback (most recent call last):
...
     File "/src/classes/billing/api_views.py", line 3, in <module>
        import stripe
      File "/src/stripe/__init__.py", line 16, in <module>
        from stripe.resource import (  # noqa
      File "/src/stripe/resource.py", line 5, in <module>
        from stripe import api_requestor, error, util
      File "/src/stripe/api_requestor.py", line 5, in <module>
        import ssl
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 60, in <module>
        import _ssl             # if we can't import it, let the error propagate
      File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/devappserver2/python/sandbox.py", line 852, in load_module
        raise ImportError('No module named %s' % fullname)
    ImportError: No module named _ssl

Are there any chances to make it working on Google AppEngine?

I believe the old lib was just fine. It would be pity if we would be forced to use some other payment system as we like Stripe very much!

TypeError: must be _socket.socket, not socket

I'm just trying to get up and running with stripe, flask and app engine. Working through the sample flask checkout guide the following code is throwing a socket error:

customer = stripe.Customer.create(
        email='[email protected]',
        card=request.form['stripeToken']
    )

The stack trace:

File "/Users/adamoakman/Documents/entourage/code/src/application/views.py", line 49, in profile_entity
email='[email protected]',
File "/Users/adamoakman/Documents/entourage/code/src/lib/stripe/resource.py", line 269, in create
response, api_key = requestor.request('post', url, params)
File "/Users/adamoakman/Documents/entourage/code/src/lib/stripe/api_requestor.py", line 126, in request
self._check_ssl_cert()
File "/Users/adamoakman/Documents/entourage/code/src/lib/stripe/api_requestor.py", line 243, in _check_ssl_cert
(uri.hostname, uri.port or 443))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 448, in get_server_certificate
s.connect(addr)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 333, in connect
self._real_connect(addr, False)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 314, in _real_connect
self.ca_certs, self.ciphers)
TypeError: must be _socket.socket, not socket

Any ideas on what is wrong?

Upgrade the "requests" library dependency or allow never versions

I have other packages that require requests 1.0 or greater so I upgraded requests. Now I get this:

Warning: the Stripe library requires that your Python "requests" library has a version no older than 0.8.8, but your "requests" library has version 1.1.0. Stripe will fall back to an alternate HTTP library, so everything should work, though we recommend upgrading your "requests" library. If you have any questions, please contact support@stripe.com. (HINT: running "pip install -U requests" should upgrade your requests library to the latest version.)

to_dict() does not account for lists

The to_dict() function does not properly serialize the whole object, since lists that could potentially contain StripeObjects are passed through as-is. A good example is the Invoice object, invoice['list']['subscriptions'][0] is still a StripeObject.

Since this stuff is all mechanical, it should be pretty easy to write unit tests for, too.

Customize timeout values

I'm actually running into the same issue as explained in the stripe-ruby issue stripe/stripe-ruby#46 . Reading the thread on that issue, it seems like Heroku will go through with the request anyway. Recently, I've seen a fair amount of our stripe charges (4 times in the past 2 weeks) taking longer than 30 seconds (and hence Heroku cutting off the request) and the charge NOT ending up going through. I'm wondering if there is another issue going on?

Generating card tokens with test cards does not throw prescribed errors.

Using the testing documentation I've been trying to generate a CardError with using a credit card token generated from the card number 4000000000000002. Charging an order with this generated token does not cause a:

CardError: Your card's security code is incorrect.

But instead charges successfully.

Why is this the case?

If this is the wrong approach, how can I generate this error to test my application?

I'm generating tokens using the class below.

import stripe
from config import settings

class StripeCardTokenGenerator:

    def __init__(self, card_type="normal"):
        stripe.api_key = settings.STRIPE_API_KEY
        self.card_type = card_type
        self.card_number = {
            "normal": 4242424242424242,
            "card_declined": 4000000000000002,
            "incorrect_number": 4242424242424241,
            "expired_card": 4000000000000069,
            "processing_error": 4000000000000119,
            "incorrect_cvc": 4000000000000127,
            "fails_all_charges": 4000000000000341,
            "visa_debit": 4000056655665556
        }[card_type]
        self.card = {
            "number": self.card_number,
            "exp_month": 12,
            "exp_year": 2015,
            "cvc": 123
        }
        self.create_stripe_card_token()

    def create_stripe_card_token(self):
        token = stripe.Token.create(card=self.card).id
        print stripe.api_key
        print token
        return token

Python SDK interface design

Hi,
recently we started integrating some of our services with the Stripe API.
We are using Python to do that and my issue is related to the way the Python SDK interface is currently designed.

Consider the credit cards interface from the documentation:

customer = stripe.Customer.retrieve({CUSTOMER_ID})
customer.cards.create(card=dict(number='', exp_month=...))

This design makes stubbing the API requests extremely hard.
In order to handle this when testing the integration, it will require mocking a mocked object.

A simple solution to avoid such situations would be to delegate the card creation and retrieval methods to the customer object instead of a nested method.

Consider an updated example:

customer = stripe.Customer.retrieve({CUSTOMER_ID})
customer.createCard(card=dict(number='', exp_month=...))

This approach is a trivial change, but it makes the sdk integration testing process much more simple and is not damaging at all to the readability of the code.

What do you think about this?

StripeObjectEncoder encodes a string, not an object

Currently, the default() method of StripeObjectEncoder returns a string when the object is a StripeObject (see init.py:572). Per the json documentation: "default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError."

In other words, StripeObjectEncoder.default() should only return obj.to_dict().

StripeObject.__repr__ causes a TypeError in Python 3

Reproduced as follows:

import stripe
stripe.api_key = "<your api key>"
print(repr(stripe.Charge.all()))

Resulting in:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.3/site-packages/stripe/resource.py", line 138, in __repr__
    ' '.join(ident_parts), hex(id(self)), str(self))
TypeError: sequence item 1: expected str instance, bytes found

Thread safety

Is this api thread safe? I looked at the flask integration example which exposed the module at the global level. Just want to make sure that it is thread safe.

"ResourceWarning: unclosed <ssl.SSLSocket"

I'm getting ResourceWarnings when using the API for basic listings:

    import stripe
    stripe.api_key = api_key
    response = stripe.Plan.all()
    response = stripe.Customer.all()


(subscribers)Johns-iMac:src john$ python test.py StripeAuthTestCase
/Users/john/Code/lib/python3.4/site-packages/stripe/resource.py:99: ResourceWarning: unclosed <ssl.SSLSocket fd=4, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=6, laddr=('192.168.0.5', 58604), raddr=('50.18.212.223', 443)>
  instance = cls(values.get('id'), api_key)

/Users/john/Code/subscribers/lib/python3.4/site-packages/stripe/resource.py:48: ResourceWarning: unclosed <ssl.SSLSocket fd=4, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=6, laddr=('192.168.0.5', 58417), raddr=('50.18.212.223', 443)>
  return super(StripeObject, self).__setattr__(k, v)




Python 3.4.1 (default, May 19 2014, 13:10:29)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
>>> stripe.VERSION
'1.19.0'

Easy enough to quash by commenting out the import warnings in resource.py but an annoyance if you're the type to heed the warnings.

Python 3 Support

Python 3 is growing with Django recently starting to support it and Pyramid having supported it for a while. I think it would be beneficial to test and develop for both Python 2 and 3 compatibility simultaneously.

Stripe Timeout on App Engine Is Too Short When Being Called from TaskQueue

Currently, on Google App Engine, the stripe client times out if a request takes more than 55 seconds. The reason for this (see code below), is because Google App Engine has a 60 second timeout for normal requests. However, App Engine backends and TaskQueues are not subject to this deadline.

It is a common usage scenario to do a lot of heavy lifting for billing on a backend (e.g., running reports, generating invoices, etc.). Often the 55 second timeout is too short and the request times out.

Please increase this timeout, or better yet, detect when running in a TaskQueue and increase it only in that situation. Thank you.

stripe.init.py:427

    # GAE requests time out after 60 seconds, so make sure we leave
    # some time for the application to handle a slow Stripe
    args['deadline'] = 55

Stripe library doesn't work on Windows

Hello,

Stripe 1.6.1 doesn't seem very happy in a Windows 7, Python 2.7.2 environment. If you simply run:
[code]

import stripe
stripe.VERSION
[/code]
You'll get: AttributeError: 'module' object has no attribute 'VERSION'

You'll receive the same error when trying to use any of the other classes as well, like Token, Customer, Charge, etc.

Add support for Decimals.

Currently, the library supports cents. This works very well, but many people (equally validly) use Decimals for representing amounts in their code. Would it be possible for the library to check whether the provided amount is a Decimal and convert it to cents if so?

cannot unset a coupon

If I create a customer, and then attach an invalid coupon via customer.coupon = "invalid" I cannot unset this coupon code by setting .coupon to None as suggested in the documentation.

e.g.,

customer.coupon = "invalid"
customer.save()
InvalidRequestError: No such coupon: invalid
customer.coupon = ""
...
.coupon = None to delete the property

customer.coupon = None
customer.save()
InvalidRequestError: You passed an empty string for 'coupon'. We assume empty values are an attempt to unset a parameter; however 'coupon' cannot be unset. You should remove 'coupon' from your request or supply a non-empty value

Partial Refunds Don't Work

I tried making a partial refund by passing in an amount into the Charge.refund() function, but it complained that i was passing in two arguments when it only accepts 1.

Depreciation warning / documentation mismatch

Not really a problem but I'm getting a lot of depreciation warnings when using the module, so I checked out your API docs to get the latest way of doing things... which is to use stripe.Invoice etc, which causes the depreciation message!

I can't see any other way other than doing a from stripe.resource import Invoice - but then there's no way to set stripe.api_key.

Docs I'm looking at: https://stripe.com/docs/api?lang=python

Support a StripeClient and custom HTTP backends

As discussed in #40, a StripeClient (with an HTTP client) is a better pattern than one-off changes to support custom configuration. Here's a proposed API for how this will work.

import stripe
import stripe.http_client

client = stripe.Client(
    api_key='sk_test_xxxxxxxxxxxxxx',
    http_client=stripe.http_client.UrlFetchClient(deadline=80)
)

You shouldn't have to use the top level resource classes with a client, so we'll need to expose the resources as attributes

client.charges.all()
client.charges.retrieve()
client.charges.create()

I'd like to make this backwards compatible change, so I'm not proposing we change the current interface, only add the new StripeClient.

This API should also solve #23, #38, and #62 (maybe)

@metcalf thoughts?

Charging orders raise a CardError but are still charged.

Hi guys,

I'm creating charges with the way the documentation suggests:

charge = stripe.Charge.create(
    amount=nail_price,
    currency="usd",
    customer=user.stripe_customer_id,
    description=description
)

But with some users the charge throws:

CardError: Your card's security code is incorrect.

Even through their CVC code check has passed:

img

Additionally, the cards were successfully created and validated by an iOS application before my application charged them.

Why the cards be charged if they are throwing the CardError?

Please let me know if you need any additional information to solve this issue.

Add Content-Type header during HTTP requests with entity-body

Although it's not strictly mandated by the HTTP spec ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1 - SHOULD rather than MUST ), it might be helpful in a few situations if the stripe-python client explicitly sets a Content-Type on HTTP requests which include an entity-body.

I ran a couple of quick tests, one with the requests library available, and one where it's unavailable (fallback to urllib2), and in both cases the header is not specified when, for example, creating a recipient or transfer.

This came up while creating a test mock endpoint, where it turns out that werkzeug is fairly strict about the situations in which it will attempt to parse entity contents ( https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/wrappers.py#L314 , https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/wrappers.py#L350 )

Non-critical and there are various workarounds (intercepting and patching outbound requests), but it'd be a nice-to-have!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.