Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,13 @@ Please follow PayWay's advice about reducing your risk of fraudulent transaction

```bash
uv python install 3.8.19
uv venv
uv venv --python 3.8.19
source .venv/bin/activate
uv sync --extra dev
```

## Testing

```bash
python -m unittest discover tests
uv run pytest tests/ -v
```
71 changes: 22 additions & 49 deletions payway/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@

import requests

from payway.conf import CUSTOMER_URL, TOKEN_NO_REDIRECT, TRANSACTION_URL
from payway.constants import (
BANK_ACCOUNT_PAYMENT_CHOICE,
CREDIT_CARD_PAYMENT_CHOICE,
CUSTOMER_URL,
PAYWAY_ERROR_RESPONSE_CODES,
TOKEN_NO_REDIRECT,
TRANSACTION_URL,
VALID_PAYMENT_METHOD_CHOICES,
)
from payway.customers import CustomerRequest
Expand Down Expand Up @@ -48,10 +51,10 @@ def __init__(
publishable_api_key: str,
) -> None:
"""
:param merchant_id : str = PayWay Merchant ID
:param bank_account_id : str = PayWay Bank Account ID
:param secret_api_key : str = PayWay Secret APi Key
:param publishable_api_key : str = PayWay Publishable API Key
:param merchant_id: PayWay Merchant ID
:param bank_account_id: PayWay Bank Account ID
:param secret_api_key: PayWay Secret APi Key
:param publishable_api_key: PayWay Publishable API Key
"""
self._validate_credentials(
merchant_id,
Expand All @@ -63,7 +66,6 @@ def __init__(
self.bank_account_id = bank_account_id
self.secret_api_key = secret_api_key
self.publishable_api_key = publishable_api_key

session = requests.Session()
session.auth = (self.secret_api_key, "")
session.headers = {"content-type": "application/x-www-form-urlencoded"}
Expand All @@ -79,16 +81,14 @@ def _validate_credentials(
secret_api_key: str,
publishable_api_key: str,
) -> None:
if not merchant_id or not bank_account_id or not secret_api_key or not publishable_api_key:
if not secret_api_key or not publishable_api_key:
logger.error("PayWay API keys not found")
raise PaywayError(
message="PayWay API keys not found",
code="INVALID_API_KEYS",
)
logger.error(
"Merchant ID, bank account ID, secret API key, publishable API key are " "invalid",
if any(not key for key in (secret_api_key, publishable_api_key)):
logger.error("PayWay API keys not found")
raise PaywayError(
message="PayWay API keys not found",
code="INVALID_API_KEYS",
)
if any(not val for val in (merchant_id, bank_account_id)):
logger.error("Merchant ID or bank account ID invalid")
raise PaywayError(
message="Invalid credentials",
code="INVALID_API_CREDENTIALS",
Expand Down Expand Up @@ -145,19 +145,17 @@ def create_token(
"paymentMethod": payway_payment_method,
},
)
endpoint = TOKEN_NO_REDIRECT
logger.info("Sending Create Token request to PayWay.")
response = self.post_request(
endpoint,
TOKEN_NO_REDIRECT,
data,
auth=(self.publishable_api_key, ""),
idempotency_key=idempotency_key,
)
errors = self._validate_response(response)
if errors:
return None, errors
token_response = TokenResponse().from_dict(response.json())
return token_response, errors
return TokenResponse().from_dict(response.json()), errors

def create_card_token(
self, card: PayWayCard, idempotency_key: str | None = None
Expand Down Expand Up @@ -187,23 +185,18 @@ def create_customer(
) -> tuple[PayWayCustomer | None, list[PaymentError] | None]:
"""
Create a customer in PayWay system

POST /customers to have PayWay generate the customer number
PUT /customers/{customerNumber} to use your own customer number

:param customer: PayWayCustomer object represents a customer in PayWay
:param idempotency_key: str: unique value to avoid duplicate POSTs
See model.PayWayCustomer
:return:
"""

data = customer.to_dict()
data.update(
{"merchantId": self.merchant_id, "bankAccountId": self.bank_account_id},
)

logger.info("Sending Create Customer request to PayWay.")

if customer.custom_id:
endpoint = f"{CUSTOMER_URL}/{customer.custom_id}"
response = self.put_request(endpoint, data)
Expand All @@ -214,11 +207,9 @@ def create_customer(
data,
idempotency_key=idempotency_key,
)

errors = self._validate_response(response)
if errors:
return None, errors

customer = PayWayCustomer().from_dict(response.json())
return customer, errors

Expand Down Expand Up @@ -246,25 +237,11 @@ def _validate_response(self, response: requests.Response) -> list[PaymentError]
Validates all responses from PayWay to catch documented PayWay errors.
:param response: requests response object
"""
if response.status_code in [
400,
401,
403,
405,
406,
407,
409,
410,
415,
429,
501,
503,
]:
if response.status_code in PAYWAY_ERROR_RESPONSE_CODES:
http_error_msg = f"{response.status_code} Client Error: {response.reason} for url: {response.url}"
raise PaywayError(code=str(response.status_code), message=http_error_msg)

if response.status_code in [404, 422]: # Documented PayWay errors in JSON
# parse error message
return PaymentError().from_dict(response.json())

if response.status_code == 500:
Expand Down Expand Up @@ -308,8 +285,7 @@ def void_transaction(
errors = self._validate_response(response)
if errors:
return None, errors
transaction = PayWayTransaction.from_dict(response.json())
return transaction, errors
return PayWayTransaction.from_dict(response.json()), errors

def refund_transaction(
self,
Expand Down Expand Up @@ -340,8 +316,7 @@ def refund_transaction(
errors = self._validate_response(response)
if errors:
return None, errors
transaction = PayWayTransaction.from_dict(response.json())
return transaction, errors
return PayWayTransaction.from_dict(response.json()), errors

def get_customer(self, customer_id: str) -> tuple[PayWayCustomer | None, list[PaymentError] | None]:
"""
Expand All @@ -353,8 +328,7 @@ def get_customer(self, customer_id: str) -> tuple[PayWayCustomer | None, list[Pa
errors = self._validate_response(response)
if errors:
return None, errors
customer = PayWayCustomer.from_dict(response.json())
return customer, errors
return PayWayCustomer.from_dict(response.json()), errors

def update_payment_setup(self, token: str, customer_id: str) -> tuple[PaymentSetup | None, list[PaymentError] | None]:
"""
Expand All @@ -372,5 +346,4 @@ def update_payment_setup(self, token: str, customer_id: str) -> tuple[PaymentSet
errors = self._validate_response(response)
if errors:
return None, errors
ps = PaymentSetup.from_dict(response.json())
return ps, errors
return PaymentSetup.from_dict(response.json()), errors
8 changes: 0 additions & 8 deletions payway/conf.py

This file was deleted.

23 changes: 22 additions & 1 deletion payway/constants.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from __future__ import annotations

PAYWAY_API_URL = "https://api.payway.com.au/rest/v1"
TOKEN_URL = PAYWAY_API_URL + "/single-use-tokens-redirect"
TRANSACTION_URL = PAYWAY_API_URL + "/transactions"
CUSTOMER_URL = PAYWAY_API_URL + "/customers"
OWN_BANK_ACCOUNTS_URL = PAYWAY_API_URL + "/your-bank-accounts"
TOKEN_NO_REDIRECT = PAYWAY_API_URL + "/single-use-tokens"
TRANSACTION_APPROVED = "0"

SUMMARY_CODES = {
Expand Down Expand Up @@ -69,7 +75,8 @@
CVN_RESPONSE_CODES = {
"M": "Matched", # i.e. the CVN is correct
"N": "Not Matched", # i.e. the CVN is incorrect
"P": "Not Processed", # i.e. the CVN was not processed for some reason; do not assume that the CVN is necessarily correct
"P": "Not Processed",
# i.e. the CVN was not processed for some reason; do not assume that the CVN is necessarily correct
"S": "Suspicious",
"U": "Unknown", # i.e. the CVN was not processed for some reason; do not assume that the CVN is necessarily correct
}
Expand Down Expand Up @@ -132,3 +139,17 @@
)
PAYMENT_METHOD_CHOICES = OTHER_PAYMENT_CHOICES + DIRECT_DEBIT_CHOICES
VALID_PAYMENT_METHOD_CHOICES = ["card", "direct_debit"]
PAYWAY_ERROR_RESPONSE_CODES = [
400,
401,
403,
405,
406,
407,
409,
410,
415,
429,
501,
503,
]
2 changes: 1 addition & 1 deletion payway/customers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import requests

from payway.conf import CUSTOMER_URL
from payway.constants import CUSTOMER_URL
from payway.model import PayWayCustomer
from payway.utils import json_list

Expand Down
Loading
Loading