PayProtocol (P3) Message Specification

This page specifies all the messages of the P3 protocol supported by the PayServer. Make sure to also make yourself familiar with the general protocol usage and message flow.


Login Merchant

  • LOGIN_MERCHANT_REQUEST
  • LOGIN_MERCHANT_RESPONSE

Use this message at the beginning of a session to save the credentials of a merchant.

Request Data
{
	"tag": "9a8ef354-81c8-4c30-adc7-3c9958bf9d4f", // Generate a unique tag for each REQUEST you send
	"type": "LOGIN_MERCHANT_REQUEST",
	"loginMerchantRequest": {
		"providerMode": "MOCK|JUNGLE|TEST|TEST_FIXED|LIVE|LIVE_FIXED",
		"merchantIdentifier": "your-merchant-identifier",
		"merchantSecret": "your-merchant-secret"
	}
}

All of the request parameters are required.

The providerMode references a value from the SDK as described in the documentation. The merchantIdentifier and merchantSecret is the same you would specify to the SDK and is obtainable in the Gateway Manager.

Response Data
{
	"tag": "9a8ef354-81c8-4c30-adc7-3c9958bf9d4f",
	"type": "LOGIN_MERCHANT_RESPONSE",
	"status": "OK",
	"loginMerchantResponse": {
		"information": {
			"location": "3rd Room"
		},
		"devices": [
			{
				"name": "USB Reader",
				"identifier": "usbReader",
				"resource": "devices/usbReader",
				"type": "MOCK|MIURA|VERIFONE",
				"comlink": "MOCK|WIFI|USB|BLUETOOTH"
			}
		]
	}
}

The response returns the server information and the list of devices which are connected to the PayServer. These are taken from the configuration file which was supplied to the server on startup.

The resource field for each device is important -- this is the resource path which you have to supply to the server if you want to interact with this device.


Execute Transaction

  • EXECUTE_TRANSACTION_REQUEST
  • EXECUTE_TRANSACTION_UPDATE
  • EXECUTE_TRANSACTION_ACTION
  • EXECUTE_TRANSACTION_RESPONSE

Use this message to execute a transaction on a connected device.

Request Data
{
	"tag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "EXECUTE_TRANSACTION_REQUEST",
	"resource": "devices/usbReader",
	"executeTransactionRequest": {
		"mode": "ONLINE | OFFLINE",
		"transactionParameters": {
			"amount": 5.00,
			"currency": <Currency>,
			"autoCapture": true|false,
			"type": "CHARGE",
			"subject": "My Subject",
			"customIdentifier": "my-custom-identifier",
			"statementDescriptor": "My Statement Descriptor",
			"applicationFee": 1.00,
			"includedTipAmount": 1.00,
			"metadata": {
				"my": "metadata"
			}
		},
		"sessionIdentifier": "62c155b6-6f7e-47e1-83b6-b13a1e4e2303",
		"processParameters": {
			"steps": {
				"askForTip": {
					"suggestedAmount": 1.00
				}
			}
		},
	}
}

You need to provide either the transactionParameters or the sessionIdentifier, not both. For more information about using the session identifier see registering transactions from your backend.

When using the transactionParameters you need to provide at least the amount, currency, type and autoCapture for the transaction. If you set autoCapture to false, the transaction will be only preauthorized and you need to capture it later using AMEND_TRANSACTION_REQUEST or from your backend.

You can also provide additional transaction parameters as documented here.

processParameters are optional steps which can be performed during the transaction process. askForTip will cause the reader to ask shopper for about adding a tip before performing the transaction. suggestedAmount is optional.

For resource make sure to provide the resource of the device.

Update Data

Since executing transactions is a long running operation, the server provides the client with update messages which inform about the current state of the transaction process.

{
	"tag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "EXECUTE_TRANSACTION_UPDATE",
	"resource": "devices/usbReader",
	"executeTransactionUpdate": {
		"state": <TransactionProcessDetailsState>,
		"stateDetails": <TransactionProcessDetailsStateDetails>,
		"information": ["Processing", "payment..."],
		"abortable": true|false,
		"transaction": {
			"amount": 5.00,
			"mode": "ONLINE | OFFLINE",
			"currency": <Currency>,
			"type": "CHARGE",
			"details": {
				"applicationFee": 1.00,
				"includedTipAmount": 1.00,
				"metadata": {
					"my": "data"
				}
			}
			"subject": "My Subject",
			"statementDescriptor": "My Statement Descriptor",
			"status": <TransactionStatus>,
			"identifier": "7e2fc2585cd24f648d96760f56fba26c",
			"referencedTransactionIdentifier": null,
			"customIdentifier": "my-custom-identifier"
		}
	}
}

The enum values <TransactionProcessDetailsState>, <TransactionProcessDetailsStateDetails>, <Currency> and < TransactionStatus> are values from the SDK as described there.

The field information is an array of exactly two strings which contain localised, human readable information about the state of the transaction. You can use them straight in your system UI.

The field abortable informs you whether the transaction process can be aborted at the moment. If true you can send an Abort Operation message for this resource. Before implementing aborts in your system make sure to understand the flow of a transaction abort. Beware that, due to the nature of networking, sending in an abort when transaction appears abortable might still result in a CANNOT_BE_ABORTED response if the abortable state has changed meanwhile, but this should happen very rarely.

Action Data
{
	"tag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "EXECUTE_TRANSACTION_ACTION",
	"resource": "devices/usbReader",
	"executeTransactionAction": {
		"type": "SIGNATURE"
	}
}

At the moment, the only possible value for type is SIGNATURE. Do not rely on this, in the future more possible values will be added.

This message tells you that the transaction process is paused and waiting for an input -- the shopper's signature which you send in a SUBMIT_SIGNATURE_REQUEST message. For more information about this message and its options see its documentation.

This message is not sent out by default, you need to explicitely enable it in the server configuration.
Response Data

Receiving an execute transaction response means that the long running operation is over and there will be no more related updates.

{
	"tag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "EXECUTE_TRANSACTION_RESPONSE",
	"resource": "devices/usbReader",
	"executeTransactionResponse": {
		"state": <TransactionProcessDetailsState>,
		"stateDetails": <TransactionProcessDetailsStateDetails>,
		"transaction": {
			"amount": 5.00,
			"mode": "ONLINE | OFFLINE",
			"currency": <Currency>,
			"type": <TransactionType>,
			"details": {
				"applicationFee": 1.00,
				"includedTipAmount": 1.00,
				"metadata": {
					"my": "data"
				}
			}
			"subject": "My Subject",
			"statementDescriptor": "My Statement Descriptor",
			"status": <TransactionStatus>,
			"identifier": "7e2fc2585cd24f648d96760f56fba26c",
			"referencedTransactionIdentifier": null,
                        "createdTimestamp": 1464009191,
			"customIdentifier": "myIdentifier",
                        "captured": true|false,
                        "paymentDetails": {
                            "scheme": <PaymentDetailsScheme>,
                            "source": <PaymentDetailsSource>,
                            "customerVerification": <PaymentDetailsCustomerVerification>,
                            "maskedAccountNumber": "541333******0086"
                        },
                        "refundDetails": {
                            "status": <RefundDetailsStatus>,
                            "process": [<RefundDetailsProcess>],
                            "refundTransactions": [
                                {
                                    "identifier": "c735ec8ed1794e83882fba8c99ccd7d2",
                                    "createdTimestamp": 1464609191,
                                    "amount": 3.00,
                                    "currency": <Currency>,
                                    "type": "REFUND",
                                    "code": <RefundTransactionCode>,
                                    "status": <TransactionStatus>,
                                    "statusDetails": {
                                        "code": <TransactionStatusDetailsCodes>,
                                        "description": "A description",
                                        "developerDescription": "A developer description",
                                    }
                                }
                            ]
                        },
                        "dccDetails": {
                            "status": "APPLIED",
                            "statusDetails": "APPLIED",
                            "convertedAmount": 123.23,
                            "convertedCurrency": "USD",
                            "rate": 12.23,
                            "markup": 2.14
                        },
                        "cardDetails": {
                            "fingerprint": "a5e2188a-f676-11e5-b944-593944fafab9",
                            "scheme": <PaymentDetailsScheme>,
                            "maskedCardNumber": "541333******0086",
                            "expiryMonth": 2,
                            "expiryYear": 2017,
                            "cardholderName": "John Doe"
                        },
                        "shopperDetails": {
                            "identifier": "c3d185cc-4c49-43d9-80f4-16a49a8660ec",
                            "email": null
                        },
			"merchantReceipt": {
				// ...
			},
			"customerReceipt": {
				// ...
			}
		}
	}
}

More information on the various transaction.status and what they mean can be found here.

The enum values <TransactionProcessDetailsState>, <TransactionProcessDetailsStateDetails>, <Currency>, < TransactionType>, <TransactionStatus>, < PaymentDetailsScheme>, < PaymentDetailsSource>, < PaymentDetailsCustomerVerification>, <TransactionStatusDetailsCodes>, <RefundDetailsProcess> and <RefundDetailsStatus> are values from the SDK as described there.

The transaction object has the same structure in all transaction related updates and responses (Get Transaction, Query Transactions, Execute Transaction, Amend Transaction)

Providing a Printed Payment Receipt

Information on creating your own receipts can be found here.



Abort Operation

  • ABORT_OPERATION_REQUEST
  • ABORT_OPERATION_RESPONSE

Use this message to abort a long running operation.

Request Data
{
	"tag": "7894cd51-ec04-4d38-994d-d735ceded39c",
	"referenceTag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "ABORT_OPERATION_REQUEST",
	"abortOperationRequest": { }
}
Response Data
{
	"tag": "7894cd51-ec04-4d38-994d-d735ceded39c",
	"referenceTag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "ABORT_OPERATION_RESPONSE",
	"status": "OK",
	"abortOperationResponse": {
		"abortStatus": "NOTHING_TO_ABORT|CANNOT_BE_ABORTED|OK"
	}
}

The abortStatus indicates the result of the abort operation. OK means that the abort is possible and that it was requested but it can take the device a while to react. Also, the referenceTag must be provided and must contain the tag value of the EXECUTE_TRANSACTION_REQUEST that you want to abort.


Submit Signature

  • SUBMIT_SIGNATURE_REQUEST
  • SUBMIT_SIGNATURE_RESPONSE

Use this message to send a signature to an ongoing process. You should only send this request after being prompted to do so by an action message as described in the submit signature action message flow.

Request Data
{
	"tag": "bb12f6f1-27e5-499a-8a00-dbb436564ed6",
	"referenceTag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "SUBMIT_SIGNATURE_REQUEST",
	"submitSignatureRequest": {
		"type": "ON_RECEIPT|DIGITAL",
		"data": "YQ=="
	}
}

The type says what kind of signature the shopper provides -- if it is on a printed receipt or a digitally captured one.

If you send type DIGITAL you also need to send the data field. This field expects a Base64 encoded image of a signature, please make sure to adhere to the formatting requirements. Also, the referenceTag must be provided and must contain the tag value of the EXECUTE_TRANSACTION_REQUEST that you want to provide the signature for.

Response Data
{
	"tag": "bb12f6f1-27e5-499a-8a00-dbb436564ed6",
	"referenceTag": "c8d08dcf-e1c6-4736-a7a6-30aee58d7a12",
	"type": "SUBMIT_SIGNATURE_RESPONSE",
	"status": "OK",
	"submitSignatureResponse": { }
}

If the general message status is OK, the request was successful and the original process will continue. Otherwise you get an ERROR response with the standard error fields

.

Amend Transaction

  • AMEND_TRANSACTION_REQUEST
  • AMEND_TRANSACTION_UPDATE
  • AMEND_TRANSACTION_RESPONSE

Use this message to amend a transaction -- refund or capture it. This message starts a long running operation but does not require a device.

Request Data
{
    "tag": "9b59ef1d-51ec-4e19-bc2a-251c914f62c3",
    "type": "AMEND_TRANSACTION_REQUEST",
    "amendTransactionRequest": {
        "mode": "ONLINE | OFFLINE",
        "transactionParameters": {
            "type": "CAPTURE|REFUND",
            "referencedTransactionIdentifier": "97a293ca3b804d639d8552962e0e3522",
            "amount": 5.00,
            "currency": <Currency>,
            "subject": "My Subject",
            "customIdentifier": "my-custom-identifier",
        }
    }
}

You need to provide at least the type and referencedTransactionIdentifier.

You can also provide additional transaction parameters as documented here.

Update Data

Since amending transactions is a long running operation, the server provides the client with update messages which inform about the current state of the process.

{
    "tag": "9b59ef1d-51ec-4e19-bc2a-251c914f62c3",
    "type": "AMEND_TRANSACTION_UPDATE",
    "amendTransactionUpdate": {
        "state": <TransactionProcessDetailsState>,
        "stateDetails": <TransactionProcessDetailsStateDetails>,
        "information": ["Processing", "payment..."],
        "abortable": false,
    }
}

The enum values <TransactionProcessDetailsState> and <TransactionProcessDetailsStateDetails> are values from the SDK as described there.

The field information is an array of exactly two strings which contain localised, human readable information about the state of the transaction. You can use them straight in your system UI.

Neither amend process is abortable at the moment.

Response Data

Receiving an amend transaction response means that the long running operation is over and there will be no more related updates.

{
    "tag": "9b59ef1d-51ec-4e19-bc2a-251c914f62c3",
    "type": "AMEND_TRANSACTION_RESPONSE",
    "amendTransactionResponse": {
        "state": <TransactionProcessDetailsState>,
        "stateDetails": <TransactionProcessDetailsStateDetails>,
        "transaction": {
            "mode": "ONLINE | OFFLINE",
            "amount": 5.00,
            "currency": <Currency>,
            "type": <TransactionType>,
            "details": {
                "applicationFee": 1.00,
                "includedTipAmount": 1.00,
                "metadata": {
                    "my": "data"
                }
            }
            "subject": "My Subject",
            "statementDescriptor": "My Statement Descriptor",
            "status": <TransactionStatus>,
            "identifier": "7e2fc2585cd24f648d96760f56fba26c",
            "referencedTransactionIdentifier": null,
            "createdTimestamp": 1464009191,
            "customIdentifier": "myIdentifier",
            "captured": true|false,
            "paymentDetails": {
                "scheme": <PaymentDetailsScheme>,
                "source": <PaymentDetailsSource>,
                "customerVerification": <PaymentDetailsCustomerVerification>,
                "maskedAccountNumber": "541333******0086"
            },
            "refundDetails": {
                "status": <RefundDetailsStatus>,
                "process": [<RefundDetailsProcess>],
                "refundTransactions": [
                    {
                        "identifier": "c735ec8ed1794e83882fba8c99ccd7d2",
                        "createdTimestamp": 1464609191,
                        "amount": 3.00,
                        "currency": <Currency>,
                        "type": "REFUND",
                        "code": <RefundTransactionCode>,
                        "status": <TransactionStatus>,
                        "statusDetails": {
                            "code": <TransactionStatusDetailsCodes>,
                            "description": "A description",
                            "developerDescription": "A developer description",
                        }
                    }
                ]
            }
            "cardDetails": {
                "fingerprint": "a5e2188a-f676-11e5-b944-593944fafab9",
                "scheme": <PaymentDetailsScheme>,
                "maskedCardNumber": "541333******0086",
                "expiryMonth": 2,
                "expiryYear": 2017,
                "cardholderName": "John Doe"
            },
            "shopperDetails": {
                "identifier": "c3d185cc-4c49-43d9-80f4-16a49a8660ec",
                "email": null
            },
            "merchantReceipt": {
                // ...
            },
            "customerReceipt": {
                // ...
            }
        }
    }
}

The returned transaction object is of the original, referenced transaction, but some fields may have been updated (mainly captured for captures and refundDetails for refunds).

The transaction object has the same structure in all transaction related updates and responses (Get Transaction, Query Transactions, Execute Transaction, Amend Transaction)

Get Devices

  • GET_DEVICES_REQUEST
  • GET_DEVICES_RESPONSE

Use this message at any point of the session to get the state of the connected devices.

Request Data
{
	"tag": "3cd89f74-4c53-4c2d-b3a2-189d9a225385",
	"type": "GET_DEVICES_REQUEST",
	"getDevicesRequest": { }
}
Response Data
{
	"tag": "3cd89f74-4c53-4c2d-b3a2-189d9a225385",
	"type": "GET_DEVICES_RESPONSE",
	"status": "OK",
	"getDevicesResponse": {
		"devices": [
			{
				"name": "USB Reader",
				"identifier": "usbReader",
				"resource": "devices/usbReader",
				"type": "MOCK|MIURA|VERIFONE",
				"comlink": "MOCK|WIFI|USB|BLUETOOTH"
			}
		]
	}
}

The device list returned in the response has the same structure and content as the one returned from login merchant.


Get Transaction

  • GET_TRANSACTION_REQUEST
  • GET_TRANSACTION_RESPONSE

Use this message to get transaction data from an already executed transaction. The transaction is identified by its identifier and could have been done outside of the PayServer, it just has to belong to your logged in merchant.

Request Data
{
	"tag": "19da497e-088d-4578-ba85-b999a4c37332",
	"type": "GET_TRANSACTION_REQUEST",
	"getTransactionRequest": {
		"mode": "ONLINE | OFFLINE",
		"transactionIdentifier": "7e2fc2585cd24f648d96760f56fba26c"
	}
}

The request parameters transactionIdentifier is required.

Response Data
{
	"tag": "19da497e-088d-4578-ba85-b999a4c37332",
	"type": "GET_TRANSACTION_RESPONSE",
	"status": "OK",
	"getTransactionResponse": {
		"transaction": {
			"amount": 5.00,
			"currency": <Currency>,
			"mode": "ONLINE | OFFLINE",
			"type": <TransactionType>,
			"details": {
				"applicationFee": 1.00,
				"includedTipAmount": 1.00,
				"metadata": {
					"my": "data"
				}
			}
			"subject": "My Subject",
			"statementDescriptor": "My Statement Descriptor",
			"status": <TransactionStatus>,
			"identifier": "7e2fc2585cd24f648d96760f56fba26c",
			"referencedTransactionIdentifier": null,
			"customIdentifier": "my-custom-identifier",
			"merchantReceipt": {
				// ...
			},
			"customerReceipt": {
				// ...
			}
		}
	}
}

Only one of the fields transaction are filled, depending on result of the transaction fetch.

The enum values <Currency>, < TransactionType> and < TransactionStatus> are values from the SDK as described there.

Information on the receipt data structure can be found here.

The transaction object has the same structure in all transaction related updates and responses (Get Transaction, Query Transactions, Execute Transaction, Amend Transaction)

Query Transactions

  • QUERY_TRANSACTIONS_REQUEST
  • QUERY_TRANSACTIONS_RESPONSE

Use this message to get transaction data from an already executed transaction. The transaction is identified by its identifier and could have been done outside of the PayServer, it just has to belong to your logged in merchant.

Request Data
{
	"tag": "b14e8223-4803-4434-9154-28d1335d8880",
	"type": "QUERY_TRANSACTIONS_REQUEST",
	"queryTransactionsRequest": {
		"mode": "ONLINE | OFFLINE",
		"filterParameters": {
			"customIdentifier": "my-custom-identifier"
		},
		"includeReceipts": true|false,
		"offset": 0,
		"limit": 20
	}
}

None of the request parameters are required. If you don't set them, the defaults are used as described in the SDK documentation. For example, if you leave the request data completely empty you will receive the last 20 transactions of your merchant.

Response Data
{
	"tag": "b14e8223-4803-4434-9154-28d1335d8880",
	"type": "QUERY_TRANSACTIONS_RESPONSE",
	"status": "OK",
	"queryTransactionsResponse": {
		"transactions": [
			{
				"amount": 5.00,
				"currency": <Currency>,
				"mode": "ONLINE | OFFLINE",
				"type": <TransactionType>,
				"details": {
					"applicationFee": 1.00,
					"includedTipAmount": 1.00,
					"metadata": {
						"my": "data"
					}
				}
				"subject": "My Subject",
				"statementDescriptor": "My Statement Descriptor",
				"status": <TransactionStatus>,
				"identifier": "7e2fc2585cd24f648d96760f56fba26c",
				"referencedTransactionIdentifier": null,
				"customIdentifier": "my-custom-identifier",
				"merchantReceipt": {
					// ...
				},
				"customerReceipt": {
					// ...
				}
			}
		]
	}
}

Only one of the fields transactions are filled, depending on result of the transaction fetch. If no transactions were found the resulting transactions array will be empty.

The enum values <Currency>, < TransactionType> and < TransactionStatus> are values from the SDK as described there.

Information on the receipt data structure can be found here.

The transaction object has the same structure in all transaction related updates and responses (Get Transaction, Query Transactions, Execute Transaction, Amend Transaction)

Can we help you?

If you cannot find your answer, contact us and we'll get in touch with you soon.

© Copyright 2017 Payworks GmbH. Legal.