Flask Quickstart

This section should give you an introduction of integrating WireXfers into a Flask application and therefore it assumes that you have Flask installed.

It also expects that you already have the required credentials from one of the supported banks. Test credentials can also be obtained from pangalink.net.

Minimal application

It’s probably easiest to start from the beginning, so we start by making a simple barebones Flask application:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello!'

if __name__ == '__main__':
    app.run(debug=True)

Just save it as testapp.py. Just make sure it’s not called flask.py or wirexfers.py because it would break everything. Now try executing it with your Python interpreter (please note that output on your machine might be a bit different):

$ python testapp.py
 * Running on http://127.0.0.1:5000/

Setting up the provider

Warning

In this tutorial we are going to use Nordea Estonia’s Solo/TUPAS as an example, mainly because they have official test system available. You still need to figure out a way to acquire credentials for it and this is left as an exercise to the reader. Sorry! ;)

In order to set up a provider, we first need to create a keychain. As payment providers use different credential system (private/public key, simple password) the keychain is used to hide away the low-level details of credential handling.

wirexfers.providers.tupas.NordeaEEProvider uses wirexfers.providers.tupas.SoloKeyChain requiring a single bank-provided MAC-key:

from wirexfers.providers.tupas import SoloKeyChain
# Replace the '<mac>' argument below!
keychain = SoloKeyChain(<mac>)

Note

Previous keychain setup is specific to NordeaEEProvider. Other providers may require different KeyChain setup. Please consult the documentation of each provider.

Now that we have created our keychain, setting up the provider is a breeze:

from wirexfers.providers.tupas import NordeaEEProvider
# Replace the <user> and <endpoint> arguments below!
provider = NordeaEEProvider(<user>, keychain, <endpoint>)

And that’s all - now our provider is configured and can be used to initiate payment request. Our current application so far looks like this:

 from flask import Flask
 from wirexfers.providers.tupas import SoloKeyChain, NordeaEEProvider

 app = Flask(__name__)

 # Replace the '<mac>' argument below!
 keychain = SoloKeyChain(<mac>)
 # Replace the <user> and <endpoint> arguments below!
 provider = NordeaEEProvider(<user>, keychain, <endpoint>)

 @app.route('/')
 def index():
     return 'Hello!'

 if __name__ == '__main__':
     app.run(debug=True)

Making the payment request

In order to make a payment, we first need to set up a payment information by filling out relevant fields of PaymentInfo. Because the payment are usually made within a request, we need to plug it into our view function:

from wirexfers import PaymentInfo, utils
info = PaymentInfo('1.00', 'Test transfer', utils.ref_731('123'))

Next we need to decide our return urls. Though we currently don’t yet handle the urls, but they still needed so provider knows where to direct user after payment operation.

Note

Return url support varies with providers. Please consult each providers documentation to see which return urls are supported.

NordeaEEProvider requires following return urls:

  • cancel - user cancels the payment
  • reject - bank rejects the payment (not enough funds, ...)
  • return - successful payment

Although we don’t yet handle these URLs, we still need to fill them out because payment provider expects them along with payment request. Therefore we just simply point these urls to the /index view and utilize Flask’s url_for() along with _external=True argument to make the URLs absolute:

urls = {'cancel': url_for('index', _external=True),
        'reject': url_for('index', _external=True),
        'return': url_for('index', _external=True)}

Now everything has been set up, so we just call our previously initialized provider with payment and urls arguments in order to create the payment request (PaymentRequest) for us:

payment = provider(info, urls)

This is all from application side, we just have to pass the payment to the template in order to show the payment form to the user:

 from flask import Flask, render_template, url_for
 from wirexfers import PaymentInfo, utils
 from wirexfers.providers.tupas import SoloKeyChain, NordeaEEProvider

 app = Flask(__name__)

 # Replace the '<mac>' argument below!
 keychain = SoloKeyChain(<mac>)
 # Replace the <user> and <endpoint> arguments below!
 provider = NordeaEEProvider(<user>, keychain, <endpoint>)

 @app.route('/')
 def index():
     info = PaymentInfo('1.00', 'Test transfer', utils.ref_731('123'))
     urls = {'cancel': url_for('index', _external=True),
             'reject': url_for('index', _external=True),
             'return': url_for('index', _external=True)}
     payment = provider(info, urls)
     return render_template('form.html', payment=payment)

 if __name__ == '__main__':
     app.run(debug=True)

We are still missing the template, though! Open up the As we are passing the payment request into template context as payment variable, we can now use form, info and provider fields to create a simple HTML form. So open up templates/form.html and make sure it contains this:

<form method="POST" action="{{ payment.provider.endpoint }}">
{% for item in payment.form -%}
    {% set name, value = item -%}
    <input name="{{ name }}" value="{{ value }}" type="hidden">
{% endfor -%}
<dl>
  <dt>Amount:</dt>
  <dd>{{ payment.info.amount }}</dd>
  <dt>Message:</dt>
  <dd>{{ payment.info.message }}</dd>
</dl>
<input type="submit">
</form>

Handling the Payment response

Warning

This section is using NordeaEEProvider as an example. Consult documentation on how to handle specific provider.

Let’s start by adding new views to handle payment different request responses and modify our urls dictionary to use those views:

urls = {'cancel': url_for('cancel', _external=True),
        'reject': url_for('reject', _external=True),
        'return': url_for('finish', _external=True)}

@app.route('/cancel')
def cancel():
    return 'Payment cancelled!'

@app.route('/reject')
def reject():
    return 'Payment rejected!'

@app.route('/finish')
def finish():
    return 'Payment successful!'

Note

NordeaEEProvider uses GET request method to handle payment responses. This may be different for other providers.

We also create view for invalid response:

@app.route('/invalid')
def invalid():
    return 'INVALID PAYMENT'

As NordeaEEProvider uses GET request for payment status confirmation, therefore we just need to parse the request data in every view with parse_response() into PaymentResponse and check whether its is_valid attribute is True.

from flask import redirect, request
payment = provider.parse_response(request.args)
if payment.is_valid:
    # Do something with the result
    return payment.data
return redirect(url_for('invalid'))

And that should be all for now! :)