Getting started with Turinpay

We are working on a basic SDK to use with Node.js.

Basic Requirements

  • Knowledge of GraphQL for use in requests against the server

  • Knowledge of WebComponents for the use of the @turinlabs/turinpay library.

To start with TurinPay it is necessary to register on the website, in order to get the api keys. Initially you will see the API keys of the two environments. The production API key is disabled until you pass the KYB.

The API keys should not be published, so it is recommended to use them in the backend, never in the frontend.

The API keys look like this:

Production Key

turinpay_sk_872678-2455-4666-bf22-54288729d

Development Key

turinpay_sk_test_eee78-de9e-4e84-b2e6-fc2ae0687

Basic Workflow

The basic workflow in TurinPay is as follows:

  • Backend: using the API key received during registration, we must configure a payment Intent.

  • Frontend: we have to use our @turinlabs/turinpay library with the paymentIntentId obtained in previous step.

  • Invoice payment: the invoice generated from button could be paid with any Lightning Network wallet. The invoice generated with the development API key, must be paid on the Lightning Network Testnet.

  • Payment confirmation: we have confirmation in frontend with an event and in backend with a webhook

Let's complete the different steps in more detail.

Backend: configure your payment Intent.

Let's configure the Intent needed to checkout a shopping cart that we are already managing on our website.

Here is all the information you need to configure your GraphQL request:

Uri

https://backend.turinlabs.com/graphql

Headers

{
  "apiKey": "turinpay_sk_test_eee78-de9e-4e84-b2e6-fc2ae0687"
}

GraphQL Query (minimal query)

mutation CREATE_PAYMENT_INTENT_MUTATION($input: CreatePaymentIntentInput!) {
  createTPayPaymentIntent(input: $input) {
    __typename
    ... on TPayPaymentIntent {
        id
    }
    ... on Error {
        code
        message
        description
    }
  }
}

Variables (sample)

{
  "input": {
    "notificationUrl": "https://merchant/chargeWebhook",
    "orderId": "2b4749df-3db9-4744-9e09-68eff244a0dd",
    "currency": "EUR",
    "price": 60,
    "description": "description of your product",
    "initDate": "2022-11-04T12:00:00",
    "endDate": "2022-11-04T13:00:00",
    "active": true,
    "multipleInvoicesAllowed": true,
    "invoiceExpirationTimeMin": 60,
    "onlyLN": false
  }
}

To configure exactly what we want to pay from the button, we have the following parameters, use it according to your needs:

  • orderId: (mandatory) identifier of the order associated to this payment intent in your system.

  • description: (mandatory) description associated to the payment intent.

  • currency: (mandatory) currency associated to the payment intent. EUR or USD allowed.

  • price: (mandatory) price associated to the payment intent. Directly related with the currency field.

  • initDate: (mandatory) Init Date of the period of validity of the payment intent.

  • endDate: (mandatory) End Date of the period of validity of the payment intent.

  • multipleInvoicesAllowed: (optional, false as default value) if true, multiple invoices could be created from this payment intent.

  • invoiceExpirationTimeMin: (optional, 30 as default value) Expiration time used in the creation of the invoice from this payment intent.

  • onlyLN: (mandatory) if true, only Lightning invoices will be generated from this payment intent. If false, the invoice creation result will contain info related with BTC, that will allow the invoice onchain payment.

  • notificationUrl: (mandatory) webhook url that will be used when an invoice associated to this payment intent has been paid.

notificationUrl is one of the most important parameters. You will receive a notification when the Intent is paid. Check that the URI can receive a POST request with JSON content.

The result of this request will look something like this:

{
  "createTPayPaymentIntent": {
    "id": "37179b97-e9bb-4120-99d3-af3c0ba50fb2"
  }
}

We call this: paymentIntentId and we will use it in the next step

Frontend: use TurinPay button

Once we have obtained the paymentIntentId in the previous step, we will use it to configure the button in our library.

The button is a WebComponent that must be rendered only in the client side, server side rendering is not supported.

Install it using:

npm i @turinlabs/turinpay
or
yarn add @turinlabs/turinpay

The properties in <turinpay-button>:

  • paymentIntent [uuid]: (mandatory) The paymentIntentId obtained in previous step.

  • size ['big'|'normal'|'small']: (default:normal) Button size to be displayed.

  • titleText [string]: (default:Pay with TurinPay) Text added to the title of the button.

  • paidText [string]: (default:Payment completed!!) Text added to the title of the button when it is already paid.

  • timeout [millis]: (default:3000) Waiting time to close the mode after payment has been made.

  • env ['pro'|'sta'|'int']: (default:pro) Environment to use. Field only for turinlabs's developers. Use with caution.

Minimal button config

  <turinpay-button
    paymentIntent="<uuid>"
  />

If the button is correctly configured, clicking on it will display a modal with a Lightning Network's QR invoice to be paid.

Invoice Payment

To continue with the workflow, we must make the payment of the invoice shown in the modal of the previous step.

In production, payment can be made with any Lightning Network wallet.

In development, we recommend you to use our TurinWallet App, among other interesting features we have a Developer mode that allows the payment on Testnet Lightning Network.

TurinWallet is currently available on Google Play and Apple Store.

Payment confirmation

After payment, two types of notifications are made:

  • an event in the frontend: usable to make changes to the layout.

  • a request to a Webhook from the backend: real confirmation of the payment and the one needed to confirm the exchange of products or services.

Frontend

By listening to the paid event you can schedule actions, while the purchase is confirmed through the Webhook from server

  (function () {
    var elem = document.querySelector('#pay-button-id');

    elem.addEventListener('paid', function (elem) {
        // Layout changes...?
    }, false);
  })()

Backend

Webhooks are used to communicate events to external applications.

This event will be emitted when an Invoice associated to a Payment Intent has been successfully paid in the system, and the funds have been transferred in the account wallet of the TurinPay.

The data that you will receive is detailed below:

{
	"app_name": "turinpay-gql-backend",
	"package_name": "turinpay-gql-backend",
	"package_version": "0.20.0",
	"payload": {
		"transactionId": "ln_28aae4fe-6325-4710-b85a-cc6757e8b72d",
		"type": "DEPOSIT_FROM_LIGHTNING",
		"amount": 29590,
		"currency": "SAT",
		"description": "The description of your product",
		"userId": "6fce6fcc-21f1-4788-a504-8f07b3a26ac5",
		"metadata": {
			"lightningInfo": {
				"request": "lnbcrt295900n1p3s72ajpp5ghuec29neh5tk2luwfnk93f8aajyx4d8dc4l0hq4x42fwrt4sa6sdqlg3hku6m90ysykmmwvusyxmm4de68y7gcqzpgxqrpcgsp57hy5s80n4kqsdyt05wlcx7ttxq336hclldw2sc5qcczpql76qv0q9qyyssq306c6ats98l4jes4m4qsy4vv4ze0c8ddhct9zv7hfqh90pvredesw6sv8dl23dtgjadzettg7m3q07epujnjrtxaqrdrqpe0t3nldjqqn70kv0"
			},
			"operationalData": {
				"purpose": "DEPOSIT"
			}
		},
		"domainApp": "TurinPay",
		"executionEnvironment": "SANDBOX_ENVIRONMENT",
		"date": "2022-08-31T09:36:52.423Z",
		"invoice": {
			"_id": "28aae4fe-6325-4710-b85a-cc6757e8b72d",
			"createdAt": "2022-08-31T09:36:50.210Z",
			"executionEnvironment": "SANDBOX_ENVIRONMENT",
			"invoiceDetail": {
				"_id": "28aae4fe-6325-4710-b85a-cc6757e8b72d",
				"amount": 29590,
				"description": "The description of your product",
				"status": "PAID",
				"onMempool": false,
				"expiresOn": 1661940410202,
				"chainAddress": "bcrt1qz5n33sj9ff8y82rk9jc9ppgcnlq6yawl8vj6j2",
				"chainEstimatedFee": 7050,
				"chainRequest": "bcrt1qz5n33sj9ff8y82rk9jc9ppgcnlq6yawl8vj6j2?amount=0.0002959",
				"request": "lnbcrt295900n1p3s72ajpp5ghuec29neh5tk2luwfnk93f8aajyx4d8dc4l0hq4x42fwrt4sa6sdqlg3hku6m90ysykmmwvusyxmm4de68y7gcqzpgxqrpcgsp57hy5s80n4kqsdyt05wlcx7ttxq336hclldw2sc5qcczpql76qv0q9qyyssq306c6ats98l4jes4m4qsy4vv4ze0c8ddhct9zv7hfqh90pvredesw6sv8dl23dtgjadzettg7m3q07epujnjrtxaqrdrqpe0t3nldjqqn70kv0",
				"domainApp": "TurinPay",
				"executionEnvironment": "SANDBOX_ENVIRONMENT",
				"paymentIntentId": "05180735-935b-4af9-827f-12b16f63f5ab"
			},
			"modifiedAt": "2022-08-31T09:36:50.210Z",
			"orderId": "orderId",
			"paymentIntentDetail": {
				"_id": "05180735-935b-4af9-827f-12b16f63f5ab",
				"active": true,
				"createdAt": "2022-08-31T09:36:46.772Z",
				"currency": "EUR",
				"description": "The description of your product",
				"endDate": "2032-12-31T11:00:00.000Z",
				"executionEnvironment": "SANDBOX_ENVIRONMENT",
				"initDate": "2022-06-01T10:00:00.000Z",
				"invoiceExpirationTimeMin": 30,
				"multipleInvoicesAllowed": false,
				"notificationUrl": "http://localhost:3000/chargeWebhook",
				"onlyLN": false,
				"orderId": "af7c1fe6-d669-414e-b066-e9733f0de7a8",
				"price": 5.99,
				"userId": "6fce6fcc-21f1-4788-a504-8f07b3a26ac5"
			}
		}
	}
}

Webhook is the secure payment confirmation mechanism. Do not exchange products or services without Webhook confirmation.

Last updated