Package: paynlsdk
python-sdkInstallationRequirementsInternal API implementationQuick start and examplesError handlingAdvanced usageInstallationThis SDK can be installed through pip.Pip is the package manager for Python.For more information on how to use/install pip, please visit:https://pypi.org/project/pip/To install the Pay.nl Python sdk into your project, simply$ pip install paynlsdkRequirementsThe Pay.nl Python SDK works on Python 3.7 and is dependent on the requests package and the marshmallow package (v2.x only)
When installing through pip these dependencies will automatically be detected and installedInternal API implementationNot all function arguments will be completely described for every case.
When using the utility/quick start classes all parameters are available, so take a look at the method arguments there for more options.
They are basically self explanatoryEvery API implementation has it's own Request and Response class, which can be found in the variouspaynlsdk.api.xxx.yyymodules.
Every one of the modules contain at least a Request and a Response class.
For example, the Transaction.info API can be located in thepaynlsdk.api.transation.infomodule and will contain both apaynlsdk.api.transaction.info.Requestand apaynlsdk.api.transaction.info.Responseclass
Usually these modules will also contain a specific (marshmallow) Schema implementation that defines the response mapping from JSON.For every call, a response object will be returned.
Using theprint(result)statement, or by investigating thepaynlsdk.objectsmodule, you can find out what attributes are available.
Every result will contain arequestobject, which essentially gives insight on the success or failure of the request.
This object is also used to throw apaynlsk.exceptions.ErrorExceptionin case the request failed.
The rest of theresponseobject will contain the information as returned by the PAYL APIAgain, refer to thepaynlsdk.objectsmodule to investigate the various objects contained in the response.
The exact contents of the response objects itself are defined in all thepaynlsdk.api.xxx.yyy.ResponseclassesQuick start and examplesDo note this quick start only makes use of the quick-call utility methods.
If you're more familiar with Python, youcoulduse the full API request/response implementations in the paynlsdk.api namespaceSet configuration (this is a MUST and should always be done before doing anything with the SDK)from paynlsdk.api.client import APIAuthentication
APIAuthentication.service_id = 'SL-xxxx-xxxx'
APIAuthentication.api_token = '<yourtokenhere>'
APIAuthentication.token_code = 'AT-xxxx-xxxx'Turn on debugging output for the API Client
Note: this uses "print" and will cause a dump of relevant information to the console such as the endpoint,
HTTP method, request parameters, http headers and the raw response as a result from the API callfrom paynlsdk.api.client import APIClient
APIClient.print_debug = TrueGet banks (ideal banks only)# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.transactionimportTransactionfrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:result=Transaction.get_banks()forbankinresult:print('{id}:{name}'.format(id=bank.id,name=bank.name))exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Get list of payment methods# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.paymentmethodsimportPaymentMethodsfrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:result=PaymentMethods.get_list()forpayment_methodinresult.values():print('{id}:{name}({visible_name})'.format(id=payment_method.id,name=payment_method.name,visible_name=payment_method.visible_name))exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Retrieving transaction info# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.transactionimportTransactionfrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:result=Transaction.info(transaction_id='1234567890X1a2b3')print(result)exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Retrieving transaction status# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.transactionimportTransactionfrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:result=Transaction.status(transaction_id='1234567890X1a2b3')print(result)exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Refunding (part of) a transaction# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.transactionimportTransactionfrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:result=Transaction.refund(transaction_id='1234567890X1a2b3')# Whenever you want to partially refund use e.g. (note: amounts are in cents)# result = Refund.transaction(transaction_id='1234567890X1a2b3', amount=500, description='partial refund')# PLEASE NOTE the refund_id is NOT guaranteed, it will only be returned when the refund is done through IBAN.# This is a known flaw, so please do not rely on the refund ID to be part of the response by defaultprint('Refund ID:{refund_id}'.format(refund_id=result.refund_id))exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Refunding (part of) a transaction (alternative method: more request options are available in this API).# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.refundimportRefundfrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:result=Refund.transaction(transaction_id='1234567890X1a2b3')# Whenever you want to partially refund use e.g. (note: amounts are in cents)# result = Refund.transaction(transaction_id='1234567890X1a2b3', amount=500, description='partial refund')# PLEASE NOTE the refund_id is NOT guaranteed, it will only be returned when the refund is done through IBAN.# This is a known flaw, so please do not rely on the refund ID to be part of the response by defaultprint('Refund ID:{refund_id}'.format(refund_id=result.refund_id))exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Retrieving refund info
Note: refund ids come in the form of 'RF-xxxx-xxxx'# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.refundimportRefundfrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:result=Refund.info(refund_id='RF-1234-1234')print(result)exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Starting a transaction# Import needed modulesfrompaynlsdk.api.clientimportAPIAuthenticationfrompaynlsdk.client.transactionimportTransactionfrompaynlsdk.objectsimportOrderData,Address,Company,datetime,TransactionEndUser,\TransactionStartStatsData,TransactionData,SalesDatafrompaynlsdk.exceptionsimport*# Set mandatory basicsAPIAuthentication.service_id='SL-xxxx-xxxx'APIAuthentication.api_token='<yourtokenhere>'APIAuthentication.token_code='AT-xxxx-xxxx'# Perform requesttry:saledata=SalesData()saledata.invoice_date=datetime(2018,10,30)saledata.delivery_date=datetime(2018,11,1)order_data=OrderData(product_id='XYZ',product_type='ARTICLE',description='XYZ description',price=900,quantity=1,vat_code='H',vat_percentage=21)saledata.order_data.append(order_data)enduser=TransactionEndUser(language='nl',initials='A',last_name='Jansen',gender='m',dob=datetime(1970,1,2),phone_number='0612345678',email_address='someone@somewhere.com',iban='<ibannumber>',address=Address(initials='A',last_name='Jansen',gender='m',street_name='Street',street_number='1',street_number_extension='A',zip_code='1234AB',city='Rotterdam',region_code='ZH',country_code='NL',country_name='Nederland'),invoice_address=Address(initials='A',last_name='Jansen',gender='m',street_name='Street',street_number='1',street_number_extension='A',zip_code='1234AB',city='Rotterdam',region_code='ZH',country_code='NL',country_name='Nederland'),company=Company(name='Wizard Inc',coc_number='12345678',vat_number='NL123456789B01',country_code='NL'))sinfo1={'amount':250,'ip_address':'192.168.0.1','finish_url':'https://somedomain.com','payment_option_id':436,'transaction':TransactionData(description='order 9999 at Wizard Inc',order_number='9999',order_exchange_url='https://somedomain.nl/exchange.php'),'stats_data':TransactionStartStatsData(extra1='IDX 9999'),'end_user':enduser,'sale_data':saledata,'test_mode':True}result=Transaction.start(**sinfo1)# print(result)print('Transaction ID:{id}\nPayment reference:{ref}\nPayment URL:{url}'.format(id=result.transaction.transaction_id,ref=result.get_payment_reference(),url=result.get_redirect_url()))exceptSchemaExceptionasse:print('SCHEMA ERROR:\n\t'+str(se))print('\nSCHEMA ERRORS:\n\t'+str(se.errors))exceptErrorExceptionasee:print('API ERROR:\n'+str(ee))exceptExceptionase:print('GENERIC EXCEPTION:\n'+str(e))Error handlingYou should always wrap your calls in an exception handler.
The SDK only contains four internal exceptions:paynlsdk.exceptions.ErrorExceptionIf, for any reason, an error arises in the communication or internally in the API, this exception will be thrownpaynlsdk.exceptions.SchemaExceptionIf, for any reason, the schema mapping (using marshmallow), shall fail , this exception is thrownpaynlsdk.exceptions.TransactionNotAuthorizedExceptionThis exception is only thrown whenever you try tovoidorcapturea transaction using the Response instance as a
result of a call to Transaction.info()paynlsdk.exceptions.TransactionStatusExceptionThis exception is only thrown whenever you try toapproveordeclinea transaction using the Response instance as a
result of a call to Transaction.info()Note: it can always happen that any other standard exceptions are thrown.
These are most likely to happen outside of the SDK but should also be handled.Advanced usageWhenever you want to make use of the Request and Response objects yourself for any purpose, you always have the option
of creating the request object for any API call. These can be found in any of the paynlsdk.api.xxx.yyy modules.
This gives you the advantage of being able to get to the raw requests parameters as well as the raw responses as
returned by Pay.nl.
Although you shouldn't normally need to, below is a complete example of thisfrom paynlsdk.api.transaction.info import Request
from paynlsdk.api.client import APIAuthentication, APIClient

APIAuthentication.service_id = 'SL-xxxx-xxxx'
APIAuthentication.api_token = '<yourtokenhere>'
APIAuthentication.token_code = 'AT-xxxx-xxxx'

# Create request.
request = Request(transaction_id='1234567890X1a2b3')
# Send request.
response = APIClient.perform_request(request)
# We now basically have all information
# Display raw request parameters:
parameters = request.get_parameters()
print('Request parameters:\n')
print(format(json.dumps(parameters)))
# Display raw response:
print('Raw response:\n')
print(request.raw_response)
print('Response class: ' + type(request.response))