2024-07-28 23:05:41 +02:00
< ? php
2024-07-29 15:28:05 +02:00
namespace App\Config\Connector ;
2024-07-28 23:05:41 +02:00
2024-07-29 15:28:05 +02:00
use App\Entity\Domain ;
2024-07-30 18:48:23 +02:00
use Ovh\Api ;
2024-08-06 21:43:37 +02:00
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException ;
2024-08-06 22:11:57 +02:00
use Symfony\Component\HttpKernel\Exception\HttpException ;
2024-07-28 23:05:41 +02:00
2024-07-29 15:28:05 +02:00
readonly class OvhConnector implements ConnectorInterface
2024-07-28 23:05:41 +02:00
{
2024-08-06 00:35:05 +02:00
public const REQUIRED_ROUTES = [
[
'method' => 'GET' ,
'path' => '/order/cart' ,
], [
'method' => 'GET' ,
'path' => '/order/cart/*' ,
],
[
'method' => 'POST' ,
'path' => '/order/cart' ,
],
[
'method' => 'POST' ,
'path' => '/order/cart/*' ,
],
[
'method' => 'DELETE' ,
'path' => '/order/cart/*' ,
],
];
2024-07-29 15:28:05 +02:00
public function __construct ( private array $authData )
{
}
2024-07-29 03:27:55 +02:00
/**
2024-08-02 23:24:52 +02:00
* Order a domain name with the OVH API .
*
* @ throws \Exception
2024-07-29 03:27:55 +02:00
*/
2024-08-06 03:38:00 +02:00
public function orderDomain ( Domain $domain , bool $dryRun = false ) : void
{
2024-08-02 23:24:52 +02:00
if ( ! $domain -> getDeleted ()) {
throw new \Exception ( 'The domain name still appears in the WHOIS database' );
}
2024-07-29 11:54:47 +02:00
2024-07-29 03:27:55 +02:00
$ldhName = $domain -> getLdhName ();
2024-08-02 23:24:52 +02:00
if ( ! $ldhName ) {
throw new \Exception ( 'Domain name cannot be null' );
}
2024-07-29 03:27:55 +02:00
2024-07-29 15:28:05 +02:00
$authData = self :: verifyAuthData ( $this -> authData );
2024-07-29 03:27:55 +02:00
2024-07-30 14:56:08 +02:00
$acceptConditions = $authData [ 'acceptConditions' ];
$ownerLegalAge = $authData [ 'ownerLegalAge' ];
$waiveRetractationPeriod = $authData [ 'waiveRetractationPeriod' ];
2024-07-29 03:27:55 +02:00
$conn = new Api (
2024-07-30 14:56:08 +02:00
$authData [ 'appKey' ],
$authData [ 'appSecret' ],
$authData [ 'apiEndpoint' ],
$authData [ 'consumerKey' ]
2024-07-29 03:27:55 +02:00
);
$cart = $conn -> post ( '/order/cart' , [
2024-08-02 23:24:52 +02:00
'ovhSubsidiary' => $authData [ 'ovhSubsidiary' ],
'description' => 'Domain Watchdog' ,
2024-07-29 03:27:55 +02:00
]);
$cartId = $cart [ 'cartId' ];
$offers = $conn -> get ( " /order/cart/ { $cartId } /domain " , [
2024-08-02 23:24:52 +02:00
'domain' => $ldhName ,
2024-07-29 03:27:55 +02:00
]);
2024-08-02 23:24:52 +02:00
$offer = array_filter ( $offers , fn ( $offer ) => 'create' === $offer [ 'action' ]
&& true === $offer [ 'orderable' ]
&& $offer [ 'pricingMode' ] === $authData [ 'pricingMode' ]
2024-07-29 03:27:55 +02:00
);
2024-07-30 01:01:04 +02:00
if ( empty ( $offer )) {
$conn -> delete ( " /order/cart/ { $cartId } " );
2024-08-02 23:24:52 +02:00
throw new \Exception ( 'Cannot buy this domain name' );
2024-07-30 01:01:04 +02:00
}
2024-07-29 03:27:55 +02:00
$item = $conn -> post ( " /order/cart/ { $cartId } /domain " , [
2024-08-02 23:24:52 +02:00
'domain' => $ldhName ,
'duration' => 'P1Y' ,
2024-07-29 03:27:55 +02:00
]);
$itemId = $item [ 'itemId' ];
2024-08-02 23:24:52 +02:00
// $conn->get("/order/cart/{$cartId}/summary");
2024-07-29 03:27:55 +02:00
$conn -> post ( " /order/cart/ { $cartId } /assign " );
$conn -> get ( " /order/cart/ { $cartId } /item/ { $itemId } /requiredConfiguration " );
$configuration = [
2024-08-02 23:24:52 +02:00
'ACCEPT_CONDITIONS' => $acceptConditions ,
'OWNER_LEGAL_AGE' => $ownerLegalAge ,
2024-07-29 03:27:55 +02:00
];
foreach ( $configuration as $label => $value ) {
$conn -> post ( " /order/cart/ { $cartId } /item/ { $itemId } /configuration " , [
2024-08-02 23:24:52 +02:00
'cartId' => $cartId ,
'itemId' => $itemId ,
'label' => $label ,
'value' => $value ,
2024-07-29 03:27:55 +02:00
]);
}
$conn -> get ( " /order/cart/ { $cartId } /checkout " );
2024-07-29 11:54:47 +02:00
2024-08-02 23:24:52 +02:00
if ( $dryRun ) {
return ;
}
2024-07-29 03:27:55 +02:00
$conn -> post ( " /order/cart/ { $cartId } /checkout " , [
2024-08-02 23:24:52 +02:00
'autoPayWithPreferredPaymentMethod' => true ,
'waiveRetractationPeriod' => $waiveRetractationPeriod ,
2024-07-29 03:27:55 +02:00
]);
}
2024-07-29 15:28:05 +02:00
/**
2024-08-02 23:24:52 +02:00
* @ throws \Exception
2024-07-29 15:28:05 +02:00
*/
public static function verifyAuthData ( array $authData ) : array
{
$appKey = $authData [ 'appKey' ];
$appSecret = $authData [ 'appSecret' ];
$apiEndpoint = $authData [ 'apiEndpoint' ];
$consumerKey = $authData [ 'consumerKey' ];
$ovhSubsidiary = $authData [ 'ovhSubsidiary' ];
$pricingMode = $authData [ 'pricingMode' ];
2024-07-30 14:56:08 +02:00
$acceptConditions = $authData [ 'acceptConditions' ];
$ownerLegalAge = $authData [ 'ownerLegalAge' ];
$waiveRetractationPeriod = $authData [ 'waiveRetractationPeriod' ];
2024-08-02 23:24:52 +02:00
if ( ! is_string ( $appKey ) || empty ( $appKey )
|| ! is_string ( $appSecret ) || empty ( $appSecret )
|| ! is_string ( $consumerKey ) || empty ( $consumerKey )
|| ! is_string ( $apiEndpoint ) || empty ( $apiEndpoint )
|| ! is_string ( $ovhSubsidiary ) || empty ( $ovhSubsidiary )
|| ! is_string ( $pricingMode ) || empty ( $pricingMode )
) {
2024-08-06 21:43:37 +02:00
throw new BadRequestHttpException ( 'Bad authData schema' );
2024-08-02 23:24:52 +02:00
}
2024-07-30 14:09:01 +02:00
2024-08-06 22:11:57 +02:00
if ( true !== $acceptConditions
|| true !== $ownerLegalAge
|| true !== $waiveRetractationPeriod ) {
throw new HttpException ( 451 , 'The user has not given explicit consent' , null , [ 'Link' => '<https://www.ovhcloud.com/fr/terms-and-conditions/contracts/>; rel="blocked-by"' ]);
}
2024-07-30 18:48:23 +02:00
$conn = new Api (
2024-07-30 14:09:01 +02:00
$appKey ,
$appSecret ,
$apiEndpoint ,
$consumerKey
);
$res = $conn -> get ( '/auth/currentCredential' );
2024-08-02 23:24:52 +02:00
if ( null !== $res [ 'expiration' ] && new \DateTime ( $res [ 'expiration' ]) < new \DateTime ()) {
throw new \Exception ( 'These credentials have expired' );
}
2024-07-30 14:09:01 +02:00
$status = $res [ 'status' ];
2024-08-02 23:24:52 +02:00
if ( 'validated' !== $status ) {
throw new \Exception ( " The status of these credentials is not valid ( $status ) " );
}
2024-07-29 15:28:05 +02:00
2024-08-06 00:35:05 +02:00
foreach ( self :: REQUIRED_ROUTES as $requiredRoute ) {
$ok = false ;
foreach ( $res [ 'rules' ] as $allowedRoute ) {
if (
$requiredRoute [ 'method' ] === $allowedRoute [ 'method' ]
&& fnmatch ( $allowedRoute [ 'path' ], $requiredRoute [ 'path' ])
) {
$ok = true ;
}
}
if ( ! $ok ) {
2024-08-06 21:43:37 +02:00
throw new BadRequestHttpException ( 'The credentials provided do not have enough permissions to purchase a domain name.' );
2024-08-06 00:35:05 +02:00
}
}
2024-07-29 15:28:05 +02:00
return [
2024-08-02 23:24:52 +02:00
'appKey' => $appKey ,
'appSecret' => $appSecret ,
'apiEndpoint' => $apiEndpoint ,
'consumerKey' => $consumerKey ,
'ovhSubsidiary' => $ovhSubsidiary ,
'pricingMode' => $pricingMode ,
'acceptConditions' => $acceptConditions ,
'ownerLegalAge' => $ownerLegalAge ,
'waiveRetractationPeriod' => $waiveRetractationPeriod ,
2024-07-29 15:28:05 +02:00
];
}
2024-08-02 23:24:52 +02:00
}