add in preapproval tokens if present, add in to purchase flow and make sure contributions are compat. (bug 707371, 707373)
This commit is contained in:
Родитель
af272542cb
Коммит
966ba81f4c
|
@ -1,5 +1,5 @@
|
|||
{# these are custom attributes on <div class="install ..."> found in
|
||||
# apps/addons/templates/addons/impala/button.html and
|
||||
{# these are custom attributes on <div class="install ..."> found in
|
||||
# apps/addons/templates/addons/impala/button.html and
|
||||
# apps/addons/templates/addons/mobile/button.html #}
|
||||
data-addon="{{ addon.id }}"
|
||||
data-icon="{{ addon.icon_url }}"
|
||||
|
|
|
@ -45,7 +45,8 @@
|
|||
</div>
|
||||
<button class="button prominent paypal"
|
||||
href="{{ shared_url('addons.purchase', addon) }}?"
|
||||
data-realurl="{{ download }}">
|
||||
data-realurl="{{ download }}"
|
||||
data-thanksurl="{{ shared_url('addons.purchase.thanks', addon) }}">
|
||||
{# The <small> makes it smaller, <em> makes it darker. Don't localize "PayPal". #}
|
||||
{{ loc('Pay <small>with</small> Pay<em>Pal</em>')|xssafe }}
|
||||
</button>
|
||||
|
|
|
@ -25,7 +25,7 @@ from abuse.models import AbuseReport
|
|||
from addons.models import (Addon, AddonDependency, AddonUpsell, AddonUser,
|
||||
Charity)
|
||||
from files.models import File
|
||||
from market.models import AddonPremium, AddonPurchase, Price
|
||||
from market.models import AddonPremium, AddonPurchase, PreApprovalUser, Price
|
||||
from paypal.tests.test import other_error
|
||||
from stats.models import Contribution
|
||||
from translations.helpers import truncate
|
||||
|
@ -151,7 +151,7 @@ class TestContributeEmbedded(amo.tests.TestCase):
|
|||
|
||||
@patch('paypal.get_paykey')
|
||||
def client_get(self, get_paykey, **kwargs):
|
||||
get_paykey.return_value = 'abc'
|
||||
get_paykey.return_value = ['abc', '']
|
||||
url = reverse('addons.contribute', args=kwargs.pop('rev'))
|
||||
if 'qs' in kwargs:
|
||||
url = url + kwargs.pop('qs')
|
||||
|
@ -296,20 +296,20 @@ class TestPurchaseEmbedded(amo.tests.TestCase):
|
|||
|
||||
@patch('paypal.get_paykey')
|
||||
def test_redirect(self, get_paykey):
|
||||
get_paykey.return_value = 'some-pay-key'
|
||||
get_paykey.return_value = ['some-pay-key', '']
|
||||
res = self.client.get(self.purchase_url)
|
||||
assert 'some-pay-key' in res['Location']
|
||||
|
||||
@patch('paypal.get_paykey')
|
||||
def test_ajax(self, get_paykey):
|
||||
get_paykey.return_value = 'some-pay-key'
|
||||
get_paykey.return_value = ['some-pay-key', '']
|
||||
res = self.client.get_ajax(self.purchase_url)
|
||||
assert json.loads(res.content)['paykey'] == 'some-pay-key'
|
||||
eq_(json.loads(res.content)['paykey'], 'some-pay-key')
|
||||
|
||||
@patch('paypal.get_paykey')
|
||||
def test_paykey_amount(self, get_paykey):
|
||||
# Test the amount the paykey for is the price.
|
||||
get_paykey.return_value = 'some-pay-key'
|
||||
get_paykey.return_value = ['some-pay-key', '']
|
||||
self.client.get_ajax(self.purchase_url)
|
||||
# wtf? Can we get any more [0]'s there?
|
||||
eq_(get_paykey.call_args_list[0][0][0]['amount'], Decimal('0.99'))
|
||||
|
@ -322,12 +322,54 @@ class TestPurchaseEmbedded(amo.tests.TestCase):
|
|||
|
||||
@patch('paypal.get_paykey')
|
||||
def test_paykey_contribution(self, get_paykey):
|
||||
get_paykey.return_value = 'some-pay-key'
|
||||
get_paykey.return_value = ['some-pay-key', '']
|
||||
self.client.get_ajax(self.purchase_url)
|
||||
cons = Contribution.objects.filter(type=amo.CONTRIB_PENDING)
|
||||
eq_(cons.count(), 1)
|
||||
eq_(cons[0].amount, Decimal('0.99'))
|
||||
|
||||
def check_contribution(self, state):
|
||||
cons = Contribution.objects.all()
|
||||
eq_(cons.count(), 1)
|
||||
eq_(cons[0].type, state)
|
||||
|
||||
@patch('paypal.check_purchase')
|
||||
@patch('paypal.get_paykey')
|
||||
def get_with_preapproval(self, get_paykey, check_purchase,
|
||||
check_purchase_result=None):
|
||||
get_paykey.return_value = ['some-pay-key', 'COMPLETED']
|
||||
check_purchase.return_value = check_purchase_result
|
||||
return self.client.get_ajax(self.purchase_url)
|
||||
|
||||
def test_paykey_pre_approval(self):
|
||||
res = self.get_with_preapproval(check_purchase_result='COMPLETED')
|
||||
eq_(json.loads(res.content)['status'], 'COMPLETED')
|
||||
self.check_contribution(amo.CONTRIB_PURCHASE)
|
||||
|
||||
def test_paykey_pre_approval_disagree(self):
|
||||
res = self.get_with_preapproval(check_purchase_result='No!!!')
|
||||
eq_(json.loads(res.content)['status'], 'NOT-COMPLETED')
|
||||
self.check_contribution(amo.CONTRIB_PENDING)
|
||||
|
||||
@patch('paypal.check_purchase')
|
||||
@patch('paypal.get_paykey')
|
||||
def test_paykey_pre_approval_no_ajax(self, get_paykey, check_purchase):
|
||||
get_paykey.return_value = ['some-pay-key', 'COMPLETED']
|
||||
check_purchase.return_value = 'COMPLETED'
|
||||
res = self.client.get(self.purchase_url)
|
||||
self.assertRedirects(res, shared_url('addons.detail', self.addon))
|
||||
|
||||
@patch('paypal.check_purchase')
|
||||
@patch('paypal.get_paykey')
|
||||
# Turning on the allow-pre-auth flag.
|
||||
@patch.object(waffle, 'flag_is_active', lambda x, y: True)
|
||||
def test_paykey_pre_approval_used(self, get_paykey, check_purchase):
|
||||
get_paykey.return_value = ['some-pay-key', 'COMPLETED']
|
||||
check_purchase.return_value = 'COMPLETED'
|
||||
pre = PreApprovalUser.objects.create(user=self.user, paypal_key='xyz')
|
||||
self.client.get_ajax(self.purchase_url)
|
||||
eq_(get_paykey.call_args[0][0]['preapproval'], pre)
|
||||
|
||||
@patch('addons.models.Addon.has_purchased')
|
||||
def test_has_purchased(self, has_purchased):
|
||||
has_purchased.return_value = True
|
||||
|
@ -548,6 +590,13 @@ class TestPaypalStart(PaypalStart):
|
|||
self.test_loggedin_notpurchased()
|
||||
eq_(Installed.objects.count(), 0)
|
||||
|
||||
def test_has_thanksurl(self):
|
||||
assert self.client.login(**self.data)
|
||||
res = self.client.get_ajax(self.url)
|
||||
eq_(pq(res.content).find('button.paypal').attr('data-thanksurl'),
|
||||
shared_url('addons.purchase.thanks', self.addon))
|
||||
|
||||
|
||||
|
||||
@patch.object(waffle, 'switch_is_active', lambda x: True)
|
||||
@patch.object(settings, 'LOGIN_RATELIMIT_USER', 10)
|
||||
|
|
|
@ -20,12 +20,14 @@ import jinja2
|
|||
import commonware.log
|
||||
import session_csrf
|
||||
from tower import ugettext as _, ugettext_lazy as _lazy
|
||||
import waffle
|
||||
from mobility.decorators import mobilized, mobile_template
|
||||
|
||||
import amo
|
||||
from amo import messages
|
||||
from amo.decorators import login_required, write
|
||||
from amo.forms import AbuseForm
|
||||
from amo.helpers import shared_url
|
||||
from amo.utils import sorted_groupby, randslice
|
||||
from amo.models import manual_order
|
||||
from amo import urlresolvers
|
||||
|
@ -499,8 +501,12 @@ def purchase(request, addon):
|
|||
uuid_ = hashlib.md5(str(uuid.uuid4())).hexdigest()
|
||||
# l10n: {0} is the addon name
|
||||
contrib_for = _(u'Purchase of {0}').format(jinja2.escape(addon.name))
|
||||
paykey, status, error = '', '', ''
|
||||
|
||||
preapproval = None
|
||||
if waffle.flag_is_active(request, 'allow-pre-auth') and request.amo_user:
|
||||
preapproval = request.amo_user.get_preapproval()
|
||||
|
||||
paykey, error = '', ''
|
||||
try:
|
||||
pattern = 'addons.purchase.finished'
|
||||
slug = addon.slug
|
||||
|
@ -508,12 +514,17 @@ def purchase(request, addon):
|
|||
pattern = 'apps.purchase.finished'
|
||||
slug = addon.app_slug
|
||||
|
||||
paykey = paypal.get_paykey(dict(uuid=uuid_, slug=slug,
|
||||
amount=amount, memo=contrib_for, email=addon.paypal_id,
|
||||
paykey, status = paypal.get_paykey(dict(
|
||||
amount=amount,
|
||||
chains=settings.PAYPAL_CHAINS,
|
||||
email=addon.paypal_id,
|
||||
ip=request.META.get('REMOTE_ADDR'),
|
||||
memo=contrib_for,
|
||||
pattern=pattern,
|
||||
preapproval=preapproval,
|
||||
qs={'realurl': request.GET.get('realurl')},
|
||||
chains=settings.PAYPAL_CHAINS))
|
||||
slug=slug,
|
||||
uuid=uuid_))
|
||||
except:
|
||||
log.error('Error getting paykey, purchase of addon: %s' % addon.pk,
|
||||
exc_info=True)
|
||||
|
@ -525,7 +536,22 @@ def purchase(request, addon):
|
|||
uuid=str(uuid_), type=amo.CONTRIB_PENDING,
|
||||
paykey=paykey, user=request.amo_user)
|
||||
log.debug('Storing contrib for uuid: %s' % uuid_)
|
||||
|
||||
# If this was a pre-approval, it's completed already, we'll
|
||||
# double check this with PayPal, just to be sure nothing went wrong.
|
||||
if status == 'COMPLETED':
|
||||
log.debug('Status is completed for uuid: %s' % uuid_)
|
||||
if paypal.check_purchase(paykey) == 'COMPLETED':
|
||||
log.debug('Check purchase is completed for uuid: %s' % uuid_)
|
||||
contrib.type = amo.CONTRIB_PURCHASE
|
||||
else:
|
||||
# In this case PayPal disagreed, we should not be trusting
|
||||
# what get_paykey said. Which is a worry.
|
||||
log.error('Check purchase failed on uuid: %s' % uuid_)
|
||||
status = 'NOT-COMPLETED'
|
||||
|
||||
contrib.save()
|
||||
|
||||
else:
|
||||
log.error('No paykey present for uuid: %s' % uuid_)
|
||||
|
||||
|
@ -535,9 +561,16 @@ def purchase(request, addon):
|
|||
if request.GET.get('result_type') == 'json' or request.is_ajax():
|
||||
return http.HttpResponse(json.dumps({'url': url,
|
||||
'paykey': paykey,
|
||||
'error': error}),
|
||||
'error': error,
|
||||
'status': status}),
|
||||
content_type='application/json')
|
||||
return http.HttpResponseRedirect(url)
|
||||
|
||||
# This is the non-Ajax fallback.
|
||||
if status != 'COMPLETED':
|
||||
return redirect(url)
|
||||
|
||||
messages.success(request, _('Purchase complete'))
|
||||
return redirect(shared_url('addons.detail', addon))
|
||||
|
||||
|
||||
# TODO(andym): again, remove this once we figure out logged out flow.
|
||||
|
@ -639,12 +672,17 @@ def contribute(request, addon):
|
|||
# l10n: {0} is the addon name
|
||||
contrib_for = _(u'Contribution for {0}').format(jinja2.escape(name))
|
||||
|
||||
paykey, error = '', ''
|
||||
paykey, error, status = '', '', ''
|
||||
try:
|
||||
paykey = paypal.get_paykey(dict(uuid=contribution_uuid,
|
||||
slug=addon.slug, amount=amount, email=paypal_id,
|
||||
memo=contrib_for, ip=request.META.get('REMOTE_ADDR'),
|
||||
pattern='%s.paypal' % ('apps' if webapp else 'addons')))
|
||||
paykey, status = paypal.get_paykey(dict(
|
||||
amount=amount,
|
||||
email=paypal_id,
|
||||
ip=request.META.get('REMOTE_ADDR'),
|
||||
memo=contrib_for,
|
||||
pattern='%s.paypal' %
|
||||
('apps' if webapp else 'addons'),
|
||||
slug=addon.slug,
|
||||
uuid=contribution_uuid))
|
||||
except:
|
||||
log.error('Error getting paykey, contribution for addon: %s'
|
||||
% addon.pk, exc_info=True)
|
||||
|
@ -672,7 +710,8 @@ def contribute(request, addon):
|
|||
# not have a paykey and the JS can cope appropriately.
|
||||
return http.HttpResponse(json.dumps({'url': url,
|
||||
'paykey': paykey,
|
||||
'error': error}),
|
||||
'error': error,
|
||||
'status': status}),
|
||||
content_type='application/json')
|
||||
return http.HttpResponseRedirect(url)
|
||||
|
||||
|
|
|
@ -24,7 +24,18 @@ class AuthError(PaypalError):
|
|||
pass
|
||||
|
||||
|
||||
class PreApprovalError(PaypalError):
|
||||
pass
|
||||
|
||||
|
||||
errors = {'520003': AuthError}
|
||||
# See http://bit.ly/vWV525 for information on these values.
|
||||
# Note that if you have and invalid preapproval key you get 580022, but this
|
||||
# also occurs in other cases so don't assume its preapproval only.
|
||||
for number in ['579024', '579025', '579026', '579027', '579028',
|
||||
'579030', '579031']:
|
||||
errors[number] = PreApprovalError
|
||||
|
||||
paypal_log = commonware.log.getLogger('z.paypal')
|
||||
|
||||
|
||||
|
@ -36,7 +47,7 @@ def should_ignore_paypal():
|
|||
return settings.DEBUG and 'sandbox' not in settings.PAYPAL_PERMISSIONS_URL
|
||||
|
||||
|
||||
def add_receivers(chains, email, amount, uuid):
|
||||
def add_receivers(chains, email, amount, uuid, preapproval=False):
|
||||
"""
|
||||
Split a payment down into multiple receivers using the chains passed in.
|
||||
"""
|
||||
|
@ -47,23 +58,30 @@ def add_receivers(chains, email, amount, uuid):
|
|||
this = (Decimal(str(float(amount) * (percent / 100.0)))
|
||||
.quantize(Decimal('.01')))
|
||||
remainder = remainder - this
|
||||
key = 'receiverList.receiver(%s)' % number
|
||||
result.update({
|
||||
'receiverList.receiver(%s).email' % number: destination,
|
||||
'receiverList.receiver(%s).amount' % number: str(this),
|
||||
'receiverList.receiver(%s).paymentType' % number: 'DIGITALGOODS',
|
||||
'receiverList.receiver(%s).primary' % number: 'false',
|
||||
'%s.email' % key: destination,
|
||||
'%s.amount' % key: str(this),
|
||||
'%s.primary' % key: 'false',
|
||||
# This is only done if there is a chained payment. Otherwise
|
||||
# it does not need to be set.
|
||||
'receiverList.receiver(0).primary': 'true',
|
||||
# Mozilla pays the fees, because we've got a special rate.
|
||||
'feesPayer': 'SECONDARYONLY'
|
||||
})
|
||||
if not preapproval:
|
||||
result['%s.paymentType' % key] = 'DIGITALGOODS'
|
||||
|
||||
result.update({
|
||||
'receiverList.receiver(0).email': email,
|
||||
'receiverList.receiver(0).amount': str(amount),
|
||||
'receiverList.receiver(0).invoiceID': 'mozilla-%s' % uuid,
|
||||
'receiverList.receiver(0).paymentType': 'DIGITALGOODS',
|
||||
'receiverList.receiver(0).invoiceID': 'mozilla-%s' % uuid
|
||||
})
|
||||
|
||||
# Adding DIGITALGOODS to a pre-approval triggers an error in PayPal.
|
||||
if not preapproval:
|
||||
result['receiverList.receiver(0).paymentType'] = 'DIGITALGOODS'
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
@ -94,17 +112,39 @@ def get_paykey(data):
|
|||
'trackingId': data['uuid'],
|
||||
'ipnNotificationUrl': absolutify(reverse('amo.paypal'))}
|
||||
|
||||
paypal_data.update(add_receivers(data.get('chains', ()), data['email'],
|
||||
data['amount'], data['uuid']))
|
||||
receivers = (data.get('chains', ()), data['email'], data['amount'],
|
||||
data['uuid'])
|
||||
|
||||
if 'preapproval' in data:
|
||||
# The paypal_key might be empty if they have removed it.
|
||||
key = data['preapproval'].paypal_key
|
||||
if key:
|
||||
paypal_log.info('Using preapproval: %s' % data['preapproval'].pk)
|
||||
paypal_data['preapprovalKey'] = key
|
||||
paypal_data.update(add_receivers(*receivers, preapproval=True))
|
||||
else:
|
||||
paypal_data.update(add_receivers(*receivers))
|
||||
|
||||
if data.get('memo'):
|
||||
paypal_data['memo'] = data['memo']
|
||||
|
||||
with statsd.timer('paypal.paykey.retrieval'):
|
||||
response = _call(settings.PAYPAL_PAY_URL + 'Pay', paypal_data,
|
||||
ip=data['ip'])
|
||||
try:
|
||||
with statsd.timer('paypal.paykey.retrieval'):
|
||||
response = _call(settings.PAYPAL_PAY_URL + 'Pay', paypal_data,
|
||||
ip=data['ip'])
|
||||
except PreApprovalError, e:
|
||||
# Let's retry just once without preapproval.
|
||||
paypal_log.error('Failed using preapproval, reason: %s' % e)
|
||||
# Now it's not a pre-approval, make sure we get the
|
||||
# DIGITALGOODS setting back in there.
|
||||
del paypal_data['preapprovalKey']
|
||||
paypal_data.update(add_receivers(*receivers))
|
||||
# If this fails, we won't try again, just fail.
|
||||
with statsd.timer('paypal.paykey.retrieval'):
|
||||
response = _call(settings.PAYPAL_PAY_URL + 'Pay', paypal_data,
|
||||
ip=data['ip'])
|
||||
|
||||
return response['payKey']
|
||||
return response['payKey'], response['paymentExecStatus']
|
||||
|
||||
|
||||
def check_purchase(paykey):
|
||||
|
|
|
@ -6,6 +6,7 @@ import urlparse
|
|||
from django.conf import settings
|
||||
|
||||
import mock
|
||||
from mock import Mock
|
||||
from nose.tools import eq_
|
||||
import time
|
||||
|
||||
|
@ -15,7 +16,6 @@ from amo.urlresolvers import reverse
|
|||
import amo.tests
|
||||
import paypal
|
||||
|
||||
|
||||
good_response = ('responseEnvelope.timestamp='
|
||||
'2011-01-28T06%3A16%3A33.259-08%3A00&responseEnvelope.ack=Success'
|
||||
'&responseEnvelope.correlationId=7377e6ae1263c'
|
||||
|
@ -26,8 +26,7 @@ auth_error = ('error(0).errorId=520003'
|
|||
'&error(0).message=Authentication+failed.+API+'
|
||||
'credentials+are+incorrect.')
|
||||
|
||||
other_error = ('error(0).errorId=520001'
|
||||
'&error(0).message=Foo')
|
||||
other_error = ('error(0).errorId=520001&error(0).message=Foo')
|
||||
|
||||
good_check_purchase = ('status=CREATED') # There is more, but I trimmed it.
|
||||
|
||||
|
@ -40,6 +39,13 @@ class TestPayKey(amo.tests.TestCase):
|
|||
'uuid': time.time(),
|
||||
'ip': '127.0.0.1',
|
||||
'pattern': 'addons.purchase.finished'}
|
||||
self.pre = Mock()
|
||||
self.pre.paypal_key = 'xyz'
|
||||
|
||||
def get_pre_data(self):
|
||||
data = self.data.copy()
|
||||
data['preapproval'] = self.pre
|
||||
return data
|
||||
|
||||
@mock.patch('urllib2.OpenerDirector.open')
|
||||
def test_auth_fails(self, opener):
|
||||
|
@ -49,7 +55,7 @@ class TestPayKey(amo.tests.TestCase):
|
|||
@mock.patch('urllib2.OpenerDirector.open')
|
||||
def test_get_key(self, opener):
|
||||
opener.return_value = StringIO(good_response)
|
||||
eq_(paypal.get_paykey(self.data), 'AP-9GD76073HJ780401K')
|
||||
eq_(paypal.get_paykey(self.data), ('AP-9GD76073HJ780401K', 'CREATED'))
|
||||
|
||||
@mock.patch('urllib2.OpenerDirector.open')
|
||||
def test_other_fails(self, opener):
|
||||
|
@ -60,7 +66,7 @@ class TestPayKey(amo.tests.TestCase):
|
|||
def test_qs_passed(self, _call):
|
||||
data = self.data.copy()
|
||||
data['qs'] = {'foo': 'bar'}
|
||||
_call.return_value = {'payKey': '123'}
|
||||
_call.return_value = {'payKey': '123', 'paymentExecStatus': ''}
|
||||
paypal.get_paykey(data)
|
||||
qs = _call.call_args[0][1]['returnUrl'].split('?')[1]
|
||||
eq_(dict(urlparse.parse_qsl(qs))['foo'], 'bar')
|
||||
|
@ -100,7 +106,7 @@ class TestPayKey(amo.tests.TestCase):
|
|||
@mock.patch('paypal._call')
|
||||
def test_dict_no_split(self, _call):
|
||||
data = self.data.copy()
|
||||
_call.return_value = {'payKey': '123'}
|
||||
_call.return_value = {'payKey': '123', 'paymentExecStatus': ''}
|
||||
paypal.get_paykey(data)
|
||||
eq_(_call.call_args[0][1]['receiverList.receiver(0).amount'], '10')
|
||||
|
||||
|
@ -108,7 +114,7 @@ class TestPayKey(amo.tests.TestCase):
|
|||
def test_dict_split(self, _call):
|
||||
data = self.data.copy()
|
||||
data['chains'] = ((13.4, 'us@moz.com'),)
|
||||
_call.return_value = {'payKey': '123'}
|
||||
_call.return_value = {'payKey': '123', 'paymentExecStatus': ''}
|
||||
paypal.get_paykey(data)
|
||||
eq_(_call.call_args[0][1]['receiverList.receiver(0).amount'], '10')
|
||||
eq_(_call.call_args[0][1]['receiverList.receiver(1).amount'], '1.34')
|
||||
|
@ -122,6 +128,55 @@ class TestPayKey(amo.tests.TestCase):
|
|||
res = paypal.add_receivers(chains, 'a@a.com', Decimal('1.99'), '123')
|
||||
eq_(res['feesPayer'], 'SECONDARYONLY')
|
||||
|
||||
@mock.patch('paypal._call')
|
||||
def test_not_preapproval_key(self, _call):
|
||||
_call.return_value = {'payKey': '123', 'paymentExecStatus': ''}
|
||||
paypal.get_paykey(self.data)
|
||||
assert 'preapprovalKey' not in _call.call_args[0][1]
|
||||
|
||||
@mock.patch('paypal._call')
|
||||
def test_preapproval_key(self, _call):
|
||||
_call.return_value = {'payKey': '123', 'paymentExecStatus': ''}
|
||||
paypal.get_paykey(self.get_pre_data())
|
||||
|
||||
called = _call.call_args[0][1]
|
||||
eq_(called['preapprovalKey'], 'xyz')
|
||||
assert 'receiverList.receiver(0).paymentType' not in called
|
||||
|
||||
@mock.patch('paypal._call')
|
||||
def test_preapproval_key_split(self, _call):
|
||||
_call.return_value = {'payKey': '123', 'paymentExecStatus': ''}
|
||||
data = self.get_pre_data()
|
||||
data['chains'] = ((13.4, 'us@moz.com'),)
|
||||
paypal.get_paykey(data)
|
||||
|
||||
called = _call.call_args[0][1]
|
||||
assert 'receiverList.receiver(0).paymentType' not in called
|
||||
assert 'receiverList.receiver(1).paymentType' not in called
|
||||
|
||||
@mock.patch('paypal._call')
|
||||
def test_preapproval_retry(self, _call):
|
||||
# Trigger an error on the preapproval and then pass.
|
||||
def error_if(*args, **kw):
|
||||
if 'preapprovalKey' in args[1]:
|
||||
raise paypal.PreApprovalError('some error')
|
||||
return {'payKey': '123', 'paymentExecStatus': ''}
|
||||
_call.side_effect = error_if
|
||||
res = paypal.get_paykey(self.get_pre_data())
|
||||
eq_(_call.call_count, 2)
|
||||
eq_(res[0], '123')
|
||||
|
||||
@mock.patch('paypal._call')
|
||||
def test_preapproval_both_fail(self, _call):
|
||||
# Trigger an error on the preapproval and then fail again.
|
||||
def error_if(*args, **kw):
|
||||
if 'preapprovalKey' in args[1]:
|
||||
raise paypal.PreApprovalError('some error')
|
||||
raise paypal.PaypalError('other error')
|
||||
_call.side_effect = error_if
|
||||
self.assertRaises(paypal.PaypalError, paypal.get_paykey,
|
||||
self.get_pre_data())
|
||||
|
||||
|
||||
class TestPurchase(amo.tests.TestCase):
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@ var purchases = {
|
|||
success: function(json) {
|
||||
$(el).removeClass(classes);
|
||||
$('.modal').trigger('close'); // Hide all modals
|
||||
if (json.paykey) {
|
||||
if (json.status == 'COMPLETED') {
|
||||
modalFromURL($(el).attr('data-thanksurl'));
|
||||
} else if (json.paykey) {
|
||||
/* This is supposed to be a global */
|
||||
//dgFlow = new PAYPAL.apps.DGFlow({expType:'mini'});
|
||||
dgFlow = new PAYPAL.apps.DGFlow({clicked: el.id});
|
||||
|
|
Загрузка…
Ссылка в новой задаче