QuickPay Embedded

The Embedded payment method gives you the option of accepting credit card payments without having to redirect to QuickPay Hosted payment window. The payment form is embedded directly into your page - giving you full control over design.

This is achieved by submitting the credit card data directly to QuickPay who then hands back a token that in turn can be used for payment (one payment only) using our API.

Implementation is very simple and can be included into your existing checkout form! You just need to add input fields for cardnumber, expiration and cvd and a little bit of JavaScript.

Please note! QuickPay Embedded is currently only available with the Clearhaus acquirer.

Security concerns

The credit card data is submitted directly to QuickPay via HTTPS. Thus, no credit card data is passing through your system.

Still, there are few additonal requirements than necessary when using the QuickPay Link or QuickPay Form:

Parameters

The JavaScript is initialized like so QuickPay.Embedded.Form('<selector>', {<parameters>}); and accepts the following parameters:

Parameter Type Description
R merchant_id /^\d+$/ The merchant id
R agreement_id /^\d+$/ The agreement id
brandChanged function(brand) Callback executed when brand of entered cardnumber is determined or changes
beforeCreateToken function(form) Callback executed before token is submitted
success function(form, token) Callback executed after tokenization. Return false to prevent form submit
failure function(form, source, message) Callback executed if card tokenizing failed

Submitted data

In addition to your own form input data the following is submitted:

Parameter Type Description
card_token UUID The card token

Examples

Frontend - Checkout form

To prevent card data being submitted by mistake the card input fields should not have name arguments but instead be identified by data-quickpay="cardnumber", data-quickpay="expiration" and data-quickpay="cvd"

When form is submitted card data will first be submitted directly to QuickPay for tokenization. If the tokenization is successful it will submit the form to your defined action with a card_token parameter which can be used to authorize the payment on your backend.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<form id="checkout-form" class="form-horizontal" action="/shop/pay" method="post">
  <label for="name">Name</label>
  <input type="text" name="name" value="">

  <label for="address">Address</label>
  <input type="text" name="address" value="">

  <label for="zipcode">Zipcode</label>
  <input type="text" name="zipcode" value="">

  <labe for="city">City</label>
  <input type="text" name="city" value="">

  <label>Card number</label>
  <div class="card">
    <div class="card-brand"></div>
    <input type="text" autocomplete="off" data-quickpay="cardnumber">
  </div>

  <label>Expiration</label>
  <input type="text" placeholder="MM / YY" autocomplete="off" data-quickpay="expiration">

  <label>CVV/CVD</label>
  <input type="text" maxlength="4" autocomplete="off" data-quickpay="cvd">

  <button class="btn btn-primary" type="submit">Pay</button>
</form>

<style type="text/css">
  .card {
    position: relative;
  }

  .card-brand {
    position: absolute;
    right: 5px;
    top: 5px;
    font-weight: bold;
  }

  input.error {
    border: 1px solid red;
  }
</style>

<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://payment.quickpay.net/embedded/v1/quickpay.js"></script>
<script type="text/javascript">
  QuickPay.Embedded.Form($('#checkout-form'), {
    merchant_id: 1234,
    agreement_id: 1234,
    brandChanged: function(brand) {
      $('.card-brand').html(brand);
    },
    beforeCreateToken: function(form) {
      $('input.error').removeClass('error');
      $('#checkout-form button').html('Please wait...');
    },
    failure: function(form, source, message) {
      if (source === 'validation') {
        for (var i = 0; i < message.length; i++) {
          $('input[data-quickpay=' + message[i] + ']').addClass('error');
        }
      } else {
        alert(source + ': ' + message);
      }
      $('#checkout-form button').html('Pay');
    }
  });
</script>

Backend

These are simplified examples that will almost certainly not fit your shop system. However, it should give an idea on how to use the Embedded payment form.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
require 'sinatra/base'
require 'quickpay/api/client' # Find the QuickPay Ruby client at https://learn.quickpay.net/tech-talk/opensource

class App < Sinatra::Base
  enable :sessions

  post '/shop/pay' do
    order = Order.new(
      name:    params[:name],
      address: params[:address],
      zipcode: params[:zipcode],
      city:    params[:city]
    )

    order.save!

    # See https://learn.quickpay.net/tech-talk/api/services
    client = QuickPay::API::Client.new(api_key: ENV['QUICKPAY_API_KEY'])
    token  = params[:card_token]

    payment = client.post('/payments', {
      order_id: order.order_id, # MUST be unique
      currency: 'EUR'
    })

    order.payment_id = payment['id']
    order.save!

    payment = client.post("/payments/#{order.payment_id}/authorize?synchronized", {
      amount: 12345, # 123.45
      card: { token: token }
    })

    if payment['approved']
      order.authorized = true
    end

    order.qp_status_code = payment['operations'].last['qp_status_code']
    order.qp_status_msg  = payment['operations'].last['qp_status_msg']
    order.aq_status_code = payment['operations'].last['aq_status_code']
    order.aq_status_msg  = payment['operations'].last['aq_status_msg']
    order.save!

    if order.authorized?
      session[:order_id] = order.id
      redirect to('/shop/receipt')
    else
      erb :error
    end
  end

  get '/shop/receipt' do
    @order = Order.find(session[:order_id])
    erb :receipt
  end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php

/**
 * This is only an very simple mocked example.
 */

require_once 'QuickPay'; // Find the QuickPay PHP client at https://learn.quickpay.net/tech-talk/opensource

use QuickPay/QuickPay as Client;
use Models/Order;

class PaymentController
{
    public function pay(Request $request)
    {
        $order = new Order([
            'name'    => $request('name'),
            'address' => $request('address'),
            'zipcode' => $request('zipcode'),
            'city'    => $request('city')
        ]);

        $order->save();

        $client = new Client(":{$this->config('API_KEY')}");

        $token = $request('card_token');

        $payment = $client->request->post("/payments", [
            'order_id' => $order->order_id, // Must be unique
            'currency' => 'EUR'
        ])->as_object();

        $order->payment_id = $payment->id;
        $order->save();

        $payment = $client->request->post("/payments/{$order->payment_id}/authorize?synchronized", [
            'amount' => 12345,
            'card'   => [ 'token' => $token ]
        ]);

        if ($payment->accepted) {
            $order->authorized = true;
        }

        $authorize = end($payment->operations);

        $order->qp_status_code = $authorize->qp_status_code;
        $order->qp_status_msg  = $authorize->qp_status_msg;
        $order->aq_status_code = $authorize->aq_status_code;
        $order->aq_status_msg  = $authorize->aq_status_msg;
        $order->save();

        if ($order->authorized()) {
            $this->session('order_id', $order->id);
            $this->redirectTo('/payment/receipt');
        } else {
            $this->render('error');
        }
    }

    public function receipt()
    {
        $order = Order::find($this->session('order_id'));
        $this->render('receipt', compact('order'));
    }
}