承接 elqora/dgp-sdk 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

elqora/dgp-sdk

Composer 安装命令:

composer require elqora/dgp-sdk

包简介

A framework-neutral protocol for digital-product implementations with minimal framework-neutral dependencies.

README 文档

README

DGP (Digital Product) SDK is a framework-neutral protocol and core toolkit for digital product implementations. It enables developers to implement structured, sandboxed plugins (handlers) that interact with host platforms through stable, strongly-typed contracts.

DGP is a framework-neutral core with minimal external dependencies, integrating elqora/config-kit for configuration management.

📦 Installation

Add the package to your composer.json file:

composer require elqora/dgp-sdk

🚀 Architectural Overview

Handlers (drivers) implement the root DgpDriverContract which aggregates semantic sub-contracts.

DgpDriverContract
├── ManifestContract              # Driver description and capabilities
├── ConfigSchemaContract          # Config schema, validation, & log redaction
├── HealthContract                # Operational health checks
├── BalanceContract               # Provider account balance monitoring
├── ServicesContract             # Service definition and price queries
├── RuntimeContract               # Order lifecycle execution (initialize, start, etc.)
├── OrderDeliveriesContract       # Progress and delivery tracking
└── OrderManagementContract       # Post-order actions and management views

🛠️ Configuration & Schemas

DGP utilizes elqora/config-kit for structured configuration. Implementing handlers declare fields, validate inputs, project safe public properties, and redact logs.

Example Configuration Schema in SMM Handler:

use Elqora\ConfigKit\Schema\ConfigSchema;
use Elqora\ConfigKit\Schema\UiConfigSchema;
use Elqora\ConfigKit\Schema\ConfigField;
use Elqora\ConfigKit\Support\ConfigBag;
use Elqora\ConfigKit\Support\ConfigValidationResult;
use Elqora\Dgp\Contracts\DgpDriverContract;

class SmmTestHandler implements DgpDriverContract
{
    public function configSchema(): ?ConfigSchema
    {
        return new ConfigSchema([
            new ConfigField(name: 'base_url', label: 'Base URL', required: true),
            new ConfigField(name: 'api_key', label: 'API Key', required: true, secret: true),
            new ConfigField(name: 'timeout', label: 'Timeout', type: 'number', required: false, default: 30),
            new ConfigField(name: 'sandbox_user', label: 'Sandbox User', required: false, sandbox: true),
        ]);
    }

    public function uiConfigSchema(): ?UiConfigSchema
    {
        return $this->configSchema()?->toUiConfigSchema();
    }

    public function validateConfig(?ConfigBag $config = null): ConfigValidationResult
    {
        if ($config === null) {
            $res = new ConfigValidationResult(false);
            $res->addError('base_url', 'Base URL is required.');
            $res->addError('api_key', 'API Key is required.');
            return $res;
        }

        $res = new ConfigValidationResult(true);
        if (!$config->filledOption('base_url')) {
            $res->addError('base_url', 'Base URL is required.');
        }
        if (!$config->secret('api_key')) {
            $res->addError('api_key', 'API Key is required.');
        }
        if ($config->isSandbox() && !$config->filledOption('sandbox_user')) {
            $res->addError('sandbox_user', 'Sandbox User is required in sandbox mode.');
        }
        return $res;
    }

    public function publicConfig(?ConfigBag $config = null): array
    {
        // Excludes secrets, exposing options safely to dashboard pages
        return $config?->toPublicArray() ?? [];
    }

    public function redactForLogs(mixed $payload): mixed
    {
        if (!is_array($payload)) {
            return $payload;
        }

        $redacted = $payload;
        foreach (['api_key', 'token', 'password', 'secret'] as $key) {
            if (array_key_exists($key, $redacted)) {
                $redacted[$key] = '[REDACTED]';
            }
        }

        // Handle nested arrays
        foreach ($redacted as $k => $v) {
            if (is_array($v)) {
                $redacted[$k] = $this->redactForLogs($v);
            }
        }
        return $redacted;
    }
    
    // ... rest of DgpDriverContract methods
}

🛒 Order Snapshots & Fallback Resolution

An OrderSnapshot describes what was selected in the frontend checkout. The handler uses this snapshot to execute provisioning.

Fallback Service Lookup:

use Elqora\Dgp\Snapshots\OrderSnapshot;

// A snapshot payload maps fallback relations
$snapshot = OrderSnapshot::fromArray([
    'version' => '1',
    'mode' => 'prod',
    'builtAt' => '2026-07-07T10:30:00.000Z',
    'selection' => ['tag' => 'tag:instagram-likes', 'buttons' => [], 'fields' => []],
    'inputs' => ['form' => [], 'selections' => []],
    'quantity' => 1000,
    'quantitySource' => ['kind' => 'fixed'],
    'min' => 100,
    'max' => 10000,
    'services' => [101, 103],
    'serviceMap' => [],
    'utilities' => [],
    'fallbacks' => [
        'global' => [
            103 => [106, 108],
        ],
        'nodes' => [
            103 => [
                'option:ultra' => [104, 106],
            ]
        ]
    ]
]);

// Resolve fallback replacement IDs with node precedence:
$fallbacks = $snapshot->fallbacksFor(103, 'option:ultra');
// Returns: [104, 106, 108] (Node-specific 104 & 106 first, then global 108, deduplicated)

⏳ Order Lifecycle & Persistence

Order fulfillment transitions from Initialization to Fulfillment through the repository.

  Host (InitializeRequest)
         │
         ▼
  Handler::initialize() ──► Returns Plan (id: null)
         │
         ▼
  Repository::savePlan(orderId, plan) ──► Persists Plan with Host ID
         │
         ▼
  Handler::start(StartRequest) ──► Returns StartResult (id: null)
         │
         ▼
  Repository::saveStartResult(planId, startResult) ──► Persists StartResult with Host ID

1. Initialize Order

use Elqora\Dgp\Configuration\Dgp;
use Elqora\Dgp\Runtime\InitializeRequest;
use Elqora\Dgp\Runtime\RuntimeContext;
use Elqora\Dgp\Runtime\References\HandlerReference;

// Resolve the repository scoped to this handler:
$repository = Dgp::runtimeRepository(HandlerReference::fromKey('smm-test'));

$request = new InitializeRequest(
    orderId: 12345, // Host-managed order ID
    snapshot: $orderSnapshot,
    runtimeContext: new RuntimeContext(
        context: ['requestedBy' => 'customer_admin'],
        meta: ['traceId' => 'tr-9988']
    )
);

$result = $handler->initialize($request);
if ($result->isSuccess()) {
    $plan = $result->value(); // Plan DTO
    
    // Save Plan through Scoped Host Repository
    $persistedPlan = $repository->savePlan(12345, $plan)->value();
}

2. Start Fulfillment

use Elqora\Dgp\Runtime\StartRequest;
use Elqora\Dgp\Runtime\RuntimeContext;

// Start Request references the persisted Plan ID
$startRequest = new StartRequest(
    planId: $persistedPlan->id,
    runtimeContext: new RuntimeContext(context: ['ip' => '127.0.0.1'])
);

$result = $handler->start($startRequest);
if ($result->isSuccess()) {
    $startResult = $result->value(); // StartResult DTO
    
    // Save StartResult through the repository under the parent plan ID
    $persistedStart = $repository->saveStartResult($persistedPlan->id, $startResult)->value();
}

🚥 Next Actions

Handlers guide the host platform or user next steps through strongly-typed next actions.

use Elqora\Dgp\Actions\RedirectAction;
use Elqora\Dgp\Runtime\Plan;

// Define a next action redirecting the customer to complete payment
$nextAction = new RedirectAction(
    url: 'https://gateway.example/pay/invoice-88',
    external: true,
    label: 'Complete Invoice Payment'
);

// Attach it to a Plan or StartResult DTO
$plan = new Plan(
    id: null,
    key: 'plan-payment',
    state: ['pending_payment' => true],
    deliveries: [],
    nextAction: $nextAction
);

Available next action types include:

  • RedirectAction (redirect): External URL or page redirects.
  • ButtonAction (button): UI button triggers.
  • FieldsAction (fields): Dynamic form input submission requests.
  • PopupAction (popup): Modal overlays with custom UI entry points.
  • PopoverAction (popover): Embedded target popover view triggers.
  • InlineAction (inline): Embedded in-page block components.
  • InstructionsAction (instructions): Static or dynamic user-facing guide/text blocks.
  • QrCodeAction (qr_code): QR code payment or scanner prompts.
  • TextAction (text): Custom descriptive or notification text block.
  • CustomAction (custom): Generic action fallback for developer-defined extensions.

🧪 Compliance Checking & Testing

Verify that custom drivers conform to the specifications by running the automated testing suite:

# Run unit & compliance tests
vendor/bin/phpunit

# Perform static analysis
vendor/bin/phpstan analyse

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-08

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固