Make a Payment

This guide will show you how to develop a flow that enables your customers to make a payment and place their order.

Order Summary Screen with selected Payment Method Payment Method Selection Screen PayPal Web App
Order-Summary-with-selected-Payment-Method.jpg
Stored-Payment-Method-Selection.jpg
PayPal-Web-App.jpg

Before proceeding, you should have implemented:

Retrieve Stored Payment Methods

If the customer is logged in, you can retrieve all stored payment methods and present them to the customer for selection.

Using /customer-accounts/{customer_account_uuid}/stored-payment-methods you can fetch all stored payment methods:

Request

Attribute Type Example Value Description
Authorization HTTP header string "Bearer {customer_account_token}" JWT Token of Customer Account
{
  "method": "get",
  "url": "https://api-public-playground.menu.app/api/customer-accounts/{customer_account_uuid}/stored-payment-methods",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": 4.38.0,
    "Content-Type": "application/json",
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
  }
}

Response

{
  "code": 200,
  "data": {
    "stored_payment_methods": [
      {
        "id": "85688223-b4ee-4c0f-8593-513c182ef7b1",
        "properties": {
          "card_type": "visa",
          "masked_number": "901010******0004",
          "expiration_date": "12/2024",
          "last_four_digits": "0004"
        },
        "preselected": true,
        "payment_method_id": "027b59de-97cb-48a0-9404-37f426659bad"
      }
    ]
  },
  "status": "OK"
}
Attribute Type Example Value Description
stored_payment_methods array[StoredPaymentMethods] Array of Stored Payment Methods that belong to the customer account
stored_payment_methods.[i].id string "85688223-b4ee-4c0f-8593-513c182ef7b1" ID of the stored payment method - will be used to initialize payment
stored_payment_methods.[i].properties.card_type string "visa" String ID for Card Type
stored_payment_methods.[i].properties.masked_number string "901010******0004" First 6 digits and last 4 digits of credit card number (PAN) - some payment processors may only return last 4 digits
stored_payment_methods.[i].properties.expiration_date string "12/2024" Month / Year in which credit card will expire
stored_payment_methods.[i].properties.last_four_digits string "0004" Last 4 digits of credit card number (PAN)
stored_payment_methods.[i].preselected bool true Defines which payment method should be pre-selected for the customer on checkout - based on last-touched (last-used) payment method for the customer
stored_payment_methods.[i].payment_method_id string "027b59de-97cb-48a0-9404-37f426659bad" UUID of a registered payment method

Initialize Payment

In order to start the payment processor, you will need to initialize a payment. Initializing a payment initiates the payment with the payment processor.

The payment initialization will contain different details depending on what the next step is to complete the payment.

Make a call to /payment-processors/init-payment:

Stored Payment Method

Request

Attribute Type Example Value Description
Authorization HTTP header string "Bearer {customer_account_token}" JWT Token of Customer Account
venue_id string "a9d6d0c8-1689-4114-b1ec-6da9c33f0384" UUID of Venue at which you are placing your order / making your payment
payment_info.stored_payment_method_id string "85688223-b4ee-4c0f-8593-513c182ef7b1" UUID from Stored Payment Method - from /customer-accounts/{customer_account_uuid}/stored-payment-methods
payment_info.amount int 255 Payment amount (lowest unit)
order_info Order object Order object as you would send it to POST /orders - see Place order for Dine-in (QS) or Takeout for more information
{
  "method": "post",
  "url": "https://api-public-playground.menu.app/api/payment-processors/init-payment",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": 4.38.0,
    "Content-Type": "application/json",
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
  },
  "body": {
    "venue_id": "a9d6d0c8-1689-4114-b1ec-6da9c33f0384",
    "payment_info": {
        "stored_payment_method_id": "85688223-b4ee-4c0f-8593-513c182ef7b1",
        "amount": 255
    },
    "order_info": {
      "customer_info": {
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane.doe@partech.com",
        "phone_number": "+11234567"
      },
      "menu_items": {
        "id": "13d45e04-3f23-11ed-936c-1a67b454859d",
        "price_level_id": "f1c0305d-74d0-4f7e-ac4f-668985dd3bb3",
        "quantity": 1,
        "comment": ""
      },
      "order_type": {
        "id": "88a3e856-82c1-40a3-8a5f-185ca4e059ce",
        "pickup_asap": true,
        "pickup_at": "2023-06-23 11:37:12"
      },
      "singular_point_id": "75b78787-e139-4db8-b126-970d00ed4868"
    }
  }
}

Response

{
  "status": "OK",
  "code": 200,
  "data": {
    "payment_processor_type_id": 8,
    "payment_init_hash": "9aafdada6062d5882dfddd598dc6b65b",
    "allows_webhooks": false,
    "expires_in": 897,
    "status_polling_interval": 5,
    "additional_info": {
      "approval_url": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-9LC27022SP413823L",
      "token": "EC-9LC27022SP413823L",
      "payment_id": "PAYID-MSKYH2Q5KM808023H7955515",
      "client_id": "Abznyi4zfZ61uuXrV4zNv3ZLDR1gQNBTKG_gpw5-fCheROpgxOwbBHsIyf6hWJ_vKgLl3taawqXShF_E"
    }
  }
}
Attribute Type Example Value Description
payment_processor_type_id id 2 Payment Processor identifier (See Payment Processors for more information)
payment_init_hash string "021224037b0e8916a8ff54f085297f82" Payment hash uniquely identifying the initiated transaction
allows_webhooks bool true Boolean flag identifying whether the payment processor supports webhook updates for payment status. If allows_webhooks is true, then expires_in and status_polling_interval are used for short polling.
expires_in int 899 Transaction validity time in seconds. This applies to all payment processors.
status_polling_interval bool 5 Recommended status poll interval in seconds
additional_info object additional_info object contains the URLs specific to some of the payment processors

Guest Payment Flow

Request

Attribute Type Example Value Description
venue_id string "a9d6d0c8-1689-4114-b1ec-6da9c33f0384" UUID of Venue at which you are placing your order / making your payment
payment_info.payment_method_id string "85688223-b4ee-4c0f-8593-513c182ef7b1" Payment method UUID. When venue information is retrieved [via /api/venues/{venue_id}?view=withNestedEntities] the response contains which payment methods are supported by the Venue and uuid for those payment methods.
payment_info.amount int 255 Payment amount (lowest unit)
order_info Order object Order object as you would send it to POST /orders - see Place order for Dine-in (QS) or Takeout for more information
{
  "method": "post",
  "url": "https://api-public-playground.menu.app/api/payment-processors/init-payment",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": 4.38.0,
    "Content-Type": "application/json"
  },
  "body":{
   "amount":1464,
   "venue_id":"4f41e5ef-4339-4570-9b6b-a1816c2f2d9c",
   "payment_info":{
      "amount":1464,
      "payment_method_id":2
   },
   "order_info":{
      "singular_point_id":"03646f80-0190-4e28-b140-0ed031fda317",
      "order_type":{
         "id":1,
         "properties":{
            
         },
         "pickup_asap":true,
         "pickup_at":"2023-08-15 08:44:36"
      },
      "tip":{
         "percentage":10
      },
      "menu_items":[
         {
            "id":"48120369-ae5e-407a-a02b-1f9df44d400e",
            "price_level_id":"76efaa5d-b849-4549-9468-72b8131b904a",
            "quantity":1,
            "comment":""
         }
      ],
      "customer_info":{
         "first_name":"Jane",
         "last_name":"Doe",
         "email":"jane.doe@partech.com",
         "demographics":[
            
         ]
      }
   },
   "additional_info":{
      "css_url":"https://order.kauwelapoke.com/saferpay-en.css"
   }
 }
}
Attribute Type Example Value Description
payment_processor_type_id id 2 Payment Processor identifier (See Payment Processors for more information)
payment_init_hash string "021224037b0e8916a8ff54f085297f82" Payment hash uniquely identifying the initiated transaction
allows_webhooks bool true Boolean flag identifying whether the payment processor supports webhook updates for payment status
expires_in int 899 Transaction validity time in seconds
status_polling_interval bool 5 Recommended status poll interval in seconds
additional_info object additional_info object contains the URLs specific to some of the payment processors

Response

{
    "status": "OK",
    "code": 200,
    "data": {
        "payment_processor_type_id": 2,
        "payment_init_hash": "7de87938a8e0d3e506aef8d3e917a6fa",
        "allows_webhooks": false,
        "expires_in": 899,
        "status_polling_interval": 5,
        "additional_info": {
            "token": "6rxxqnreznx6td2cw0l0vlqg9",
            "approval_url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/6rxxqnreznx6td2cw0l0vlqg9",
            "url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/6rxxqnreznx6td2cw0l0vlqg9"
        }
    }
}
Attribute Type Example Value Description
payment_processor_type_id id 2 Payment Processor identifier (See Payment Processors for more information)
payment_init_hash string "7de87938a8e0d3e506aef8d3e917a6fa" Payment hash uniquely identifying the initiated transaction
allows_webhooks bool true Boolean flag identifying whether the payment processor supports webhook updates for payment status. If allows_webhooks is true, then expires_in and status_polling_interval are used for short polling.
expires_in int 899 Transaction validity time in seconds. This applies to all payment processors.
status_polling_interval bool 5 Recommended status poll interval in seconds
additional_info object additional_info object contains the URLs specific to some of the payment processors
additional_info.token string "6rxxqnreznx6td2cw0l0vlqg9" Optional field that is specific to Saferpay payment processor
additional_info.approval_url string "https://test.saferpay.com/vt2..." Optional field that is specific to Saferpay payment processor. In this case, you can use either approval_url or url to embed the hosted form into an iFrame.
additional_info.url string "https://test.saferpay.com/vt2..." Optional field that is specific to Saferpay payment processor. In this case, you can use either url orapproval_url to embed the hosted form into an iFrame.
actions object actions object contains next available actions and the correspondent URLs. Differs between payment processors. For ParPay contains type, which is redirect, and url for redirection.

Payment Processor Web-App

Once the customer initializes the payment, the next step can differ based on the payment method chosen.

Credit / debit cards

In the case of credit/debit cards, depending on the payment processor that works behind the scenes, the customer should either:

  1. See an embedded iframe where card details need to be entered

    • White label apps receive the URL for the from a generate-tokens request in case of authenticated flow, or from an init-payment request in case of a guest flow
    • Once the iframe is displayed, the customer enters their payment details and submits the form to the payment processor. To fetch the status of the payment, a listener should be implemented to verify the payment status
    • Payment processors: Saferpay, FAC, Powertranz, Computop, Paystack, Freedompay, CCV, PAR Pay
  2. See a custom form that has separate iframes for each input field that the customer needs to populate or generally an empty division HTML container for embedding the whole third-party form

    • Upon initializing the payment via the init-payment or generating a token for storing payment cards via generate-tokens request, the related payment solution's SDK needs to be initialized
    • Once the form is displayed, the customer enters their payment details and submits the form to the payment processor. To fetch the status of the payment, you need to adapt the payment solution's recommended ways (through their SDK) for verifying the payment -- most of them have callbacks for successful/failed payments
    • Payment processors: Adyen, Cybersource, Checkout, FirstData
  3. See a third-party form that is embedded in an empty division HTML container where card details need to be entered. Still, once a customer clicks on a third-party "Pay" / "Add" button, the customer is redirected to a third-party web application (triggered by third-party SDK) where a customer needs to complete the payment

    • After the payment has been processed, the third-party web application redirects the customer back to a white-label web application. It is important to note that upon being redirected back, the white-label app would need to immediately send either the order create request or stored-payment-method request (depending on the customer's action). PAR Ordering API is responsible for verifying the payment status
    • Our web application supports that behavior only for PayMaya payment processor
  4. Immediately gets redirected to a third-party web application (triggered by the white-label app) where a customer needs to enter card information and complete the payment

    • After the payment has been processed, the third-party web application redirects the customer back to a white-label web application. It is important to note that upon being redirected back, the white-label app would need to immediately send either the POST order request or POST stored-payment-method request (depending on the customer's action). PAR Ordering API is responsible for verifying the payment status
    • Our web application supports that behavior only for Transbank payment processor

If 3DS is enforced on our CMS Brand level / enabled on Venue level configurations and the payment processor supports it, additional 3DS authentication might be required. Read more in the 3DS Authentication section.


Gift cards

In the case of gift cards, the customer should see the custom-made form for entering the gift card number, and if required, a security code. - Currently implemented and tied to PAR Pay integration


Alternative payment methods

In the case of alternative payment methods, we differentiate three types of integrations that PAR Ordering supports:

  1. APMs that work with their own SDK or a gateway script
    • Upon initializing the payment via the init-payment request and receiving unnecessary data, you would need to initialize the relevant SDK and the customer should see just a button (e.g. “Pay with PayPal”) which would open the payment solution’s dialog (wallet).
    • You should check out the relevant SDK and third-party documentation to see how to verify the payment status – most of them have callbacks for successful/failed payments
    • Payment methods/gateways: PayPal, MercadoPago, ApplePay, GooglePay
  2. APMs that are embedded in an iframe
    • Upon initializing the payment via the init-payment request, you will receive the URL which should be embedded into an iframe. The customer might need to authenticate within the iframe, but that depends on the payment method/gateway
    • Once the iframe is displayed, the customer enters their payment details and submits the form to the payment processor. To fetch the status of the payment, a listener should be implemented to verify the payment status updates
    • Payment methods/gateways: GCash, Paystack Bank, Paystack USSD, Paystack Transfer, Paystack VisaQR
  3. APMs that require top-window redirection
    • Upon initializing the payment via the init-payment request, the customer should be immediately redirected to the third-party company web application where the customer needs to complete the payment. After that, the customer is redirected back to the white-label application. It is important to note that upon being redirected back, the white-label app would need to immediately trigger the order creation by sending the POST order request. PAR Ordering API is responsible for verifying the payment status
    • Payment methods/gateways: iDEAL, “Pay With PayMaya”

Where to find necessary initialization data

There are two main ways to get the necessary information before showing an iframe or initializing the third-party SDK:

  1. From the generate-tokens response
  2. From the init-payment response

For the authenticated customer, at the step of storing the payment card, you will call the generate-tokens endpoint.

The response can differ from one payment processor to another. It can be found either in tokens.actions[i].url or in tokens.additional_info.url. Here are a few different examples.

Generate tokens response examplesPAR Pay:
{
	"status": "OK",
	"code": 200,
	"data": {
		"tokens": [
			{
				"payment_processor_id": 392,
				"payment_processor_type_id": 32,
				"token": "47f3aa74-7583-4d2e-9261-4af468243bd9",
				"actions": [
					{
						"type": "redirect",
						"url": "https://api-public-playground.menu.app/api/payment-processors/init_token?mt_application_id={app_id}&mt_payment_processor_id={pp_id}&tokenType=1&template=card&isPayment=0&successUrl=https%3A%2F%2Fapi-public-playground.menu.app%2Fapi%2Fpayment-processors%2Fsuccess%3Fmt_application_id%3D683&failUrl=https%3A%2F%2Fapi-public-playground.menu.app%2Fapi%2Fpayment-processors%2Ffail%3Fmt_application_id%3D683&sessionId=309200423254396777680000333032&iframeUrl=https%3A%2F%2Fuatps48.aurusepay.com%2Fstoreservices%2Fecom%2Fgetiframe%3Fa%3D036937EFf1e9b6fe33a826efb184f6ecb618ef26582c0e1230febc98c8b2c6e3313e5e58ea96b27ca545ba2eada315a4ca74e7f225a212befa057406daa000b5cd1285379b41d776b891e78d654148e45ce4bf1f026e72cc005b6d37f86b0651276b12feb182913a8290da91a9566a25272615f9dbe2b8f8a261063146241bfc11a8be7689baf937b78cad120644c0a3d584b306e786b4821841b0a93dcc69c42290f9662d86ab452e2e09e0c7d66c51ab5333ca915df03d8a991e90cb0be695fc40859d99db4a7d03d656a0d1307847fdfda4aa2ccde314b0caca7a29f7ab0695dd5e8321e58309b85840708ec2e1d90f7515c801b9e609c6395decb1044765e2937cb2dd4fefc978f537833f263eb90120d14de5763b1279b2f20407ccd11c369095428675e3fd8364c82798f99446036e21c4b48b62f04eabdbd2ae7e9668348edf4ef0102af87ab8d15e67060cfbd8bc0147fb68a535fee9c70f65bf2001e30735d0e0dc700cea4ca00c8a552714c949b4ad558033c6b22dfff9e4b64f4894a133a5"
					}
				]
			},
			
		]
	}
}

Saferpay:

{
	"status": "OK",
	"code": 200,
	"data": {
		"tokens": [
			{
				"payment_processor_id": 109,
				"payment_processor_type_id": 2,
				"token": "ol2ukt07agaearjz2k75u82xp",
				"additional_info": {
					"url": "https://test.saferpay.com/vt2/api/register/card/241265/ol2ukt07agaearjz2k75u82xp"
				}
			}
		]
	}
}

For the guest customer, as well as for alternative payment methods, at the step of vaulting, you will call the init-payment endpoint. Remember that we do not store payment cards for guest customers, and we also don't store APMs. Thus, the generate-tokens endpoint is never needed.

The response can differ from one payment processor to another. It can be found either in actions[i].url or in additional_info.url. Here are a few different examples.

Init payment response examplesPAR Pay:
{
  "status": "OK",
  "code": 200,
  "data": {
    "payment_processor_type_id": 32,
    "payment_init_hash": "08a12c45ae3643fa1d1875fa9f2493b0",
    "allows_webhooks": false,
    "expires_in": 898,
    "status_polling_interval": 5,
    "additional_info": null,
    "actions": [
        {
            "type": "redirect",
            "url": "https://api-public-playground.menu.app/api/payment-processors/init_token?mt_application_id={app_id}&mt_payment_processor_id={pp_id}&tokenType=1&template=card&isPayment=1&successUrl=https%3A%2F%2Fapi-public-playground.menu.app%2Fapi%2Fpayment-processors%2Fsuccess%3Fmt_application_id%3D683%26mt_payment_init_hash%3D08a12c45ae3643fa1d1875fa9f2493b0&failUrl=https%3A%2F%2Fapi-playground.menu.app%2Fapi%2Fpayment-processors%2Ffail%3Fmt_application_id%3D683%26mt_payment_init_hash%3D08a12c45ae3643fa1d1875fa9f2493b0&sessionId=309200223254404540620000370295&iframeUrl=https%3A%2F%2Fuatps48.aurusepay.com%2Fstoreservices%2Fecom%2Fgetiframe%3Fa%3D0369733Ff1e9b6fe33a826efb184f6ecb618ef26582c0e1230febc98c8b2c6e3313e5e58ea96b27ca545ba2eada315a4ca74e7f259025e0b77baa8235b8857c6ff633ab9397fc0f256fbbe4b600bbd581fd7994140df0cdb847a7fe370d33f7870b94eafb182913a8290da91a9566a25272615f94e955adcc467a55d4d266e33f35df96789baf937b78cad120644c0a3d584b306e786b4821841b0a93dcc69c42290f9662d86ab452e2e09e0c7d66c51ab5333ca915df03d8a991e90cb0be695fc40859d99db4a7d03d656a0d1307847fdfda4aa2ccde314b0caca7a29f7ab0695dd5e8321e58309b85840708ec2e1d90f7515c801b9e609c6395decb1044765e2937cb2dd4fefc978f537833f263eb90120d14de5763b1279b2f20407ccd11c369095428675e3fd8364c82798f99446036e21c4b48b62f04eabdbd2ae7e9668348edf4ef0102af87ab8d15e67060cfbd8bc0147fb68a535fee9c70f65bf2001e30735d0e0dc700cea4ca00c8a552714c949b4ad558033c6b22dfff9e4b64f4894a133a5"
        }
    ]
  }
}

Saferpay:

{
    "status": "OK",
    "code": 200,
    "data": {
        "payment_processor_type_id": 2,
        "payment_init_hash": "272b59b61af516b90cafa0cfd20b574e",
        "allows_webhooks": false,
        "expires_in": 899,
        "status_polling_interval": 5,
        "additional_info": {
            "token": "93itiab7h54m83r1byqlk2cs8",
            "approval_url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/93itiab7h54m83r1byqlk2cs8",
            "url": "https://test.saferpay.com/vt2/Api/Post/241265/17998427/93itiab7h54m83r1byqlk2cs8"
        }
    }
}

Poll Payment Status

Some of the payment processors support webhook payment status updates. allows_webhooks flag sent during init-payment identifies whether this feature is supported.

Webhooks is a server-to-server communication mechanism that allows payment gateway to send the notifications directly to the server, thus avoiding the potential client app issues. The idea is that, upon receiving a "payment created" notification, server should be able to create an order related to that payment without waiting for a client app to send the actual order create request.

Mainly webhooks implementation in PAR Ordering app is intended to be additional/backup flow that will take over if regular (redirect) flow fails.

To fetch the payment status, GET /api/payment-processors/init-payment/{init-payment-hash}/status should be called

Request

Attribute Type Example Value Description
hash string "27ef05b0d82e2512026f8f3833d887fb" Request parameter - init transaction payment hash (received from init-payment call as payment_init_hash property)
{
  "method": "get",
  "url": "https://api-public-playground.menu.app/api/payment-processors/init-payment/{hash}/status",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": 4.38.0,
    "Content-Type": "application/json",
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
  }
}

Response

{
  "code": 200,
  "data": {
    "payment_initialization_status": {
      "order_uuid": "239e7982-3f23-11ed-936c-1a67b454859d",
      "order_flow_status": "Success",
      "order_flow_trigger_type": 1
    }
  },
  "status": "OK"
}
Attribute Type Example Value Description
payment_initialization_status.order_uuid string "2da170c9-874c-4398-9436-12221fa1a9d3" Created Order UUID
payment_initialization_status.order_flow_status string "Success" Current status for the transaction. Possible values: Pending → initial status, the order flow has still not been triggered. Processing → the order flow has been triggered, but the order creation is still in progress. Success → order flow triggered and order creation has been completed successfully. Failed → order flow triggered, but order creation failed.
payment_initialization_status.order_flow_trigger_type int 2 If order flow status is not Pending then this value determines how the order procssing was triggered: 1 → triggered by order create API request, 2 → triggered by a webhook, 3 → triggered manually by a CLI command

3DS Authentication

The 3D Secure will be enabled when these conditions are met:

  1. The configuration for 3DS is set on the CMS
    1. Enforced on the Brand-level configurations
    2. or enabled on the Venue-level configurations
  2. The payment processor supports it

The PAR Pay integration doesn’t support 3DS authentication, however, some other PAR Ordering integrations, such as Adyen, Cybersource, etc. do support it.

The API endpoint for fetching the URL in order to show the 3DS dialog is called auth-payment. It should be called after the init-payment call, after the customer submits the card details. Body of the request, as well as the response, depends on the payment processor used.

POST /api/payment-processors/auth-payment

Request

{
  "method": "post",
  "url": "https://api-public-playground.menu.app/api/payment-processors/auth-payment",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": 4.38.0,
    "Content-Type": "application/json",
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
  },
  "body": {
    "payment_init_hash": "fe455eb0e472cc60f8e286abc2221d2e",
    "auth_info": {
      "action_result": "eyJkZXRhaWxzIjp7InRocmVlZHMyLmZpbmdlcnByaW50IjoiZXlKMGFISmxaVVJUUTI5dGNFbHVaQ0k2SWxraWZRPT0ifSwicGF5bWVudERhdGEiOiJBYjAyYjRjMCFCUUFCQWdDem9uNEtNU0FWc1hWRklpcWFFNm8wWmY1d0lUbWlCVXFPaTdRQWN4cjdiN0RkdkxCWUtsWGNiVGR5YUpuRHJQMmluTGdlQjgyRmk0R3lqNFV3eGRudUxGVUFKSm83TWo3YWJReDY3NEdkSSsvWkJ4eXVBTnN2dnliREl6OWFrYU5IRHJnUGxteE1TZzBnQm8rQm90cjJWUU00RjFzdmlwSDFaYnArd2gxdHRKWEJQbXlzb2J3bDJVZXM4YmZHcWZNWHd3ZzFHQ0lz..."
    }
  }
}
Attribute Type Example Value Description
payment_init_hash string "fe455eb0e472cc60f8e286abc2221d2e" Payment hash uniquely identifying the initiated transaction
auth_info.action_result string "eyJkZXRhaWxzIjp7InRocmVWc1..." The object received from Adyen SDK, that we then turn into string and encode it using Base64 btoa global DOM API function. Optional parameter used for Adyen payment processor.
auth_info.transient_token string "eyJkZXRhaWxzIjp7InRocmVWc1..." The string received from Cybersource SDK, encoded in Base64. Optional parameter used for Cybersource payment processor.

Response

{
	"status": "OK",
	"code": 200,
	"data": {
		"payment_processor_type_id": 11,
		"payment_processor_id": "5bab16ce-bb27-4e62-aff4-124266647eaf",
		"payment_init_hash": "fe455eb0e472cc60f8e286abc2221d2e",
		"additional_info": {
			"approval_url": null,
			"approval_action": "eyJwYXltZW50RGF0YSI6IkFiMDJiNGMwIUJRQUJBZ0JqTXpQRlVWN2x3Y2tTYUxWT3kzR0R0QWV2V3JhbkFUUWtSM0plXC95R0JNQzUwYWhRS2UxbkQ0a05PT3NSaVg2UlE2MFBmdktXNThTZ1UyclBwUk11U0FGVlVKQXNDN3l2K0pmK0wzMUdoSnk5cURuQ1UwbVNqVFNlNHZqczJcL1ZSQisrUHg1RnVwYjdaM1ZXOUFNTjJheDV5cUdKaW5DOVdXY2pLRzBmXC8ySDdCU1dKaSs5djZ1UVVHMGFpTHh2SmcxbzBlSTkxcUhwQ1l0b2VpeHRwN2o3T0dKRzNZeUd0XC9LUGpYaU1GZUNKcitsUFhzN08wdnVCTUY4ZlRja1BXVjVENUprZUp5ZGNrcHUzdW9Ud01YSUsraGxqUUxXOHVZdmhBTllyaWpPR2J3cm9GTEpcL0tkcVA1RUVhMlhUdWdRaDlNaUxDMDNBYXk0eXpJOWFid1pnbEFNT0VCN0FVUTZJd0Jkd2RWWHJ...",
			"client_encryption_public_key": "10001|A3795C2E0A78E5FF639AB006428D5EC19166AF82C402828476442E44476AE3DB9BE22468C15D8744574080DE5697FB81FBC4A0E0AB27B3B33A2739F20B1A514C6DCCBA3414E36F8056D4E1C007B6BF9ED5579A47313BDB651A3A984864E927B3A5D47CDA068E6A5C3AD76FB88A4173BC57EE672D421B13B3434F2D4B03FC250AAD86D64121A1760C83289EE7097A4643E493333ADE8373E9FB36A24F156C4B42D404879BBD8896705E0E91CD4F8BEC0E02A3F38D6EE275B6440F40B40E88B3D1B3292ABB331F9CB10E11D5AC81977ADCD0C22B7ECF009D608C651CC1FD7D4AA114B2130C6E82272224248B29CE4529DE93E5D010BD3976557067FD48E090B653",
		}
	}
}
Attribute Type Example Value Description
payment_processor_type_id int 11 Payment Processor identifier (See Payment Processors for more information)
payment_processor_id string "5bab16ce-bb27-4e62-aff4-124266647eaf" Payment Processor UUID
payment_init_hash string "fe455eb0e472cc60f8e286abc2221d2e" Payment hash uniquely identifying the initiated transaction
additional_info.approval_action string "eyJwYXltZW50RGF0YSI6IkFiM..." Base64 encoded string that can to be decoded using atob global DOM API function and then parsed into object. The object is then passed to payment processor SDK for initializing 3DS dialog.
additional_info.approval_url string or null "eyJwYXltZW50RGF0YSI6IkFiM..." Base64 encoded string passed usually together with approval_action to payment processor SDK for initializing 3DS dialog. For Adyen payment processor, this field is not needed, but for Cybersrouce both approval_url and approval_action are passed to Cybersource SDK as raw as they are.
additional_info.client_encryption_public_key string or null "10001A3795C2E0A78E5FF639A..." Optional parameter, specific to Adyen payment processor
additional_info.authentication_transaction_id string or null "10001A3795C2E0A78E5FF639A..." Optional parameter, specific to Cybersource payment processor

Place Order

The payment status listener and the webhook long polling are the two processes running in parallel. The order creation process depends on the process that gets the update first:

  • In case the payment status update is received on the frontend side from the iFrame form, the order creation should be called directly from the client application by calling https://api-public-playground.menu.app/api/orders (See the Generic Order create template for more details, or read more in the Ordering section)

  • In case the payment status update is received via webhooks, the order is created automatically by PAR Ordering Core and can be polled by the payment_initialization_status.order_uuid via

POST https://api-public-playground.menu.app/api/orders/{order_uuid}/poll

Request

Attribute Type Example Value Description
order_uuid string "27ef05b0d82e2512026f8f3833d887fb" Request parameter - order UUID
{
  "method": "post",
  "url": "https://api-public-playground.menu.app/api/orders/{order_uuid}/poll",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": 4.38.0,
    "Content-Type": "application/json",
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS1wdWJsaWMtcGxheWdyb3VuZC5tZW51LmFwcC9hcGkvY3VzdG9tZXJzL3JlZnJlc2giLCJpYXQiOjE2OTEzMzA4NjUsImV4cCI6MTY5MTM4Nzg4OCwibmJmIjoxNjkxMzg0Mjg4LCJqdGkiOiJvNjF6Z2pqaVF4NHpUdTRaIiwic2V0UmVmcmVzaFRUTCI6MjYyODAwMCwic3ViIjoiNTA5MDYzNyIsInBydiI6ImNjMzI5MjFhMTU0ODBhMTE3ZDliYmM3MmMwZTEyNTZhNjg1MjQ1OGIiLCJhcHBsaWNhdGlvbl9pZCI6MjAxNSwic2Vzc2lvbl9pZCI6MjY2MjF9.9kk79vbjxOfcJprxGYoEeb8GYL3N3-k4KI-JaTgEdoQ"
  }
}

Response

{
  "code": 200,
  "data": {
    "order": {
      "id": "a823c634-6300-4f43-b536-8f1a183d568c",
      "tax": 842,
      "tip": 0,
      "code": "BQIXC",
      "uuid": "a823c634-6300-4f43-b536-8f1a183d568c",
      "total": 17692,
      "status": "SendDelayed",
      "send_at": "2023-07-28 12:51:34",
      "subsidy": 0,
      "discount": 0,
      "ready_at": "string",
      "subtotal": 17692,
      "tip_rate": 0,
      "venue_id": "b8baafab-3f22-11ed-936c-1a67b454859d",
      "discounts": [
        {}
      ],
      "init_hash": "5e6af1f1d4106e5221b181864bedb149",
      "pickup_at": "2023-07-28 12:52:44",
      "tax_rates": {
        "5": 842
      },
      "ticket_id": "4a70a67b-b8d1-44b2-9ce4-e2fa6225a8d0",
      "created_at": "2023-07-28 12:50:44",
      "order_type": 4,
      "arriving_at": "2023-07-28 12:52:44",
      "combo_meals": [
        {
          "tax": 124,
          "name": "Acai Bowl Early Nene-nui Combo",
          "image": {
            "fullsize": "/storage/images/combo_item_images/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
            "thumbnail_small": "/storage/images/combo_item_images/_thumbs280/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
            "thumbnail_medium": "/storage/images/combo_item_images/_thumbs720/2021-09-08/6fd364994648905d3a74b3f05c299b42.png"
          },
          "items": [
            {
              "tax": 124,
              "name": "Làpana Bowl ",
              "type": "Food",
              "image": {
                "fullsize": "/storage/images/combo_item_images/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
                "thumbnail_small": "/storage/images/combo_item_images/_thumbs280/2021-09-08/6fd364994648905d3a74b3f05c299b42.png",
                "thumbnail_medium": "/storage/images/combo_item_images/_thumbs720/2021-09-08/6fd364994648905d3a74b3f05c299b42.png"
              },
              "total": 2599,
              "pos_id": "string",
              "comment": "test comment combo item 1",
              "type_id": 3,
              "discount": 0,
              "quantity": 1,
              "subtotal": 2599,
              "tax_rate": 5,
              "modifiers": [
                {
                  "name": "Organic Wild Rice",
                  "price": 0,
                  "pos_id": "string",
                  "modifier_id": "2049c354-3f23-11ed-936c-1a67b454859d",
                  "translations": {
                    "name": "Arroz Salvaje Ecológico"
                  }
                }
              ],
              "combo_group": {
                "name": "Combo group",
                "pos_id": "\"\"",
                "type_id": 1,
                "translations": {
                  "name": "Combo group"
                },
                "combo_group_id": "c1d5cd5e-3f22-11ed-936c-1a67b454859d"
              },
              "price_level": {
                "name": "string",
                "price": 2599,
                "pos_id": "string",
                "translations": {
                  "name": "string"
                },
                "menu_item_price_level_id": "0ffb254c-3f23-11ed-936c-1a67b454859d"
              },
              "menu_item_id": "19a394da-3f23-11ed-936c-1a67b454859d",
              "translations": {
                "name": "Làpana Bowl "
              },
              "service_charge": 0,
              "is_self_serving": true,
              "unpaid_item_hash": "string"
            }
          ],
          "total": 2599,
          "pos_id": "string",
          "type_id": 1,
          "discount": 0,
          "quantity": 1,
          "subtotal": 2599,
          "tax_rates": {
            "5": 124
          },
          "custom_name": "Acai Bowl Early Nene-nui Combo",
          "translations": {
            "name": "Combo Cuenco Nene-nui Temprano con Acai",
            "custom_name": "WCombo Cuenco Nene-nui Temprano con Acai"
          },
          "combo_meal_id": "04abaf54-3f23-11ed-936c-1a67b454859d",
          "service_charge": 0
        }
      ],
      "delivery_at": "2023-07-28 12:51:34",
      "order_items": [
        {
          "tax": 95,
          "name": "Làpana Bowl",
          "type": "Food",
          "image": {
            "fullsize": "/storage/images/item_images/2021-09-08/233451fe2256b3acf14ee5288e1b7dd0.png",
            "thumbnail_small": "/storage/images/item_images/_thumbs280/2021-09-08/233451fe2256b3acf14ee5288e1b7dd0.png",
            "thumbnail_medium": "/storage/images/item_images/_thumbs720/2021-09-08/233451fe2256b3acf14ee5288e1b7dd0.png"
          },
          "total": 1999,
          "pos_id": "string",
          "comment": "test comment",
          "type_id": 1,
          "discount": 0,
          "quantity": 1,
          "subtotal": 1999,
          "tax_rate": 5,
          "modifiers": [
            {
              "name": "Organic Wild Rice",
              "price": 0,
              "pos_id": "string",
              "modifier_id": "2049c354-3f23-11ed-936c-1a67b454859d",
              "translations": {
                "name": "Arroz Salvaje Ecológico"
              }
            }
          ],
          "price_level": {
            "name": "string",
            "price": 0,
            "pos_id": "string",
            "translations": {
              "name": "string"
            },
            "menu_item_price_level_id": "0ffb254c-3f23-11ed-936c-1a67b454859d"
          },
          "menu_item_id": "19a394da-3f23-11ed-936c-1a67b454859d",
          "translations": {
            "name": "Cuenco de lapana,"
          },
          "service_charge": 0,
          "is_self_serving": true,
          "unpaid_item_hash": "string"
        }
      ],
      "pickup_code": "string",
      "delivery_fee": 0,
      "discount_info": "string",
      "external_code": "string",
      "pos_ticket_id": "\"\"",
      "tax_exemption": 0,
      "payment_status": "Reserved",
      "service_charge": 0,
      "delivery_status": "string",
      "pos_ticket_code": "\"\"",
      "delivery_fee_tax": 0,
      "minimum_surcharge": 0,
      "calculation_method": "string",
      "external_reference": "string",
      "external_channel_id": "string",
      "regret_cancel_until": "2023-07-28 12:51:34",
      "service_charge_rate": 0,
      "tax_rates_exemption": {
        "5": 0
      },
      "minimal_order_amount": 0,
      "customer_account_info": {
        "id": "6735e303-50a1-4887-9b11-915a6919cc66",
        "email": "john.doe@partech.com",
        "state": 1,
        "locale": "en",
        "type_id": 2,
        "brand_id": "ea3c2a24-6210-40b3-84ef-447ee9d471b9",
        "last_name": "Doe",
        "first_name": "John",
        "phone_number": "+3811111111",
        "discount_cards": [
          {}
        ],
        "reference_type": "CustomerAccount",
        "optin_status_pn": 3,
        "optin_status_sms": 3,
        "optin_status_email": 3
      },
      "delivery_fee_tax_rate": 0,
      "minimum_surcharge_tax": 0,
      "order_additional_info": {},
      "order_type_properties": {
        "type_id": 4,
        "pickup_at": "order pickup at time",
        "pickup_asap": true,
        "customer_phone_number": "+3811111111"
      },
      "fraud_detection_status": "string",
      "service_charge_tax_rate": 0,
      "additional_delivery_info": "string"
    }
  },
  "status": "OK"
}
Attribute Type Example Value Description
order.id string "77711288-ce6c-4e13-9a51-e6482c06fd37" Order UUID
order.tax int 842 The amount of order tax
order.tip int 0 The amount of order tips
order.code string "BQIXC" Unique order id in PAR Ordering system, Management Center and CMS
order.total int 1870 The total order amount in cents
order.status string "SendDelayed" Order status (see Order Statuses for more information)
order.send_at string 2023-07-28 12:51:34 Time when the order is to be sent to the POS printer
order.ready_at string 2023-07-28 12:59:34 Estimated time when the order will be ready