E-shop Extension Vendor Integration
This guide shows how to integrate PACKAGE.broker with an e-shop platform to automatically provision Composer tokens when customers purchase extensions.
Use Case Overview
Scenario: You develop PHP extensions (e.g., Magento modules, WordPress plugins) and sell them through an e-shop. When a customer purchases an extension, they need a Composer token to download and install it.
Solution: Use PACKAGE.broker's Management API to automatically create customer-specific tokens when purchase events occur.
Architecture
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ E-shop │ ──▶ │ Webhook/API │ ──▶ │ PACKAGE.broker │
│ Platform │ │ Handler │ │ Management API │
└─────────────┘ └──────────────┘ └─────────────────┘
│ │
│ ▼
│ ┌─────────────────┐
│ │ Customer Token│
│ │ (scoped to │
│ │ vendor/*) │
└──────────────────────────────────▶└─────────────────┘
Customer receives token
Prerequisites
The Management API authentication and customer token provisioning features described in this guide are planned but not yet implemented. See Roadmap for implementation status.
- PACKAGE.broker instance deployed and accessible
- Management API token with
tokens:writepermission - E-shop platform capable of making HTTP requests (webhook support)
Step 1: Create Management API Token
First, create a Management API token in PACKAGE.broker for your e-shop integration:
- Log into PACKAGE.broker dashboard
- Navigate to Settings → API Tokens
- Click Create Management Token
- Select scopes:
tokens:write- Create customer tokenstokens:read- List customer tokenscustomers:read- Access customer information (if available)
- Copy the token - you'll use this in your e-shop integration
Step 2: Configure Repository Sources
Ensure your extension packages are available in PACKAGE.broker:
- Add repository sources for your extension packages
- Configure package filters if needed (e.g.,
your-vendor/*) - Verify packages are synced and available
Step 3: Implement Purchase Webhook
In your e-shop platform, create a webhook handler that triggers on purchase completion:
Example: PHP Webhook Handler
<?php
// webhook-handler.php
$managementApiUrl = 'https://package-broker.example.com/api';
$managementToken = 'your-management-api-token';
// Receive purchase event from e-shop
$purchaseData = json_decode(file_get_contents('php://input'), true);
$customerId = $purchaseData['customer_id'];
$customerEmail = $purchaseData['customer_email'];
$orderId = $purchaseData['order_id'];
$expiresAt = strtotime('+1 year'); // Token expires in 1 year
// Create customer token via Management API
$tokenData = [
'description' => "Customer: {$customerEmail} (Order: {$orderId})",
'permissions' => 'readonly',
'expires_at' => $expiresAt,
'allowed_package_prefixes' => ['your-vendor/'], // Scope to your extensions
'metadata' => [
'customer_id' => $customerId,
'customer_email' => $customerEmail,
'order_id' => $orderId,
],
];
$ch = curl_init("{$managementApiUrl}/tokens");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($tokenData),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $managementToken,
'Content-Type: application/json',
],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 201) {
$tokenResponse = json_decode($response, true);
$composerToken = $tokenResponse['token'];
// Send token to customer via email or store in order
sendTokenToCustomer($customerEmail, $composerToken, $orderId);
} else {
error_log("Failed to create token: {$response}");
}
Example: Node.js Webhook Handler
// webhook-handler.js
const axios = require('axios');
const MANAGEMENT_API_URL = 'https://package-broker.example.com/api';
const MANAGEMENT_TOKEN = 'your-management-api-token';
async function handlePurchase(purchaseData) {
const { customerId, customerEmail, orderId } = purchaseData;
// Calculate expiration (1 year from now)
const expiresAt = Math.floor(Date.now() / 1000) + (365 * 24 * 60 * 60);
try {
const response = await axios.post(
`${MANAGEMENT_API_URL}/tokens`,
{
description: `Customer: ${customerEmail} (Order: ${orderId})`,
permissions: 'readonly',
expires_at: expiresAt,
allowed_package_prefixes: ['your-vendor/'], // Scope to your extensions
metadata: {
customer_id: customerId,
customer_email: customerEmail,
order_id: orderId,
},
},
{
headers: {
'Authorization': `Bearer ${MANAGEMENT_TOKEN}`,
'Content-Type': 'application/json',
},
}
);
const composerToken = response.data.token;
// Send token to customer
await sendTokenToCustomer(customerEmail, composerToken, orderId);
return { success: true, token: composerToken };
} catch (error) {
console.error('Failed to create token:', error.response?.data || error.message);
throw error;
}
}
Step 4: Send Token to Customer
After creating the token, send it to the customer via email or include it in the order confirmation:
Email Template Example
<!DOCTYPE html>
<html>
<head>
<title>Your Extension Access Token</title>
</head>
<body>
<h1>Thank you for your purchase!</h1>
<p>Your Composer access token is ready. Use it to install your extensions:</p>
<h2>Configure Composer</h2>
<p>Add this to your <code>composer.json</code>:</p>
<pre><code>{
"repositories": [
{
"type": "composer",
"url": "https://package-broker.example.com"
}
]
}</code></pre>
<p>Configure authentication:</p>
<pre><code>$ composer config http-basic.package-broker.example.com token YOUR_TOKEN_HERE</code></pre>
<p><strong>Your token:</strong> <code>YOUR_TOKEN_HERE</code></p>
<p><em>This token expires on: EXPIRATION_DATE</em></p>
<p>For detailed installation instructions, visit: https://docs.example.com/install</p>
</body>
</html>
Step 5: Handle Subscription Cancellations
When a customer cancels their subscription or access is revoked, revoke their token:
<?php
// revoke-token.php
$managementApiUrl = 'https://package-broker.example.com/api';
$managementToken = 'your-management-api-token';
$customerId = $_POST['customer_id'];
// Find token by customer ID
$tokens = getCustomerTokens($customerId, $managementApiUrl, $managementToken);
foreach ($tokens as $token) {
// Revoke token
$ch = curl_init("{$managementApiUrl}/tokens/{$token['id']}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $managementToken,
],
]);
curl_exec($ch);
curl_close($ch);
}
function getCustomerTokens($customerId, $apiUrl, $token) {
$ch = curl_init("{$apiUrl}/tokens?customer_id={$customerId}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
],
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
Security Considerations
Token Scoping
Always scope customer tokens to your vendor namespace:
{
"allowed_package_prefixes": ["your-vendor/"]
}
This ensures customers can only access your extensions, not other packages in the instance.
Token Expiration
Set appropriate expiration dates based on your subscription model:
- One-time purchases: Token expires after reasonable period (e.g., 1 year)
- Subscriptions: Token expires when subscription ends
- Renewals: Create new token or extend existing token
Rate Limiting
Configure rate limits on customer tokens to prevent abuse:
{
"rate_limit_max": 1000 // Requests per hour
}
Audit Logging
All token creation and revocation events are logged for compliance and troubleshooting.
API Reference
Create Customer Token
Endpoint: POST /api/tokens
Headers:
Authorization: Bearer <management-api-token>
Content-Type: application/json
Request Body:
{
"description": "Customer: customer@example.com (Order: 12345)",
"permissions": "readonly",
"expires_at": 1735689600,
"allowed_package_prefixes": ["your-vendor/"],
"rate_limit_max": 1000,
"metadata": {
"customer_id": "cust_123",
"customer_email": "customer@example.com",
"order_id": "order_12345"
}
}
Response (201 Created):
{
"id": "token_abc123",
"token": "the-actual-token-value-showed-once",
"description": "Customer: customer@example.com (Order: 12345)",
"permissions": "readonly",
"expires_at": 1735689600,
"created_at": 1704067200
}
List Customer Tokens
Endpoint: GET /api/tokens?customer_id=cust_123
Headers:
Authorization: Bearer <management-api-token>
Response (200 OK):
[
{
"id": "token_abc123",
"description": "Customer: customer@example.com (Order: 12345)",
"permissions": "readonly",
"expires_at": 1735689600,
"created_at": 1704067200,
"last_used_at": 1704153600
}
]
Revoke Token
Endpoint: DELETE /api/tokens/{token_id}
Headers:
Authorization: Bearer <management-api-token>
Response (200 OK):
{
"message": "Token revoked"
}
Troubleshooting
Token Creation Fails
- Verify Management API token has
tokens:writepermission - Check token hasn't expired
- Ensure request format matches API specification
- Review PACKAGE.broker logs for detailed error messages
Customer Can't Access Packages
- Verify token has correct
allowed_package_prefixes - Check package names match the vendor namespace
- Ensure repository sources are synced and active
- Verify token hasn't expired
Rate Limiting Issues
- Check token
rate_limit_maxsetting - Consider increasing limit for legitimate high-volume customers
- Monitor token usage via Management API
Next Steps
- Review API documentation: API Reference
- Understand token management: Token Management
- Check Roadmap for Management API implementation status