cube43/ebics-client

PHP 库,用于通过 EBICS 协议与银行通信。

0.11.0 2023-12-12 09:33 UTC

README

PHP 库,用于通过 EBICS 协议与银行通信。

Build Status Latest Stable Version Total Downloads License

许可证

cube43/ebics-client 基于 MIT 许可证授权,详情请见 LICENSE 文件。

注意

此库是对 andrew-svirin/ebics-client-php 的重构,以支持多个协议版本、单元测试和端到端测试。

支持的 EBICS 协议版本

  • 2.4
  • 2.5
  • 3.0

支持的命令

  • INI
  • HIA
  • HPB
  • FDL

此库仅与 X509 认证的通信一起工作。

安装

composer require cube43/ebics-client

初始化客户端

您需要从您的银行获取以下信息

  • 主机 ID
  • 主机 URL
  • 合作伙伴 ID
  • 用户 ID
  • 协议版本
$bankInfo            = new \Cube43\Component\Ebics\BankInfo($HOST_ID, $HOST_URL, \Cube43\Component\Ebics\Version::v24(), $PARTNER_ID, $USER_ID);
$keyring             = new \Cube43\Component\Ebics\KeyRing('myPassword');
$x509OptionGenerator = new \Cube43\Component\Ebics\X509\DefaultX509OptionGenerator();

注意 : $HOST_ID, $HOST_URL, $PARTNER_ID, $USER_ID 和版本是由您和您的银行决定的。

使用方法

在执行您想要达成的操作(例如 FDL 调用)之前,您必须生成密钥并将其与服务器(INI、HIA 和 HPB 命令)通信。

INI 命令

INI 命令将生成类型 A 的证书并发送到 EBICS 服务器。在发出此请求后,您必须保存带有新生成证书的密钥环,因为以后将使用它。

$keyring = (new \Cube43\Component\Ebics\Command\INICommand())->__invoke($bankInfo, $keyring, $x509OptionGenerator);
// save keyring

HIA 命令

HIA 命令将生成类型 e 和 x 的证书并发送到 EBICS 服务器。在发出此请求后,您必须保存带有新生成证书的密钥环,因为以后将使用它。

$keyring = (new \Cube43\Component\Ebics\Command\HIACommand())->__invoke($bankInfo, $keyring, $x509OptionGenerator);
// save keyring

HPB 命令

HPB 命令将从 EBICS 服务器检索类型 e 和 x 的证书。在发出此请求后,您必须保存带有新检索证书的密钥环,因为以后将使用它。

$keyring = (new \Cube43\Component\Ebics\Command\HPBCommand())->__invoke($bankInfo, $keyring);
// save keyring

一旦运行了 INI、HIA 和 HPB,您就可以使用 EBICS 协议了。

FDL 命令

<?php

$response = (new \Cube43\Component\Ebics\Command\FDLCommand())->__invoke($bankInfo, $keyring, new FDLParams($fdlFromBank, 'FR', new DateTimeImmutable(), new DateTimeImmutable()));

if ($response->data === null) {
    var_dump('no file');
} else {
    var_dump('file : ', $response->data);
}
    
$response = (new \Cube43\Component\Ebics\Command\FDLAknowledgementCommand())->__invoke($response);

保存密钥环

<?php

$keyring = new \Cube43\Component\Ebics\KeyRing('myPassword');
$keyringAsArray = $keyring->jsonSerialize(); 
$keyringAsJson  = json_encode($keyring); 

// put $keyringAsArray or $keyringAsJson in db, file etc...

唤醒密钥环

$keyring = \Cube43\Component\Ebics\KeyRing::fromArray($keyringAsArray, 'myPassword');

重要信息

本网站提供了一个 EBICS 服务器测试环境:[https://software.elcimai.com/efs/accueil-qualif.jsp](https://software.elcimai.com/efs/accueil-qualif.jsp)

生成证书和获取信件的完整示例

<?php

use Cube43\Component\Ebics\BankInfo;
use Cube43\Component\Ebics\KeyRing;
use Cube43\Component\Ebics\Command\INICommand;
use Cube43\Component\Ebics\Command\HIACommand;
use Cube43\Component\Ebics\Command\HPBCommand;
use Cube43\Component\Ebics\X509\DefaultX509OptionGenerator;
use Cube43\Component\Ebics\Version;

require 'vendor/autoload';

$bank                = new BankInfo('EBIXQUAL', 'https://server-ebics.webank.fr:28103/WbkPortalFileTransfert/EbicsProtocol', Version::v24(), $partnerId, $userId);
$keyRing             = KeyRing::fromFile('keyring.json', 'myPassword');
$x509OptionGenerator = new DefaultX509OptionGenerator();


if (!$keyRing->hasUserCertificatA()) {
    $keyring = (new INICommand())->__invoke($bank, $keyRing, $x509OptionGenerator);
    file_put_contents('keyring.json', json_encode($keyring));
}

if (!$keyRing->hasUserCertificateEAndX()) {
    $keyring = (new HIACommand())->__invoke($bank, KeyRing::fromFile('keyring.json', 'myPassword'), $x509OptionGenerator);
    file_put_contents('keyring.json', json_encode($keyring));
}

if (!$keyRing->hasBankCertificate()) {
    $keyring = (new HPBCommand())->__invoke($bank, KeyRing::fromFile('keyring.json', 'myPassword'));
    file_put_contents('keyring.json', json_encode($keyring));
}


echo '
<table class="table table-borderless">
    <tbody>
        <tr>
            <td>User ID</td>
            <td>'.$bank->getUserId().'</td>
        </tr>
        <tr>
            <td>PartnerID</td>
            <td>'.$bank->getPartnerId().'</td>
        </tr>
        <tr>
            <td>Hash '.$keyring->getUserCertificateA()->getCertificatType()->toString().' ('.$keyring->getUserCertificateA()->getCertificatType()->getHash().')</td>
            <td>
                <div class="digest">'.nl2br($keyring->getUserCertificateA()->getCertificatX509()->digest()).'</div>
            </td>
        </tr>
        <tr>
            <td>Hash '.$keyring->getUserCertificateE()->getCertificatType()->toString().' ('.$keyring->getUserCertificateE()->getCertificatType()->getHash().')</td>
            <td>
                <div class="digest">'.nl2br($keyring->getUserCertificateE()->getCertificatX509()->digest()).'</div>
            </td>
        </tr>
        <tr>
            <td>Hash '.$keyring->getUserCertificateX()->getCertificatType()->toString().' ('.$keyring->getUserCertificateX()->getCertificatType()->getHash().')</td>
            <td>
                <div class="digest">'.nl2br($keyring->getUserCertificateX()->getCertificatX509()->digest()).'</div>
            </td>
        </tr>
    </tbody>
</table>
';

使用 Doctrine2 而不是文件进行工作

/**
 * @ORM\Table(name="ebics")
 * @ORM\Entity()
 *
 * @Type()
 */
class Ebics
{
    /**
     * @ORM\Column(type="uuid")
     * @ORM\Id
     */
    private UuidInterface $id;
    /** @ORM\Column(type="string") */
    private string $hostUrl;
    /** @ORM\Column(type="string") */
    private string $partnerId;
    /** @ORM\Column(type="string") */
    private string $userId;
    /** @ORM\Column(type="string") */
    private string $hostId;
    /** @ORM\Column(type="json") */
    private array $certificat;

    public function __construct(
        string $hostUrl,
        string $hostId,
        string $partnerId,
        string $userId
    ) {
        $this->id           = Uuid::uuiv4();
        $this->hostUrl      = $hostUrl;
        $this->partnerId    = $partnerId;
        $this->userId       = $userId;
        $this->hostId       = $hostId;
        $this->certificat   = [];
    }

    public function getKeyring(): KeyRing
    {
        return KeyRing::fromArray($this->getCertificat(), (string) getenv('PASSWORD'));
    }

    public function getBank(): Bank
    {
        return new Bank($this->getHostId(), $this->getHostUrl(), Version::v24(), $this->getPartnerId(), $this->getUserId());
    }
    
    public function setCertificat(KeyRing $keyRing): void
    {
        $this->certificat = json_decode(json_encode($keyRing->jsonSerialize()), true);
    }

}



$ebicsEntity         = new Ebics('EBIXQUAL', 'https://server-ebics.webank.fr:28103/WbkPortalFileTransfert/EbicsProtocol', Version::v24(), $partnerId, $userId);
$x509OptionGenerator = new DefaultX509OptionGenerator();


if (!$ebicsEntity->getKeyring()->hasUserCertificatA()) {
    $ebicsEntity->setCertificat((new INICommand())->__invoke($ebicsEntity->getBank(), $ebicsEntity->getKeyring(), $x509OptionGenerator));
}

if (!$ebicsEntity->getKeyring()->hasUserCertificateEAndX()) {
    $ebicsEntity->setCertificat((new HIACommand())->__invoke($ebicsEntity->getBank(), $ebicsEntity->getKeyring(), $x509OptionGenerator));
}

if (!$ebicsEntity->getKeyring()->hasBankCertificate()) {
    $ebicsEntity->setCertificat((new HPBCommand())->__invoke($ebicsEntity->getBank(), $ebicsEntity->getKeyring()));
}

``