PHP code example of uengage.io / php-platform-sdk

1. Go to this page and download the library: Download uengage.io/php-platform-sdk library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

uengage.io / php-platform-sdk example snippets


use Uengage\PlatformSdk\Client;

$platform = Client::create([
    'serviceId' => 'edge-zones-admin',
    'serviceSecret' => getenv('EDGE_ZONES_ADMIN_SECRET'),
]);

// Zones - the new spatial primitive
$zone = $platform->zones->create([
    'geometry' => [
        'type' => 'Polygon',
        'coordinates' => [[
            [77.5, 12.9], [77.6, 12.9], [77.6, 13.0], [77.5, 13.0], [77.5, 12.9],
        ]],
    ],
    'tags' => ['type' => 'delivery-area', 'city' => 'BLR'],
]);

$matches = $platform->zones->containing([
    'point' => ['lat' => 12.97, 'lng' => 77.59],
    'tags' => ['type' => 'delivery-area'],
]);

// Business read
$record = $platform->business->get(42, ['profile']);
// Groups: profile, branding, locale (public); compliance, address, contact, hours, slots,
// order_types, delivery, charges, attributes, app_config, payment_gateway, bank (need grants).

// Audit (buffered; flushed at shutdown or on demand)
$platform->audit->record([
    'event_type' => 'business.profile_updated',
    'tenant' => ['id' => '42', 'parent_id' => null],
    'actor' => ['type' => 'service', 'id' => 'edge-zones-admin'],
    'resource' => ['type' => 'business', 'id' => '42'],
    'changes' => ['name' => ['before' => 'Old', 'after' => 'New']],
]);
$platform->audit->flush(); // optional; shutdown hook will best-effort flush

// Wallet — getWallet(...) returns a handle bound to one business.
// Needs wallet.balance:read (reads) / wallet.transactions:read|write (writes).
// Service ids: use Uengage\PlatformSdk\Wallet\Services (RECHARGE, SMS_CAMPAIGN,
// WHATSAPP_CAMPAIGN, FLASH_DELIVERY, EMAIL, PRISM_AI, WHATSAPP_ALERT, SMS_ALERT).
$wallet = $platform->wallet->getWallet(['id' => 'business:8841']);

$balance = $wallet->getBalance();           // ['balance'=>float, 'balanceMinor'=>int, 'currency'=>[...], 'source'=>..]
$currency = $wallet->getCurrency();          // ['code'=>'INR', 'symbol'=>'₹']

// getBalance() answers with what the business can still SPEND. For a
// merchant on the credit line that is their available credit, and
// 'source' says so ('wallet_balance' | 'credit_line') — so a caller that
// only pre-checks a balance before allowing a charge needs no change.

// On a dashboard, START HERE — wallet balance or credit line?
$o = $wallet->getOverview();   // ['mode' => 'prepaid'|'credit', 'balance' => [...], 'creditLine' => [...]]
// See "Wallet + credit line" below for the rest of the surface.

$txn = $wallet->credit([                     // or ->debit([...])
    'referenceId' => 'order-12345',          // idempotency key
    'amountMinor' => 1180,                    // ₹11.80, in integer minor units of the wallet currency
    'service'     => Services::RECHARGE,      // legacy service_id; see Wallet\Services
    'description' => 'wallet top-up',
    'tags'        => ['source' => 'edge'],
    // 'reversalOf' => '<debit id>',           // on credit → a refund capped by that debit
    // 'isRefund'   => true,                   // on credit → refund:1, uncapped, no link
    // 'paymentId'  => '',                     // on credit; '' is stored verbatim
    // 'allowNegative' => true,                // on debit → permit overdraw
    // 'rto'        => false,                  // on debit
    // Legacy-ledger passthroughs, written as TOP-LEVEL ledger fields:
    // 'taskId' => 'TASK-9912',                // → task_id + transaction_order_id
    // 'units' => 1, 'serviceBaseCost' => 38.5, // serviceBaseCost is MAJOR units
    // 'updatedBy' => 'PetPooja',              // → updated_by; `actor` still records the client
    // 'occurredAt' => '2026-07-01 10:15:00',  // IST; dates the CHARGE, not the write
    //                                         // (backfills/replays) — ≤90 days back, never future
    // 'wallet' => ['parentBusinessId' => '100', 'childBusinessId' => '500'],
    //                                         // names the wallet outright, bypassing routing;
    //                                         // parentBusinessId is asserted, not filtered on
    //                                         // (409 wallet_identity_mismatch if it disagrees)
]);

$page = $wallet->listTransactions(['type' => 'debit', 'limit' => 20]); // keyset-paginated
$one  = $wallet->getTransaction($txn['id']);

$platform->events->publish('order.status_changed', [
    'orderId' => $order->id,
    'orderType' => $order->type,
    'status' => $order->status,
    'deliveryStatus' => $order->deliveryStatus,
    'statusRank' => $rank,
], ['tenantId' => $order->businessId]);

$messageId = $platform->alerts->raise([
    'type'        => 'wallet.low_balance',   // category is derived, never sent
    'title'       => 'Wallet balance low',
    'description' => 'Balance fell below the configured threshold.',
    'tenant'      => ['parentId' => 7175, 'businessId' => 38112], // int or string
    'notify'      => false,                   // optional, default false
    'context'     => ['balanceMinor' => 12050, 'currency' => 'INR'], // optional, flat
]);

$page = $platform->alerts->list([
    'businessId' => 38112,      // at least one of businessId, parentId, type, category, status, userId, notify => true
    'status'     => 'open',     // open | resolved | muted
    'limit'      => 25,         // 1-100
]);
foreach ($page['items'] as $alert) { /* ... */ }
$next = $page['nextCursor'];   // pass back as 'cursor'; null on the last page

// Every alert of one identity, newest lastSeenAt first: current and resolved ones.
$history = $platform->alerts->list(['businessId' => 38112, 'type' => 'wallet.low_balance']);

// Alerts whose latest message had notify on (false = no filter).
$bell = $platform->alerts->list(['notify' => true, 'status' => 'open']);

// Only alerts this dashboard user can see (their id is in the alert's userIds).
// Counts as a filter on its own and combines with the others. Trusted like
// `actor`: your backend decides which user it is acting for.
$mine = $platform->alerts->list(['userId' => $dashboardUser->id, 'status' => 'open']);

$alert = $platform->alerts->get($alertId);

$platform->alerts->setStatus($alertId, [
    'status'  => 'resolved',        // open | resolved | muted
    'comment' => 'Wallet topped up', // 

try {
    $platform->alerts->setStatus($alertId, ['status' => 'open', 'actor' => $user]);
} catch (\Uengage\PlatformSdk\Alerts\AlertsApiException $e) {
    if ($e->getErrorCode() === \Uengage\PlatformSdk\Alerts\AlertsClient::ERROR_NEWER_ALERT_OPEN) {
        $current = $e->getNewerAlertId(); // act on this one instead
    }
}

// 1. Which slots does this screen have? Once per screen, cacheable.
$placements = $platform->upsell->placements([
    'channel'    => 'whitelabel_web',
    'parentId'   => 5,   // the brand
    'businessId' => 6,   // the outlet being ordered from
]);

// 2. What goes in one? Re-ask whenever the cart changes.
$result = $platform->upsell->suggest([
    'channel'   => 'whitelabel_web',
    'placement' => 'cart_recommendation',
    'tenant'    => ['parentId' => 5, 'businessId' => 6],
    'context'   => [
        'cart' => [
            'subtotal' => 500,
            'items'    => [
                [
                    'itemId'      => 101,
                    'qty'         => 1,
                    'unitPrice'   => 400,
                    'itemSlug'    => 'margherita',
                    'sectionName' => 'Pizzas',  // drives category no-repeat
                    'veg'         => 1,         // drives the dietary rule
                ],
            ],
        ],
        'fulfilmentMode' => 'delivery',
        'sessionId'      => session_id(),
    ],
]);

if ($result['items'] === []) {
    return '';  // a normal answer — render nothing at all
}

// 3. Report what happened. Fails open — no try/catch needed: a timeout,
//    an expired token or a 500 is logged and returns ['accepted' => 0].
$platform->upsell->reportEvents([
    'channel'       => 'whitelabel_web',
    'placement'     => 'cart_recommendation',
    'tenant'        => ['parentId' => 5, 'businessId' => 6],
    'sessionId'     => session_id(),
    'configVersion' => $result['meta']['configVersion'],
    'events'        => [
        ['type' => 'shown', 'itemId' => 48346322, 'reasonCode' => 'popular_now'],
        ['type' => 'added', 'itemId' => 48346322],
    ],
]);

$rows = $platform->upsell->adminListPlacements(['parentId' => 5]);

$platform->upsell->adminUpsertPlacement([
    'parentId'   => 5,
    'channel'    => 'whitelabel_web',
    'key'        => 'cart_recommendation',
    'touchpoint' => 'cart',
    'enabled'    => true,
    'display'    => [
        'title'    => 'Complete your order',
        'maxItems' => 6,
        'layout'   => 'grid_2xn_modal',
    ],
]);

$platform->upsell->adminDeletePlacement([
    'parentId' => 5,
    'channel'  => 'whitelabel_web',
    'key'      => 'cart_recommendation',
]);

$o = $wallet->getOverview();

if ($o['mode'] === 'credit') {
    $o['creditLine']['limit']['amountMinor'];   // net of GST
    $o['creditLine']['band'];                   // normal|warning|critical|blocked
} else {
    $o['balance']['balanceMinor'];              // prepaid: the wallet balance
}

$line = $wallet->getCreditLine();   // 404 credit_line_not_found if prepaid
$line['consumed'];                  // net, UNPAID — spans months
$line['available'];                 // limit − consumed
$line['estimatedInvoice']['total']; // exact, from recorded GST — not consumed × 1.18

$wallet->setCreditLimit([                              // wallet.credit:write
    'referenceId' => 'admin:limit:1200:2026-09-02',    // idempotency key
    'limitMinor'  => 10000000,                         // ₹1,00,000, NET of GST; 0 blocks
    'onBehalfOf'  => 'user:4471',                      // ditEvents();                           // limit changes + settlements
$wallet->listCreditEvents(['limit' => 200]);           // the service defaults to 50
$platform->wallet->getCreditUtilisation(['band' => 'warning']);  // cross-merchant

} catch (WalletApiException $e) {
    if ($e->errorCode() === 'credit_limit_reached') {
        $f = $e->creditFigures();
        if ($f['availableMinor'] > 0) {
            // Limit NOT used up — this ONE charge is larger than what is
            // left. A smaller order would go through; do not send them to
            // their account manager.
        }
        // Otherwise the ceiling is reached — possibly from unpaid
        // invoices rather than this month's spend.
    }
}

$platform = Client::create(['serviceId' => '...', 'serviceSecret' => '...']);

$vault = $platform->vault->forTenant(5, 7175);   // brand 5, outlet 7175

$meta = $vault->credentials()->create([
    'type' => 'pg.razorpay',
    'value' => ['key_id' => 'rzp_live_x', 'key_secret' => $secret],
    'referenceId' => 'razorpay-main',          // optional, unique per tenant
    'tags' => ['env' => 'live'],
]);
$meta['masked'];                                // ['key_secret' => 'rzp_******jiu', ...]

$vault->credentials()->get($meta['id']);
$vault->credentials()->getByReference('razorpay-main', 7175);
$page = $vault->credentials()->list(['class' => 'pg', 'tags' => ['env' => 'live'], 'limit' => 50]);
foreach ($vault->credentials()->listAll(['type' => 'pg.razorpay']) as $meta) { /* ... */ }
$vault->credentials()->versions($id);           // masked history
$vault->credentials()->rotate($id, ['key_id' => '...', 'key_secret' => '...']);
$vault->credentials()->setTags($id, ['env' => 'test']);   // replaces the whole set
$vault->credentials()->disable($id);

$cred = $vault->credentials()->decrypt(['id' => $id]);
// or ['referenceId' => 'razorpay-main', 'businessId' => 7175]

$api = new Razorpay\Api($cred['value']['key_id']->reveal(), $cred['value']['key_secret']->reveal());

foreach ($vault->credentials()->decryptAll(['class' => 'pos', '

$token = $platform->auth->mintVaultToken(
    $clientId,
    $clientSecret,
    5,                                        // parentId
    7175,                                     // businessId; null for a brand-wide token
    ['vault.kyc:read', 'vault.kyc:write'],    // null for every allowed vault scope
    900,                                      // expiresIn, 60-14400 s (default 300)
    'user-42'                                 // onBehalfOf, recorded in audit
);
// ['token' => '...', 'expiresIn' => 900, 'parentId' => 5, 'businessId' => 7175,
//  'scope' => 'vault.kyc:read vault.kyc:write']

// Your own route, after authenticating the dashboard user
$token = $platform->auth->mintAlertToken(
    $clientId,
    $clientSecret,
    (string) $user->id,                  // userId, 1-64 printable ASCII
    ['alerts:read'],                     // add 'alerts:write' to allow resolve / mute / reopen; null for every allowed one
    900,                                 // expiresIn, 60-14400 s (default 300)
    'user-42'                            // onBehalfOf, recorded in logs (optional)
);
// ['token' => '...', 'expiresIn' => 900, 'userId' => '101', 'scope' => 'alerts:read']

header('Cache-Control: no-store');
echo json_encode(['token' => $token['token'], 'expiresIn' => $token['expiresIn']]);

$platform = Client::create([
    'authToken' => $vaultToken,
    'getToken' => function () use ($backend) {          // optional
        return $backend->fetchVaultToken();              // string, or ['accessToken' => ..., 'expiresIn' => ...]
    },
]);
$platform->vault->credentials()->list(['class' => 'pg']);
$platform->vault->forTenant(5, 7175);   // optional: throws ConfigException if the token is for another tenant

$docs = $vault->documents();
$doc = $docs->upload([
    'type' => 'kyc.gst_certificate',
    'contentType' => 'application/pdf',
    'filename' => 'gst.pdf',
    'referenceId' => 'gst:2026',
], file_get_contents($path));                     // DocumentMeta, status 'uploaded'
$view = $docs->view($doc['id'], 'KYC review');    // ['url' => presigned GET (5 min), 'expiresAt' => ...]

$platform->vault->types()->register([
    'type' => 'pg.razorpay',
    'mask' => ['prefix' => 4, 'suffix' => 4, 'minLength' => 12],
    'hiddenFields' => ['webhook_secret'],
]);
$platform->vault->types()->list('pg');
bash
composer