Skip to content

Commit 7ffb544

Browse files
iulian03Iulian Masar
and
Iulian Masar
authored
[release] 3.42.0 (#406)
* [feature] recipients (#395) * support for recipients * added event types for recipients * updated RecipientSchema * updated RecipientPropertySchema * updated Recipient properties --------- Co-authored-by: Iulian Masar <iulian.masar@codegile.com> * handle sca context on transfers (#398) Co-authored-by: Iulian Masar <iulian.masar@codegile.com> * handle user close endpoints (#405) Co-authored-by: Iulian Masar <iulian.masar@codegile.com> * updated tests * updated tests --------- Co-authored-by: Iulian Masar <iulian.masar@codegile.com>
1 parent 0168fc1 commit 7ffb544

File tree

13 files changed

+719
-91
lines changed

13 files changed

+719
-91
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The SDK supports Python 3.9, 3.10, 3.11, and 3.12.
1414
- [POST Create a Pay by Bank PayIn](https://docs.mangopay.com/api-reference/pay-by-bank/create-pay-by-bank-payin), including related `PAYIN_NORMAL_PROCESSING_STATUS_PENDING_SUCCEEDED` webhook event type
1515
- PayPal recurring payments, thanks to the `PaymentType` value `PAYPAL` on [Recurring PayIn Registrations](https://docs.mangopay.com/api-reference/recurring-payin-registrations/create-recurring-payin-registration-paypal) and new endpoints ([POST Create a Recurring PayPal PayIn (CIT)](https://docs.mangopay.com/api-reference/paypal/create-recurring-paypal-payin-cit) and [POST Create a Recurring PayPal PayIn (MIT)](https://docs.mangopay.com/api-reference/paypal/create-recurring-paypal-payin-mit)
1616

17-
## [3.40.1] - 2025-03-19
17+
## [3.40.1] - 2025-04-02
1818
### Changed
1919
- User-Agent Header value standardized on format: User-Agent: Mangopay-SDK/`SDKVersion` (`Language`/`LanguageVersion`)
2020

mangopay/api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def custom_request(self, method, url, data=None, idempotency_key=None, oauth_req
163163
requests.codes.created, requests.codes.accepted,
164164
requests.codes.no_content):
165165
self._create_apierror(result, url=url, data=data, method=method)
166-
elif result.status_code == requests.codes.no_content:
166+
elif result.status_code == requests.codes.no_content or (result.status_code == requests.codes.ok and result.content == b''):
167167
return result, None
168168
else:
169169
if result.content:

mangopay/base.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import six
2-
31
from copy import deepcopy
42

3+
import six
4+
5+
from . import get_default_handler
56
from .fields import PrimaryKeyField, FieldDescriptor, Field, ForeignRelatedObject
6-
from .query import UpdateQuery, InsertQuery, SelectQuery
7+
from .query import UpdateQuery, InsertQuery, SelectQuery, DeleteQuery
78
from .signals import pre_save, post_save
89
from .utils import force_text, force_str
9-
from . import get_default_handler
1010

1111

1212
class DoesNotExist(Exception):
@@ -263,6 +263,10 @@ def list(self, resource_model, **kwargs):
263263
def all(cls, *args, **kwargs):
264264
return cls.select().all(*args, **kwargs)
265265

266+
@classmethod
267+
def delete(cls, *args, **kwargs):
268+
return DeleteQuery(cls, *args, **kwargs).execute()
269+
266270
def get_pk(self):
267271
return getattr(self, self._meta.pk_name, None)
268272

mangopay/constants.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,11 @@
199199
('IDENTITY_VERIFICATION_FAILED', 'identity_verification_failed', 'Identity Verification Failed'),
200200
('IDENTITY_VERIFICATION_INCONCLUSIVE', 'identity_verification_inconclusive', 'Identity Verification Inconclusive'),
201201
('IDENTITY_VERIFICATION_OUTDATED', 'identity_verification_outdated', 'Identity Verification Outdated'),
202-
('IDENTITY_VERIFICATION_TIMEOUT', 'identity_verification_timeout', 'Identity Verification Timeout')
202+
('IDENTITY_VERIFICATION_TIMEOUT', 'identity_verification_timeout', 'Identity Verification Timeout'),
203+
204+
('RECIPIENT_ACTIVE', 'recipient_active', 'Recipient Active'),
205+
('RECIPIENT_CANCELED', 'recipient_canceled', 'Recipient Canceled'),
206+
('RECIPIENT_DEACTIVATED', 'recipient_deactivated', 'Recipient Deactivated'),
203207
)
204208

205209
NOTIFICATION_STATUS_CHOICES = Choices(

mangopay/fields.py

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
PlatformCategorization, Billing, SecurityInfo, Birthplace, ApplepayPaymentData, GooglepayPaymentData, \
1212
ScopeBlocked, BrowserInfo, Shipping, CurrentState, FallbackReason, InstantPayout, CountryAuthorizationData, \
1313
PayinsLinked, ConversionRate, CardInfo, LocalAccountDetails, InternationalAccountDetails, \
14-
VirtualAccountCapabilities, PaymentRef, PendingUserAction, LegalRepresentative
14+
VirtualAccountCapabilities, PaymentRef, PendingUserAction, LegalRepresentative, IndividualRecipient, \
15+
BusinessRecipient, RecipientPropertySchema, IndividualRecipientPropertySchema, BusinessRecipientPropertySchema
1516

1617

1718
class FieldDescriptor(object):
@@ -161,7 +162,7 @@ def python_value(self, value):
161162

162163
class DictField(Field):
163164
def api_value(self, value):
164-
return json.dumps(value)
165+
return value
165166

166167
def python_value(self, value):
167168
if value is not None and isinstance(value, str):
@@ -917,6 +918,7 @@ def api_value(self, value):
917918

918919
return value
919920

921+
920922
class ConversionRateField(Field):
921923
def python_value(self, value):
922924
if value is not None:
@@ -1066,3 +1068,115 @@ def api_value(self, value):
10661068
}
10671069

10681070
return value
1071+
1072+
1073+
class IndividualRecipientField(Field):
1074+
def python_value(self, value):
1075+
if value is not None:
1076+
return IndividualRecipient(first_name=value.get('FirstName', None), last_name=value.get('LastName', None),
1077+
address=value.get('Address', None))
1078+
1079+
return value
1080+
1081+
def api_value(self, value):
1082+
value = super(IndividualRecipientField, self).api_value(value)
1083+
1084+
if isinstance(value, IndividualRecipient):
1085+
value = {
1086+
'FirstName': value.first_name,
1087+
'LastName': value.last_name,
1088+
'Address': value.address
1089+
}
1090+
1091+
return value
1092+
1093+
1094+
class BusinessRecipientField(Field):
1095+
def python_value(self, value):
1096+
if value is not None:
1097+
return BusinessRecipient(business_name=value.get('BusinessName', None), address=value.get('Address', None))
1098+
1099+
return value
1100+
1101+
def api_value(self, value):
1102+
value = super(BusinessRecipientField, self).api_value(value)
1103+
1104+
if isinstance(value, BusinessRecipient):
1105+
value = {
1106+
'BusinessName': value.business_name,
1107+
'Address': value.address
1108+
}
1109+
1110+
return value
1111+
1112+
1113+
class RecipientPropertySchemaField(Field):
1114+
def python_value(self, value):
1115+
if value is not None:
1116+
return RecipientPropertySchema(required=value.get('Required', None),
1117+
max_length=value.get('MaxLength', None),
1118+
min_length=value.get('MinLength', None),
1119+
pattern=value.get('Pattern', None),
1120+
allowed_values=value.get('AllowedValues', None),
1121+
label=value.get('Label', None),
1122+
end_user_display=value.get('EndUserDisplay', None))
1123+
1124+
return value
1125+
1126+
def api_value(self, value):
1127+
value = super(RecipientPropertySchemaField, self).api_value(value)
1128+
1129+
if isinstance(value, RecipientPropertySchema):
1130+
value = {
1131+
'Required': value.required,
1132+
'MaxLength': value.max_length,
1133+
'MinLength': value.min_length,
1134+
'Pattern': value.pattern,
1135+
'AllowedValues': value.allowed_values,
1136+
'Label': value.label,
1137+
'EndUserDisplay': value.end_user_display
1138+
}
1139+
1140+
return value
1141+
1142+
1143+
class IndividualRecipientPropertySchemaField(Field):
1144+
def python_value(self, value):
1145+
if value is not None:
1146+
return IndividualRecipientPropertySchema(first_name=value.get('FirstName', None),
1147+
last_name=value.get('LastName', None),
1148+
address=value.get('Address', None))
1149+
1150+
return value
1151+
1152+
def api_value(self, value):
1153+
value = super(IndividualRecipientPropertySchemaField, self).api_value(value)
1154+
1155+
if isinstance(value, IndividualRecipientPropertySchema):
1156+
value = {
1157+
'FirstName': value.first_name,
1158+
'LastName': value.last_name,
1159+
'Address': value.address
1160+
}
1161+
1162+
return value
1163+
1164+
1165+
class BusinessRecipientPropertySchemaField(Field):
1166+
def python_value(self, value):
1167+
if value is not None:
1168+
return BusinessRecipientPropertySchema(business_name=value.get('BusinessName', None),
1169+
address=value.get('Address', None))
1170+
1171+
return value
1172+
1173+
def api_value(self, value):
1174+
value = super(BusinessRecipientPropertySchemaField, self).api_value(value)
1175+
1176+
if isinstance(value, BusinessRecipientPropertySchema):
1177+
value = {
1178+
'BusinessName': value.business_name,
1179+
'Address': value.address
1180+
}
1181+
1182+
return value

mangopay/query.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,25 @@ def execute(self, handler=None):
174174
return self.parse_result(data)
175175

176176

177+
class DeleteQuery(BaseQuery):
178+
identifier = 'DELETE'
179+
180+
def __init__(self, model, reference, **kwargs):
181+
self.delete_query = kwargs
182+
self.reference = reference
183+
super(DeleteQuery, self).__init__(model, 'DELETE')
184+
185+
def execute(self, handler=None):
186+
handler = handler or self.handler
187+
188+
meta_url = self.parse_url(self.model._meta.url, self.delete_query)
189+
url = '%s/%s' % (meta_url, self.reference)
190+
191+
result, data = handler.request(self.method, url)
192+
193+
return self.parse_result(data)
194+
195+
177196
class ActionQuery(BaseQuery):
178197

179198
def __init__(self, model, reference, identifier, method='PUT', params=None, **kwargs):

0 commit comments

Comments
 (0)