forked from CGM_Public/pretix_original
Stripe: Convert all payment methods to intents except multibanco (#3780)
Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -208,7 +208,7 @@ var pretixstripe = {
|
||||
}
|
||||
);
|
||||
},
|
||||
'handleCardAction': function (payment_intent_client_secret) {
|
||||
'withStripe': function (callback) {
|
||||
$.ajax({
|
||||
url: 'https://js.stripe.com/v3/',
|
||||
dataType: 'script',
|
||||
@@ -223,13 +223,68 @@ var pretixstripe = {
|
||||
locale: $.trim($("body").attr("data-locale"))
|
||||
});
|
||||
}
|
||||
pretixstripe.stripe.handleCardAction(
|
||||
payment_intent_client_secret
|
||||
).then(function (result) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
'handleAlipayAction': function (payment_intent_client_secret) {
|
||||
pretixstripe.withStripe(function () {
|
||||
pretixstripe.stripe.confirmAlipayPayment(
|
||||
payment_intent_client_secret,
|
||||
{
|
||||
return_url: window.location.href
|
||||
}
|
||||
).then(function (result) {
|
||||
if (result.error) {
|
||||
waitingDialog.hide();
|
||||
$(".stripe-errors").stop().hide().removeClass("sr-only");
|
||||
$(".stripe-errors").html("<div class='alert alert-danger'>Technical error, please contact support: " + result.error.message + "</div>");
|
||||
$(".stripe-errors").slideDown();
|
||||
} else {
|
||||
waitingDialog.show(gettext("Confirming your payment …"));
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
'handleWechatAction': function (payment_intent_client_secret) {
|
||||
pretixstripe.withStripe(function () {
|
||||
pretixstripe.stripe.confirmWechatPayPayment(
|
||||
payment_intent_client_secret,
|
||||
{
|
||||
payment_method_options: {
|
||||
wechat_pay: {
|
||||
client: 'web',
|
||||
},
|
||||
},
|
||||
}
|
||||
).then(function (result) {
|
||||
if (result.error) {
|
||||
waitingDialog.hide();
|
||||
$(".stripe-errors").stop().hide().removeClass("sr-only");
|
||||
$(".stripe-errors").html("<div class='alert alert-danger'>Technical error, please contact support: " + result.error.message + "</div>");
|
||||
$(".stripe-errors").slideDown();
|
||||
} else {
|
||||
waitingDialog.show(gettext("Confirming your payment …"));
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
'handleCardAction': function (payment_intent_client_secret) {
|
||||
pretixstripe.withStripe(function () {
|
||||
pretixstripe.stripe.handleCardAction(
|
||||
payment_intent_client_secret
|
||||
).then(function (result) {
|
||||
if (result.error) {
|
||||
waitingDialog.hide();
|
||||
$(".stripe-errors").stop().hide().removeClass("sr-only");
|
||||
$(".stripe-errors").html("<div class='alert alert-danger'>Technical error, please contact support: " + result.error.message + "</div>");
|
||||
$(".stripe-errors").slideDown();
|
||||
} else {
|
||||
waitingDialog.show(gettext("Confirming your payment …"));
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
'handlePaymentRedirectAction': function (payment_intent_next_action_redirect_url) {
|
||||
@@ -270,6 +325,12 @@ $(function () {
|
||||
} else if ($("#stripe_payment_intent_next_action_redirect_url").length) {
|
||||
let payment_intent_next_action_redirect_url = $.trim($("#stripe_payment_intent_next_action_redirect_url").html());
|
||||
pretixstripe.handlePaymentRedirectAction(payment_intent_next_action_redirect_url);
|
||||
} else if ($.trim($("#stripe_payment_intent_action_type").html()) === "wechat_pay_display_qr_code") {
|
||||
let payment_intent_client_secret = $.trim($("#stripe_payment_intent_client_secret").html());
|
||||
pretixstripe.handleWechatAction(payment_intent_client_secret);
|
||||
} else if ($.trim($("#stripe_payment_intent_action_type").html()) === "alipay_handle_redirect") {
|
||||
let payment_intent_client_secret = $.trim($("#stripe_payment_intent_client_secret").html());
|
||||
pretixstripe.handleAlipayAction(payment_intent_client_secret);
|
||||
} else if ($("#stripe_payment_intent_client_secret").length) {
|
||||
let payment_intent_client_secret = $.trim($("#stripe_payment_intent_client_secret").html());
|
||||
pretixstripe.handleCardAction(payment_intent_client_secret);
|
||||
|
||||
@@ -7,56 +7,65 @@
|
||||
<dt>{% trans "Charge ID" %}</dt>
|
||||
<dd>{{ payment_info.id }}</dd>
|
||||
{% endif %}
|
||||
{% if "source" in payment_info %}
|
||||
{% if payment_info.source.card %}
|
||||
{% if details %}
|
||||
{% if details.card %}
|
||||
<dt>{% trans "Card type" %}</dt>
|
||||
<dd>{{ payment_info.source.card.brand }}</dd>
|
||||
<dt>{% trans "Card number" %}</dt>
|
||||
<dd>**** **** **** {{ payment_info.source.card.last4 }}</dd>
|
||||
{% if payment_info.source.owner.name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ payment_info.source.owner.name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if payment_info.source.type == "sepa_debit" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ payment_info.source.sepadirectdebit.bank_name }}</dd>
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ payment_info.source.owner.verified_name|default:payment_info.source.owner.name }}</dd>
|
||||
{% endif %}
|
||||
{% if payment_info.source.type == "giropay" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ payment_info.source.giropay.bank_name }} ({{ payment_info.source.giropay.bic }})</dd>
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ payment_info.source.owner.verified_name|default:payment_info.source.owner.name }}</dd>
|
||||
{% endif %}
|
||||
{% if payment_info.source.type == "bancontact" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ payment_info.source.bancontact.bank_name }} ({{ payment_info.source.bancontact.bic }})</dd>
|
||||
{% if owner in payment_info.source %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ payment_info.source.owner.verified_name|default:payment_info.source.owner.name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if payment_info.source.type == "ideal" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ payment_info.source.ideal.bank }} ({{ payment_info.source.ideal.bic }})</dd>
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ payment_info.source.owner.verified_name|default:payment_info.source.owner.name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if payment_info.charges.data.0 %}
|
||||
{% if payment_info.charges.data.0.payment_method_details.card %}
|
||||
<dt>{% trans "Card type" %}</dt>
|
||||
<dd>{{ payment_info.charges.data.0.payment_method_details.card.brand }}</dd>
|
||||
<dd>{{ details.card.brand }}</dd>
|
||||
<dt>{% trans "Card number" %}</dt>
|
||||
<dd>
|
||||
**** **** **** {{ payment_info.charges.data.0.payment_method_details.card.last4 }}
|
||||
{% if payment_info.charges.data.0.payment_method_details.card.moto %}
|
||||
**** **** **** {{ details.card.last4 }}
|
||||
{% if details.card.moto %}
|
||||
<span class="label label-info">{% trans "MOTO" %}</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if details.type == "sepa_debit" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ details.sepadirectdebit.bank_name }}</dd>
|
||||
{% if details.sepadirectdebit.verified_name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ details.sepadirectdebit.verified_name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if details.type == "giropay" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ details.giropay.bank_name }} ({{ details.giropay.bic }})</dd>
|
||||
{% if details.giropay.verified_name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ details.giropay.verified_name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if details.type == "eps" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ details.eps.bank }}</dd>
|
||||
{% if details.eps.verified_name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ details.eps.verified_name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if details.type == "bancontact" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ details.bancontact.bank_name }} ({{ details.bancontact.bic }})</dd>
|
||||
{% if details.bancontact.verified_name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ details.bancontact.verified_name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if details.type == "ideal" %}
|
||||
<dt>{% trans "Bank" %}</dt>
|
||||
<dd>{{ details.ideal.bank }} ({{ details.ideal.bic }})</dd>
|
||||
{% if details.ideal.verified_name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ details.ideal.verified_name }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if details.owner.verified_name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ details.owner.verified_name }}</dd>
|
||||
{% elif details.owner.name %}
|
||||
<dt>{% trans "Payer name" %}</dt>
|
||||
<dd>{{ details.owner.name }}</dd>
|
||||
{% endif %}
|
||||
{% if "amount" in payment_info %}
|
||||
<dt>{% trans "Total value" %}</dt>
|
||||
|
||||
@@ -6,9 +6,14 @@
|
||||
{% block custom_header %}
|
||||
{{ block.super }}
|
||||
{% include "pretixplugins/stripe/presale_head.html" with settings=stripe_settings %}
|
||||
<script type="text/plain" id="stripe_payment_intent_action_type">{{ payment_intent_action_type }}</script>
|
||||
<script type="text/plain" id="stripe_payment_intent_client_secret">{{ payment_intent_client_secret }}</script>
|
||||
<script type="text/plain" id="stripe_payment_intent_next_action_redirect_url">{{ payment_intent_next_action_redirect_url }}</script>
|
||||
<script type="text/plain" id="stripe_payment_intent_redirect_action_handling">{{ payment_intent_redirect_action_handling }}</script>
|
||||
{% if payment_intent_next_action_redirect_url %}
|
||||
<script type="text/plain" id="stripe_payment_intent_next_action_redirect_url">{{ payment_intent_next_action_redirect_url }}</script>
|
||||
{% endif %}}
|
||||
{% if payment_intent_redirect_action_handling %}
|
||||
<script type="text/plain" id="stripe_payment_intent_redirect_action_handling">{{ payment_intent_redirect_action_handling }}</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="panel panel-primary">
|
||||
@@ -18,6 +23,9 @@
|
||||
Confirm payment: {{ code }}
|
||||
{% endblocktrans %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="stripe-errors sr-only panel-body">
|
||||
|
||||
</div>
|
||||
<div class="panel-body embed-responsive embed-responsive-sca" id="scacontainer">
|
||||
|
||||
|
||||
@@ -273,7 +273,11 @@ def charge_webhook(event, event_json, charge_id, rso):
|
||||
prov._init_api()
|
||||
|
||||
try:
|
||||
charge = stripe.Charge.retrieve(charge_id, expand=['dispute'], **prov.api_kwargs)
|
||||
charge = stripe.Charge.retrieve(
|
||||
charge_id,
|
||||
expand=['dispute', 'refunds', 'payment_intent', 'payment_intent.latest_charge'],
|
||||
**prov.api_kwargs
|
||||
)
|
||||
except stripe.error.StripeError:
|
||||
logger.exception('Stripe error on webhook. Event data: %s' % str(event_json))
|
||||
return HttpResponse('Charge not found', status=500)
|
||||
@@ -321,7 +325,7 @@ def charge_webhook(event, event_json, charge_id, rso):
|
||||
|
||||
order.log_action('pretix.plugins.stripe.event', data=event_json)
|
||||
|
||||
is_refund = charge['refunds']['total_count'] or charge['dispute']
|
||||
is_refund = charge['amount_refunded'] or charge['refunds']['total_count'] or charge['dispute']
|
||||
if is_refund:
|
||||
known_refunds = [r.info_data.get('id') for r in payment.refunds.all()]
|
||||
migrated_refund_amounts = [r.amount for r in payment.refunds.all() if not r.info_data.get('id')]
|
||||
@@ -354,6 +358,8 @@ def charge_webhook(event, event_json, charge_id, rso):
|
||||
OrderPayment.PAYMENT_STATE_CANCELED,
|
||||
OrderPayment.PAYMENT_STATE_FAILED):
|
||||
try:
|
||||
if getattr(charge, "payment_intent", None):
|
||||
payment.info = str(charge.payment_intent)
|
||||
payment.confirm()
|
||||
except LockTimeoutException:
|
||||
return HttpResponse("Lock timeout, please try again.", status=503)
|
||||
@@ -439,14 +445,14 @@ def paymentintent_webhook(event, event_json, paymentintent_id, rso):
|
||||
prov._init_api()
|
||||
|
||||
try:
|
||||
paymentintent = stripe.PaymentIntent.retrieve(paymentintent_id, **prov.api_kwargs)
|
||||
paymentintent = stripe.PaymentIntent.retrieve(paymentintent_id, expand=["latest_charge"], **prov.api_kwargs)
|
||||
except stripe.error.StripeError:
|
||||
logger.exception('Stripe error on webhook. Event data: %s' % str(event_json))
|
||||
return HttpResponse('Charge not found', status=500)
|
||||
|
||||
for charge in paymentintent.charges.data:
|
||||
if paymentintent.latest_charge:
|
||||
ReferencedStripeObject.objects.get_or_create(
|
||||
reference=charge.id,
|
||||
reference=paymentintent.latest_charge.id,
|
||||
defaults={'order': rso.payment.order, 'payment': rso.payment}
|
||||
)
|
||||
|
||||
@@ -581,6 +587,7 @@ class ScaView(StripeOrderView, View):
|
||||
try:
|
||||
intent = stripe.PaymentIntent.retrieve(
|
||||
payment_info['id'],
|
||||
expand=["latest_charge"],
|
||||
**prov.api_kwargs
|
||||
)
|
||||
except stripe.error.InvalidRequestError:
|
||||
@@ -591,12 +598,15 @@ class ScaView(StripeOrderView, View):
|
||||
messages.error(self.request, _('Sorry, there was an error in the payment process.'))
|
||||
return self._redirect_to_order()
|
||||
|
||||
if intent.status == 'requires_action' and intent.next_action.type in ['use_stripe_sdk', 'redirect_to_url']:
|
||||
if intent.status == 'requires_action' and intent.next_action.type in [
|
||||
'use_stripe_sdk', 'redirect_to_url', 'alipay_handle_redirect', 'wechat_pay_display_qr_code'
|
||||
]:
|
||||
ctx = {
|
||||
'order': self.order,
|
||||
'stripe_settings': StripeSettingsHolder(self.order.event).settings,
|
||||
}
|
||||
if intent.next_action.type == 'use_stripe_sdk':
|
||||
ctx['payment_intent_action_type'] = intent.next_action.type
|
||||
if intent.next_action.type in ('use_stripe_sdk', 'alipay_handle_redirect', 'wechat_pay_display_qr_code'):
|
||||
ctx['payment_intent_client_secret'] = intent.client_secret
|
||||
elif intent.next_action.type == 'redirect_to_url':
|
||||
ctx['payment_intent_next_action_redirect_url'] = intent.next_action.redirect_to_url['url']
|
||||
|
||||
@@ -30,7 +30,8 @@ from django.core import mail as djmail
|
||||
from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
from django_scopes import scopes_disabled
|
||||
from stripe.error import APIConnectionError
|
||||
from stripe import error
|
||||
from tests.plugins.stripe.test_checkout import apple_domain_create
|
||||
from tests.plugins.stripe.test_provider import MockedCharge
|
||||
|
||||
from pretix.base.models import InvoiceAddress, Order, OrderPosition
|
||||
@@ -744,13 +745,14 @@ def test_payment_refund_fail(token_client, organizer, event, order, monkeypatch)
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_payment_refund_success(token_client, organizer, event, order, monkeypatch):
|
||||
def charge_retr(*args, **kwargs):
|
||||
def refund_create(amount):
|
||||
r = MockedCharge()
|
||||
r.id = 'foo'
|
||||
r.status = 'succeeded'
|
||||
return r
|
||||
|
||||
def refund_create(*args, **kwargs):
|
||||
r = MockedCharge()
|
||||
r.id = 'foo'
|
||||
r.status = 'succeeded'
|
||||
return r
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
c = MockedCharge()
|
||||
c.refunds.create = refund_create
|
||||
return c
|
||||
@@ -765,7 +767,9 @@ def test_payment_refund_success(token_client, organizer, event, order, monkeypat
|
||||
'id': 'ch_123345345'
|
||||
})
|
||||
)
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", charge_retr)
|
||||
monkeypatch.setattr("stripe.Refund.create", refund_create)
|
||||
resp = token_client.post('/api/v1/organizers/{}/events/{}/orders/{}/payments/{}/refund/'.format(
|
||||
organizer.slug, event.slug, order.code, p1.local_id
|
||||
), format='json', data={
|
||||
@@ -784,7 +788,7 @@ def test_payment_refund_success(token_client, organizer, event, order, monkeypat
|
||||
def test_payment_refund_unavailable(token_client, organizer, event, order, monkeypatch):
|
||||
def charge_retr(*args, **kwargs):
|
||||
def refund_create(amount):
|
||||
raise APIConnectionError(message='Foo')
|
||||
raise error.APIConnectionError(message='Foo')
|
||||
|
||||
c = MockedCharge()
|
||||
c.refunds.create = refund_create
|
||||
|
||||
@@ -43,6 +43,7 @@ from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
from django_scopes import scopes_disabled
|
||||
from tests.base import SoupTest
|
||||
from tests.plugins.stripe.test_checkout import apple_domain_create
|
||||
from tests.plugins.stripe.test_provider import MockedCharge
|
||||
|
||||
from pretix.base.models import (
|
||||
@@ -2081,15 +2082,17 @@ def test_refund_paid_order_automatically_failed(client, env, monkeypatch):
|
||||
p.confirm()
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
def refund_create(amount):
|
||||
raise PaymentException('This failed.')
|
||||
def refund_create(*args, **kwargs):
|
||||
raise PaymentException('This failed.')
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
c = MockedCharge()
|
||||
c.refunds.create = refund_create
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", charge_retr)
|
||||
monkeypatch.setattr("stripe.Refund.create", refund_create)
|
||||
|
||||
r = client.post('/control/event/dummy/dummy/orders/FOO/refund', {
|
||||
'start-partial_amount': '7.00',
|
||||
@@ -2123,18 +2126,20 @@ def test_refund_paid_order_automatically(client, env, monkeypatch):
|
||||
p.confirm()
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
def refund_create(amount):
|
||||
r = MockedCharge()
|
||||
r.id = 'foo'
|
||||
r.status = 'succeeded'
|
||||
return r
|
||||
def refund_create(*args, **kwargs):
|
||||
r = MockedCharge()
|
||||
r.id = 'foo'
|
||||
r.status = 'succeeded'
|
||||
return r
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
c = MockedCharge()
|
||||
c.refunds.create = refund_create
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", charge_retr)
|
||||
monkeypatch.setattr("stripe.Refund.create", refund_create)
|
||||
|
||||
client.post('/control/event/dummy/dummy/orders/FOO/refund', {
|
||||
'start-partial_amount': '7.00',
|
||||
|
||||
@@ -43,7 +43,7 @@ from pretix.base.models import (
|
||||
from pretix.testutils.sessions import add_cart_session, get_cart_session_key
|
||||
|
||||
|
||||
class MockedCharge():
|
||||
class MockedCharge:
|
||||
status = ''
|
||||
paid = False
|
||||
id = 'ch_123345345'
|
||||
@@ -52,18 +52,27 @@ class MockedCharge():
|
||||
pass
|
||||
|
||||
|
||||
class Object():
|
||||
class Object:
|
||||
pass
|
||||
|
||||
|
||||
class MockedPaymentintent():
|
||||
class MockedPaymentintent:
|
||||
status = ''
|
||||
id = 'pi_1EUon12Tb35ankTnZyvC3SdE'
|
||||
latest_charge = MockedCharge()
|
||||
charges = Object()
|
||||
charges.data = [MockedCharge()]
|
||||
charges.data = [latest_charge]
|
||||
last_payment_error = None
|
||||
|
||||
|
||||
class MockedAppleDomain:
|
||||
livemode = True
|
||||
|
||||
|
||||
def apple_domain_create(**kwargs):
|
||||
return MockedAppleDomain()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env(client):
|
||||
orga = Organizer.objects.create(name='CCC', slug='ccc')
|
||||
@@ -80,6 +89,7 @@ def env(client):
|
||||
quota_tickets.items.add(ticket)
|
||||
event.settings.set('attendee_names_asked', False)
|
||||
event.settings.set('payment_stripe__enabled', True)
|
||||
event.settings.set('payment_stripe_publishable_key', 'nokey')
|
||||
add_cart_session(client, event, {'email': 'admin@localhost'})
|
||||
return client, ticket
|
||||
|
||||
@@ -92,10 +102,11 @@ def test_payment(env, monkeypatch):
|
||||
assert kwargs['payment_method'] == 'pm_189fTT2eZvKYlo2CvJKzEzeu'
|
||||
c = MockedPaymentintent()
|
||||
c.status = 'succeeded'
|
||||
c.charges.data[0].paid = True
|
||||
c.latest_charge.paid = True
|
||||
setattr(paymentintent_create, 'called', True)
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.PaymentIntent.create", paymentintent_create)
|
||||
|
||||
client, ticket = env
|
||||
|
||||
@@ -55,6 +55,7 @@ def env():
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now(), live=True
|
||||
)
|
||||
event.settings.set('payment_stripe_publishable_key', 'nokey')
|
||||
o1 = Order.objects.create(
|
||||
code='FOOBAR', event=event, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PENDING,
|
||||
@@ -75,11 +76,11 @@ def factory():
|
||||
return RequestFactory()
|
||||
|
||||
|
||||
class MockedRefunds():
|
||||
class MockedRefunds:
|
||||
pass
|
||||
|
||||
|
||||
class MockedCharge():
|
||||
class MockedCharge:
|
||||
status = ''
|
||||
paid = False
|
||||
id = 'ch_123345345'
|
||||
@@ -96,18 +97,27 @@ class MockedCharge():
|
||||
pass
|
||||
|
||||
|
||||
class Object():
|
||||
class Object:
|
||||
pass
|
||||
|
||||
|
||||
class MockedPaymentintent():
|
||||
class MockedPaymentintent:
|
||||
status = ''
|
||||
id = 'pi_1EUon12Tb35ankTnZyvC3SdE'
|
||||
latest_charge = MockedCharge()
|
||||
charges = Object()
|
||||
charges.data = [MockedCharge()]
|
||||
charges.data = [latest_charge]
|
||||
last_payment_error = None
|
||||
|
||||
|
||||
class MockedAppleDomain:
|
||||
livemode = True
|
||||
|
||||
|
||||
def apple_domain_create(**kwargs):
|
||||
return MockedAppleDomain()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_perform_success(env, factory, monkeypatch):
|
||||
event, order = env
|
||||
@@ -118,9 +128,10 @@ def test_perform_success(env, factory, monkeypatch):
|
||||
assert kwargs['payment_method'] == 'pm_189fTT2eZvKYlo2CvJKzEzeu'
|
||||
c = MockedPaymentintent()
|
||||
c.status = 'succeeded'
|
||||
c.charges.data[0].paid = True
|
||||
c.latest_charge.paid = True
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.PaymentIntent.create", paymentintent_create)
|
||||
|
||||
prov = StripeCC(event)
|
||||
@@ -152,9 +163,10 @@ def test_perform_success_zero_decimal_currency(env, factory, monkeypatch):
|
||||
assert kwargs['payment_method'] == 'pm_189fTT2eZvKYlo2CvJKzEzeu'
|
||||
c = MockedPaymentintent()
|
||||
c.status = 'succeeded'
|
||||
c.charges.data[0].paid = True
|
||||
c.latest_charge.paid = True
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.PaymentIntent.create", paymentintent_create)
|
||||
prov = StripeCC(event)
|
||||
req = factory.post('/', {
|
||||
@@ -180,6 +192,7 @@ def test_perform_card_error(env, factory, monkeypatch):
|
||||
def paymentintent_create(**kwargs):
|
||||
raise error.CardError(message='Foo', param='foo', code=100)
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.PaymentIntent.create", paymentintent_create)
|
||||
prov = StripeCC(event)
|
||||
req = factory.post('/', {
|
||||
@@ -206,6 +219,7 @@ def test_perform_stripe_error(env, factory, monkeypatch):
|
||||
def paymentintent_create(**kwargs):
|
||||
raise error.CardError(message='Foo', param='foo', code=100)
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.PaymentIntent.create", paymentintent_create)
|
||||
prov = StripeCC(event)
|
||||
req = factory.post('/', {
|
||||
@@ -236,11 +250,12 @@ def test_perform_failed(env, factory, monkeypatch):
|
||||
c = MockedPaymentintent()
|
||||
c.status = 'failed'
|
||||
c.failure_message = 'Foo'
|
||||
c.charges.data[0].paid = True
|
||||
c.latest_charge.paid = True
|
||||
c.last_payment_error = Object()
|
||||
c.last_payment_error.message = "Foo"
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.PaymentIntent.create", paymentintent_create)
|
||||
prov = StripeCC(event)
|
||||
req = factory.post('/', {
|
||||
@@ -264,18 +279,20 @@ def test_perform_failed(env, factory, monkeypatch):
|
||||
def test_refund_success(env, factory, monkeypatch):
|
||||
event, order = env
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
def refund_create(amount):
|
||||
r = MockedCharge()
|
||||
r.id = 'foo'
|
||||
r.status = 'succeeded'
|
||||
return r
|
||||
def refund_create(*args, **kwargs):
|
||||
r = MockedCharge()
|
||||
r.id = 'foo'
|
||||
r.status = 'succeeded'
|
||||
return r
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
c = MockedCharge()
|
||||
c.refunds.create = refund_create
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", charge_retr)
|
||||
monkeypatch.setattr("stripe.Refund.create", refund_create)
|
||||
order.status = Order.STATUS_PAID
|
||||
p = order.payments.create(provider='stripe_cc', amount=order.total, info=json.dumps({
|
||||
'id': 'ch_123345345'
|
||||
@@ -294,15 +311,17 @@ def test_refund_success(env, factory, monkeypatch):
|
||||
def test_refund_unavailable(env, factory, monkeypatch):
|
||||
event, order = env
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
def refund_create(amount):
|
||||
raise error.APIConnectionError(message='Foo')
|
||||
def refund_create(*args, **kwargs):
|
||||
raise error.APIConnectionError(message='Foo')
|
||||
|
||||
def charge_retr(*args, **kwargs):
|
||||
c = MockedCharge()
|
||||
c.refunds.create = refund_create
|
||||
return c
|
||||
|
||||
monkeypatch.setattr("stripe.ApplePayDomain.create", apple_domain_create)
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", charge_retr)
|
||||
monkeypatch.setattr("stripe.Refund.create", refund_create)
|
||||
order.status = Order.STATUS_PAID
|
||||
p = order.payments.create(provider='stripe_cc', amount=order.total, info=json.dumps({
|
||||
'id': 'ch_123345345'
|
||||
|
||||
@@ -151,12 +151,22 @@ def test_webhook_all_good(env, client, monkeypatch):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_webhook_mark_paid_without_reference_and_payment(env, client, monkeypatch):
|
||||
def test_webhook_mark_paid(env, client, monkeypatch):
|
||||
order = env[1]
|
||||
order.status = Order.STATUS_PENDING
|
||||
order.save()
|
||||
|
||||
charge = get_test_charge(env[1])
|
||||
charge["amount_refunded"] = 0
|
||||
with scopes_disabled():
|
||||
payment = env[1].payments.create(
|
||||
provider='stripe', amount=env[1].total, info='{}', state=OrderPayment.PAYMENT_STATE_CREATED,
|
||||
)
|
||||
ReferencedStripeObject.objects.create(
|
||||
order=order,
|
||||
payment=payment,
|
||||
reference="pi_123456",
|
||||
)
|
||||
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", lambda *args, **kwargs: charge)
|
||||
|
||||
client.post('/dummy/dummy/stripe/webhook/', json.dumps(
|
||||
@@ -169,6 +179,10 @@ def test_webhook_mark_paid_without_reference_and_payment(env, client, monkeypatc
|
||||
"object": {
|
||||
"id": "ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
"object": "charge",
|
||||
"payment_intent": "pi_123456",
|
||||
"metadata": {
|
||||
"event": order.event_id,
|
||||
}
|
||||
# Rest of object is ignored anway
|
||||
}
|
||||
},
|
||||
@@ -253,6 +267,7 @@ def test_webhook_global(env, client, monkeypatch):
|
||||
order.save()
|
||||
|
||||
charge = get_test_charge(env[1])
|
||||
charge["amount_refunded"] = 0
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", lambda *args, **kwargs: charge)
|
||||
|
||||
with scopes_disabled():
|
||||
@@ -261,6 +276,8 @@ def test_webhook_global(env, client, monkeypatch):
|
||||
)
|
||||
ReferencedStripeObject.objects.create(order=order, reference="ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
payment=payment)
|
||||
ReferencedStripeObject.objects.create(order=order, reference="pi_123456",
|
||||
payment=payment)
|
||||
|
||||
client.post('/_stripe/webhook/', json.dumps(
|
||||
{
|
||||
@@ -272,6 +289,10 @@ def test_webhook_global(env, client, monkeypatch):
|
||||
"object": {
|
||||
"id": "ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
"object": "charge",
|
||||
"payment_intent": "pi_123456",
|
||||
"metadata": {
|
||||
"event": order.event_id,
|
||||
}
|
||||
# Rest of object is ignored anway
|
||||
}
|
||||
},
|
||||
@@ -293,6 +314,7 @@ def test_webhook_global_legacy_reference(env, client, monkeypatch):
|
||||
order.save()
|
||||
|
||||
charge = get_test_charge(env[1])
|
||||
charge["amount_refunded"] = 0
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", lambda *args, **kwargs: charge)
|
||||
|
||||
with scopes_disabled():
|
||||
@@ -300,6 +322,7 @@ def test_webhook_global_legacy_reference(env, client, monkeypatch):
|
||||
provider='stripe', amount=order.total, info=json.dumps(charge), state=OrderPayment.PAYMENT_STATE_CREATED
|
||||
)
|
||||
ReferencedStripeObject.objects.create(order=order, reference="ch_18TY6GGGWE2Ias8TZHanef25")
|
||||
ReferencedStripeObject.objects.create(order=order, reference="pi_123456")
|
||||
|
||||
client.post('/_stripe/webhook/', json.dumps(
|
||||
{
|
||||
@@ -311,6 +334,10 @@ def test_webhook_global_legacy_reference(env, client, monkeypatch):
|
||||
"object": {
|
||||
"id": "ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
"object": "charge",
|
||||
"payment_intent": "pi_123456",
|
||||
"metadata": {
|
||||
"event": order.event_id,
|
||||
}
|
||||
# Rest of object is ignored anway
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user