Skip to content

Commit

Permalink
Merge pull request #7 from AltaPay/agreement_parameters_and_apple_pay
Browse files Browse the repository at this point in the history
Add new agreement parameters and Apple Pay support
  • Loading branch information
emicha authored Jul 27, 2022
2 parents e1c719f + b94099d commit cf13441
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Setup Python
run: sudo add-apt-repository -y ppa:deadsnakes/ppa && sudo apt-get install -y python3.6 python3.7 python3.9
run: sudo add-apt-repository -y ppa:deadsnakes/ppa && sudo apt-get install -y python3.6 python3.7 python3.9 python3.6-distutils python3.7-distutils python3.9-distutils

- name: Install dependencies
run: |
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Change Log
----------

1.5.2
+++++++++++++++++++++

**Features**

- Add support for new 'Agreements Engine' parameters
- Add support for Apple Pay

1.5.1
+++++++++++++++++++++

Expand Down
2 changes: 1 addition & 1 deletion altapay/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__title__ = 'altapay'
__version__ = '1.5.1'
__version__ = '1.5.2'
__author__ = 'Coolshop.com'
__license__ = 'MIT'
__github_url__ = 'https://github.com/coolshop-com/AltaPay'
Expand Down
81 changes: 81 additions & 0 deletions altapay/card_wallet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from __future__ import absolute_import, unicode_literals

import altapay.callback
from altapay.resource import Resource


class CardWallet(Resource):
def session(self, terminal, validation_url, domain):
"""
This is the step to receive Apple Pay session.
By invoking this method we will reach Apple Pay with Merchant key and
certificate to retrieve a session
which should be used to proceed with Apple Pay payment.
Returned session object should be used in
session.completeMerchantValidation(JSON.parse(merchantSession));
:arg terminal: The title of your terminal which was configured
with Apple Pay
:arg validation_url: Validation URL which was passed from
requestSession ApplePayValidateMerchantEvent.validationURL
:arg domain: The domain from which you are initializing the request,
which requires to be verified.
Otherwise, the request will use the default domain specified
in the terminal.
"""
parameters = {
'terminal': terminal,
'validationURL': validation_url,
'domain': domain
}

response = self.api.post(
'API/cardWallet/session', data=parameters)['APIResponse']

return altapay.callback.Callback.from_xml_callback(response)

def authorize(self, provider_data, terminal, shop_orderid, amount,
currency, **kwargs):
"""
This step is required to process Apple Pay data.
By invoking this method we will decrypt data
with Processing Key and Authorize it against selected acquirer.
Returned response is similar to callback xml.
:arg provider_data: The string value of
ApplePayPaymentAuthorizedEvent.payment.token
as produced by JSON.stringify()
:arg terminal: The title of your terminal which was configured
with Apple Pay
:arg shop_orderid: The id of the order in your webshop.
This is what we will post back to you so you know which order
a given payment is associated with.
:arg amount: The amount of the payment in english notation (ex. 89.95)
:arg currency: The currency of the payment in ISO-4217 format.
Either the 3-digit numeric code, or the 3-letter character code
:arg kwargs: used for optional parameters
The optional parameters follow the same logic as
with eCommerce/API/createPaymentRequest.
For details, see the documentation for createPaymentRequest.
Note that you will need to use lists and dictionaries to map the
URL structures from the AltaPay documentation into these kwargs.
:rtype: :py:class:`altapay.Callback` object.
"""
parameters = {
'provider_data': provider_data,
'terminal': terminal,
'shop_orderid': shop_orderid,
'amount': amount,
'currency': currency,
}

parameters.update(kwargs)

response = self.api.post(
'API/cardWallet/authorize',
data=parameters)['APIResponse']

return altapay.callback.Callback.from_xml_callback(response)
8 changes: 6 additions & 2 deletions altapay/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ def charge_subscription(self, **kwargs):
:rtype: :py:class:`altapay.Callback` object.
"""
parameters = {
'transaction_id': self.transaction_id
'agreement': {
'id': self.transaction_id
}
}

parameters.update(kwargs)
Expand All @@ -122,7 +124,9 @@ def reserve_subscription_charge(self, **kwargs):
:rtype: :py:class:`altapay.Callback` object.
"""
parameters = {
'transaction_id': self.transaction_id
'agreement': {
'id': self.transaction_id
}
}

parameters.update(kwargs)
Expand Down
82 changes: 74 additions & 8 deletions tests/integration/test_merchant_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ def test_create_payment_request(self):
self.assertIn('url', payment)
self.assertEqual(len(payment.url) > 0, True)

def test_create_payment_request_with_agreement(self):
payment = Payment(api=self.api)
params = {
'terminal': altapay_test_terminal_name,
'shop_orderid': generate_order_id(),
'amount': 7.00,
'currency': 'EUR',
'type': 'subscription',
'agreement': {
'type': 'unscheduled',
'unscheduled_type': 'incremental'
}
}
self.assertEqual(payment.create(**params), True)
self.assertIn('url', payment)
self.assertEqual(len(payment.url) > 0, True)

def test_create_moto_reservation(self):
reservation = Reservation(api=self.api)
date_today = date.today()
Expand All @@ -51,6 +68,28 @@ def test_create_moto_reservation(self):
self.assertEqual(reservation.create(**params), True)
self.assertEqual(reservation.success, True)

def test_create_moto_reservation_with_agreement(self):
reservation = Reservation(api=self.api)
date_today = date.today()
params = {
'terminal': altapay_test_terminal_name,
'shop_orderid': generate_order_id(),
'amount': '77',
'currency': 'DKK',
'cardnum': '4111000011110002',
'emonth': date_today.month,
'eyear': date_today.year + 1,
'cvc': '123',
'type': 'subscription',
'agreement': {
'type': 'unscheduled',
'unscheduled_type': 'incremental'
}
}

self.assertEqual(reservation.create(**params), True)
self.assertEqual(reservation.success, True)

def test_reservation_capture(self):
reservation = Reservation(api=self.api)
date_today = date.today()
Expand Down Expand Up @@ -203,7 +242,10 @@ def test_charge_subscription(self):
'eyear': date_today.year + 1,
'cvc': '123',
'type': 'subscription',
'agreement_type': 'recurring'
'agreement': {
'type': 'unscheduled',
'unscheduled_type': 'incremental'
}
}
reservation.create(**params)
# parse transaction from reservation response object
Expand All @@ -212,7 +254,10 @@ def test_charge_subscription(self):

transaction = Transaction.find(transaction_id, self.api)
transaction_params = {
'transaction_id': transaction_id,
'agreement': {
'id': transaction_id,
'unscheduled_type': 'incremental'
},
'reconciliation_identifier': order_id,
'amount': '21',
'currency': 'DKK'
Expand All @@ -221,20 +266,24 @@ def test_charge_subscription(self):

self.assertEqual(capture_result.result, "Success")

def test_reverse_subscription_charge(self):
def test_reserve_subscription_charge_with_agreement_and_capture(self):
reservation = Reservation(api=self.api)
date_today = date.today()
order_id = generate_order_id()
params = {
'terminal': altapay_test_terminal_name,
'shop_orderid': generate_order_id(),
'amount': '25',
'shop_orderid': order_id,
'amount': '7777',
'currency': 'DKK',
'cardnum': '4111000011110002',
'emonth': date_today.month,
'eyear': date_today.year + 1,
'cvc': '123',
'type': 'subscription',
'agreement_type': 'recurring'
'agreement': {
'type': 'unscheduled',
'unscheduled_type': 'incremental'
}
}
reservation.create(**params)
# parse transaction from reservation response object
Expand All @@ -243,14 +292,31 @@ def test_reverse_subscription_charge(self):

transaction = Transaction.find(transaction_id, self.api)
transaction_params = {
'transaction_id': transaction_id,
'amount': '21',
'agreement': {
'id': transaction_id,
'unscheduled_type': 'incremental',
},
'amount': '7777',
'currency': 'DKK'
}
resp = transaction.reserve_subscription_charge(**transaction_params)

self.assertEqual(resp.result, "Success")

for t in resp.transactions():
if t.auth_type == 'subscription_payment':
transaction_id = t.transaction_id
break
transaction = Transaction.find(transaction_id, self.api)

c_t_params = {
'transaction_id': transaction_id,
'amount': 7777
}

# capture existing transaction with defined params
self.assertEqual(transaction.capture(**c_t_params).result, 'Success')

def test_funding_list(self):
funding_list = FundingList(api=self.api)
self.assertIsNotNone(funding_list.fundings)
Expand Down

0 comments on commit cf13441

Please sign in to comment.