Skip to content

Commit 04c6ff2

Browse files
author
CryptAPI
committed
Added support for new features:
- Pending transactions (through the `payment_pending` signal) - Monero
1 parent a2d7070 commit 04c6ff2

File tree

8 files changed

+58
-27
lines changed

8 files changed

+58
-27
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ Where:
8787

8888
``request`` is Django's view HttpRequest object
8989
``order_id`` is just your order id
90-
``coin`` is the coin you wish to use, can be one of: ``['btc', 'eth', 'bch', 'ltc', 'iota']`` and you need to have a ``Provider`` set up for that coin.
91-
``value`` is an integer of the value of your order, either in satoshi, litoshi, wei or IOTA
90+
``coin`` is the coin you wish to use, can be one of: ``['btc', 'eth', 'bch', 'ltc', 'xmr', 'iota']`` and you need to have a ``Provider`` set up for that coin.
91+
``value`` is an integer of the value of your order, either in satoshi, litoshi, wei, piconero or IOTA
9292

9393

9494
### Getting notified when the user pays
@@ -122,7 +122,7 @@ This library has a couple of helpers to help you get started
122122
There's also some template tags which you can import to help you with conversions and the protocols.
123123
You just need to load ``cryptapi_helper`` on your template and use the following tags / filters:
124124

125-
``{% convert_value coin value %}`` where the coin is one of ``['btc', 'eth', 'bch', 'ltc', 'iota']`` and the value is the value in satoshi, litoshi, wei or IOTA, will convert to the main coin denomination.
125+
``{% convert_value coin value %}`` where the coin is one of ``['btc', 'eth', 'bch', 'ltc', 'xmr', 'iota']`` and the value is the value in satoshi, litoshi, wei or IOTA, will convert to the main coin denomination.
126126

127127

128128
``{{ coin|coin_name }}`` will output the properly formatted cryptocurrency name

cryptapi/choices.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
('bch', 'Bitcoin Cash'),
88
('ltc', 'Litecoin'),
99
('iota', 'IOTA'),
10+
('xmr', 'Monero'),
1011
)
1112

1213

1314
STATUS = (
1415
('created', _('Created')),
16+
('pending', _('Pending')),
1517
('insufficient', _('Payment Insufficient')),
1618
('received', _('Received')),
1719
('done', _('Done')),
@@ -24,4 +26,5 @@
2426
'ltc': 100000000,
2527
'eth': 1000000000000000000,
2628
'iota': 1000000,
29+
'xmr': 1000000000000,
2730
}

cryptapi/dispatchers.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11

22
class CallbackDispatcher:
33

4-
def __init__(self, coin, request, payment, raw_data):
4+
def __init__(self, coin, request, payment, raw_data, pending=False):
55
self.coin = coin
66
self.request = request
77
self.payment = payment
88
self.raw_data = raw_data
9+
self.pending = pending
910

1011
def callback(self):
1112

1213
from cryptapi.models import Request, PaymentLog
13-
from cryptapi.signals import payment_received, payment_complete
14+
from cryptapi.signals import payment_received, payment_complete, payment_pending
1415

1516
try:
1617
request = Request.objects.get(
@@ -21,10 +22,23 @@ def callback(self):
2122

2223
payment, created = request.payment_set.get_or_create(txid_in__iexact=self.payment['txid_in'])
2324

24-
if created:
25-
[setattr(payment, k, v) for k, v in self.payment.items()]
25+
[setattr(payment, k, v) for k, v in self.payment.items()]
26+
27+
payment.pending = self.pending
28+
payment.save()
2629

27-
payment.save()
30+
if self.pending:
31+
payment_pending.send_robust(
32+
sender=self.__class__,
33+
order_id=request.order_id,
34+
payment=payment,
35+
value=self.payment['value_paid']
36+
)
37+
38+
request.status = 'pending'
39+
request.save()
40+
41+
else:
2842

2943
# Notify payment received
3044
payment_received.send_robust(
@@ -39,7 +53,7 @@ def callback(self):
3953
total_received = self.payment['value_paid']
4054

4155
if total_received < request.value_requested:
42-
total_received_list = request.payment_set.all().values_list('value_paid', flat=True)
56+
total_received_list = request.payment_set.filter(pending=False).values_list('value_paid', flat=True)
4357
total_received = sum(total_received_list)
4458

4559
if total_received < request.value_requested:
@@ -57,16 +71,16 @@ def callback(self):
5771

5872
request.save()
5973

60-
pl = PaymentLog(
61-
payment=payment,
62-
raw_data=self.raw_data
63-
)
74+
pl = PaymentLog(
75+
payment=payment,
76+
raw_data=self.raw_data
77+
)
6478

65-
pl.save()
79+
pl.save()
6680

67-
if request.status in ['received']:
68-
request.status = 'done'
69-
request.save()
81+
if request.status in ['received']:
82+
request.status = 'done'
83+
request.save()
7084

7185
return True
7286

@@ -110,7 +124,8 @@ def address(self):
110124

111125
params = {
112126
'callback': cb_url,
113-
'address': provider.cold_wallet
127+
'address': provider.cold_wallet,
128+
'pending': 1,
114129
}
115130

116131
raw_response = process_request(self.coin, 'create', params)

cryptapi/forms.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from .choices import COINS
33

44

5-
class CallbackForm(forms.Form):
5+
class BaseCallbackForm(forms.Form):
66

77
# Request data
88
request_id = forms.IntegerField()
@@ -13,9 +13,13 @@ class CallbackForm(forms.Form):
1313

1414
# Payment data
1515
txid_in = forms.CharField(max_length=256)
16-
txid_out = forms.CharField(max_length=256)
1716
confirmations = forms.IntegerField()
1817
value = forms.DecimalField(max_digits=65, decimal_places=0)
18+
19+
20+
class CallbackForm(BaseCallbackForm):
21+
# Payment data
22+
txid_out = forms.CharField(max_length=256)
1923
value_forwarded = forms.DecimalField(max_digits=65, decimal_places=0)
2024

2125

cryptapi/meta.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from distutils.version import StrictVersion
22

33

4-
VERSION = StrictVersion('0.1.2')
4+
VERSION = StrictVersion('0.1.3')

cryptapi/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Payment(models.Model):
3737
value_received = models.DecimalField(_('Value Received'), default=0, max_digits=65, decimal_places=0)
3838
txid_in = models.CharField(_('TXID in'), max_length=256, default='')
3939
txid_out = models.CharField(_('TXID out'), max_length=256, default='')
40+
pending = models.BooleanField(default=True)
4041
confirmations = models.IntegerField(default=0)
4142
timestamp = models.DateTimeField(auto_now_add=True)
4243

@@ -59,4 +60,4 @@ class PaymentLog(models.Model):
5960
timestamp = models.DateTimeField(auto_now_add=True)
6061

6162
def __str__(self):
62-
return "#{} ({})".format(self.payment_id, self.timestamp.strftime('%x %X'))
63+
return "#{} ({})".format(self.payment_id, self.timestamp.strftime('%x %X'))

cryptapi/signals.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.dispatch import Signal
22

3+
payment_pending = Signal(providing_args=['order_id', 'payment', 'value'])
34
payment_received = Signal(providing_args=['order_id', 'payment', 'value'])
45
payment_complete = Signal(providing_args=['order_id', 'payment', 'value'])

cryptapi/views.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import json
22
from django.http import HttpResponse
3-
from cryptapi.forms import CallbackForm
3+
from cryptapi.forms import CallbackForm, BaseCallbackForm
44
from cryptapi.dispatchers import CallbackDispatcher
55

66

77
def callback(_r):
88

9-
form = CallbackForm(data=_r.GET)
9+
pending = _r.GET.get('pending', False)
10+
11+
if not pending:
12+
form = CallbackForm(data=_r.GET)
13+
else:
14+
form = BaseCallbackForm(data=_r.GET)
1015

1116
if form.is_valid():
1217

@@ -23,15 +28,17 @@ def callback(_r):
2328
# Payment data
2429
payment = {
2530
'txid_in': form.cleaned_data.get('txid_in'),
26-
'txid_out': form.cleaned_data.get('txid_out'),
2731
'value_paid': form.cleaned_data.get('value'),
28-
'value_received': form.cleaned_data.get('value_forwarded'),
2932
'confirmations': form.cleaned_data.get('confirmations'),
3033
}
3134

35+
if not pending:
36+
payment['txid_out'] = form.cleaned_data.get('txid_out')
37+
payment['value_received'] = form.cleaned_data.get('value_forwarded')
38+
3239
raw_data = json.dumps(_r.GET)
3340

34-
dispatcher = CallbackDispatcher(coin, request, payment, raw_data)
41+
dispatcher = CallbackDispatcher(coin, request, payment, raw_data, pending=pending)
3542

3643
if dispatcher.callback():
3744
return HttpResponse('*ok*')

0 commit comments

Comments
 (0)