2012-08-30 23:51:59 +00:00
|
|
|
# https://github.com/stripe/stripe-python
|
|
|
|
# https://stripe.com/docs/api?lang=python#top
|
|
|
|
|
2012-09-24 23:29:20 +00:00
|
|
|
import logging
|
|
|
|
from datetime import datetime, timedelta
|
2012-09-01 05:59:22 +00:00
|
|
|
from pytz import utc
|
|
|
|
|
2012-09-24 23:29:20 +00:00
|
|
|
from django.conf import settings
|
|
|
|
|
[#37053797] reverting stripelib.py -- Sn tests run but django command test_stripe_charge fails: done so Eric can fix circular import issue:
>>> >>> >>> (regluitdj14)raymond-yees-computer:regluit raymondyee$ django-admin.py test_stripe_charge
Traceback (most recent call last):
File "/Users/raymondyee/.virtualenvs/regluitdj14/bin/django-admin.py", line 5, in <module>
management.execute_from_command_line()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 261, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/management/commands/test_stripe_charge.py", line 2, in <module>
from regluit.payment import stripelib
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/stripelib.py", line 10, in <module>
from regluit.payment.models import Account
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/models.py", line 4, in <module>
from regluit.core.models import Campaign, Wishlist, Premium, PledgeExtra
File "/Users/raymondyee/C/src/Gluejar/regluit/core/models.py", line 998, in <module>
from regluit.payment.manager import PaymentManager
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/manager.py", line 2, in <module>
from regluit.payment.models import Transaction, Receiver, PaymentResponse
ImportError: cannot import name Transaction
2012-10-02 19:02:45 +00:00
|
|
|
from regluit.payment.models import Account
|
2012-09-21 18:24:42 +00:00
|
|
|
from regluit.payment.parameters import PAYMENT_HOST_STRIPE
|
2012-09-27 16:32:29 +00:00
|
|
|
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, PAYMENT_TYPE_AUTHORIZATION, TRANSACTION_STATUS_CANCELED
|
[#37053797] reverting stripelib.py -- Sn tests run but django command test_stripe_charge fails: done so Eric can fix circular import issue:
>>> >>> >>> (regluitdj14)raymond-yees-computer:regluit raymondyee$ django-admin.py test_stripe_charge
Traceback (most recent call last):
File "/Users/raymondyee/.virtualenvs/regluitdj14/bin/django-admin.py", line 5, in <module>
management.execute_from_command_line()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 261, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/management/commands/test_stripe_charge.py", line 2, in <module>
from regluit.payment import stripelib
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/stripelib.py", line 10, in <module>
from regluit.payment.models import Account
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/models.py", line 4, in <module>
from regluit.core.models import Campaign, Wishlist, Premium, PledgeExtra
File "/Users/raymondyee/C/src/Gluejar/regluit/core/models.py", line 998, in <module>
from regluit.payment.manager import PaymentManager
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/manager.py", line 2, in <module>
from regluit.payment.models import Transaction, Receiver, PaymentResponse
ImportError: cannot import name Transaction
2012-10-02 19:02:45 +00:00
|
|
|
from regluit.payment import baseprocessor
|
2012-09-21 18:24:42 +00:00
|
|
|
from regluit.utils.localdatetime import now, zuluformat
|
|
|
|
|
2012-08-17 00:24:18 +00:00
|
|
|
import stripe
|
|
|
|
|
2012-09-24 23:29:20 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
class StripeError(Exception):
|
|
|
|
pass
|
|
|
|
|
2012-08-30 23:51:59 +00:00
|
|
|
try:
|
|
|
|
import unittest
|
|
|
|
from unittest import TestCase
|
|
|
|
except:
|
|
|
|
from django.test import TestCase
|
|
|
|
from django.utils import unittest
|
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
# if customer.id doesn't exist, create one and then charge the customer
|
|
|
|
# we probably should ask our users whether they are ok with our creating a customer id account -- or ask for credit
|
|
|
|
# card info each time....
|
|
|
|
|
2012-08-17 00:24:18 +00:00
|
|
|
# should load the keys for Stripe from db -- but for now just hardcode here
|
2012-09-05 23:11:32 +00:00
|
|
|
# moving towards not having the stripe api key for the non profit partner in the unglue.it code -- but in a logically
|
|
|
|
# distinct application
|
|
|
|
|
2012-08-17 00:24:18 +00:00
|
|
|
try:
|
|
|
|
from regluit.core.models import Key
|
|
|
|
STRIPE_PK = Key.objects.get(name="STRIPE_PK").value
|
|
|
|
STRIPE_SK = Key.objects.get(name="STRIPE_SK").value
|
|
|
|
logger.info('Successful loading of STRIPE_*_KEYs')
|
|
|
|
except Exception, e:
|
2012-08-30 23:51:59 +00:00
|
|
|
# currently test keys for Gluejar and for raymond.yee@gmail.com as standin for non-profit
|
2012-08-27 14:49:43 +00:00
|
|
|
STRIPE_PK = 'pk_0EajXPn195ZdF7Gt7pCxsqRhNN5BF'
|
|
|
|
STRIPE_SK = 'sk_0EajIO4Dnh646KPIgLWGcO10f9qnH'
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 23:51:59 +00:00
|
|
|
# set default stripe api_key to that of unglue.it
|
|
|
|
|
2012-08-17 00:24:18 +00:00
|
|
|
stripe.api_key = STRIPE_SK
|
2012-08-30 23:51:59 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
# https://stripe.com/docs/testing
|
|
|
|
|
|
|
|
TEST_CARDS = (
|
|
|
|
('4242424242424242', 'Visa'),
|
|
|
|
('4012888888881881', 'Visa'),
|
|
|
|
('5555555555554444', 'MasterCard'),
|
|
|
|
('5105105105105100', 'MasterCard'),
|
|
|
|
('378282246310005', 'American Express'),
|
|
|
|
('371449635398431', 'American Express'),
|
|
|
|
('6011111111111117', 'Discover'),
|
|
|
|
('6011000990139424', 'Discover'),
|
|
|
|
('30569309025904', "Diner's Club"),
|
|
|
|
('38520000023237', "Diner's Club"),
|
|
|
|
('3530111333300000', 'JCB'),
|
|
|
|
('3566002020360505','JCB')
|
|
|
|
)
|
|
|
|
|
2012-08-31 18:19:05 +00:00
|
|
|
ERROR_TESTING = dict((
|
|
|
|
('ADDRESS1_ZIP_FAIL', ('4000000000000010', 'address_line1_check and address_zip_check will both fail')),
|
|
|
|
('ADDRESS1_FAIL', ('4000000000000028', 'address_line1_check will fail.')),
|
|
|
|
('ADDRESS_ZIP_FAIL', ('4000000000000036', 'address_zip_check will fail.')),
|
|
|
|
('CVC_CHECK_FAIL', ('4000000000000101', 'cvc_check will fail.')),
|
2012-09-01 05:59:22 +00:00
|
|
|
('BAD_ATTACHED_CARD', ('4000000000000341', 'Attaching this card to a Customer object will succeed, but attempts to charge the customer will fail.')),
|
2012-08-31 18:19:05 +00:00
|
|
|
('CHARGE_DECLINE', ('4000000000000002', 'Charges with this card will always be declined.'))
|
|
|
|
))
|
2012-08-30 16:24:42 +00:00
|
|
|
|
2012-09-01 05:59:22 +00:00
|
|
|
# types of errors / when they can be handled
|
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
#card_declined: Use this special card number - 4000000000000002.
|
|
|
|
#incorrect_number: Use a number that fails the Luhn check, e.g. 4242424242424241.
|
|
|
|
#invalid_expiry_month: Use an invalid month e.g. 13.
|
|
|
|
#invalid_expiry_year: Use a year in the past e.g. 1970.
|
|
|
|
#invalid_cvc: Use a two digit number e.g. 99.
|
|
|
|
|
|
|
|
|
|
|
|
def filter_none(d):
|
|
|
|
return dict([(k,v) for (k,v) in d.items() if v is not None])
|
2012-08-17 00:24:18 +00:00
|
|
|
|
|
|
|
# if you create a Customer object, then you'll be able to charge multiple times. You can create a customer with a token.
|
|
|
|
|
|
|
|
# https://stripe.com/docs/tutorials/charges
|
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
def card (number=TEST_CARDS[0][0], exp_month='01', exp_year='2020', cvc=None, name=None,
|
|
|
|
address_line1=None, address_line2=None, address_zip=None, address_state=None, address_country=None):
|
|
|
|
|
|
|
|
card = {
|
|
|
|
"number": number,
|
|
|
|
"exp_month": str(exp_month),
|
|
|
|
"exp_year": str(exp_year),
|
|
|
|
"cvc": str(cvc) if cvc is not None else None,
|
|
|
|
"name": name,
|
|
|
|
"address_line1": address_line1,
|
|
|
|
"address_line2": address_line2,
|
|
|
|
"address_zip": address_zip,
|
|
|
|
"address_state": address_state,
|
|
|
|
"address_country": address_country
|
|
|
|
}
|
|
|
|
|
|
|
|
return filter_none(card)
|
|
|
|
|
|
|
|
|
|
|
|
class StripeClient(object):
|
|
|
|
def __init__(self, api_key=STRIPE_SK):
|
|
|
|
self.api_key = api_key
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 23:51:59 +00:00
|
|
|
# key entities: Charge, Customer, Token, Event
|
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
@property
|
|
|
|
def charge(self):
|
|
|
|
return stripe.Charge(api_key=self.api_key)
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
@property
|
|
|
|
def customer(self):
|
|
|
|
return stripe.Customer(api_key=self.api_key)
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
@property
|
|
|
|
def token(self):
|
|
|
|
return stripe.Token(api_key=self.api_key)
|
2012-09-01 05:59:22 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def transfer(self):
|
|
|
|
return stripe.Transfer(api_key=self.api_key)
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
@property
|
|
|
|
def event(self):
|
|
|
|
return stripe.Event(api_key=self.api_key)
|
2012-09-01 05:59:22 +00:00
|
|
|
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
def create_token(self, card):
|
|
|
|
return stripe.Token(api_key=self.api_key).create(card=card)
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
def create_customer (self, card=None, description=None, email=None, account_balance=None, plan=None, trial_end=None):
|
|
|
|
"""card is a dictionary or a token"""
|
|
|
|
# https://stripe.com/docs/api?lang=python#create_customer
|
2012-08-17 00:24:18 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
customer = stripe.Customer(api_key=self.api_key).create(
|
|
|
|
card=card,
|
|
|
|
description=description,
|
|
|
|
email=email,
|
|
|
|
account_balance=account_balance,
|
|
|
|
plan=plan,
|
|
|
|
trial_end=trial_end
|
|
|
|
)
|
|
|
|
|
|
|
|
# customer.id is useful to save in db
|
|
|
|
return customer
|
|
|
|
|
|
|
|
|
|
|
|
def create_charge(self, amount, currency="usd", customer=None, card=None, description=None ):
|
|
|
|
# https://stripe.com/docs/api?lang=python#create_charge
|
2012-09-19 00:56:38 +00:00
|
|
|
# customer.id or card required but not both
|
2012-08-30 16:24:42 +00:00
|
|
|
# charge the Customer instead of the card
|
|
|
|
# amount in cents
|
2012-09-10 14:23:03 +00:00
|
|
|
|
2012-08-30 16:24:42 +00:00
|
|
|
charge = stripe.Charge(api_key=self.api_key).create(
|
|
|
|
amount=int(100*amount), # in cents
|
|
|
|
currency=currency,
|
2012-09-19 00:56:38 +00:00
|
|
|
customer=customer,
|
2012-09-10 14:23:03 +00:00
|
|
|
card=card,
|
2012-08-30 16:24:42 +00:00
|
|
|
description=description
|
|
|
|
)
|
|
|
|
|
|
|
|
return charge
|
|
|
|
|
|
|
|
def refund_charge(self, charge_id):
|
|
|
|
# https://stripe.com/docs/api?lang=python#refund_charge
|
|
|
|
ch = stripe.Charge(api_key=self.api_key).retrieve(charge_id)
|
|
|
|
ch.refund()
|
|
|
|
return ch
|
|
|
|
|
|
|
|
def list_all_charges(self, count=None, offset=None, customer=None):
|
|
|
|
# https://stripe.com/docs/api?lang=python#list_charges
|
|
|
|
return stripe.Charge(api_key=self.api_key).all(count=count, offset=offset, customer=customer)
|
|
|
|
|
2012-08-30 23:51:59 +00:00
|
|
|
# what to work through?
|
|
|
|
|
2012-09-01 05:59:22 +00:00
|
|
|
# can't test Transfer in test mode: "There are no transfers in test mode."
|
|
|
|
|
2012-08-30 23:51:59 +00:00
|
|
|
#pledge scenario
|
2012-08-31 18:19:05 +00:00
|
|
|
# bad card -- what types of erros to handle?
|
|
|
|
# https://stripe.com/docs/api#errors
|
|
|
|
|
|
|
|
# what errors are handled in the python library and how?
|
2012-09-05 23:11:32 +00:00
|
|
|
#
|
2012-08-31 18:19:05 +00:00
|
|
|
|
2012-09-01 05:59:22 +00:00
|
|
|
# Account?
|
|
|
|
|
2012-09-05 23:11:32 +00:00
|
|
|
# https://stripe.com/docs/api#event_types
|
|
|
|
# events of interest -- especially ones that do not directly arise immediately (synchronously) from something we do -- I think
|
|
|
|
# especially: charge.disputed
|
|
|
|
# I think following (charge.succeeded, charge.failed, charge.refunded) pretty much sychronous to our actions
|
2012-09-01 05:59:22 +00:00
|
|
|
# customer.created, customer.updated, customer.deleted
|
2012-09-05 23:11:32 +00:00
|
|
|
|
|
|
|
# transfer
|
|
|
|
# I expect the ones related to transfers all happen asynchronously: transfer.created, transfer.updated, transfer.failed
|
2012-09-01 05:59:22 +00:00
|
|
|
|
|
|
|
# When will the money I charge with Stripe end up in my bank account?
|
|
|
|
# Every day, we transfer the money that you charged seven days previously?that is, you receive the money for your March 1st charges on March 8th.
|
2012-08-31 18:19:05 +00:00
|
|
|
|
|
|
|
# pending payments?
|
|
|
|
# how to tell whether money transferred to bank account yet
|
|
|
|
# best practices for calling Events -- not too often.
|
2012-08-30 23:51:59 +00:00
|
|
|
|
|
|
|
class PledgeScenarioTest(TestCase):
|
2012-08-31 18:19:05 +00:00
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
cls._sc = StripeClient(api_key=STRIPE_SK)
|
|
|
|
|
|
|
|
# valid card
|
2012-08-30 23:51:59 +00:00
|
|
|
card0 = card()
|
2012-08-31 18:19:05 +00:00
|
|
|
cls._good_cust = cls._sc.create_customer(card=card0, description="test good customer", email="raymond.yee@gmail.com")
|
|
|
|
|
|
|
|
# bad card
|
2012-09-01 05:59:22 +00:00
|
|
|
test_card_num_to_get_BAD_ATTACHED_CARD = ERROR_TESTING['BAD_ATTACHED_CARD'][0]
|
|
|
|
card1 = card(number=test_card_num_to_get_BAD_ATTACHED_CARD)
|
2012-08-31 18:19:05 +00:00
|
|
|
cls._cust_bad_card = cls._sc.create_customer(card=card1, description="test bad customer", email="rdhyee@gluejar.com")
|
|
|
|
|
2012-08-30 23:51:59 +00:00
|
|
|
def test_charge_good_cust(self):
|
2012-09-19 00:56:38 +00:00
|
|
|
charge = self._sc.create_charge(10, customer=self._good_cust.id, description="$10 for good cust")
|
2012-09-15 00:00:21 +00:00
|
|
|
self.assertEqual(type(charge.id), str)
|
|
|
|
|
|
|
|
# print out all the pieces of Customer and Charge objects
|
|
|
|
print dir(charge)
|
|
|
|
print dir(self._good_cust)
|
2012-08-31 18:19:05 +00:00
|
|
|
|
2012-09-01 05:59:22 +00:00
|
|
|
def test_error_creating_customer_with_declined_card(self):
|
|
|
|
# should get a CardError upon attempt to create Customer with this card
|
|
|
|
_card = card(number=card(ERROR_TESTING['CHARGE_DECLINE'][0]))
|
|
|
|
self.assertRaises(stripe.CardError, self._sc.create_customer, card=_card)
|
|
|
|
|
2012-08-31 18:19:05 +00:00
|
|
|
def test_charge_bad_cust(self):
|
2012-09-01 05:59:22 +00:00
|
|
|
# expect the card to be declined -- and for us to get CardError
|
2012-08-31 18:19:05 +00:00
|
|
|
self.assertRaises(stripe.CardError, self._sc.create_charge, 10,
|
2012-09-19 00:56:38 +00:00
|
|
|
customer = self._cust_bad_card.id, description="$10 for bad cust")
|
2012-09-15 00:00:21 +00:00
|
|
|
|
2012-09-10 14:23:03 +00:00
|
|
|
|
2012-08-31 18:19:05 +00:00
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
2012-09-15 00:00:21 +00:00
|
|
|
# clean up stuff we create in test -- right now list current objects
|
|
|
|
|
|
|
|
#cls._good_cust.delete()
|
|
|
|
|
2012-09-01 05:59:22 +00:00
|
|
|
print "list of customers"
|
2012-09-15 00:00:21 +00:00
|
|
|
print [(i, c.id, c.description, c.email, datetime.fromtimestamp(c.created, tz=utc), c.account_balance, c.delinquent, c.active_card.fingerprint, c.active_card.type, c.active_card.last4, c.active_card.exp_month, c.active_card.exp_year, c.active_card.country) for(i, c) in enumerate(cls._sc.customer.all()["data"])]
|
2012-09-01 05:59:22 +00:00
|
|
|
|
|
|
|
print "list of charges"
|
2012-09-15 00:00:21 +00:00
|
|
|
print [(i, c.id, c.amount, c.amount_refunded, c.currency, c.description, datetime.fromtimestamp(c.created, tz=utc), c.paid, c.fee, c.disputed, c.amount_refunded, c.failure_message, c.card.fingerprint, c.card.type, c.card.last4, c.card.exp_month, c.card.exp_year) for (i, c) in enumerate(cls._sc.charge.all()['data'])]
|
2012-09-01 05:59:22 +00:00
|
|
|
|
2012-09-15 00:00:21 +00:00
|
|
|
# can retrieve events since a certain time?
|
2012-08-31 18:19:05 +00:00
|
|
|
print "list of events", cls._sc.event.all()
|
2012-09-15 00:00:21 +00:00
|
|
|
print [(i, e.id, e.type, e.created, e.pending_webhooks, e.data) for (i,e) in enumerate(cls._sc.event.all()['data'])]
|
2012-08-30 23:51:59 +00:00
|
|
|
|
[#37053797] reverting stripelib.py -- Sn tests run but django command test_stripe_charge fails: done so Eric can fix circular import issue:
>>> >>> >>> (regluitdj14)raymond-yees-computer:regluit raymondyee$ django-admin.py test_stripe_charge
Traceback (most recent call last):
File "/Users/raymondyee/.virtualenvs/regluitdj14/bin/django-admin.py", line 5, in <module>
management.execute_from_command_line()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 261, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/management/commands/test_stripe_charge.py", line 2, in <module>
from regluit.payment import stripelib
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/stripelib.py", line 10, in <module>
from regluit.payment.models import Account
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/models.py", line 4, in <module>
from regluit.core.models import Campaign, Wishlist, Premium, PledgeExtra
File "/Users/raymondyee/C/src/Gluejar/regluit/core/models.py", line 998, in <module>
from regluit.payment.manager import PaymentManager
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/manager.py", line 2, in <module>
from regluit.payment.models import Transaction, Receiver, PaymentResponse
ImportError: cannot import name Transaction
2012-10-02 19:02:45 +00:00
|
|
|
class StripePaymentRequest(baseprocessor.BasePaymentRequest):
|
|
|
|
"""so far there is no need to have a separate class here"""
|
|
|
|
pass
|
2012-09-21 18:24:42 +00:00
|
|
|
|
2012-09-27 16:32:29 +00:00
|
|
|
def requires_explicit_preapprovals():
|
|
|
|
"""a function that returns for the given payment processor"""
|
|
|
|
return False
|
|
|
|
|
2012-09-24 18:30:21 +00:00
|
|
|
def make_account(user, token):
|
|
|
|
"""returns a payment.models.Account based on stripe token and user"""
|
|
|
|
|
|
|
|
sc = StripeClient()
|
|
|
|
|
|
|
|
# create customer and charge id and then charge the customer
|
2012-09-24 23:29:20 +00:00
|
|
|
customer = sc.create_customer(card=token, description=user.username,
|
2012-09-24 18:30:21 +00:00
|
|
|
email=user.email)
|
[#37053797] reverting stripelib.py -- Sn tests run but django command test_stripe_charge fails: done so Eric can fix circular import issue:
>>> >>> >>> (regluitdj14)raymond-yees-computer:regluit raymondyee$ django-admin.py test_stripe_charge
Traceback (most recent call last):
File "/Users/raymondyee/.virtualenvs/regluitdj14/bin/django-admin.py", line 5, in <module>
management.execute_from_command_line()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 261, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/management/commands/test_stripe_charge.py", line 2, in <module>
from regluit.payment import stripelib
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/stripelib.py", line 10, in <module>
from regluit.payment.models import Account
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/models.py", line 4, in <module>
from regluit.core.models import Campaign, Wishlist, Premium, PledgeExtra
File "/Users/raymondyee/C/src/Gluejar/regluit/core/models.py", line 998, in <module>
from regluit.payment.manager import PaymentManager
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/manager.py", line 2, in <module>
from regluit.payment.models import Transaction, Receiver, PaymentResponse
ImportError: cannot import name Transaction
2012-10-02 19:02:45 +00:00
|
|
|
|
2012-09-24 23:29:20 +00:00
|
|
|
account = Account(host = PAYMENT_HOST_STRIPE,
|
2012-09-24 18:30:21 +00:00
|
|
|
account_id = customer.id,
|
|
|
|
card_last4 = customer.active_card.last4,
|
|
|
|
card_type = customer.active_card.type,
|
|
|
|
card_exp_month = customer.active_card.exp_month,
|
|
|
|
card_exp_year = customer.active_card.exp_year,
|
|
|
|
card_fingerprint = customer.active_card.fingerprint,
|
|
|
|
card_country = customer.active_card.country,
|
|
|
|
user = user
|
|
|
|
)
|
|
|
|
|
|
|
|
account.save()
|
|
|
|
|
2012-09-24 23:29:20 +00:00
|
|
|
return account
|
2012-09-24 18:30:21 +00:00
|
|
|
|
[#37053797] reverting stripelib.py -- Sn tests run but django command test_stripe_charge fails: done so Eric can fix circular import issue:
>>> >>> >>> (regluitdj14)raymond-yees-computer:regluit raymondyee$ django-admin.py test_stripe_charge
Traceback (most recent call last):
File "/Users/raymondyee/.virtualenvs/regluitdj14/bin/django-admin.py", line 5, in <module>
management.execute_from_command_line()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 261, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/management/commands/test_stripe_charge.py", line 2, in <module>
from regluit.payment import stripelib
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/stripelib.py", line 10, in <module>
from regluit.payment.models import Account
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/models.py", line 4, in <module>
from regluit.core.models import Campaign, Wishlist, Premium, PledgeExtra
File "/Users/raymondyee/C/src/Gluejar/regluit/core/models.py", line 998, in <module>
from regluit.payment.manager import PaymentManager
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/manager.py", line 2, in <module>
from regluit.payment.models import Transaction, Receiver, PaymentResponse
ImportError: cannot import name Transaction
2012-10-02 19:02:45 +00:00
|
|
|
class Pay(StripePaymentRequest, baseprocessor.Pay):
|
|
|
|
pass
|
2012-09-24 18:30:21 +00:00
|
|
|
|
[#37053797] reverting stripelib.py -- Sn tests run but django command test_stripe_charge fails: done so Eric can fix circular import issue:
>>> >>> >>> (regluitdj14)raymond-yees-computer:regluit raymondyee$ django-admin.py test_stripe_charge
Traceback (most recent call last):
File "/Users/raymondyee/.virtualenvs/regluitdj14/bin/django-admin.py", line 5, in <module>
management.execute_from_command_line()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
utility.execute()
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 261, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/Users/raymondyee/.virtualenvs/regluitdj14/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/management/commands/test_stripe_charge.py", line 2, in <module>
from regluit.payment import stripelib
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/stripelib.py", line 10, in <module>
from regluit.payment.models import Account
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/models.py", line 4, in <module>
from regluit.core.models import Campaign, Wishlist, Premium, PledgeExtra
File "/Users/raymondyee/C/src/Gluejar/regluit/core/models.py", line 998, in <module>
from regluit.payment.manager import PaymentManager
File "/Users/raymondyee/C/src/Gluejar/regluit/payment/manager.py", line 2, in <module>
from regluit.payment.models import Transaction, Receiver, PaymentResponse
ImportError: cannot import name Transaction
2012-10-02 19:02:45 +00:00
|
|
|
class Preapproval(StripePaymentRequest, baseprocessor.Preapproval):
|
2012-09-22 00:40:33 +00:00
|
|
|
|
|
|
|
def __init__( self, transaction, amount, expiry=None, return_url=None, paymentReason=""):
|
|
|
|
|
|
|
|
# set the expiration date for the preapproval if not passed in. This is what the paypal library does
|
|
|
|
|
|
|
|
self.transaction = transaction
|
|
|
|
|
|
|
|
now_val = now()
|
|
|
|
if expiry is None:
|
|
|
|
expiry = now_val + timedelta( days=settings.PREAPPROVAL_PERIOD )
|
|
|
|
transaction.date_authorized = now_val
|
|
|
|
transaction.date_expired = expiry
|
|
|
|
|
|
|
|
sc = StripeClient()
|
|
|
|
|
|
|
|
# let's figure out what part of transaction can be used to store info
|
|
|
|
# try placing charge id in transaction.pay_key
|
|
|
|
# need to set amount
|
|
|
|
# how does transaction.max_amount get set? -- coming from /pledge/xxx/ -> manager.process_transaction
|
|
|
|
# max_amount is set -- but I don't think we need it for stripe
|
|
|
|
|
2012-09-24 18:30:21 +00:00
|
|
|
# ASSUMPTION: a user has any given moment one and only one active payment Account
|
2012-09-24 23:29:20 +00:00
|
|
|
|
|
|
|
if transaction.user.account_set.filter(date_deactivated__isnull=True).count() > 1:
|
|
|
|
logger.warning("user {0} has more than one active payment account".format(transaction.user))
|
|
|
|
elif transaction.user.account_set.filter(date_deactivated__isnull=True).count() == 0:
|
|
|
|
logger.warning("user {0} has no active payment account".format(transaction.user))
|
|
|
|
raise StripeError("user {0} has no active payment account".format(transaction.user))
|
|
|
|
|
|
|
|
account = transaction.user.account_set.filter(date_deactivated__isnull=True)[0]
|
|
|
|
logger.info("user: {0} customer.id is {1}".format(transaction.user, account.account_id))
|
2012-09-22 00:40:33 +00:00
|
|
|
|
|
|
|
# settings to apply to transaction for TRANSACTION_STATUS_ACTIVE
|
|
|
|
# should approved be set to False and wait for a webhook?
|
|
|
|
transaction.approved = True
|
|
|
|
transaction.type = PAYMENT_TYPE_AUTHORIZATION
|
|
|
|
transaction.host = PAYMENT_HOST_STRIPE
|
|
|
|
transaction.status = TRANSACTION_STATUS_ACTIVE
|
|
|
|
|
2012-09-24 23:29:20 +00:00
|
|
|
transaction.preapproval_key = account.account_id
|
2012-09-22 00:40:33 +00:00
|
|
|
|
|
|
|
transaction.currency = 'USD'
|
2012-09-24 23:29:20 +00:00
|
|
|
transaction.amount = amount
|
2012-09-22 00:40:33 +00:00
|
|
|
|
|
|
|
transaction.save()
|
2012-09-24 23:29:20 +00:00
|
|
|
|
|
|
|
def key(self):
|
|
|
|
return self.transaction.preapproval_key
|
2012-09-25 18:52:56 +00:00
|
|
|
|
|
|
|
def next_url(self):
|
|
|
|
"""return None because no redirection to stripe is required"""
|
|
|
|
return None
|
2012-09-22 00:40:33 +00:00
|
|
|
|
|
|
|
|
2012-09-21 18:24:42 +00:00
|
|
|
class Execute(StripePaymentRequest):
|
|
|
|
|
|
|
|
'''
|
|
|
|
The Execute function sends an existing token(generated via the URL from the pay operation), and collects
|
|
|
|
the money.
|
|
|
|
'''
|
|
|
|
|
|
|
|
def __init__(self, transaction=None):
|
|
|
|
self.transaction = transaction
|
|
|
|
|
|
|
|
# execute transaction
|
|
|
|
assert transaction.host == PAYMENT_HOST_STRIPE
|
|
|
|
|
|
|
|
sc = StripeClient()
|
|
|
|
|
|
|
|
# look at transaction.preapproval_key
|
|
|
|
# is it a customer or a token?
|
|
|
|
|
|
|
|
# BUGBUG: replace description with somethin more useful
|
|
|
|
if transaction.preapproval_key.startswith('cus_'):
|
|
|
|
charge = sc.create_charge(transaction.amount, customer=transaction.preapproval_key, description="${0} for test / retain cc".format(transaction.amount))
|
|
|
|
elif transaction.preapproval_key.startswith('tok_'):
|
|
|
|
charge = sc.create_charge(transaction.amount, card=transaction.preapproval_key, description="${0} for test / cc not retained".format(transaction.amount))
|
|
|
|
|
|
|
|
transaction.status = TRANSACTION_STATUS_COMPLETE
|
|
|
|
transaction.pay_key = charge.id
|
|
|
|
transaction.date_payment = now()
|
|
|
|
transaction.save()
|
|
|
|
|
|
|
|
self.charge = charge
|
|
|
|
|
|
|
|
def api(self):
|
|
|
|
return "Base Pay"
|
|
|
|
|
|
|
|
def key(self):
|
|
|
|
# IN paypal land, our key is updated from a preapproval to a pay key here, just return the existing key
|
|
|
|
return self.transaction.pay_key
|
|
|
|
|
2012-09-27 16:32:29 +00:00
|
|
|
|
|
|
|
class PreapprovalDetails(StripePaymentRequest):
|
|
|
|
'''
|
|
|
|
Get details about an authorized token
|
|
|
|
|
|
|
|
This api must set 4 different class variables to work with the code in manager.py
|
|
|
|
|
|
|
|
status - one of the global transaction status codes
|
|
|
|
approved - boolean value
|
|
|
|
currency - not used in this API, but we can get some more info via other APIs - TODO
|
|
|
|
amount - not used in this API, but we can get some more info via other APIs - TODO
|
|
|
|
|
|
|
|
'''
|
|
|
|
def __init__(self, transaction):
|
|
|
|
|
|
|
|
self.transaction = transaction
|
|
|
|
self.status = self.transaction.status
|
|
|
|
if self.status == TRANSACTION_STATUS_CANCELED:
|
|
|
|
self.approved = False
|
|
|
|
else:
|
|
|
|
self.approved = True
|
|
|
|
|
|
|
|
# Set the other fields that are expected. We don't have values for these now, so just copy the transaction
|
|
|
|
self.currency = transaction.currency
|
|
|
|
self.amount = transaction.amount
|
2012-09-21 18:24:42 +00:00
|
|
|
|
2012-08-30 23:51:59 +00:00
|
|
|
def suite():
|
|
|
|
|
|
|
|
testcases = [PledgeScenarioTest]
|
|
|
|
#testcases = []
|
|
|
|
suites = unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(testcase) for testcase in testcases])
|
|
|
|
#suites.addTest(LibraryThingTest('test_cache'))
|
|
|
|
#suites.addTest(SettingsTest('test_dev_me_alignment')) # give option to test this alignment
|
|
|
|
return suites
|
|
|
|
|
|
|
|
|
2012-08-17 00:24:18 +00:00
|
|
|
# IPNs/webhooks: https://stripe.com/docs/webhooks
|
2012-08-30 23:51:59 +00:00
|
|
|
# how to use pending_webhooks ?
|
2012-08-17 00:24:18 +00:00
|
|
|
|
|
|
|
# all events
|
|
|
|
# https://stripe.com/docs/api?lang=python#list_events
|
2012-08-30 23:51:59 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
#unittest.main()
|
|
|
|
suites = suite()
|
|
|
|
#suites = unittest.defaultTestLoader.loadTestsFromModule(__import__('__main__'))
|
|
|
|
unittest.TextTestRunner().run(suites)
|