API Reference

Payment (CP) - Stripe

Card-Present payments done using Stripe terminal/reader hardware.

Overview

We currently do not have our own JavaScript library that will abstract functionality for each processor, so you will need to implement client side JS functionality using the processors JavaScript library. This section is for card-present / terminal / in-person payments. It does not require you to be PCI compliant.

Stripe

A quick start for collecting payments is here:
https://stripe.com/docs/terminal/quickstart

An overview of the process for collection payments using Stripe is here:
https://stripe.com/docs/terminal/features/connect#destination

A more detailed explanation of using the JS library is here:
https://stripe.com/docs/terminal/payments/collect-payment#create-client-side

Their JS SDK reference is here:
https://stripe.com/docs/terminal/references/api/js-sdk

For testing without a physical terminal:
https://stripe.com/docs/terminal/references/testing

A good checklist:
https://stripe.com/docs/terminal/references/checklist

Stripe Examples

When working with your point-of-sale software and the terminal hardware, the first step is to make sure you are connected to your hardware. You can learn more here:
https://quilt-payment-api.readme.io/reference/readers-terminals

Once connected, this example will show you how to make a payment with the terminal. This begins with a call to create an intent. The intent tells us how much you intend to collect from the credit card payment. The documentation for the call is here:
https://quilt-payment-api.readme.io/reference/createpaymentintent-1

Automatically Capture

This example sets the capture_method to "automatic" which means as soon as the customer swipes their card, we'll automatically capture the funds and there there will be no additional calls needed to capture the funds.

const options = {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': Bearer <jwt token>
  },
  body: JSON.stringify({
    external_account_id: "my merchants account id",
    "amount": 12.99,
    payment_method_types: 'card_present',
    capture_method: 'automatic',
    external_transaction_id: "my transaction id"
  })
};

fetch('https://<your portal domain>/v1/payment/intent', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));

Authorize only and capture later

If you would only like to authorize the transaction and then capture it later, you would change the above JSON with capture_method set to "manual". Please note, when doing authorized card-present payments, the authorization will only be available to capture for 24 hours. After that they will automatically expire.

{
    external_account_id: "my merchants account id",
    "amount": 12.99,
    payment_method_types: 'card_present',
    capture_method: 'manual',
    external_transaction_id: "my transaction id"
  }

Response

This will return a response that looks like below. The intent_id is a unique ID for this payment, a status of "requires_payment_method" means that we are waiting for the customer to swipe their card at the terminal and the token is what we will send to the terminal via the JavaScript SDK to process the payment.

{
    "intent_id": "pi_3LQZ8GIWUp0iWB8W17Ge94LG",
    "status": "requires_payment_method",
    "token": "pi_3LQZ8GIWUp0iWB8W17Ge94LG_secret_GAsbU4YI4mXXyWpQJfOoDwLOD",
    "request_id": 2125
}

Collecting Payment

Once you have a token, you will pass it to the terminal SDK to collect payment from the terminal. There is not yet a way to collect payment using the API.

terminal.collectPaymentMethod(client_secret).then(function(result) {
  if (result.error) {
    // Placeholder for handling result.error
  } else {
    log('terminal.collectPaymentMethod', result.paymentIntent);
    terminal.processPayment(result.paymentIntent).then(function(result) {
    if (result.error) {
      console.log(result.error)
    } else if (result.paymentIntent) {
      paymentIntentId = result.paymentIntent.id;
      log('terminal.processPayment', result.paymentIntent);
    }
  });
}

Capture

If you did an authorize only payment in the above example, you will need to capture the authorized payment in order for the funds to be finalized. You will need the payment You can do that by calling the capture API documented here:
https://quilt-payment-api.readme.io/reference/capturepayment-1

You can call the capture API from JavaScript or you can call it server side.

const params = {
  payment_id: 'pi_1HukElJKggKyYsMVXSTqKZ24',
  amount: '12.99',
  external_account_id: 'account_123456'
};
axios.post('/api/payment/capture', params).then((response) => {
  if (response.data.error) {
    console.error(response.data.error);
  } else {
  	console.log(response);
  }
}.catch((err) => {
  console.error(err);
});
import requests

url = "https://<your portal domain>/v1/payment/capture"
import requests
payload = {
    "payment_id": "pi_1HukElJKggKyYsMVXSTqKZ24",
    "amount": "12.99",
    "external_account_id": "account_123456"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
use GuzzleHttp\Client;

$ciient = new Client();
$response = $client->post('http://<your portal domain>/v1/payment/capture', [
  "payment_id" => "pi_1HukElJKggKyYsMVXSTqKZ24",
  "amount" => "12.99",
  "external_account_id" => "account_123456"
]);
print_r($esponse);

Payment Details

If all calls above succeed, then you have collected the payment and captured the funds. We recommend that you retain the payment_id for your own records and associate it with your payment record in your system. You can get the payment details using the payment_id using this API call:
https://quilt-payment-api.readme.io/reference/getpayment-1

However, it is not required that you keep the payment ID if there is a 1-to-1 association with your your external_transaction_id and the payment_id as you can also retrieve it using this API call:
https://quilt-payment-api.readme.io/reference/getpaymentbyexternalid-1