From 11e648884691e8b28e0ab5a91fa708a010d9af46 Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Mon, 15 Jun 2020 01:00:30 +0200 Subject: [PATCH 1/9] make compatible with django 2.2 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index aae6109..865fda5 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ url='https://github.com/taywa/django-saferpay', keywords=['saferpay', 'payment'], install_requires=[ - 'Django>=1.11,<2.2', + 'Django>=1.11,<=3', ], include_package_data=True, classifiers=[ From 4104141b1c52436c87e6e92ad780e68e6875df54 Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Mon, 22 Jun 2020 22:19:14 +0200 Subject: [PATCH 2/9] enable optional preselection of payment method --- .gitignore | 2 ++ saferpay/gateway.py | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 1521c8b..55c2281 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ dist +django_saferpay.egg-info/ +__pycache__/ diff --git a/saferpay/gateway.py b/saferpay/gateway.py index 03a1b80..e729817 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -23,16 +23,16 @@ class SaferpayService: - def __init__(self, order_id=None, notify_token='', amount=None, currency=None, + def __init__(self, order_id=None, notify_token='', amount=None, currency=None, payment_methods=None, language_code='en', token=None, sp_trans=None): - self.order_id, self.amount, self.currency = ( - order_id, amount, currency + self.order_id, self.amount, self.currency, self.payment_methods = ( + order_id, amount, currency, payment_methods ) self.language_code = language_code self.FORCE_LIABILITY_SHIFT_ACTIVE = getattr( settings, 'SAFERPAY_FORCE_LIABILITYSHIFT_ACTIVE', False ) - self.DO_NOTIFY = getattr( + self.DO_NOTIFY = getattr( # according to the docs, this is only relevant to Paydirekt transactions settings, 'SAFERPAY_DO_NOTIFY', False ) self.ORDER_TEXT_NR = getattr(settings, 'SAFERPAY_ORDER_TEXT_NR', 'Order nr. %s') @@ -112,7 +112,9 @@ def payload_init(self, billing_address): 'Fail': self.FAIL_URL } } - + # PaymentMethods according to http://saferpay.github.io/jsonapi/#Payment_v1_Transaction_Initialize + if self.payment_methods: + payload['PaymentMethods'] = self.payment_methods return payload def add_do_notify(self, payload, notify_token): From 7582a318f0b5fb1d8118e8f67080164ab6342013 Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Tue, 23 Jun 2020 00:26:38 +0200 Subject: [PATCH 3/9] add PayerNote --- saferpay/gateway.py | 1 + 1 file changed, 1 insertion(+) diff --git a/saferpay/gateway.py b/saferpay/gateway.py index e729817..e4fee00 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -101,6 +101,7 @@ def payload_init(self, billing_address): 'CurrencyCode': self.currency }, 'OrderId': self.order_id, + 'PayerNote': "Ref: {}".format(self.order_id), 'BillingAddress': billing_address, 'Description': self.ORDER_TEXT_NR % self.order_id, }, From e72926964ce5ed8203ad9c0c19ff03766d1a54c7 Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Mon, 29 Jun 2020 16:59:15 +0200 Subject: [PATCH 4/9] support saferpay alias and an order id that includes characters --- saferpay/gateway.py | 12 ++++++++++++ saferpay/migrations/0008_auto_20200627_2048.py | 18 ++++++++++++++++++ saferpay/models.py | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 saferpay/migrations/0008_auto_20200627_2048.py diff --git a/saferpay/gateway.py b/saferpay/gateway.py index e4fee00..a3120d1 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -55,6 +55,7 @@ def __init__(self, order_id=None, notify_token='', amount=None, currency=None, p self._next_url, self.sp_trans, self.token, self.notify_token = ( None, sp_trans, token, notify_token ) + self.capture_response_payload, self.assert_response_payload, init_response_payload = (None, None, None) @classmethod def init_from_transaction(cls, token=None): @@ -108,6 +109,10 @@ def payload_init(self, billing_address): "Payer": { 'LanguageCode': self.language_code }, + 'RegisterAlias': { # this alias can later be used to execute operations in SaferPay with the payment info + 'IdGenerator': 'RANDOM_UNIQUE', + 'Lifetime': getattr(settings, "SAFERPAY_ALIAS_LIFETIME", 1600) + }, 'ReturnUrls': { 'Success': self.SUCCESS_CAPTURE_URL, 'Fail': self.FAIL_URL @@ -137,13 +142,16 @@ def paymentpage_init(self, payload): amount=self.amount, currency=self.currency, language_code=self.language_code ) sp_trans.save() + self._new_saferpay_response( 'PAYMENTPAGE_INIT', payload, res, res_time, sp_trans, status_code=res.status_code ) + self.init_response_payload = res.json() # somebody might need the result synchronously in the instanc self._next_url = data['RedirectUrl'] self.token = data['Token'] return data['Token'] elif res: + self.init_response_payload = res.json() raise GatewayError('PAYMENTPAGE_INIT failed') else: print(res.status_code, res.text) @@ -172,6 +180,7 @@ def paymentpage_assert(self): self.sp_trans.transaction_id = res_data['Transaction']['Id'] self.sp_trans.status = res_data['Transaction']['Status'] self.sp_trans.save() + self.assert_response_payload = res.json() # somebody might need the result synchronously in the instance self._new_saferpay_response( 'PAYMENTPAGE_ASSERT', payload, res, res_time, self.sp_trans, status_code=res.status_code @@ -188,6 +197,7 @@ def paymentpage_assert(self): 'PAYMENTPAGE_ASSERT', payload, res, res_time, self.sp_trans, status_code=res.status_code ) + self.assert_response_payload = res.json() raise GatewayError('PAYMENTPAGE_ASSERT failed') else: raise PaymentError('PAYMENTPAGE_ASSERT') @@ -213,6 +223,7 @@ def transaction_capture(self): and res.json()['Status'] == 'CAPTURED': self.sp_trans.status = 'CAPTURED' self.sp_trans.save() + self.capture_response_payload = res.json() # someone might need the response synchronously in the instance self._new_saferpay_response( 'TRANSACTION_CAPTURE', payload, res, res_time, self.sp_trans, status_code=res.status_code @@ -224,6 +235,7 @@ def transaction_capture(self): status_code=res.status_code ) self.transaction_cancel() + self.capture_response_payload = res.json() raise UnableToTakePayment('TRANSACTION_CAPTURE failed') else: raise PaymentError('TRANSACTION_CAPTURE') diff --git a/saferpay/migrations/0008_auto_20200627_2048.py b/saferpay/migrations/0008_auto_20200627_2048.py new file mode 100644 index 0000000..91ddc91 --- /dev/null +++ b/saferpay/migrations/0008_auto_20200627_2048.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.12 on 2020-06-27 18:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('saferpay', '0007_auto_20180911_2207'), + ] + + operations = [ + migrations.AlterField( + model_name='saferpaytransaction', + name='order_id', + field=models.CharField(max_length=64), + ), + ] diff --git a/saferpay/models.py b/saferpay/models.py index 122866f..19e067d 100644 --- a/saferpay/models.py +++ b/saferpay/models.py @@ -10,7 +10,7 @@ class SaferpayTransaction(models.Model): ('CANCELD', 'CANCELD'), ) token = models.CharField(max_length=32, primary_key=True) - order_id = models.IntegerField() + order_id = models.CharField(max_length=64) date_created = models.DateTimeField(auto_now_add=True) amount = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True) currency = models.CharField(max_length=8, null=True, blank=True) From cb86de03738b7552ba4baf7b0852ea314724f19c Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Thu, 23 Jul 2020 06:36:02 +0200 Subject: [PATCH 5/9] dont automatically capture, there are setups where the payment is captured by a third party system later (for example) --- saferpay/gateway.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/saferpay/gateway.py b/saferpay/gateway.py index a3120d1..0b2d6d7 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -188,10 +188,7 @@ def paymentpage_assert(self): if self.FORCE_LIABILITY_SHIFT_ACTIVE and 'Liability' in res_data \ and res_data['Liability']['LiabilityShift'] is False: return self.transaction_cancel() - if res_data['Transaction']['Status'] == 'AUTHORIZED': - return self.transaction_capture() - elif res_data['Transaction']['Status'] == 'CAPTURED': - return 'CAPTURED' + return res_data['Transaction']['Status'] elif res: self._new_saferpay_response( 'PAYMENTPAGE_ASSERT', payload, res, res_time, self.sp_trans, From 26141fe4310445d1b756028c5a3e22eab53018b3 Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Thu, 23 Jul 2020 07:20:57 +0200 Subject: [PATCH 6/9] some payment methods such as POSTCARD do not support registering an alias --- saferpay/gateway.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/saferpay/gateway.py b/saferpay/gateway.py index 0b2d6d7..7fac2a8 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -87,7 +87,7 @@ def _new_saferpay_response( ) sp_res.save() - def payload_init(self, billing_address): + def payload_init(self, billing_address, register_alias=False): payload = { 'RequestHeader': { 'SpecVersion': SPECVERSION, @@ -109,15 +109,20 @@ def payload_init(self, billing_address): "Payer": { 'LanguageCode': self.language_code }, - 'RegisterAlias': { # this alias can later be used to execute operations in SaferPay with the payment info - 'IdGenerator': 'RANDOM_UNIQUE', - 'Lifetime': getattr(settings, "SAFERPAY_ALIAS_LIFETIME", 1600) - }, 'ReturnUrls': { 'Success': self.SUCCESS_CAPTURE_URL, 'Fail': self.FAIL_URL } } + + if register_alias: + # this alias can later be used to execute operations in SaferPay with the payment info + # only works with credit cards + payload['RegisterAlias'] = { + 'IdGenerator': 'RANDOM_UNIQUE', + 'Lifetime': getattr(settings, "SAFERPAY_ALIAS_LIFETIME", 1600) + } + # PaymentMethods according to http://saferpay.github.io/jsonapi/#Payment_v1_Transaction_Initialize if self.payment_methods: payload['PaymentMethods'] = self.payment_methods From 88e2defa8a72be8d580f631ae8325a8cb154b461 Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Mon, 14 Dec 2020 00:53:31 +0100 Subject: [PATCH 7/9] Update gateway.py --- saferpay/gateway.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saferpay/gateway.py b/saferpay/gateway.py index 7fac2a8..b16f8b6 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -19,7 +19,7 @@ TRANSACTION_CANCEL='/Payment/v1/Transaction/Cancel' ) API_PATHS_LOOKUP = {v: k for k, v in API_PATHS.items()} -SPECVERSION = 1.9 +SPECVERSION = 1.20 class SaferpayService: From c59cb1126617b45d5fbfc8e121e83dc7d8e2618b Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Thu, 17 Dec 2020 22:06:00 +0100 Subject: [PATCH 8/9] fix error messages --- saferpay/gateway.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/saferpay/gateway.py b/saferpay/gateway.py index b16f8b6..271ab8e 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -233,7 +233,7 @@ def transaction_capture(self): return 'CAPTURED' elif res: self._new_saferpay_response( - 'PAYMENTPAGE_ASSERT', payload, res, res_time, self.sp_trans, + 'TRANSACTION_CAPTURE', payload, res, res_time, self.sp_trans, status_code=res.status_code ) self.transaction_cancel() @@ -270,6 +270,6 @@ def transaction_cancel(self): 'TRANSACTION_CANCEL', payload, res, res_time, self.sp_trans, status_code=res.status_code ) - raise UnableToTakePayment('TRANSACTION_CAPTURE failed') + raise UnableToTakePayment('TRANSACTION_CANCEL failed') else: - raise PaymentError('TRANSACTION_CAPTURE') + raise PaymentError('TRANSACTION_CANCEL') From 2d775187d19bcece7e5a159152641091b22ee547 Mon Sep 17 00:00:00 2001 From: Mario Colombo Date: Thu, 17 Dec 2020 23:26:37 +0100 Subject: [PATCH 9/9] fix spec version error (1.2 != 1.20) --- saferpay/gateway.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saferpay/gateway.py b/saferpay/gateway.py index 271ab8e..9ff011f 100644 --- a/saferpay/gateway.py +++ b/saferpay/gateway.py @@ -19,7 +19,7 @@ TRANSACTION_CANCEL='/Payment/v1/Transaction/Cancel' ) API_PATHS_LOOKUP = {v: k for k, v in API_PATHS.items()} -SPECVERSION = 1.20 +SPECVERSION = "1.20" class SaferpayService: