﻿
# Basic External Provisioning and Web Service Contacts

This guide describes a minimal deployment of Acrobits external provisioning and Web Service Contacts using the example PHP scripts from the [`integration-snippets`](https://github.com/Acrobits-Dev/integration-snippets) repository.

The example service does two things:

1. Validates the user against a CSV file and returns Account XML for external provisioning.
2. Returns a JSON contacts list from the same CSV data for Web Service Contacts.

Use this as a starting point for simple deployments or proof-of-concept integrations. For production, review the security and scaling notes before exposing the service to end users.

## Source Files

Download or copy these files from the snippet repository:

- [`helpers.php`](https://github.com/Acrobits-Dev/integration-snippets/blob/main/helpers.php)
- [`acrobits_prov.php`](https://github.com/Acrobits-Dev/integration-snippets/blob/main/acrobits_prov.php)
- [`acrobits_contacts.php`](https://github.com/Acrobits-Dev/integration-snippets/blob/main/acrobits_contacts.php)
- [`example-data/extProv/SAMPLE.xml`](https://github.com/Acrobits-Dev/integration-snippets/blob/main/example-data/extProv/SAMPLE.xml)
- [`example-data/users/SAMPLE.csv`](https://github.com/Acrobits-Dev/integration-snippets/blob/main/example-data/users/SAMPLE.csv)

## Server Requirements

The server needs:

- PHP 7.4 or newer.
- A web server with PHP support, such as Apache or Nginx with PHP-FPM.
- HTTPS enabled.
- Read access from the PHP process to `/srv/data/provisioning/`.

HTTPS is required because the provisioning endpoint receives user credentials in the request.

## Deploy the PHP Files

Place the PHP files together in a public web directory:

```text
/var/www/html/provisioning/
|-- helpers.php
|-- acrobits_prov.php
`-- acrobits_contacts.php
```

The public URLs will then look like this:

```text
https://customer-domain.example/provisioning/acrobits_prov.php
https://customer-domain.example/provisioning/acrobits_contacts.php
```

## Prepare the Data Directory

Store customer data outside the public web root. The example scripts use this layout:

```text
/srv/data/provisioning/
|-- users/
|   `-- SAMPLE.csv
`-- extProv/
    `-- SAMPLE.xml
```

The filename must match the `cloud_id`. Use uppercase filenames, for example `SAMPLE.csv` and `SAMPLE.xml` for `cloud_id=SAMPLE`.

The scripts also normalize editable Cloud Softphone versions by stripping a trailing `*` from the Cloud ID, so `SAMPLE*` and `SAMPLE` use the same data files.

## Create the User CSV

Place the user CSV file at:

```text
/srv/data/provisioning/users/SAMPLE.csv
```

The sample CSV uses this structure:

```csv
cloud_username,cloud_password,username,password,display_name,first_name,last_name,avatar,phone_number1
user001,SAMPLE_PASSWORD,1001,ACCOUNT_PASSWORD_1001,Example User One,Example,User One,https://example.com/avatar-user001.png,1001
user002,bcrypt:<bcrypt_hash_for_user002>,1002,ACCOUNT_PASSWORD_1002,Example User Two,Example,User Two,https://example.com/avatar-user002.png,1002
```

The provisioning endpoint looks up users by `cloud_username`.

The `cloud_password` value can be stored as:

- Plain text, useful only for quick local testing.
- A bcrypt hash in the format `bcrypt:<hash>`, recommended for real deployments.

The `username` and `password` columns are the SIP account credentials returned in the Account XML. The `cloud_username` and `cloud_password` columns are the credentials entered by the user during app activation.

## Create the Account XML Template

Place the external provisioning XML template at:

```text
/srv/data/provisioning/extProv/SAMPLE.xml
```

The XML template may contain placeholders matching CSV column names. During provisioning, placeholders such as `{username}`, `{password}`, and `{display_name}` are replaced with values from the matching CSV row.

Example:

```xml
<account>
    <title>{display_name}</title>
    <acrobitsDisplayName>{display_name}</acrobitsDisplayName>
    <cloud_id>{cloud_id}</cloud_id>
    <cloud_username>{cloud_username}</cloud_username>
    <cloud_password>{cloud_password}</cloud_password>
    <username>{username}</username>
    <password>{password}</password>
</account>
```

`{cloud_password}` is replaced with the password submitted by the app after validation succeeds, not with the stored CSV value. This prevents a stored bcrypt hash from being returned to the app.

## Add Web Service Contacts Configuration

If you want the same deployment to enable Web Service Contacts, add the `wsContacts*` settings to the Account XML returned by external provisioning, or configure equivalent values in the Cloud Softphone portal.

Example Account XML fragment:

```xml
<wsContactsUrl>https://customer-domain.example/provisioning/acrobits_contacts.php?cloud_id=%account[cloud_id]%&amp;cloud_username=%account[cloud_username]%</wsContactsUrl>
<wsContactsMethod>GET</wsContactsMethod>
<wsContactsRefresh>180</wsContactsRefresh>
```

The contacts endpoint returns JSON in the format expected by Web Service Contacts:

```json
{
  "contacts": [
    {
      "fname": "Example",
      "lname": "User Two",
      "displayName": "Example User Two",
      "contactId": "1002",
      "cloudUsername": "user002",
      "networkId": "SAMPLE",
      "avatar": "https://example.com/avatar-user002.png",
      "largeAvatar": "https://example.com/avatar-user002.png",
      "contactEntries": [
        {
          "entryId": "tel:sip",
          "label": "SIP extension",
          "type": "tel",
          "uri": "1002"
        }
      ]
    }
  ]
}
```

The sample contacts script skips the requesting user's own `cloud_username`, uses `username` as `contactId` when available, and maps `phone_number1` through `phone_number5` into additional phone entries.

## Configure Initial External Provisioning

In the Cloud Softphone portal, configure initial external provisioning to call the PHP provisioning endpoint.

Use a URL like this:

```text
https://customer-domain.example/provisioning/acrobits_prov.php?cloud_id=%fullcode%&cloud_username=%username%&cloud_password=%password%
```

Use `GET` for the basic example.

The placeholders are expanded by the app during initial provisioning:

- `%fullcode%` is the Cloud ID.
- `%username%` is the username entered by the user.
- `%password%` is the password entered by the user.

The PHP script validates the submitted credentials against the CSV row. If validation succeeds, it returns the XML template with placeholders replaced by values from that row.

## Test the Deployment

Test external provisioning:

```bash
curl "https://customer-domain.example/provisioning/acrobits_prov.php?cloud_id=SAMPLE&cloud_username=user001&cloud_password=SAMPLE_PASSWORD"
```

Expected result: an XML response with one `<account>` root node.

Test Web Service Contacts:

```bash
curl "https://customer-domain.example/provisioning/acrobits_contacts.php?cloud_id=SAMPLE&cloud_username=user001"
```

Expected result: a JSON response containing a `contacts` array.

If the provisioning password is invalid, the sample provisioning script returns HTTP `410` with a JSON error body.

## Production Notes

Keep `/srv/data/provisioning/` outside the public web directory. The CSV file may contain passwords and must not be directly downloadable.

Use bcrypt hashes for `cloud_password` values instead of plain text passwords.

Restrict file permissions so only the web server process can read the provisioning data.

The sample contacts script is intentionally simple and does not implement `Last-Modified` or `304 Not Modified` handling. For large contact lists, add caching support so apps do not download the full contacts payload every refresh interval.

Validate and escape any additional fields you add to the XML template. The sample provisioning script escapes placeholder values with `htmlspecialchars()` before returning XML.

