Skip to content

Commit 2626fda

Browse files
committed
Create Webhook to process received payments
1 parent 434907d commit 2626fda

6 files changed

Lines changed: 447 additions & 1 deletion

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,4 @@ target/
6363
.ipynb_checkpoints
6464

6565
.venv
66+
.*.swp

pretix_pix_openpix/urls.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.urls import re_path
2+
3+
from . import views
4+
5+
urlpatterns = [
6+
re_path(r"^_pretix_pix_openpix/webhook/", views.webhook, name="webhook"),
7+
]

pretix_pix_openpix/views.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import json
2+
from http import HTTPStatus
3+
4+
from django.http import HttpResponse
5+
from django.views.decorators.csrf import csrf_exempt
6+
from django_scopes import scopes_disabled
7+
8+
from pretix.base.models import Order, OrderPayment
9+
10+
11+
@csrf_exempt
12+
def webhook(request):
13+
event_body = request.body.decode("utf-8").strip()
14+
15+
try:
16+
data = json.loads(event_body)
17+
except json.decoder.JSONDecodeError:
18+
return HttpResponse(status=HTTPStatus.OK)
19+
20+
event = data.get("event") or ""
21+
if event == "OPENPIX:CHARGE_COMPLETED":
22+
pix = data.get("pix") or {}
23+
charge = pix.get("charge") or {}
24+
25+
identifier = charge.get("identifier")
26+
value = charge.get("value", 0.0) / 100
27+
28+
with scopes_disabled():
29+
order_payment = OrderPayment.objects.filter(
30+
order__code=identifier,
31+
order__status=Order.STATUS_PENDING,
32+
amount=value,
33+
provider="pix_openpix",
34+
state__in=(
35+
OrderPayment.PAYMENT_STATE_CREATED,
36+
OrderPayment.PAYMENT_STATE_PENDING,
37+
),
38+
).last()
39+
if order_payment:
40+
order_payment.confirm()
41+
42+
return HttpResponse(status=HTTPStatus.OK)

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ requires = [
3636
homepage = "https://github.com/lhc/pretix-pix-openpix"
3737
repository = "https://github.com/lhc/pretix-pix-openpix"
3838

39+
[tool.pytest.ini_options]
40+
DJANGO_SETTINGS_MODULE = "pretix.testutils.settings"
41+
3942
[tool.setuptools]
4043
include-package-data = true
4144

tests/conftest.py

Lines changed: 221 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,221 @@
1-
# put your pytest fixtures here
1+
from datetime import datetime, timedelta, timezone
2+
from decimal import Decimal
3+
4+
import pytest
5+
6+
from pretix.base.models import Event, Order, OrderPayment, Organizer, SalesChannel
7+
8+
9+
@pytest.fixture
10+
def organizer(db):
11+
return Organizer.objects.create(name="Test Organizer", slug="test-organizer")
12+
13+
14+
@pytest.fixture
15+
def event(db, organizer):
16+
return Event.objects.create(
17+
organizer=organizer,
18+
name="Test Event",
19+
slug="test_event",
20+
date_from=datetime(2025, 8, 20, 10, 0, 0, tzinfo=timezone.utc),
21+
plugins="pretix.plugins.pix_openpix",
22+
)
23+
24+
25+
@pytest.fixture
26+
def order(db, event):
27+
sales_channel = SalesChannel.objects.create(
28+
organizer=event.organizer,
29+
label="Test Sales Channel",
30+
identifier="SALES-CHANNEL",
31+
type="SALES-CHANNEL",
32+
)
33+
34+
_order = Order.objects.create(
35+
code="FOOBAR",
36+
event=event,
37+
email="dummy@dummy.test",
38+
status=Order.STATUS_PENDING,
39+
expires=datetime.now() + timedelta(days=10),
40+
total=Decimal("100.0"),
41+
sales_channel=sales_channel,
42+
)
43+
OrderPayment.objects.create(
44+
local_id=1,
45+
state=OrderPayment.PAYMENT_STATE_CREATED,
46+
amount=_order.total,
47+
order=_order,
48+
provider="pix_openpix",
49+
process_initiated=True,
50+
)
51+
52+
return _order
53+
54+
55+
@pytest.fixture
56+
def create_payload():
57+
def _create_payload(
58+
*,
59+
order_code="CODE",
60+
payload_event="OPENPIX:CHARGE_COMPLETED",
61+
order_total=Decimal("100.0")
62+
):
63+
value = 10000
64+
65+
return {
66+
"event": payload_event,
67+
"charge": {
68+
"customer": {
69+
"name": "cliente",
70+
"email": "cliente@openpix.com.br",
71+
"phone": "+5511973591090",
72+
"taxID": {"taxID": "67784666004", "type": "BR:CPF"},
73+
"correlationID": "4f8093dc-1800-4e6b-bf83-178c24f1e0cd",
74+
"address": {
75+
"zipcode": "",
76+
"street": "",
77+
"number": "",
78+
"neighborhood": "",
79+
"city": "",
80+
"state": "",
81+
"complement": "",
82+
},
83+
},
84+
"value": value,
85+
"comment": "",
86+
"identifier": order_code,
87+
"paymentLinkID": "36e4f36d-813c-48e4-916f-fcf061231074",
88+
"transactionID": "79a955477ca34fffae213363d5c34070",
89+
"status": "COMPLETED",
90+
"additionalInfo": [],
91+
"discount": 0,
92+
"valueWithDiscount": value,
93+
"expiresDate": "2024-01-25T09:50:56.954Z",
94+
"type": "DYNAMIC",
95+
"correlationID": "b05a3247-5d2b-432b-9b29-253db3125634",
96+
"createdAt": "2024-01-25T09:45:57.562Z",
97+
"updatedAt": "2024-01-25T09:46:15.544Z",
98+
"paidAt": "2024-01-25T09:46:14.824Z",
99+
"payer": {
100+
"name": "EDUARDO MACIEL DE MATOS",
101+
"taxID": {"taxID": "67784666004", "type": "BR:CPF"},
102+
"correlationID": "a191393b-2f72-4cbb-8ce7-e1810153b0db",
103+
"address": {
104+
"zipcode": "13142514",
105+
"street": "Rua OpenPix",
106+
"number": "2019",
107+
"neighborhood": "Casa",
108+
"city": "Sao Paulo",
109+
"state": "SP",
110+
"complement": "Brooklin",
111+
},
112+
},
113+
"brCode": "00020101021226950014br.gov.bcb.pix2573api.openpix.com.br/api/testaccount/qr/v1/79a955477ca34fffae213363d5c340705204000053039865406100.005802BR5914EDUARDO_MACIEL6009Sao_Paulo6229052579a955477ca34fffae213363d6304219B",
114+
"expiresIn": 300,
115+
"pixKey": "5081d2e9-45d0-4075-86b6-64c77bc5b73b",
116+
"paymentLinkUrl": "https://openpix.com.br/pay/36e4f36d-813c-48e4-916f-fcf061231074",
117+
"qrCodeImage": "https://api.openpix.com.br/openpix/charge/brcode/image/36e4f36d-813c-48e4-916f-fcf061231074.png",
118+
"globalID": "Q2hhcmdlOjY1YjIyZGQ1MGU3ODU5YTRhZTNmZDM5NA==",
119+
},
120+
"pix": {
121+
"customer": {
122+
"name": "cliente",
123+
"email": "cliente@openpix.com.br",
124+
"phone": "+5511973591090",
125+
"taxID": {"taxID": "67784666004", "type": "BR:CPF"},
126+
"correlationID": "4f8093dc-1800-4e6b-bf83-178c24f1e0cd",
127+
"address": {
128+
"zipcode": "",
129+
"street": "",
130+
"number": "",
131+
"neighborhood": "",
132+
"city": "",
133+
"state": "",
134+
"complement": "",
135+
"country": "BR",
136+
"location": {"coordinates": []},
137+
"_id": "6512f4da3343177a352199cb",
138+
},
139+
},
140+
"payer": {
141+
"name": "EDUARDO MACIEL DE MATOS",
142+
"taxID": {"taxID": "67784666004", "type": "BR:CPF"},
143+
"correlationID": "4f8093dc-1800-4e6b-bf83-178c24f1e0cd",
144+
"address": {
145+
"zipcode": "13142514",
146+
"street": "Rua OpenPix",
147+
"number": "2019",
148+
"neighborhood": "Casa",
149+
"city": "Sao Paulo",
150+
"state": "SP",
151+
"complement": "Brooklin",
152+
"country": "BR",
153+
"location": {"coordinates": []},
154+
"_id": "64e37c0fea92115c2e2a5ecc",
155+
},
156+
},
157+
"charge": {
158+
"customer": {
159+
"name": "rumbling",
160+
"email": "cris@entria.com.br",
161+
"phone": "+5511973591090",
162+
"address": {
163+
"zipcode": "",
164+
"street": "",
165+
"number": "",
166+
"neighborhood": "",
167+
"city": "",
168+
"state": "",
169+
"complement": "",
170+
},
171+
"taxID": {"taxID": "67784666004", "type": "BR:CPF"},
172+
"correlationID": "4f8093dc-1800-4e6b-bf83-178c24f1e0cd",
173+
},
174+
"value": value,
175+
"comment": "",
176+
"identifier": order_code,
177+
"paymentLinkID": "36e4f36d-813c-48e4-916f-fcf061231074",
178+
"transactionID": "79a955477ca34fffae213363d5c34070",
179+
"status": "COMPLETED",
180+
"additionalInfo": [],
181+
"discount": 0,
182+
"valueWithDiscount": value,
183+
"expiresDate": "2024-01-25T09:50:56.954Z",
184+
"type": "DYNAMIC",
185+
"correlationID": "b05a3247-5d2b-432b-9b29-253db3125634",
186+
"createdAt": "2024-01-25T09:45:57.562Z",
187+
"updatedAt": "2024-01-25T09:46:15.544Z",
188+
"paidAt": "2024-01-25T09:46:14.824Z",
189+
"payer": {
190+
"name": "EDUARDO MACIEL DE MATOS",
191+
"taxID": {"taxID": "67784666004", "type": "BR:CPF"},
192+
"correlationID": "a191393b-2f72-4cbb-8ce7-e1810153b0db",
193+
"address": {
194+
"zipcode": "13142514",
195+
"street": "Rua OpenPix",
196+
"number": "2019",
197+
"neighborhood": "Casa",
198+
"city": "Sao Paulo",
199+
"state": "SP",
200+
"complement": "Brooklin",
201+
},
202+
},
203+
"brCode": "00020101021226950014br.gov.bcb.pix2573api.openpix.com.br/api/testaccount/qr/v1/79a955477ca34fffae213363d5c340705204000053039865406100.005802BR5914EDUARDO_MACIEL6009Sao_Paulo6229052579a955477ca34fffae213363d6304219B",
204+
"expiresIn": 300,
205+
"pixKey": "5081d2e9-45d0-4075-86b6-64c77bc5b73b",
206+
"paymentLinkUrl": "https://openpix.com.br/pay/36e4f36d-813c-48e4-916f-fcf061231074",
207+
"qrCodeImage": "https://api.openpix.com.br/openpix/charge/brcode/image/36e4f36d-813c-48e4-916f-fcf061231074.png",
208+
"globalID": "Q2hhcmdlOjY1YjIyZGQ1MGU3ODU5YTRhZTNmZDM5NA==",
209+
},
210+
"value": value,
211+
"time": "2024-01-25T09:46:14.824Z",
212+
"endToEndId": "Eac490bf76a684b21a2e458d56f888091",
213+
"transactionID": "79a955477ca34fffae213363d5c34070",
214+
"infoPagador": "OpenPix testing",
215+
"type": "PAYMENT",
216+
"createdAt": "2024-01-25T09:46:15.446Z",
217+
"globalID": "UGl4VHJhbnNhY3Rpb246NjViMjJkZTczNzJlMDNlNDhiZTI0ZDc0",
218+
},
219+
}
220+
221+
return _create_payload

0 commit comments

Comments
 (0)