Skip to content
Open
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.pypirc
*.pyc
test.py
venv
build
3 changes: 1 addition & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
include *.txt
recursive-include docs *.txt
include LICENSE *.rst *.txt *.md
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

FasterPay Python SDK enables you to integrate the FasterPay's Checkout Page seamlessly without having the hassle of integrating everything from Scratch.
Once your customer is ready to pay, FasterPay will take care of the payment, notify your system about the payment and return the customer back to your Thank You page.
For more information on the API Parameters, refer to our entire API Documentation [here](https://docs.fasterpay.com/api#section-custom-integration)

## Downloading the FasterPay Python SDK

Expand All @@ -12,7 +13,7 @@ $ git clone https://github.com/FasterPay/fasterpay-python3.git
## Installing the FasterPay Python SDK.
```sh
$ cd fasterpay-python3
$ sudo python setup.py install
$ pip install -e .
```

## Initiating Payment Request using Python SDK
Expand Down Expand Up @@ -40,8 +41,6 @@ if __name__ == "__main__":
print paymentForm
```

For more information on the API Parameters, refer to our entire API Documentation [here](https://docs.fasterpay.com/api#section-custom-integration)

## Handling FasterPay Pingbacks

```python
Expand Down
18 changes: 18 additions & 0 deletions fasterpay/address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import requests


class Address:
def __init__(self, gateway):
self.gateway = gateway
self.api_url = gateway.config.external_api_url

def get_address(self, country_code: str) -> dict:
"""Retrieve the address fields required for the specified country."""
if not country_code:
raise ValueError("country_code is required to retrieve address fields.")

url = f"{self.api_url}/api/external/address/fields/{country_code}"

response = requests.get(url)
response.raise_for_status()
return response.json()
53 changes: 32 additions & 21 deletions fasterpay/config.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
class Config:
def __init__(
self,
private_key: str,
public_key: str,
is_test: bool = False,
api_version: str = "1.0.0",
):
self._private_key = private_key
self._public_key = public_key
self._api_base_url = (
"https://pay.sandbox.fasterpay.com"
if is_test else
"https://pay.fasterpay.com"
)
self._api_version = api_version
self._external_api_url = "https://business.fasterpay.com"

def __init__(self, privateKey, publicKey, is_test = False, apiVersion = None):
self.publicKey = publicKey
self.privateKey = privateKey
if is_test is True :
self.API_BASE_URL = "https://pay.fasterpay.com"
else:
self.API_BASE_URL = "https://pay.sandbox.fasterpay.com"
@property
def public_key(self) -> str:
return self._public_key

if apiVersion is not None :
self.VERSION = apiVersion
else:
self.VERSION = "1.0.0"
@property
def private_key(self) -> str:
return self._private_key

def get_public_key(self):
return self.publicKey
@property
def api_url(self) -> str:
return self._api_base_url

def get_private_key(self):
return self.privateKey

def get_api_url(self):
return self.API_BASE_URL

def get_api_version(self):
return self.VERSION
@property
def api_version(self) -> str:
return self._api_version

@property
def external_api_url(self) -> str:
return self._external_api_url
152 changes: 152 additions & 0 deletions fasterpay/contact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import requests

class Contact:
def __init__(self, gateway):
self.gateway = gateway
self.api_url = gateway.config.external_api_url
self.api_key = gateway.config.private_key

def create_contact(self, params: dict) -> dict:
"""
Create a new contact.

Parameters (at least one of `email` or `phone` is required):
- email (str): Email address of the contact.
- phone (str): Phone number of the contact.
- phone_country_code (str): Required if phone is provided. ISO 3166-1 alpha-2 format (e.g., 'US').
- first_name (str, optional): Max 90 characters.
- last_name (str, optional): Max 90 characters.
- country (str, optional): ISO 3166-1 alpha-2 code.
- favorite (bool, optional): Mark this contact as favorite.

Endpoint:
POST https://business.fasterpay.com/api/external/contacts

Docs:
https://docs.fasterpay.com/api#section-create-contact

Returns:
dict: Contact creation result.
"""
email = params.get("email")
phone = params.get("phone")
phone_code = params.get("phone_country_code")

if not email and not phone:
raise ValueError("Either 'email' or 'phone' is required.")

if phone and not phone_code:
raise ValueError("'phone_country_code' is required when 'phone' is provided.")

url = f"{self.api_url}/api/external/contacts"
response = requests.post(url, json=params)
response.raise_for_status()
return response.json()

def list_contacts(self, params: dict = None) -> dict:
"""
Retrieve a list of contacts with optional filtering and sorting.

Optional Parameters:
- prefer_favorite (bool): Show favorite contacts first.
- fasterpay_account_only (bool): Show only contacts with FasterPay accounts.
- name (str): Filter by full name (first or last name).
- email (str): Filter by email prefix.
- phone (str): Filter by phone number.
- country (str): Filter by ISO 3166-1 alpha-2 country code.
- sort_by (str): Required if `order_by` is present. One of: first_name, last_name, favorite, updated_at, last_transfer_at.
- order_by (str): Required if `sort_by` is present. One of: asc, desc.
- page (int): Page number to retrieve (default 1).
- per_page (int): Max records per page (max 1000).

Endpoint:
GET https://business.fasterpay.com/api/external/contacts

Docs:
https://docs.fasterpay.com/api#section-contact-list

Returns:
dict: Paginated list of contacts.
"""
params = params or {}

if "sort_by" in params and "order_by" not in params:
raise ValueError("'order_by' is required when 'sort_by' is provided.")
if "order_by" in params and "sort_by" not in params:
raise ValueError("'sort_by' is required when 'order_by' is provided.")

url = f"{self.api_url}/api/external/contacts"
response = requests.get(url, params=params)
response.raise_for_status()
return response.json()

def get_contact(self, contact_id: str) -> dict:
"""
Retrieve details of a specific contact by ID.

Parameters:
- contact_id (str): ID of the contact (e.g., CT-250527-AZARCIJE)

Endpoint:
GET https://business.fasterpay.com/api/external/contacts/{contact_id}

Returns:
dict: Contact detail response.
"""
if not contact_id:
raise ValueError("contact_id is required to retrieve a contact.")

url = f"{self.api_url}/api/external/contacts/{contact_id}"
response = requests.get(url)
response.raise_for_status()
return response.json()

def update_contact(self, contact_id: str, params: dict) -> dict:
"""
Update a contact's details.

Parameters:
- contact_id (str): ID of the contact to update.
- params (dict): Fields to update:
- email (str, optional)
- phone (str, optional)
- phone_country_code (str): Required if phone is present.
- first_name (str, optional)
- last_name (str, optional)
- country (str, optional)
- favorite (bool, optional)

Endpoint:
PUT https://business.fasterpay.com/api/external/contacts/{contact_id}

Returns:
dict: Updated contact info.
"""
if not contact_id:
raise ValueError("contact_id is required to update a contact.")

url = f"{self.api_url}/api/external/contacts/{contact_id}"
response = requests.put(url, json=params)
response.raise_for_status()
return response.json()

def delete_contact(self, contact_id: str) -> dict:
"""
Delete a contact by ID.

Parameters:
- contact_id (str): ID of the contact to delete.

Endpoint:
DELETE https://business.fasterpay.com/api/external/contacts/{contact_id}

Returns:
dict: API response with success status.
"""
if not contact_id:
raise ValueError("contact_id is required to delete a contact.")

url = f"{self.api_url}/api/external/contacts/{contact_id}"
response = requests.delete(url)
response.raise_for_status()
return response.json()
Loading