Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge master #44

Merged
merged 56 commits into from
Nov 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
99cf811
CustomerSubscriptionWebhook: let sync_customer fetch the live customer
blueyed Oct 6, 2017
da7eab1
Merge branch 'master' into CustomerSubscriptionWebhook-lazy-stripe_cu…
blueyed Oct 9, 2017
e7790dd
Merge branch 'master' into CustomerSubscriptionWebhook-lazy-stripe_cu…
blueyed Oct 16, 2017
9bf1c12
Plan: currency: blank=False
blueyed Oct 11, 2017
e3e9942
Merge branch 'master' into CustomerSubscriptionWebhook-lazy-stripe_cu…
blueyed Oct 23, 2017
f52bfe7
Merge branch 'master' into fix-plan-currency
blueyed Oct 23, 2017
274abcf
add_event: get stripe_account from message
blueyed Oct 25, 2017
0a91f0a
Merge branch 'master' into add-event-stripe-account
blueyed Oct 25, 2017
573fbbe
Merge branch 'master' into fix-plan-currency
paltman Oct 25, 2017
030bb9e
Merge branch 'master' into add-event-stripe-account
paltman Oct 25, 2017
c1d69aa
Merge branch 'master' into fix-plan-currency
paltman Oct 25, 2017
cbec232
Merge pull request #451 from blueyed/merge-migrations
paltman Oct 25, 2017
73ee8db
Merge branch 'master' into add-event-stripe-account
blueyed Oct 25, 2017
fd2261f
Merge branch 'master' into account-publishable_key
blueyed Oct 25, 2017
60a0254
coverage: use default exclude_lines and clean up
blueyed Oct 25, 2017
477e3e7
Fix type checking of balance_transaction
lukeburden Oct 22, 2017
908fab2
doc fixes
blueyed Oct 6, 2017
c1bd6ac
Set related name to avoid conflict with DUA
paltman Oct 26, 2017
1b67b87
Merge pull request #455 from pinax/related-name
paltman Oct 26, 2017
3594038
pinax/stripe/tests/settings: fix deprecation warnings
blueyed Oct 26, 2017
9dd1160
pinax/stripe/tests/settings: remove support for Django < 1.8
blueyed Oct 26, 2017
0f8c5f6
Add Event.__repr__
blueyed Oct 26, 2017
f30c2fc
tests: improve/merge/rename existing repr tests
blueyed Oct 26, 2017
6fd9d3c
doc: fix dupe_event_exists
blueyed Oct 26, 2017
258d94a
actions.charges.create: require customer or source
blueyed Oct 26, 2017
4a08673
Merge branch 'master' into account-publishable_key
blueyed Oct 26, 2017
6c7189b
Merge branch 'master' into fix-plan-currency
blueyed Oct 26, 2017
ba8d8e6
Webhook.post: use body with log_exception
blueyed Oct 27, 2017
0724834
Update python versions in Environment Setup
grahamu Oct 29, 2017
94426f5
Merge pull request #453 from blueyed/improve-test_customer_admin-capt…
paltman Oct 30, 2017
817bda2
Merge pull request #454 from blueyed/coverage-pragma
paltman Oct 30, 2017
92bbf25
Merge pull request #456 from blueyed/fix-test-settings
paltman Oct 30, 2017
19b22be
Merge pull request #457 from blueyed/fix-test-settings-old
paltman Oct 30, 2017
afe0b48
Merge pull request #458 from blueyed/event-repr
paltman Oct 30, 2017
95e7aee
Merge pull request #459 from blueyed/minor
paltman Oct 30, 2017
57a834a
Merge pull request #460 from blueyed/charge-customer-or-source
paltman Oct 30, 2017
d996ace
Merge pull request #449 from blueyed/add-event-stripe-account
paltman Oct 30, 2017
8dacc4e
Merge pull request #461 from blueyed/test_webhook_duplicate_event-data
paltman Oct 30, 2017
83e5e44
Merge pull request #386 from blueyed/CustomerSubscriptionWebhook-lazy…
paltman Oct 30, 2017
2afd0ba
Merge pull request #396 from blueyed/fix-plan-currency
paltman Oct 30, 2017
091a3a7
Merge remote-tracking branch 'origin/master' into account-publishable…
blueyed Oct 30, 2017
57523f3
Merge migrations
blueyed Oct 30, 2017
009fcfd
Merge branch 'master' into account-foregin-key
paltman Oct 30, 2017
abdc904
Merge pull request #433 from lukeburden/fix-string-check-on-charge-ba…
paltman Oct 30, 2017
087d016
Add CircleCI Badge
paltman Oct 30, 2017
229b3be
Merge pull request #441 from blueyed/account-publishable_key
paltman Oct 30, 2017
2ad68de
Merge branch 'master' into account-foregin-key
paltman Oct 30, 2017
e45b225
isort complains about the space
paltman Oct 30, 2017
924cb4b
Fix add_event for changes in master
blueyed Oct 30, 2017
dd8bfc7
Merge migrations
blueyed Oct 30, 2017
2c0d585
Merge pull request #463 from pinax/fix-readme-matrix
paltman Oct 30, 2017
e7bcb03
Merge pull request #427 from ticosax/account-foregin-key
paltman Oct 30, 2017
277bf0d
Merge branch 'master' into next
blueyed Oct 30, 2017
7bee473
Revert "Merge pull request #25 from blueyed/revert-stripe_publishable…
blueyed Oct 30, 2017
3f7dc39
Merge migrations
blueyed Oct 30, 2017
ac40f67
Attempt to solve migration conflict
ticosax Nov 1, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[![](https://img.shields.io/badge/license-MIT-blue.svg)](https://pypi.python.org/pypi/pinax-stripe/)

[![Codecov](https://img.shields.io/codecov/c/github/pinax/pinax-stripe.svg)](https://codecov.io/gh/pinax/pinax-stripe)
[![CircleCI](https://circleci.com/gh/pinax/pinax-stripe.svg?style=svg)](https://circleci.com/gh/pinax/pinax-stripe)
![](https://img.shields.io/github/contributors/pinax/pinax-stripe.svg)
![](https://img.shields.io/github/issues-pr/pinax/pinax-stripe.svg)
![](https://img.shields.io/github/issues-pr-closed/pinax/pinax-stripe.svg)
Expand Down Expand Up @@ -52,21 +53,20 @@ Then:
```
$ CFLAGS="-I$(xcrun --show-sdk-path)/usr/include -I$(brew --prefix openssl)/include" \
LDFLAGS="-L$(brew --prefix openssl)/lib" \
pyenv install 2.7.10 3.2.6 3.3.6 3.4.3 3.5.0
pyenv install 2.7.14 3.4.7 3.5.4 3.6.3

$ pyenv virtualenv 2.7.10 test-2.7.10
$ pyenv virtualenv 3.2.6 test-3.2.6
$ pyenv virtualenv 3.3.6 test-3.3.6
$ pyenv virtualenv 3.4.3 test-3.4.3
$ pyenv virtualenv 3.5.0 test-3.5.0
$ pyenv global 2.7.10 test-2.7.10 test-3.2.6 test-3.2.6 test-3.3.6 test-3.4.3 test-3.5.0
$ pyenv virtualenv 2.7.14
$ pyenv virtualenv 3.4.7
$ pyenv virtualenv 3.5.4
$ pyenv virtualenv 3.6.3
$ pyenv global 2.7.14 3.4.7 3.5.4 3.6.3

$ pip install detox
```

To run test suite:

Make sure you are not inside a `virtualenv` and then:
Make sure you are NOT inside a `virtualenv` and then:

```
$ detox
Expand Down
3 changes: 1 addition & 2 deletions docs/reference/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ Args:
- api_version: the version of the Stripe API used.
- request_id: the id of the request that initiated the webhook.
- pending_webhooks: the number of pending webhooks. Defaults to `0`.
- stripe_account: the stripe_id of a Connect account

#### pinax.stripe.actions.events.dupe_event_exists

Expand Down Expand Up @@ -228,7 +227,7 @@ This assumes line items from a Stripe invoice.lines property and not through
the invoicesitems resource calls. At least according to the documentation
the data for an invoice item is slightly different between the two calls.

For example, going through the invoiceitems resource you don't get a "type"
For example, going through the invoiceitems resource you do not get a "type"
field on the object.

Args:
Expand Down
6 changes: 3 additions & 3 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

#### pinax.stripe.management.commands.init_customers

Create `pinax.stripe.models.Customer` objects for existing users that don't
Create `pinax.stripe.models.Customer` objects for existing users that do not
have one.

#### pinax.stripe.management.commands.sync_customers

Synchronizes customer data from the Stripe API
Synchronizes customer data from the Stripe API.

Utilizes the following actions:

Expand All @@ -17,6 +17,6 @@ Utilizes the following actions:

#### pinax.stripe.management.commands.sync_plans

Make sure your Stripe account has the plans
Make sure your Stripe account has the plans.

Utilizes `pinax.stripe.actions.plans.sync_plans`.
6 changes: 2 additions & 4 deletions docs/reference/webhooks.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Webhooks

Stripe sends a events for just about everything that happens in it's system as
Stripe sends a events for just about everything that happens in its system as
a JSON payload to a webhook.

A webhook is an endpoint running your site that accepts `POST` requests. You
Expand Down Expand Up @@ -32,18 +32,16 @@ pictured above is:

https://yourdomain.com/payments/webhook/


## Security

Since this is a wide open URL we don't want to record and react to any data
Since this is a wide open URL we do not want to record and react to any data
sent our way. Therefore, we actually record the data that is sent, but then
before processing it, we validate it against the Stripe API. If it validates
as untampered data, then we continue the processing.

If validation fails, then `Event.valid` will be set to `False` enabling at
least some data to try and hunt down any malicious activity.


## Signals

`pinax-stripe` handles certain events in the webhook processing that are
Expand Down
20 changes: 14 additions & 6 deletions pinax/stripe/actions/charges.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.db.models import Q

import stripe
from six import string_types

from .. import hooks, models, utils

Expand Down Expand Up @@ -40,7 +41,9 @@ def capture(charge, amount=None):
sync_charge_from_stripe_data(stripe_charge)


def _validate_create_params(amount, application_fee, destination_account, destination_amount, on_behalf_of):
def _validate_create_params(customer, source, amount, application_fee, destination_account, destination_amount, on_behalf_of):
if not customer and not source:
raise ValueError("Must provide `customer` or `source`.")
if not isinstance(amount, decimal.Decimal):
raise ValueError(
"You must supply a decimal value for `amount`."
Expand All @@ -63,18 +66,23 @@ def _validate_create_params(amount, application_fee, destination_account, destin


def create(
amount, customer, source=None, currency="usd", description=None,
amount, customer=None, source=None, currency="usd", description=None,
send_receipt=settings.PINAX_STRIPE_SEND_EMAIL_RECEIPTS, capture=True,
email=None, destination_account=None, destination_amount=None,
application_fee=None, on_behalf_of=None,
):
"""
Create a charge for the given customer.
Create a charge for the given customer or source.

If both customer and source are provided, the source must belong to the
customer.

See https://stripe.com/docs/api#create_charge-customer.

Args:
amount: should be a decimal.Decimal amount
customer: the Stripe id of the customer to charge
source: the Stripe id of the source belonging to the customer
source: the Stripe id of the source to charge
currency: the currency with which to charge the amount in
description: a description of the charge
send_receipt: send a receipt upon successful charge
Expand All @@ -87,7 +95,7 @@ def create(
Returns:
a pinax.stripe.models.Charge object
"""
_validate_create_params(amount, application_fee, destination_account, destination_amount, on_behalf_of)
_validate_create_params(customer, source, amount, application_fee, destination_account, destination_amount, on_behalf_of)
kwargs = dict(
amount=utils.convert_amount_for_api(amount, currency), # find the final amount
currency=currency,
Expand Down Expand Up @@ -175,7 +183,7 @@ def sync_charge_from_stripe_data(data):
if data["refunded"]:
obj.amount_refunded = obj.amount
balance_transaction = data.get("balance_transaction")
if balance_transaction and not isinstance(balance_transaction, str):
if balance_transaction and not isinstance(balance_transaction, string_types):
obj.available = balance_transaction["status"] == "available"
obj.available_on = utils.convert_tstamp(
balance_transaction, "available_on"
Expand Down
14 changes: 10 additions & 4 deletions pinax/stripe/actions/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


def add_event(stripe_id, kind, livemode, message, api_version="",
request_id="", pending_webhooks=0, stripe_account=None):
request_id="", pending_webhooks=0):
"""
Adds and processes an event from a received webhook

Expand All @@ -15,8 +15,14 @@ def add_event(stripe_id, kind, livemode, message, api_version="",
api_version: the version of the Stripe API used
request_id: the id of the request that initiated the webhook
pending_webhooks: the number of pending webhooks
stripe_account: the stripe_id of a Connect account
"""
stripe_account_id = message.get("account")
if stripe_account_id:
stripe_account, _ = models.Account.objects.get_or_create(
stripe_id=stripe_account_id
)
else:
stripe_account = None
event = models.Event.objects.create(
stripe_account=stripe_account,
stripe_id=stripe_id,
Expand All @@ -38,9 +44,9 @@ def dupe_event_exists(stripe_id):
Checks if a duplicate event exists

Args:
stripe_id: the Stripe ID of the event to Checks
stripe_id: the Stripe ID of the event to check

Returns:
True, if the event already exists, otherwise, False
True if the event already exists, False otherwise
"""
return models.Event.objects.filter(stripe_id=stripe_id).exists()
2 changes: 1 addition & 1 deletion pinax/stripe/management/commands/init_customers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class Command(BaseCommand):

help = "Create customer objects for existing users that don't have one"
help = "Create customer objects for existing users that do not have one"

def handle(self, *args, **options):
User = get_user_model()
Expand Down
12 changes: 6 additions & 6 deletions pinax/stripe/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@

try:
from django.urls import resolve
except ImportError: # coverage: omit
from django.core.urlresolvers import resolve # coverage: omit
except ImportError:
from django.core.urlresolvers import resolve

try:
from django.utils.deprecation import MiddlewareMixin as MixinorObject
except ImportError: # coverage: omit
MixinorObject = object # coverage: omit
except ImportError:
MixinorObject = object


class ActiveSubscriptionMiddleware(MixinorObject):

def process_request(self, request):
is_authenticated = request.user.is_authenticated
if django.VERSION < (1, 10): # coverage: omit
is_authenticated = is_authenticated() # coverage: omit
if django.VERSION < (1, 10):
is_authenticated = is_authenticated()

if is_authenticated and not request.user.is_staff:
url_name = resolve(request.path).url_name
Expand Down
20 changes: 20 additions & 0 deletions pinax/stripe/migrations/0011_account_publishable_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-24 09:13
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('pinax_stripe', '0010_connect'),
]

operations = [
# migrations.AddField(
# model_name='account',
# name='stripe_publishable_key',
# field=models.CharField(blank=True, max_length=100, null=True),
# ),
]
22 changes: 22 additions & 0 deletions pinax/stripe/migrations/0013_auto_20171025_2153.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-26 02:53
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('pinax_stripe', '0012_merge_20171025_1443'),
]

operations = [
migrations.AlterField(
model_name='account',
name='user',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stripe_accounts', to=settings.AUTH_USER_MODEL),
),
]
16 changes: 16 additions & 0 deletions pinax/stripe/migrations/0014_merge_20171030_1554.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-30 14:54
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('pinax_stripe', '0011_account_publishable_key'),
('pinax_stripe', '0013_auto_20171025_2153'),
]

operations = [
]
16 changes: 16 additions & 0 deletions pinax/stripe/migrations/0015_merge_20171030_1852.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-30 17:52
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('pinax_stripe', '0013_auto_20171027_1443'),
('pinax_stripe', '0014_merge_20171030_1554'),
]

operations = [
]
16 changes: 16 additions & 0 deletions pinax/stripe/migrations/0024_merge_20171030_1941.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-30 18:41
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('pinax_stripe', '0023_merge_20171027_1626'),
('pinax_stripe', '0015_merge_20171030_1852'),
]

operations = [
]
15 changes: 13 additions & 2 deletions pinax/stripe/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def stripe_account_stripe_id(self):
@python_2_unicode_compatible
class Plan(AccountRelatedStripeObject):
amount = models.DecimalField(decimal_places=2, max_digits=9)
currency = models.CharField(max_length=15)
currency = models.CharField(max_length=15, blank=False)
interval = models.CharField(max_length=15)
interval_count = models.IntegerField()
name = models.CharField(max_length=150)
Expand Down Expand Up @@ -171,6 +171,15 @@ def message(self):
def __str__(self):
return "{} - {}".format(self.kind, self.stripe_id)

def __repr__(self):
return "Event(pk={!r}, kind={!r}, customer={!r}, valid={!r}, stripe_id={!r})".format(
self.pk,
str(self.kind),
self.customer,
self.valid,
str(self.stripe_id),
)


class Transfer(AccountRelatedStripeObject):

Expand Down Expand Up @@ -501,7 +510,7 @@ def card(self):
@python_2_unicode_compatible
class Account(StripeObject):

user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE, related_name="stripe_accounts")

business_name = models.TextField(blank=True, null=True)
business_url = models.TextField(blank=True, null=True)
Expand Down Expand Up @@ -543,6 +552,8 @@ class Account(StripeObject):

stripe_publishable_key = models.CharField(null=True, blank=True, max_length=100)

stripe_publishable_key = models.CharField(null=True, blank=True, max_length=100)

product_description = models.TextField(null=True, blank=True)
statement_descriptor = models.TextField(null=True, blank=True)
support_email = models.TextField(null=True, blank=True)
Expand Down
Loading