Skip to content

Onlineweb payme nibble

Torrib edited this page Apr 13, 2016 · 19 revisions

Nibble / Payme

Payment system for the Online office.
User beeps their card. A tablet displays a webpage with user info and saldo and allows the user to perform an operation(Select product, Add money, subtract money, undo previous operation)
Integration in Onlineweb for adding money using Stripe.

Functionality

  • Adding and subtracting money
  • Undo / revert transaction
  • Keep stock
  • Buying products
  • Possibility for users to add money using Stripe
  • Adding/Setting RFID (Might have to be done in Onlineweb as it should be authenticated)
  • Notify trikom when supply is running low

Objects

Product Category

  • Name

Product

  • Name
  • Price
  • Description
  • Amount
  • Available (If the product should be displayed to the user)
  • Product Category

Transaction

  • User
  • Money diff (minus for subtraction, plus for addition) (Optional)
  • Product (Optional)
  • Timestamp

OnlineUser

  • Add saldo field

Backend

  • Add/remove/edit products in the admin panel/dashboard
  • Tab in my profile where the user can see transaction history, saldo and add money to their saldo using Stripe.
  • Rest API

Rest endpoints

Overview

Get inventory - /api/v1/inventory/ - {"pk", "name", "price", "description"}
Get user information - /api/v1/usersaldo/?rfid=<rfid> - {"pk", "first_name", "last_name", "saldo"}
Add or subtract from saldo - /api/v1/transactions/ - POST{"user": [pk], "amount": <amount>}
Buy - /api/v1/orderline/ - POST{"user":<user_id>, "orders":[{"object_id": id, "quantity": 2}]}
Set RFID - /api/v1/rfid/ - POST{"username", "password", "rfid"}
Get access token - /api/v1/auth/ - POST{"grant_type", "client_id", "client_secret"}

TODO

  • /payme/undo - POST{"user": } - Undoes the previous transaction for the user.

Examples

Authentication

Use the client_id and client_secret to get an access_token that lasts for 1 hour.

var getToken = function(){
	$.ajax({
	type: "POST",
	headers: {
	 "Content-Type": "application/x-www-form-urlencoded",
	 },
	url: "http://localhost:8001/api/v1/auth",
	data: {
		"grant_type":"client_credentials",
		"client_id":"24Qy0p75pY4usMHKPQdJJYYoO9zigEU1RkCTibZU",
		"client_secret":"BVarpTofBtIqiO0QJksgbueHx3tERuGCgxJRs8i2zABPDLVzrEp2tY7lv5jD0Zk8jKqR3oeKhi5N5gN2lNlITjBkizZSNgeSlqETwyhCFSnTYVLpacLFka4gyu9HdCjd",
	},
	dataType: "json",
	success: function(data) {
			console.log(data.access_token);
	},
	error: function(msg) {
	 console.log(msg);
	}  
	});
}

This token will be used to perform actions on the other endpoints.
If a call returns 401 UNAUTHORIZED a new access_token is needed.

User info

A users RFID can be used to retrieve the users ID, name and saldo.

var getUserSaldo = function(rfid){
	$.ajax({
	url: "http://localhost:8001/api/v1/usersaldo/?format=json&rfid=" + rfid,
	type: 'GET',
	beforeSend: function (xhr) {
	    xhr.setRequestHeader('Authorization', 'Bearer <access_token>');
	},
	data: {},
	success: function (data) { console.log(data.results)},
	error: function (msg) { console.log(msg)},
	});
}

returns:

{"pk", "first_name", "last_name", "saldo"}

If the RFID does not exists an emtpy list is returned.

New RFID

If the RFID is new it can be connected to a user using user credentials.
Note! This will replace old RFIDs connected to the user.

var setRFID = function(username, password, rfid){
$.ajax({
	url: "http://localhost:8001/api/rfid/",
	type: 'POST',
	beforeSend: function (xhr) {
	    xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
	},
	data: {
		'username': username,
		'password': password,
		'rfid': rfid,
	},
	success: function (data) { console.log(data)},
	error: function (msg) { console.log(msg)},
	});
}

Returns 200_OK on success and 409_CONFLICT on invalid user credentials.

Getting item information

Returns a list of items that are on sale. http://localhost:8001/api/v1/inventory/?format=json Returns

{
        "pk": 2,
        "name": "Cola",
        "price": 30,
        "description": "0.5l",
        "image": {
            "id": 1,
            "name": "øl",
            "timestamp": "2016-01-27T19:20:59.370101Z",
            "description": "sdfghjk",
            "thumb": "/media/images/responsive/thumbnails/1eee7777-7972-457f-8228-5fccd574d51b.jpeg",
            "original": "/media/images/responsive/1eee7777-7972-457f-8228-5fccd574d51b.jpeg",
            "wide": "/media/images/responsive/wide/1eee7777-7972-457f-8228-5fccd574d51b.jpeg",
            "lg": "/media/images/responsive/lg/1eee7777-7972-457f-8228-5fccd574d51b.jpeg",
            "md": "/media/images/responsive/md/1eee7777-7972-457f-8228-5fccd574d51b.jpeg",
            "sm": "/media/images/responsive/sm/1eee7777-7972-457f-8228-5fccd574d51b.jpeg",
            "xs": "/media/images/responsive/xs/1eee7777-7972-457f-8228-5fccd574d51b.jpeg",
            "tags": [
                "øl"
            ],
            "photographer": ""
        },
        "category": {
            "pk": 1,
            "name": "Sjokolade4"
        }
}

Note: image, description and category can be null

Adding or subtracting from the users saldo

The userId received from userinformation as PK.
Positive amount for adding currency to the saldo, negative to decrease saldo.

var transaction = function(userId, amount){
$.ajax({
	url: "http://localhost:8001/api/v1/transactions/",
	type: 'POST',
	beforeSend: function (xhr) {
	    xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
	},
	data: {
		'user': userId,
		'amount': amount,
	},
	success: function (data) { console.log(data)},
	error: function () { console.log("error")},
	});
}

Values reducing the saldo to less than zero will return a 406_NOT_ACCEPTABLE

Buying

var json= '{"user": 1, "orders": [{"object_id": 2, "quantity": 1}, {"object_id": 1, "quantity": 1}]}'

var buy = function(){
$.ajax({
    url: "http://localhost:8001/api/v1/orderline/",
    type: 'POST',
    contentType:"application/json",
    beforeSend: function (xhr) {
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
    },
    data: json,
    success: function (data) { console.log(data)},
    error: function (msg) { console.log(msg)},
    });
}

If the order is more expensive than the users saldo a 406_NOT_ACCEPTABLE will be returned.

Design

Views

Bilder til papir mockup

  • Front page
    • Beep card message
  • User beeps unknown card
    • Rfid unknown - authenticate with user
    • Inform the user that the rfid is connect to the onlineuser (events etc)
    • Cancel button
  • Users beeps known card
    • Name and saldo
    • items - select multiple (name, price, description)
    • History (Low pri)
    • Display total price
    • Add cash
    • Remove cash
    • Buy
    • Cancel
  • User buys
    • New saldo
    • Price
    • Bought items
    • Undo button
    • Finish button (Exit screen automatically after x seconds)

Hardware

Either:

TODO

  • Design
  • Security
    • Secure the rest end point (token, white list MAC/IP, certificate or something similar)
    • Restrict the tablet to a webpage.

Other things?

  • Reporting system for trikom when they are running out of for instance cups or forks or something similar.