Checkout API
The SchoolPay Checkout integration allows the use of our payment pages to collect cardholder data, as a “man in the middle” approach. Your customer starts at your website, then pays at our website, and finally returns to your website once the process is completed. This service is very easy to implement and has an unlimited number of practical applications.
Format is HTTP POST. URL is /api/sso/open
. Variables are as follows:
Variable | Type | Description |
---|---|---|
version | Number | Specifies how the landing page should act. To use the behavior from this document please send “5”. |
items | JSON-encoded array of objects | Describes the payment object that the user is going to make. |
return_url | URL | Describes which page the user’s browser should be forwarded to upon completion of payment. |
notification_url | URL | Describes the location of the notification receiver for this specific payment. |
provider | String | Your unique provider name. If you do not have one you may leave this blank. |
Sample Request
items=[{"amount":"20","code":"SqgGY1","quantity":"1","title":"Test SP Checkout Item"}]
&version=5
¬ification_url=http://requestb.in/1dge8101
&return_url=http://www.google.com/&provider=apidemo
Development Values:
- Checkout Endpoint: https://dev.schoolpayqa.com/api/sso/open
- Item ID: SqgGY1
- API Endpoint: https://dev.schoolpayqa.com/services/graphql
- API Username: Demo
- API Password: 5d74b4999d87394dfc9f1c1e32ceddf7e574992e63269c38985618294fe7167a
This is all pretty simple with the exception of the items array. The items array can receive any number of distinct “temporary” items that are backed by any number of items in the SchoolPay system.
In a standard set up, you will have one SchoolPay item per bank account. To purchase multiple items against the same bank account, you’d use the same SchoolPay item with different amounts and titles.
Item Object
The item object has the same keys as the item object from previous versions of the checkout. You may send over values for any of the below keys.
Variable | Type | Req’d | Description |
---|---|---|---|
code | String | Yes | Identifier to look up the base item in the SchoolPay system. |
amount | Currency Amount | Yes | The amount of the item being purchased. This is a base price, and does not include fees, tax, or shipping values. |
title | String | Yes | Distinctive name to give the item. |
description | HTML | No | A description to give the item |
quantity | String | No | The quantity of the item being purchased |
convenience_fee | Currency Amount | No | An additional fee to add to the price of the item. |
tax | Currency Amount | No | An additional amount to add to the price of the item described as tax. |
shipping | Currency Amount | No | An additional amount to add to the price of the item described as shipping. |
chart_of_accounts_number | String | No | The number for the associated chart of accounts account (GL ledger) |
chart_of_accounts_label | String | No | The label for the associated chart of accounts account (GL ledger) |
student_id | String | No | The ID of the student to associate with the transaction. |
student_name | String | No | The name of the student to associate with the transaction. Helpful for identifying problems with the integration. |
custom_fields | Object | No | JSON-encoded object of additional custom fields. It is of the format: {“label”:”value”, “label”:”value”, …} |
Please note: the default values of non-required fields are configured from item set up in your district’s account. It does not exactly make sense to have a default value for convenience_fee, but the system does allow it.
Once your user arrives at our page, we will make a session cart filled with the items and item overrides you have provided. This user’s cart will be marked as immutable and thus items cannot be added or removed from it. If the user is logged in, their session cart will take priority over their users cart, and their users cart won’t be accessible until they either pay for the session cart, or log out. This behavior is meant to avoid any discrepancies between values on your side and values in the notifications we send you.
Notifications (Postbacks)
Once the payment has successfully posted, we will notify you of payment. We will send a notification of money successfully moving when a payment enters the “Pending” state (funds authorized, but not taken) or the “Settled” state (funds withdrawn). We will only send you one notification per payment.
We will abstain from sending you notifications for a variety of situations in attempt to help you make good software design choices on your side.
We will NOT send you notifications for failed payments for the following reasons:
- Your software needs to be able to handle the case of the user simply closing the browser window on our side.
- Users do not need historical information of failed payments.
- Our software will allow them to try again in the case of a decline. You do not need to handle the retry loop.
- The need for a decline notification is typically due to using a wait semaphore1 implementer’s side. This can be a very bad design as the user would be stuck in “waiting for payment to complete” even after closing out a browser window and coming back!
We will NOT send you notifications for refund or voids for the following reasons:
- Refunds may happen as much as months after the original payment and the context/reasons for doing so may not be clear enough to make programmatic decisions on.
- Partial refunds complicate what exactly is being refunded.
- Refunds need to be invoked by someone in a position of power on your side, so there is little need to automate its behavior.
A program designed to accept a notification and act upon the data inside it is called a notification receiver. This program needs to have a publicly accessible URL that accepts a standard HTTP POST. It is not required to set up encryption on this connection as we do not send any sensitive2 data in the transmission.
The following data is sent to you in the transmission:
Key | Value |
---|---|
transaction_id | Unique SchoolPay assigned identifier on the transaction. |
posted_amount | The amount you sent to us with the customer. |
total_amount | This is the full amount of the transaction. |
When you receive this notification, you should use our GraphQL API to look up the transaction by transaction ID.
The following code is PHP but the concepts should work in any language.
function getTxn(string $txnId, string $username, string $password, bool $prod)
{
$query = 'query GetRefundState($txnid: ID!) {
Txn(first: 1, Search: {ID: [$txnid]}) {
edges {
node {
ID
Amount
AmountRefundable
AmountAlreadyRefunded
Status
TxnItem {
ID
Quantity
Amount
AmountRefundable
AmountAlreadyRefunded
}
}
}
}
}';
$hostname = $prod ? 'www.schoolpay.com' : 'schoolpayqa.com';
$authorization = base64_encode("$username:$password");
// Make request
$c = curl_init();
curl_setopt_array($c, [
CURLOPT_URL => "https://$hostname/services/graphql",
CURLOPT_HTTPHEADER => [
"Authorization: Basic $authorization",
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'query' => $query,
'variables' => [
'txnid' => $txnId,
],
]),
CURLOPT_RETURNTRANSFER => 1,
]);
$result = curl_exec($c);
// Unwrap result
return current(json_decode($result, true)['data']['Txn']['edges'])['node'];
}
$txn = getTxn('553', 'demo', 'ef013a426fe7bab64a132c0996ed4783a13f615562762afefebbeb8dcaff6dd5', false);
1 Value that controls program execution flow
2 “Sensitive” terms of PCI compliance. Implementers may deem some pieces of information as sensitive and would then elect to use an encrypted connection to communicate with SchoolPay.