openeuropa/epoetry-client

为ePoetry服务的PHP客户端。

2.0.0-beta2 2024-02-15 16:30 UTC

README

为ePoetry服务的PHP客户端。

在进行下一步之前,建议阅读官方"简介和术语"部分以及ePoetry文档

典型的翻译请求工作流程概述如下

  • 网络应用程序(例如Drupal网站)通过执行SOAP方法调用,向ePoetry服务创建一个翻译请求。
  • ePoetry服务同步地以响应对象或错误来回答这样的调用。
  • 翻译请求由DGT后台办公室手动处理,这可能需要几天时间。
  • 一旦完成,ePoetry服务通过SOAP方法调用将通知发送给网络应用程序,其中包含请求的翻译。

此项目提供了请求翻译并处理来自ePoetry服务的通知所需的所有代码(SOAP对象、中间件等)。

版本

  • 2.x版本应与PHP > 8.1.26和Symfony >= 5.x一起使用。
  • 1.x版本应与PHP 8.0和Symfony 4.x一起使用。

项目概述

认证

ePoetry服务使用欧盟登录作为可信第三方认证系统。想要使用ePoetry客户端的应用程序需要请求欧盟登录作业账户。

您可以通过访问此页面并联系DGT进行访问设置来从DIGIT请求欧盟登录作业账户。在请求您的作业账户时,请注意:

  • ePoetry测试环境使用欧盟登录接受
  • ePoetry预生产和生产环境使用欧盟登录生产

注意:在请求作业账户时,请确保要求DIGIT在作业账户的“部门”字段中插入您的DG:这是ePoetry服务所必需的。

一旦您获得作业账户,您有两种方式可以验证服务

  • 通过客户端证书登录
  • 通过OpenID Connect

请注意:上述两种方法都需要将额外的依赖项添加到您的项目中,请查阅以下相应部分以获取更多信息。

通过客户端证书登录进行认证

在欧盟登录中,运行ePoetry库的应用程序(例如,一个Drupal网站)可以通过一种特殊类型的用户账户表示,称为“作业账户”。

为了设置此认证方法,您需要向欧盟登录请求作业账户,与运行ePoetry库的网站相关联。您可以要求您的直接经理或Scrum Master发起请求作业账户的请求。有关更多信息,请查看此页面

在获得欧盟登录作业账户后,您需要将其传达给DGT,以便他们可以在ePoetry服务上完成设置。有关此程序的信息,请查看此页面

一旦您获得作业账户,您需要请求客户端证书:您也可以向Scrum Master提出此请求。在验收环境中,您可以在https://webgate.acceptance.ec.europa.eu/cas/selfCertWeb上自行请求。

一旦您收到实际的客户端证书文件(以.p12格式)及其密码,您就可以配置认证插件服务。以下是一个可能的设置示例

  client_cert_authentication:
    class: \OpenEuropa\EPoetry\Authentication\ClientCertificate\ClientCertificateAuthentication
    arguments:
      $serviceUrl: "https://www.cc.cec/epoetry/webservices/dgtService"
      $certFilepath: "/path/to/certs/j123abc.p12"
      $certPassword: "password"
      $euLoginBasePath: "https://ecas.cc.cec.eu.int:7003"
      $logger: "..." # A PSR compatible logger implementation.

对于ePoetry验收,请使用以下

      $serviceUrl: "https://www.acceptance.cc.cec/epoetry/webservices/dgtService"

请注意:此认证方法需要以下依赖项,如composer.json中“建议”部分指定

    "suggest": {
        "symfony/http-client": "Require this in your project if you use the client certificate authentication plugin."
    },

通过OpenID Connect进行认证

您可以使用OpenIDAuthentication插件通过OpenID Connect进行认证。

此认证插件需要设置以下参数

为了获取此信息,您需要按照 这些说明 将您的应用程序注册为OpenID Connect客户端。

以下是一个客户端元数据的示例

{
  "application_type" : "web",
  "client_id" : "...",
  "client_id_issued_at" : 1656329142,
  "client_name" : "[Name of your application]",
  "client_secret" : "...",
  "client_secret_expires_at" : 0,
  "client_type" : "confidential",
  "contacts" : [ "[Email of the EC official issuing the request]" ],
  "grant_types" : [ "client_credentials" ],
  "id_token_signed_response_alg" : "PS512",
  "job_account" : "[Your EU Login Job Account ID]",
  "oauth_application_type" : "web_application",
  "redirect_uris" : [ "[Your application's URL]" ],
  "registration_access_token" : "...",
  "registration_client_uri" : "...",
  "response_types" : [ ],
  "scope" : "openid",
  "subject_type" : "public",
  "token_endpoint_auth_method" : "client_secret_jwt"
} 

使用上述值作为参考来配置您自己的客户端元数据。请确保您设置如下

...
  "application_type" : "web",
  "grant_types" : [ "client_credentials" ],
  "id_token_signed_response_alg" : "PS512",
  "oauth_application_type" : "web_application",
  "token_endpoint_auth_method" : "client_secret_jwt"
...

一旦获得此类信息,请将其存储在应用程序可访问的JSON文件中,因为这将是配置身份验证服务所需的。以下是一个可能的配置示例

  openid_authentication:
    class: \OpenEuropa\EPoetry\Authentication\OpenID\OpenIDAuthentication
    arguments:
      $wellKnownUrl: "https://ecas.ec.europa.eu/cas/oauth2/.well-known/openid-configuration"
      $clientMetadataFilepath: "/path/to/client-metadata.json"
      $serviceUrl: "https://www.cc.cec/epoetry/webservices/dgtService"
      $tokenEndpoint: "https://ecas.ec.europa.eu/cas/oauth2/token"
      $logger: "..." # A PSR compatible logger implementation.

对于ePoetry验收,请使用以下

      $serviceUrl: "https://www.acceptance.cc.cec/epoetry/webservices/dgtService"

请注意:此认证方法需要以下依赖项,如composer.json中“建议”部分指定

    "suggest": {
        "facile-it/php-openid-client": "Require this in your project if you use the OpenID Connect authentication plugin.",
        "web-token/jwt-signature-algorithm-hmac": "Require this in your project if you use the OpenID Connect authentication plugin.",
    },

ePoetry通知

ePoetry服务向网站发送消息,包含关于翻译请求状态更改、翻译内容等信息。

为了使您的应用程序能够接收和处理ePoetry通知,您需要公开两个端点

  • 一个向ePoetry服务提供网站的WSDL。
  • 一个处理来自ePoetry服务的POST入站请求。

NotificationServerFactory 可用于实现这两个端点。

NotificationServerFactory 服务需要以下依赖项

  • $callback:处理入站POST请求的网站的端点。
  • $eventDispatcher:一个Symfony事件调度器实例。
  • $logger:一个PSR兼容的日志实现。
  • $serializer:库的 Serializer类 的实例。
  • $ticketValidation:可选的,票据验证服务 的实例。

以下是一个实现这两个端点的Symfony控制器的示例

<?php

namespace App\Controller;

use Http\Discovery\Psr17Factory;
use OpenEuropa\EPoetry\NotificationServerFactory;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;

class TranslationController extends AbstractController
{
    private NotificationServerFactory $factory;

    /**
     * @param \OpenEuropa\EPoetry\NotificationServerFactory $factory
     */
    public function __construct(NotificationServerFactory $factory) {
        $this->factory = $factory;
    }

    /**
     * @Route("/translation", name="translation_get", methods={"GET"})
     */
    public function getWsdl(Request $request): Response
    {
        $response = new Response($this->factory->getWsdl());
        $response->headers->set('Content-Type', 'application/xml');
        return $response;
    }

    /**
     * @Route("/translation", name="translation_post", methods={"POST"})
     */
    public function handleNotification(Request $request): Response
    {
        $psr17Factory = new Psr17Factory();
        $psrHttpFactory = new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
        $response = $this->factory->handle($psrHttpFactory->createRequest($request));
        return (new HttpFoundationFactory())->createResponse($response);
    }
}

在上面的示例中,NotificationServerFactory$callback 将是:https://my-site.com/translation

处理入站通知时,NotificationServerFactory 触发以下Symfony事件

有关ePoetry通知的更多信息,请参阅官方文档

验证传入通知

传入的通知需要使用欧盟登录票据验证服务进行验证。为此,该库提供了EuLoginTicketValidation服务,该服务在构建NotificationServerFactory时需要注入。

EuLoginTicketValidation服务需要以下依赖项

  • $callbackUrl:处理请求的NotificationServerFactory所在的网站的URL。
  • $euLoginBasePath:欧盟登录的公共基本URL。对于ePoetry生产和验收,应将其设置为https://ecas.ec.europa.eu
  • $jobAccount:ePoetry作业帐户。应将其设置为j97brfy。请注意,这可能在将来发生变化,请确保您查阅以下文档页面
  • $requestFactory:PSR兼容的HTTP请求工厂,请查看此列表以获取可能的候选者。
  • $httpClient:PSR兼容的HTTP客户端,请查看此列表以获取可能的候选者。
  • $logger:一个PSR兼容的日志实现。

以下是一个可能的设置示例

  eu_login_ticket_validation:
    class: \OpenEuropa\EPoetry\TicketValidation\EuLogin\EuLoginTicketValidation
    arguments:
      $callbackUrl: "https://my-site.europa.eu/my/epoetry/endpoint"
      $euLoginBasePath: "https://ecas.ec.europa.eu"
      $jobAccount: "j97brfy"
      $requestFactory: "..." # A PSR compatible HTTP request factory.
      $httpClient: "..." # PSR compatible HTTP client.
      $logger: "..." # A PSR compatible logger implementation

生成SOAP相关类

该库使用PHP SOAP客户端项目构建,该项目可以自动生成与SOAP相关的PHP类,前提是提供WSDL/XSD文件对。

要(重新)生成代码,运行以下命令:

./vendor/bin/run generate:request
./vendor/bin/run generate:notification
./vendor/bin/run generate:authentication

或者,简单地运行以下命令,它将执行上述三个命令:

./vendor/bin/run generate

注意,方法\OpenEuropa\EPoetry\Notification\Type\RequestReference::getReference()是手动添加的,它不会自动生成:请确保您使用本地Git历史记录恢复它。

通过命令行与服务交互

该库提供以下便利的CLI命令来与ePoetry服务交互。您可以通过设置通常的-v-vv-vvv标志来设置命令的详细程度。如果您想设置最大详细程度,请将EPOETRY_CONSOLE_DEBUG=1设置在.env中。您还可以将.env复制到.env.local中并覆盖那里的值:.env.local默认情况下由git忽略。

开发人员注意: Symfony在./var下存储命令容器的编译版本:如果您修改了以下内容,请确保删除此目录:./config/console/services.yml

  • 修改./config/console/services.yml的内容
  • 添加或更改命令类

从EU Login获取认证令牌

运行

$ ./bin/epoetry authentication:get-ticket

这将使用在Symfony Console容器中设置的认证方法检索认证票据。如果成功,票据将被打印出来

$ ./bin/epoetry authentication:get-ticket
ST-1785405-EQb6PwLuh9PKnpLk6hiGHAD...

默认的认证方法是客户端证书登录,您可以在这里更改它为OpenID Connect插件,通过设置以下./config/console/services.yml中的替代值:

OpenEuropa\EPoetry\Authentication\AuthenticationInterface: "@openid_authentication"

客户端证书方法需要一个指向客户端证书文件的路径,格式为.p12,以及其密码。这两个参数可以通过以下环境变量设置:

EPOETRY_CONSOLE_CLIENT_CERT_SERVICE_URL=https://www.test.cc.cec/epoetry/webservices/dgtService
EPOETRY_CONSOLE_CLIENT_CERT_PATH=/path/to/certs/j905dyi.p12
EPOETRY_CONSOLE_CLIENT_CERT_PASSWORD=password

OpenID Connect方法需要一个有效的客户端元数据JSON文件,该文件位于本地。您可以通过更改以下环境变量来控制该值以及其他认证设置:

EPOETRY_CONSOLE_OPENID_AUTH_CLIENT_METADATA=/path/to/client-metadata.json
EPOETRY_CONSOLE_OPENID_WELL_KNOWN_URL=https://ecas.acceptance.ec.europa.eu/cas/oauth2/.well-known/openid-configuration
EPOETRY_CONSOLE_OPENID_SERVICE_URL=https://www.test.cc.cec/epoetry/webservices/dgtService
EPOETRY_CONSOLE_OPENID_TOKEN_ENDPOINT=https://ecas.acceptance.ec.europa.eu/cas/oauth2/token

通过评估PHP代码执行请求

运行

$ ./bin/epoetry request:evaluate /path/to/request.php

PHP文件/path/to/request.php应该返回一个具有以下签名的函数:

<?php

use OpenEuropa\EPoetry\RequestClientFactory;
use OpenEuropa\EPoetry\Console\Command\EvaluateRequestReturn;

return function(): EvaluateRequestReturn {
    // Build $object here...
    $request = (new CreateLinguisticRequest())
        ->setRequestDetails($requestDetails)
        ->setApplicationName('FOO')
        ->setTemplateName('WEBTRA');
    return new EvaluateRequestReturn($request, 'createLinguisticRequest');
};

该命令将需要上面的文件并使用返回的值对ePoetry服务执行实际请求。您可以通过以下环境变量设置所需的服务URL:

EPOETRY_CONSOLE_SERVICE_URL=https://webgate.acceptance.ec.europa.eu/epoetrytst/epoetry/webservices/dgtService

如果成功,该命令将以JSON格式返回ePoetry响应

$ ./bin/epoetry request:evaluate /path/to/request.php
Request:
{
    "requestDetails": {
        "title": "Content title",
        "internalReference": "Translation request 1",
        "requestedDeadline": "2121-07-06T11:51:00+01:00",
        "sensitive": false,
        ...
}
Response:
{
    "return": {
        "requestReference": {
            "dossier": {
                "requesterCode": "COMM",
                "number": 25,
                "year": 2023
            },
            "productType": "TRA",
            "part": 0,
            "version": 0
        },
        "requestDetails": {
            "title": "Content title",
            "workflowCode": "WEB",
            ...
}

使用-vvv运行命令将显示原始HTTP请求和响应。

从ePoetry服务接收通知

运行

$ ./bin/epoetry notification:start-listener

这将启动一个服务,在端口8088上监听传入的消息。

所有POST传入请求都将保存在.sink/notifications中,无论它们是否为实际的ePoetry通知。此外,将处理ePoetry通知,服务响应将打印到控制台。

对您的服务发出的任何GET请求将打印出服务WSDL,其中包含回调URL。当在公开可访问的服务器上运行时,您可能想要通过设置以下ENV变量来更改回调URL:

EPOETRY_CONSOLE_CALLBACK_URL=https://my-host.com:8088

请记住删除./var目录以强制重新构建Symfony命令容器。

您可以按以下方式覆盖命令的默认参数:

$ ./bin/epoetry notification:start-listener --port=80 --save-to=/path/to/folder

如果您希望返回错误,请使用-e标志启动服务。

$ ./bin/epoetry notification:start-listener -e

建议始终使用-vvv以获取完整的详细输出。

在European Commission Cloud9环境中使用

在Cloud9环境中使用控制台命令时,添加一个包含以下内容的docker-compose.override.yml文件:

version: "2"
services:
  php:
    image: registry.fpfis.eu/fpfis/httpd-php:8.1-dev
    working_dir: /var/www/html

然后登录到php容器并运行:

apt update
apt install php-bcmath -y

在官方Docker镜像支持所需的PHP扩展之前,这是必要的。

在欧洲委员会网站上使用

ePoetry客户端库需要ext-bcmath PHP扩展,而这个扩展并不一定在所有用于欧洲委员会基础设施的镜像上已启用。

当在网站上使用此库时,请确保通过在网站的.opts.yml文件中指定它来安装ext-bcmath扩展,如下所示:

extra_pkgs:
- ext-bcmath

有关更多信息,请参阅管道配置文档

已知问题

ePoetry架构中不正确地指定了updateCallbackUrl方法,因此我们已在这个PR中对本地架构进行了修补。如果需要,记得在更新WSDL/XSD文件后重新应用此类更改。