Example: Simple Rating

Introduction

This walkthrough provides a step by step guide to running through a number of simple rating scenarios with the OCS. This walkthrough assumes that the OCS is running, and that the OCS HTTP API is accessible.

To trigger these API requests, it is suggested that a HTTP REST interface tester such as postman is used.

Setup

Create a subscriber

    POST 
    http://localhost:5490/resource/wallet
    {
        "id": "6463581140"
    }

Give the subscriber money and data

1000 units of cash are given. The OCS uses microcents internally, but this denomination may be granted different meaning by the environment.

    POST 
    http://localhost:5490/resource/wallet/6463581140/bucket
    {
    "value": 1000,
    "unit": "microcents"
    }

Grant 10MB:

    POST 
    http://localhost:5490/resource/wallet/6463581140/bucket
    {
    "value": 100000000,
    "unit": "bytes"
    }

Create an immediate use lifecycle

This is a simple lifecycle that grants buckets to a subscriber after debiting their wallet

    POST 
    http://localhost:5490/resource/lifecycle
    {
        "id": "single-use-lifecycle",
        "name": "SingleUseLifecycle",
        "description": "Single use subscription lifecycle, for use for once-off purchases.",
        "active": true,
        "lifecycleclass": "subscription"
    }
    POST 
    http://localhost:5490/resource/lifecycle/single-use-lifecycle/state 
    {
        "id": "initial-state",
        "name": "INITIAL",
        "description": "the starting point",
        "action": "engine.debit_wallet(context.getJsonObject('debit')); wallet.add_buckets_j(context.getJsonArray('buckets')); 'success'"
    }
    POST 
    http://localhost:5490/resource/lifecycle/single-use-lifecycle/state
    {
        "id": "complete-state",
        "name": "COMPLETE",
        "description": "cleanup point",
        "action": "lifecycle.delete()"
    }
    PUT
    http://localhost:5490/resource/lifecycle/single-use-lifecycle
    {
        "initial_state": "INITIAL"
    }
    POST 
    http://localhost:5490/resource/lifecycle/single-use-lifecycle/state/initial-state/transition
    {
        "event": "success"
        , "to_state": "COMPLETE"
    }

Create a service which will charge the user 150 units, for 1 day of seconds:

    POST 
    http://localhost:5490/resource/service
    {
        "id": "24-hour-basic-cable",
        "name": "24 Hour Basic Cable",
        "description": "Access to cable for 24 hours from time of purchase.",
        "active": true,
        "lifecycle": "single-use-lifecycle",
        "serviceclass": "value-pack",
        "properties": { 
                "buckets": [
                        {
                                "value": 86400,
                                "unit": "seconds",
                                "expiry": {
                                    "days": 1
                                }
                            }
                ]
                , "debit": {
                        "rating_requested": [{
                            "unit": "microcents",
                            "value": 150
                        }]
                    }
        },
        "cardinality": 1
    }

Event Charging

In this example, we want to charge a user 50 units, but we want to reserve it, then ultimately commit it 10 minutes later. We simulate this using two messages , a reservation request, then a commit, highlighting between these two the subscriber’s intermediate wallet.

Initially display the user’s wallet

    GET
    http://localhost:5490/resource/wallet/6463581140

First, we want to perform session based charging. We include a session ID, because that will often come from the client. We include the rating requested as well.

    POST
    http://localhost:5490/engine/wallet/6463581140/session
    {
        "id": "session-1",
        "rating_requested": [
          {
            "unit": "microcents",
            "value": 50
          }]}

We can review the user’s wallet, to see the session in progress, and the ongoing reservations on a per-bucket basis:

    GET
    http://localhost:5490/resource/wallet/6463581140

We can see the user’s wallet - the session, and the reservation, and the bucket value.

    [{
            "sessions": {
                "session-1": {
                    "initial_creation_timestamp": "2018-01-11T07:29:14.408Z",
                    "id": "session-1"
                }},
            "buckets": [
                {
                    "value": 1000,
                    "id": "8470ede6-d3b5-4406-b7bf-9a402b497c55",
                    "unit": "microcents",
                    "reservations": [
                        {
                            "value": 50,
                            "session": "session-1"
                        }]}],
            "id": "6463581140"
        }]

We can further see the affect ongoing sessions have, but doing a price enquiry:

    POST 
    http://localhost:5490/engine/wallet/6463581140/enquire
    {
        "rating_requested": [
          {
            "unit": "microcents"
            ,"value":0
          }]
    }

In the response, the decrease in available funds is clear:

    "funds_available": [{
            "unit": "microcents",
            "value": 950
        }]

We can then commit the reservation:

    POST
    http://localhost:5490/engine/wallet/6463581140/session/session-1/commit

Once the commit has been complete, the OCS can be queried to see the wallet’s session list is empty, and the reservations on the bucket are removed.

We can additional see the use of unit conversions to charge for MB using money:

    POST 
    http://localhost:5490/engine/wallet/6463581140/enquire
    {
        "rating_requested": [
          {
            "unit": "bytes"
            ,"value":0
          }],
          "rating_context": {
          "unit_conversion_ratios": [{
                "from_unit": "bytes",
                            "to_unit": "microcents",
                        "from_unit_count": 1024,
                        "to_unit_count": 1
    }]}}

Time Based Usage

In this example, we purchase 48 hours of unlimited data access:

    POST
    http://localhost:5490/engine/wallet/6463581140/subscribe
    {
        "service": "24-hour-basic-cable"
    }

This grants the user a time based bucket. On a subscriber query, we can see this in their wallet:

    [
        {
            "audit": {
                "initial_creation_timestamp": "2018-01-09T03:02:47.848Z",
                "last_change_timestamp": "2018-01-09T19:30:44.647Z",
                "last_change_host": "localhost:5490",
                "lock": "2018-01-09T19:30:44.647Z"
            },
            "buckets": [
                {
                    "value": 950,
                    "id": "539816c8-d5eb-400a-95bb-6f659bd21f33",
                    "unit": "microcents"
                },
                {
                    "value": 86400,
                    "id": "4505374b-2319-4f8f-9618-f0f2ac9ee074",
                    "unit": "seconds",
                    "expiry": "2018-01-10T19:30:44.645Z"
                }
            ],
            "id": "6463581140"
        }
    ]

Note that bucket annotations - e.g. to flag this time based bucket as “unlimited” time, with its expiry, and with a minimum value (so it doesn’t go negative) can be incorporated. For simplicity this demonstration has skipped this.

Note also that the user may be granted 24 hours of time - e.g. of cumulative time which they can use of the course of a week, or unlimited watching within 24 hours. This may the be charged and then we can request time usage can be charge. First we can request how much time the user has available using an enquire method:

    POST 
    http://localhost:5490//engine/wallet/6463581140/enquire
    {
     "rating_requested": [{
                "value": 0
                , "unit": "seconds"
        }]}

This will confirm the user has time. The system will respond with funds available:

    "funds_available": [
        {
            "unit": "seconds",
            "value": 86400
        }]

(Note that the expiry of these funds will occur 24 hours after being granted).

The cable system can then grant access, and use these funds through standard debiting - e.g. debit every 60 seconds:

    POST 
    http://localhost:5490/engine/wallet/6463581140/debit
    {
     "rating_requested": [{
        "value": 60
        , "unit": "seconds"
     }]}

Once the time bucket expires, or has been completely used, e.g. delete the bucket using:

    DELETE
    http://localhost:5490/resource/wallet/6463581140/bucket/4505374b-2319-4f8f-9618-f0f2ac9ee074

Then the debit will fail:

    POST 
    http://localhost:5490/engine/wallet/6463581140/xfe
    
    {
     "rating_requested": [{
        "value": 60
        , "unit": "seconds"
     }]}

with a return value of 402: Insufficient Funds.

Data Charging

In this example, we want to charge a user for data usage during a data session. For this, we reserve funds in 1MB chunks, and then, at the end of the session, charge for the actual data MB used.

First, we want to perform session based charging. We include a session ID, because that will often come from the client. We include the rating requested as well.

    POST
    http://localhost:5490/engine/wallet/6463581140/session
    {
        "id": "session-1",
        "rating_requested": [
          {
            "unit": "byte",
            "value": 1000000
          }]}

We can review the user’s wallet, to see the session in progress, and the ongoing reservations on a per-bucket basis:

    GET
    http://localhost:5490/resource/wallet/6463581140

We can see the user’s wallet - the session, and the reservation, and the bucket value.

    [{
            "sessions": {
                "session-1": {
                    "initial_creation_timestamp": "2018-01-11T07:29:14.408Z",
                    "id": "session-1"
                }},
            "buckets": [
                {
                    "value": 100000000,
                    "id": "8470ede6-d3b5-4406-b7bf-9a402b497c55",
                    "unit": "bytes",
                    "reservations": [
                        {
                            "value": 1000000,
                            "session": "session-1"
                        }]}],
            "id": "6463581140"
        }]

We can further see the affect ongoing sessions have, by doing a price enquiry:

    POST 
    http://localhost:5490/engine/wallet/6463581140/enquire
    {
        "rating_requested": [
          {
            "unit": "bytes"
            ,"value":0
          }]
    }

In the response, the decrease in available funds is clear:

    "funds_available": [{
            "unit": "bytes",
            "value": 102809580
        }]

We can then perform more reservations to request more time. Eventually, we can then commit the reservation:

    POST
    http://localhost:5490/engine/wallet/6463581140/session/session-1/commit
    {
        "id": "session-1",
        "rating_used": [
          {
            "unit": "bytes",
            "value": 500000
    }]}

Once the commit has been complete, the OCS can be queried to see the wallet’s session list is empty, and the reservations on the bucket are removed, and the actually requested rating has been used.