Skip to content

Commit

Permalink
Merge pull request #339 from Mangopay/rel/3.28.0
Browse files Browse the repository at this point in the history
Rel/3.28.0
  • Loading branch information
iulian03 authored Sep 18, 2023
2 parents d700b5e + 4896d15 commit d79bb9a
Show file tree
Hide file tree
Showing 5 changed files with 589 additions and 86 deletions.
38 changes: 30 additions & 8 deletions mangopay/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
TRANSACTION_TYPE_CHOICES = Choices(
('PAYIN', 'payin', 'Pay In'),
('PAYOUT', 'payout', 'Pay out'),
('TRANSFER', 'transfer', 'Transfer')
('TRANSFER', 'transfer', 'Transfer'),
('CARD_VALIDATION', 'card_validation', 'Card validation')
)

NATURE_CHOICES = Choices(
Expand Down Expand Up @@ -172,11 +173,20 @@

('DEPOSIT_PREAUTHORIZATION_CREATED', 'deposit_preauthorization_created', 'Deposit Preauthorization Created'),
('DEPOSIT_PREAUTHORIZATION_FAILED', 'deposit_preauthorization_failed', 'Deposit Preauthorization Failed'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_WAITING', 'deposit_preauthorization_payment_waiting', 'Deposit Preauthorization Payment Waiting'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_EXPIRED', 'deposit_preauthorization_payment_expired', 'Deposit Preauthorization Payment Expired'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_CANCEL_REQUESTED', 'deposit_preauthorization_payment_cancel_requested', 'Deposit Preauthorization Payment Cancel Requested'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_CANCELED', 'deposit_preauthorization_payment_canceled', 'Deposit Preauthorization Payment Canceled'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_VALIDATED', 'deposit_preauthorization_payment_validated', 'Deposit Preauthorization Payment Validated')
('DEPOSIT_PREAUTHORIZATION_PAYMENT_WAITING', 'deposit_preauthorization_payment_waiting',
'Deposit Preauthorization Payment Waiting'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_EXPIRED', 'deposit_preauthorization_payment_expired',
'Deposit Preauthorization Payment Expired'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_CANCEL_REQUESTED', 'deposit_preauthorization_payment_cancel_requested',
'Deposit Preauthorization Payment Cancel Requested'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_CANCELED', 'deposit_preauthorization_payment_canceled',
'Deposit Preauthorization Payment Canceled'),
('DEPOSIT_PREAUTHORIZATION_PAYMENT_VALIDATED', 'deposit_preauthorization_payment_validated',
'Deposit Preauthorization Payment Validated'),

('CARD_VALIDATION_CREATED', 'card_validation_created', 'Card Validation Created'),
('CARD_VALIDATION_FAILED', 'card_validation_failed', 'Card Validation Failed'),
('CARD_VALIDATION_SUCCEEDED', 'card_validation_succeeded', 'Card Validation Succeeded'),
)

NOTIFICATION_STATUS_CHOICES = Choices(
Expand Down Expand Up @@ -287,7 +297,13 @@
("BANK_WIRE", "bank_wire", "Bank Wire"),
("APPLEPAY", "applepay", "Applepay"),
("GOOGLEPAY", "googlepay", "Googlepay"),
("MBWAY", "mbway", "Mbway")
("GOOGLE_PAY", "google_pay", "Google Pay"),
("MBWAY", "mbway", "Mbway"),
("PAYPAL", "paypal", "PayPal"),
("MULTIBANCO", "multibanco", "Multibanco"),
("SATISPAY", "satispay", "Satispay"),
("BLIK", "blik", "Blik"),
("KLARNA", "klarna", "Klarna")
)

CARD_STATUS_CHOICES = Choices(
Expand Down Expand Up @@ -338,4 +354,10 @@
('CREATED', 'created', 'Created'),
('SUCCEEDED', 'succeeded', 'Succeeded'),
('FAILED', 'failed', 'Failed')
)
)

SHIPPING_PREFERENCE_CHOICES = Choices(
('SET_PROVIDED_ADDRESS', 'set_provided_address', 'Set Provided Address'),
('GET_FROM_FILE', 'get_from_file', 'Get From File'),
('NO_SHIPPING', 'no_shipping', 'No Shipping')
)
189 changes: 180 additions & 9 deletions mangopay/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,25 +336,53 @@ def get_transactions(self, *args, **kwargs):
select.identifier = 'CARD_GET_TRANSACTIONS'
return select.all(*args, **kwargs)

def validate(self, *args, **kwargs):
kwargs['id'] = self.id
insert = InsertQuery(self, **kwargs)
insert.identifier = 'CARD_VALIDATE'
return insert.execute()

class Meta:
verbose_name = 'card'
verbose_name_plural = 'cards'
url = {
SelectQuery.identifier: '/cards',
UpdateQuery.identifier: '/cards',
'CARDS_FOR_FINGERPRINT': '/cards/fingerprints/%(fingerprint)s',
'CARD_VALIDATE': '/cards/%(id)s/validate'}
'CARDS_FOR_FINGERPRINT': '/cards/fingerprints/%(fingerprint)s'
}

def __str__(self):
return '%s of user %s' % (self.card_type, self.user_id)


class CardValidation(BaseModel):
creation_date = DateTimeField(api_name='CreationDate')
author = ForeignKeyField(User, api_name='AuthorId', required=True)
ip_address = CharField(api_name='IpAddress', required=True)
browser_info = BrowserInfoField(api_name='BrowserInfo', required=True)
secure_mode_return_url = CharField(api_name='SecureModeReturnURL', required=True)
secure_mode_redirect_url = CharField(api_name='SecureModeRedirectURL')
secure_mode_needed = BooleanField(api_name='SecureModeNeeded')
validity = CharField(api_name='Validity',
choices=constants.VALIDITY_CHOICES,
default=constants.VALIDITY_CHOICES.unknown)
type = CharField(api_name='Type', choices=constants.TRANSACTION_TYPE_CHOICES, default=None)
applied_3ds_version = CharField(api_name='Applied3DSVersion')
status = CharField(api_name='Status',
choices=constants.STATUS_CHOICES,
default=None)
result_code = CharField(api_name='ResultCode')
result_message = CharField(api_name='ResultMessage')

def validate(self, card_id, **kwargs):
insert = InsertQuery(self, **kwargs)
insert.insert_query = self.get_field_dict()
insert.insert_query['id'] = card_id
insert.identifier = 'CARD_VALIDATE'
return insert.execute()

class Meta:
verbose_name = 'card_validation'
verbose_name_plural = 'card_validations'
url = {
'CARD_VALIDATE': '/cards/%(id)s/validation'
}


class CardRegistration(BaseModel):
user = ForeignKeyField(User, api_name='UserId', required=True, related_name='card_registrations')
currency = CharField(api_name='Currency', required=True)
Expand Down Expand Up @@ -477,7 +505,13 @@ def cast(cls, result):
("BANK_WIRE", "EXTERNAL_INSTRUCTION"): BankWirePayInExternalInstruction,
("APPLEPAY", "DIRECT"): ApplepayPayIn,
("GOOGLEPAY", "DIRECT"): GooglepayPayIn,
("MBWAY", "DIRECT"): MbwayPayIn
("GOOGLE_PAY", "DIRECT"): GooglePayDirectPayIn,
("MBWAY", "WEB"): MbwayPayIn,
("PAYPAL", "WEB"): PayPalWebPayIn,
("MULTIBANCO", "WEB"): MultibancoPayIn,
("SATISPAY", "WEB"): SatispayPayIn,
("BLIK", "WEB"): BlikPayIn,
("KLARNA", "WEB"): KlarnaPayIn
}

return types.get((payment_type, execution_type), cls)
Expand Down Expand Up @@ -692,6 +726,31 @@ class Meta:
}


@python_2_unicode_compatible
class PayPalWebPayIn(PayIn):
creation_date = DateTimeField(api_name='CreationDate')
author = ForeignKeyField(User, api_name='AuthorId', required=True)
debited_funds = MoneyField(api_name='DebitedFunds', required=True)
fees = MoneyField(api_name='Fees', required=True)
credited_wallet = ForeignKeyField(Wallet, api_name='CreditedWalletId', required=True)
return_url = CharField(api_name='ReturnURL', required=True)
redirect_url = CharField(api_name='RedirectURL')
statement_descriptor = CharField(api_name='StatementDescriptor')
shipping = ShippingField(api_name='Shipping')
line_items = ListField(api_name='LineItems', required=True)
culture = CharField(api_name='Culture')
shipping_preference = CharField(api_name='ShippingPreference', choices=constants.SHIPPING_PREFERENCE_CHOICES,
default=None)

class Meta:
verbose_name = 'payin'
verbose_name_plural = 'payins'
url = {
InsertQuery.identifier: '/payins/payment-methods/paypal',
SelectQuery.identifier: '/payins'
}


@python_2_unicode_compatible
class PayconiqPayIn(PayIn):
author = ForeignKeyField(User, api_name='AuthorId', required=True)
Expand Down Expand Up @@ -743,6 +802,33 @@ class Meta:
InsertQuery.identifier: '/payins/googlepay/direct'
}


class GooglePayDirectPayIn(PayIn):
tag = CharField(api_name='Tag')
author = ForeignKeyField(User, api_name='AuthorId', required=True)
credited_wallet = ForeignKeyField(Wallet, api_name='CreditedWalletId', required=True)
debited_funds = MoneyField(api_name='DebitedFunds', required=True)
fees = MoneyField(api_name='Fees', required=True)
secure_mode_return_url = CharField(api_name='SecureModeReturnURL', required=True)
secure_mode = CharField(api_name='SecureMode',
choices=constants.SECURE_MODE_CHOICES,
default=constants.SECURE_MODE_CHOICES.default)
ip_address = CharField(api_name='IpAddress', required=True)
browser_info = BrowserInfoField(api_name='BrowserInfo', required=True)
payment_data = CharField(api_name='PaymentData', required=True)
shipping = ShippingField(api_name='Shipping')
billing = BillingField(api_name='Billing')
statement_descriptor = CharField(api_name='StatementDescriptor')

class Meta:
verbose_name = 'googlepay_direct_payin'
verbose_name_plural = 'googlepay_direct_payins'
url = {
InsertQuery.identifier: '/payins/payment-methods/googlepay',
SelectQuery.identifier: '/payins'
}


class MbwayPayIn(PayIn):
creation_date = DateTimeField(api_name='CreationDate')
author = ForeignKeyField(User, api_name='AuthorId', required=True)
Expand All @@ -759,6 +845,90 @@ class Meta:
SelectQuery.identifier: '/payins'
}


class MultibancoPayIn(PayIn):
creation_date = DateTimeField(api_name='CreationDate')
author = ForeignKeyField(User, api_name='AuthorId', required=True)
debited_funds = MoneyField(api_name='DebitedFunds', required=True)
fees = MoneyField(api_name='Fees', required=True)
statement_descriptor = CharField(api_name='StatementDescriptor')
redirect_url = CharField(api_name='RedirectURL')
return_url = CharField(api_name='ReturnURL', required=True)

class Meta:
verbose_name = 'multibanco_payin'
verbose_name_plural = 'multibanco_payins'
url = {
InsertQuery.identifier: '/payins/payment-methods/multibanco',
SelectQuery.identifier: '/payins'
}


class SatispayPayIn(PayIn):
creation_date = DateTimeField(api_name='CreationDate')
author = ForeignKeyField(User, api_name='AuthorId', required=True)
debited_funds = MoneyField(api_name='DebitedFunds', required=True)
fees = MoneyField(api_name='Fees', required=True)
return_url = CharField(api_name='ReturnURL', required=True)
redirect_url = CharField(api_name='RedirectURL')
country = CharField(api_name='Country', required=True)
statement_descriptor = CharField(api_name='StatementDescriptor')

class Meta:
verbose_name = 'satispay_payin'
verbose_name_plural = 'satispay_payins'
url = {
InsertQuery.identifier: '/payins/payment-methods/satispay',
SelectQuery.identifier: '/payins'
}


class BlikPayIn(PayIn):
creation_date = DateTimeField(api_name='CreationDate')
author = ForeignKeyField(User, api_name='AuthorId', required=True)
debited_funds = MoneyField(api_name='DebitedFunds', required=True)
fees = MoneyField(api_name='Fees', required=True)
statement_descriptor = CharField(api_name='StatementDescriptor')
return_url = CharField(api_name='ReturnURL', required=True)
redirect_url = CharField(api_name='RedirectURL')

class Meta:
verbose_name = 'blik_payin'
verbose_name_plural = 'blik_payins'
url = {
InsertQuery.identifier: '/payins/payment-methods/blik',
SelectQuery.identifier: '/payins'
}


class KlarnaPayIn(PayIn):
author = ForeignKeyField(User, api_name='AuthorId', required=True)
debited_funds = MoneyField(api_name='DebitedFunds', required=True)
fees = MoneyField(api_name='Fees', required=True)
return_url = CharField(api_name='ReturnURL', required=True)
line_items = ListField(api_name='LineItems', required=True)
country = CharField(api_name='Country', required=True)
phone = CharField(api_name='Phone', required=True)
email = EmailField(api_name='Email', required=True)
additional_data = CharField(api_name='AdditionalData', required=True)
billing = BillingField(api_name='Billing', required=True)
merchant_order_id = CharField(api_name='MerchantOrderId', required=True)
culture = CharField(api_name='Culture', required=True)
shipping = ShippingField(api_name='Shipping')
creation_date = DateTimeField(api_name='CreationDate')
credited_funds = MoneyField(api_name='CreditedFunds')
redirect_url = CharField(api_name='RedirectURL')
payment_method = CharField(api_name='PaymentMethod')

class Meta:
verbose_name = 'klarna_payin'
verbose_name_plural = 'klarna_payins'
url = {
InsertQuery.identifier: '/payins/payment-methods/klarna',
SelectQuery.identifier: '/payins'
}


class CardWebPayIn(PayIn):
author = ForeignKeyField(User, api_name='AuthorId', required=True)
credited_wallet = ForeignKeyField(Wallet, api_name='CreditedWalletId', required=True)
Expand Down Expand Up @@ -849,6 +1019,7 @@ class Meta:
SelectQuery.identifier: '/payins'
}


class PreAuthorization(BaseModel):
author = ForeignKeyField(User, api_name='AuthorId', required=True)
debited_funds = MoneyField(api_name='DebitedFunds', required=True)
Expand Down
22 changes: 22 additions & 0 deletions mangopay/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -923,3 +923,25 @@ def to_api_json(self):
"PayinCaptureId": self.payin_capture_id,
"PayinComplementId": self.payin_complement_id
}


class LineItem(object):
def __init__(self, name=None, quantity=None, unit_amount=None, tax_amount=None, description=None):
self.name = name
self.quantity = quantity
self.unit_amount = unit_amount
self.tax_amount = tax_amount
self.description = description

def __str__(self):
return 'LineItem: %s %s %s %s %s' % \
(self.name, self.quantity, self.unit_amount, self.tax_amount, self.description)

def to_api_json(self):
return {
"Name": self.name,
"Quantity": self.quantity,
"UnitAmount": self.unit_amount,
"TaxAmount": self.tax_amount,
"Description": self.description
}
37 changes: 33 additions & 4 deletions tests/test_cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
except ImportError:
import urllib as urlrequest

from mangopay.resources import Card, CardRegistration
from mangopay.resources import Card, CardRegistration, CardValidation
from tests.test_base import BaseTest
from tests.test_base import BaseTestLive

Expand Down Expand Up @@ -279,7 +279,36 @@ def test_getCardTransactions(self):
self.assertIsInstance(transactions_page.data, list)

def test_cardValidation(self):
card = BaseTestLive.get_johns_card()
validatedCard = card.validate()
user = BaseTestLive.get_john()

card_registration = CardRegistration()
card_registration.user = user
card_registration.currency = 'EUR'

self.assertIsNotNone(validatedCard)
saved_registration = card_registration.save()
data = {
'cardNumber': '4970107111111119',
'cardCvx': '123',
'cardExpirationDate': '1224',
'accessKeyRef': card_registration.access_key,
'data': card_registration.preregistration_data
}
headers = {
'content-type': 'application/x-www-form-urlencoded'
}
registration_data_response = requests.post(card_registration.card_registration_url, data=data, headers=headers)
saved_registration['registration_data'] = registration_data_response.text
updated_registration = CardRegistration(**saved_registration).save()
card_id = updated_registration['card_id']

card_validation = CardValidation()
card_validation.author = user
card_validation.tag = "test"
card_validation.secure_mode_return_url = "http://www.example.com/"
card_validation.ip_address = "2001:0620:0000:0000:0211:24FF:FE80:C12C"
card_validation.browser_info = BaseTest.get_browser_info()

validation_response = card_validation.validate(card_id)

self.assertIsNotNone(validation_response)
self.assertIsNotNone(validation_response['id'])
Loading

0 comments on commit d79bb9a

Please sign in to comment.