Unofficial async
Python module to interface with the payment processor
Payconiq.
Warning
This is an initial PoC and integration of the module. The API will most likely change in future releases.
The module can be directly installed through pip:
pip install pyconiq
For development purposes, and once the project cloned or the codespace ready,
you can install the project
dependencies. You can use the dev
extra to install the development
dependencies.
poetry install --with=dev
Or using pip:
pip install -e .[dev]
Before you can integrate your application with Payconiq,
you need access to a so-called Merchant profile. The process of onboarding with
Payconiq, both for their development (EXT
) and production (PROD
) environment
involves opening a support ticket (e-mail) and exchanging some information to setup
your account. In particular, your mobile phone number, address, Tax ID (if availablef),
and company name amongst others. The onboarding procedure is outlined
here.
Important
You will have to provide a default callback URL to the support team that Payconiq will use to send updates regarding payment requests and transactions.
Once onboarded by the support team, you'll most likely have access to the
EXT
infrastructure. This means you have access to the necessary API keys and unique
merchant identifier. In the wild, the most common integration a consumer will experience
(we think) is the Static QR code integration. This QR code is uniquely tied to a
specific Point of Sale (PoS) of a merchant. Meaning, a Point of Sale is uniquely
identified by the tuple (Merchant ID and PoS ID), the latter is in your control.
pyconiq
supports to inject several runtime defaults through environment variables.
This is especially useful when targetting the EXT
infrastructure compared to the
default PROD
infrastructure.
Variable | Default | Context |
---|---|---|
PYCONIQ_BASE |
https://payconiq.com |
Base endpoint of Payconiq.com. |
PYCONIQ_API_BASE |
https://api.payconiq.com |
The primary API endpoint of Payconiq (or some mock service). By default this variable will target the Payconiq production environment. For the EXT environment this variable should be set to https://api.ext.payconiq.com . Note that setting this environment variable is not necessary. It can be defined in the codebase when allocating specific integrations. |
PYCONIQ_DEFAULT_MERCHANT |
None |
Default Merchant ID that will be used when allocating merchants. |
PYCONIQ_API_KEY_STATIC |
None |
Default API key for the Static QR code integration. |
PYCONIQ_API_KEY_INVOICE |
None |
Default API key for the Invoice integration whenever no key is manually specified. |
PYCONIQ_API_KEY_RECEIPT |
None |
Default API key for the Receipt integration whenever no key is manually specified. |
PYCONIQ_API_KEY_APP2APP |
None |
Default API key for the App2App integration whenever no key is manually specified. |
PYCONIQ_PAYMENT_PROFILE_STATIC |
None |
Payment profile identifier of the Static QR code integration |
First, before you use the Static QR
integration, you need a QR code for your customers to scan. You can obtain this QR
code through Payconiq's API. However, pyconiq
provides a utility to generate
this on the fly for you, with various error correction levels and customization options.
This functionality is powered by the awesome qrcode
module.
Tip
Note, the default merchant identifier and the default payment profile for the static can be set through the PYCONIQ_DEFAULT_MERCHANT
and PYCONIQ_PAYMENT_PROFILE_STATIC
environment variables respectively.
import pyconiq.qr
# Assign a unique identifier to your point of sale.
# This is managed by us, the merchant.
point_of_sale_id = "test"
# Set your merchant configuration, this will implicetly use the
# `PYCONIQ_DEFAULT_MERCHANT` environment variable for populating
# the merchant identifier.
merchant = pyconiq.merchant()
# Alternatively, the merchant can be generated as.
merchant = pyconiq.merchant(merchant_id="YourMerchantIdentifier")
integration = StaticIntegration(merchant=merchant, profile="YourPaymentProfileId)
# Second, we need a QR code that is associated with our PoS (point of sale).
# In this case, the identifier of the PoS is `test`.
qr = pyconiq.qr.static(integration=integration, pos=point_of_sale_id)
# Show the QR code in the terminal.
qr.print_ascii(tty=True)
this produces the following QR code (in your terminal) for our test Merchant;
█▀▀▀▀▀▀▀██▀██▀█▀███▀█▀█▀▀▀▀▀▀▀█
█ █▀▀▀█ █▀▀ ▄ █▀ ▄███▀█ █▀▀▀█ █
█ █ █ ██▄ ▄█▄ ██▄ ▄█ █ █ █
█ ▀▀▀▀▀ █▀▄▀█▀▄▀▄▀▄▀▄▀█ ▀▀▀▀▀ █
█▀▀▀█▀▀▀▀ ▄ ▀▄▄▀▀█ ▄ █▀▀███▀███
███▄▀ ▀▀▀█▀▄▄█▀██ █ ▄▄▄▄█▄██ ▀█
█▄▀ ▄▀█ ██▄▀██▄ ▄▀ ▀▄█▀█ █▀▀█
████▄█▀▀█▄▄▀ ▄▀█▀█ ▀███▀ █
█ █▀▀▄▀▄▀▀▀▀▄▄ ▀▄█▀ ▄▀█▄█▀ ▄▄█
█▀▄▀█▀█▀▀▀ ▄█▀▄▄ █▄█▄▄ █▀▄▄█
█▀▄▀ ▀▀▀▀ █▄▀██ █ ▄ ▀▀▀ ███▀█
█▀▀▀▀▀▀▀█ ▄▄ ▄▀▀ █▀█ █▀█ ▀▄█ █
█ █▀▀▀█ █ ▄▀▀▄▄ █▀▄█ ▀▀▀ █ █▄█
█ █ █ █▀ ▀▄█▀▄▄ █▄▀ ██ ▄▀█▀█
█ ▀▀▀▀▀ █ █▀▄▀██▀▀▄█▄██ █▀▀ ▄ █
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
Once the QR code has been generated, we can now create payment requests (which we
call transactions internally). Such requests are allocated through "Integrations".
For this particular type, we're using a StaticIntegration
, which corresponds to the
integration supported the previously generated static QR code.
# Initiate a payment request with a static QR integration.
transaction = await integration.create(
amount=2000, # IMPORTANT: Amount is in Eurocent
pos=point_of_sale_id,
reference="PYCONIQ TEST", # Reference that will appear as a reference in the bank log.
)
Tip
You can specify custom Callback URL's using the callback
parameter when creating transactions.
At this point, the transaction has been allocated and is currently in a PENDING
state.
For the Static QR integration, transactions remain in a PENDING
state for about 2
minutes before expiring. Updates regarding payment information will be provided through
the callback URL. However, if you're simply testing locally, you can poll the status
of the transaction like this:
#Just scan the QR code now.
while not transaction.terminal(): # Is the transaction in a `terminal` state?
await asyncio.sleep(1)
await transaction.update()
if transaction.expired():
print("Failed to pay on time :(")
elif transaction.succeeded():
print("Paid!")
elif transaction.cancelled():
print("The transaction was cancelled!")
else:
print("Some other status :/")
Important
The infrastructure supporting the External build is switched off each day from 21h30(CET) to 6h00 (CET) and during the weekends from Friday 21h30 (CET) until Monday 6h00 (CET).
Detailed information regarding the Payconiq's API specification can be found here.
Currently, only the Static QR code integration is supported. In the near future, we intent to support the Invoice integration.