Skip to content

Commit

Permalink
Merge pull request #3 from shellrent/feature/1.1.0
Browse files Browse the repository at this point in the history
Mutual authentication support and new SCT-INST Payment simulation API
  • Loading branch information
svdigital-development authored Mar 31, 2021
2 parents 8906a03 + d7a1620 commit 2870b0d
Show file tree
Hide file tree
Showing 15 changed files with 377 additions and 168 deletions.
184 changes: 152 additions & 32 deletions src/IntesaSanPaoloClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@

use DateTime;
use DateInterval;
use Shellrent\OpenBanking\Models\PaymentSimulated;
use Shellrent\OpenBanking\Models\PaymentStatus;
use stdClass;

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\RequestOptions;
use GuzzleHttp\Exception\ClientException;

use Shellrent\OpenBanking\Exceptions\Exception;
use Shellrent\OpenBanking\Exceptions\HttpException;
use Shellrent\OpenBanking\Models\Balance;
use Shellrent\OpenBanking\Models\Collections\Transactions;
use Shellrent\OpenBanking\Models\Collections\PaymentInfos;
use Shellrent\OpenBanking\Models\PaymentExecution;
use Shellrent\OpenBanking\Models\PaymentExecuted;

use Shellrent\OpenBanking\Exceptions\Exception;
use Shellrent\OpenBanking\Exceptions\HttpException;


class IntesaSanPaoloClient {
/**
Expand All @@ -33,7 +32,7 @@ class IntesaSanPaoloClient {
* Environment
* @var bool
*/
private $Live = false;
private $Live;

/**
* App Client ID
Expand All @@ -59,12 +58,6 @@ class IntesaSanPaoloClient {
*/
private $BaseUri;

/**
* URI for oAuth2
* @var string
*/
private $Oauth2Url;

/**
* oAuth2 Bearer
* @var string
Expand All @@ -79,10 +72,16 @@ class IntesaSanPaoloClient {
private $Oauth2BearerExpiry;

/**
* Base URI for API requests
* @var string
* Mutual Authentication Certificate paths
* @var string[]|string|null
*/
private $ApiBaseUri;
private $MutualAuthenticationCertificate;

/**
* Mutual Authentication private key paths
* @var string[]|string|null
*/
private $MutualAuthenticationPrivateKey;



Expand All @@ -100,20 +99,30 @@ public function __construct( string $clientId, string $clientSecret, string $iba
$this->Iban = $iban;

$this->BaseUri = 'https://external-api.intesasanpaolo.com';
$this->ApiBaseUri = sprintf( '%s/%s/v1', $this->BaseUri, $this->Live ? 'live' : 'sandbox' );
$this->Oauth2Url = sprintf( '%s/auth/oauth/v2/token', $this->BaseUri );

$this->HttpClient = new Client();
}


/**
* Builds the base URI for API requests
* @return string
*/
private function getApiBaseUri(): string {
$live = $this->Live ? 'live' : 'sandbox';
$mutualAuthentication = $this->MutualAuthenticationCertificate ? 'twa/' : '';

return sprintf( '%s/%s%s/v1', $this->BaseUri, $mutualAuthentication, $live );
}


/**
* Login: oAuth2 request
*
* @throws Exception
*/
private function login() {
$response = $this->HttpClient->request( 'POST', $this->Oauth2Url, [
$response = $this->HttpClient->request( 'POST', sprintf( '%s/auth/oauth/v2/token', $this->BaseUri ), [
RequestOptions::HEADERS => [
'Host' => 'external-api.intesasanpaolo.com',
'Content-Type' => 'application/x-www-form-urlencoded',
Expand Down Expand Up @@ -142,26 +151,43 @@ private function login() {
* @param string $method
* @param string $url
* @param array $queryParameters
* @param string $body
* @param array|object $jsonBody
* @param string $plainBody
*
* @return stdClass
*/
private function request( string $method, string $url, array $queryParameters = [], string $body = null ): ?stdClass {
private function request( string $method, string $url, array $queryParameters = [], $jsonBody = null, string $plainBody = null ): ?stdClass {
$now = new DateTime();

try {
if( empty( $this->Oauth2Bearer ) or ( $this->Oauth2BearerExpiry < $now ) ) {
$this->login();
}

$response = $this->HttpClient->request( $method, $url, [
$requestParams = [
RequestOptions::HEADERS => [
'apikey' => $this->ClientId,
'Authorization' => sprintf( 'Bearer %s', $this->Oauth2Bearer ),
],
RequestOptions::QUERY => $queryParameters,
RequestOptions::BODY => $body,
]);
];

if( !empty( $jsonBody ) ) {
$requestParams[RequestOptions::JSON] = $jsonBody;

} elseif( !empty( $plainBody ) ) {
$requestParams[RequestOptions::BODY] = $plainBody;
}

if( $this->MutualAuthenticationCertificate ) {
$requestParams[RequestOptions::CERT] = $this->MutualAuthenticationCertificate;

if( $this->MutualAuthenticationPrivateKey ) {
$requestParams[RequestOptions::SSL_KEY] = $this->MutualAuthenticationPrivateKey;
}
}

$response = $this->HttpClient->request( $method, $url, $requestParams );

} catch( ClientException $ex ) {
throw new HttpException( $ex );
Expand Down Expand Up @@ -216,6 +242,56 @@ private function buildTransactions( string $url, array $params = [] ): Transacti
}


/**
* Enables the use of mutual authentication with an SSL Certificate
* @param string $certificatePath Path to the SSL Certificate; must be in PEM format or PKCS#12-encoded format if Guzzle is 7.3.0+
* @param string|null $certificatePassphrase String containing the passphrase for the Certificate
* @param string|null $privateKeyPath Path to the Private Key file
* @param string|null $privateKeyPassphrase String containing the passphrase for the Private Key
* @return $this
*/
public function enableMutualAuthentication( string $certificatePath, ?string $certificatePassphrase = null, string $privateKeyPath = null, string $privateKeyPassphrase = null ): self {
if( !empty( $certificatePassphrase ) ) {
$this->MutualAuthenticationCertificate = [
$certificatePath,
$certificatePassphrase,
];

} else {
$this->MutualAuthenticationCertificate = $certificatePath;
}

if( !empty( $privateKeyPath ) ) {
if( !empty( $privateKeyPassphrase ) ) {
$this->MutualAuthenticationPrivateKey = [
$privateKeyPath,
$privateKeyPassphrase,
];

} else {
$this->MutualAuthenticationPrivateKey = $privateKeyPath;
}

} else {
$this->MutualAuthenticationPrivateKey = null;
}

return $this;
}


/**
* Disables the use of mutual authentication with an SSL Certificate
* @return $this
*/
public function disableMutualAuthentication(): self {
$this->MutualAuthenticationCertificate = null;
$this->MutualAuthenticationPrivateKey = null;

return $this;
}


/**
* Get the current Balance
*
Expand All @@ -231,7 +307,7 @@ public function getBalance( DateTime $date ): Balance {
$params['date'] = $date->format( 'Ymd' );
}

$balanceResponse = $this->request( 'GET', sprintf( '%s/accounts/%s/balance', $this->ApiBaseUri, $this->Iban ), $params );
$balanceResponse = $this->request( 'GET', sprintf( '%s/accounts/%s/balance', $this->getApiBaseUri(), $this->Iban ), $params );

return new Balance( $balanceResponse );
}
Expand All @@ -245,7 +321,7 @@ public function getBalance( DateTime $date ): Balance {
* @return Transactions
*/
public function getTransactions( DateTime $date ): Transactions {
return $this->buildTransactions( sprintf( '%s/accounts/%s/transactions', $this->ApiBaseUri, $this->Iban ), [
return $this->buildTransactions( sprintf( '%s/accounts/%s/transactions', $this->getApiBaseUri(), $this->Iban ), [
'date' => $date->format( 'Ymd' ),
]);
}
Expand All @@ -257,7 +333,32 @@ public function getTransactions( DateTime $date ): Transactions {
* @return Transactions
*/
public function getTodayTransactions(): Transactions {
return $this->buildTransactions( sprintf( '%s/accounts/%s/transactions/today', $this->ApiBaseUri, $this->Iban ) );
return $this->buildTransactions( sprintf( '%s/accounts/%s/transactions/today', $this->getApiBaseUri(), $this->Iban ) );
}


/**
* Simulates an Instant Payment (SCT-Instant-Simulation)
*
* @param PaymentExecution $payment
*
* @return PaymentSimulated
*/
public function simulateInstantPayment( PaymentExecution $payment ): PaymentSimulated {
$data = [
'debtorName' => $payment->getDebtorName(),
'debtorIBAN' => $payment->getDebtorIban(),
'creditorName' => $payment->getCreditorName(),
'creditorIBAN' => $payment->getCreditorIban(),
'amount' => $payment->getAmount(),
'paymentInformation' => $payment->getPaymentInformation(),
'endToEndId' => empty( $payment->getEndToEndId() ) ? '' : $payment->getEndToEndId(),
'siaCode' => empty( $payment->getSiaCode() ) ? '' : $payment->getSiaCode(),
];

$paymentSimulationResponse = $this->request( 'POST', sprintf( '%s/payments/sct/instant/simulation', $this->getApiBaseUri() ), [], $data );

return new PaymentSimulated( $paymentSimulationResponse );
}


Expand All @@ -278,23 +379,42 @@ public function createInstantPayment( PaymentExecution $payment ): PaymentExecut
'paymentInformation' => $payment->getPaymentInformation(),
'endToEndId' => $payment->getEndToEndId(),
'siaCode' => $payment->getSiaCode(),
'simulationId' => $payment->getSimulationId(),
];

if( $payment->getResubmit() ) {
$data['resubmit'] = true;
$data['resubmitId'] = $payment->getResubmitId();

} else {
$data['resubmit'] = false;
$data['resubmitId'] = '';
}

$paymentExecutedResponse = $this->request( 'POST', sprintf( '%s/payments/sct/instant', $this->ApiBaseUri ), [], json_encode( $data ) );
if( is_null( $data['siaCode'] ) ) {
$data['siaCode'] = '';
}

$paymentExecutedResponse = $this->request( 'POST', sprintf( '%s/payments/sct/instant', $this->getApiBaseUri() ), [], $data );

return new PaymentExecuted( $paymentExecutedResponse );
}


/**
* Get the status of a payment (SCT Instant - Payment Status API)
* @param string $orderId
* @return PaymentStatus
*/
public function getPaymentStatus( string $orderId, string $paymentId = null ): PaymentStatus {
$params = [];

if( $paymentId ) {
$params['paymentId'] = $paymentId;
}

$paymentStatusResponse = $this->request( 'GET', sprintf( '%s/payments/sct/instant/%s/history/%s', $this->getApiBaseUri(), $this->Iban, $orderId ), $params );

return new PaymentStatus( $paymentStatusResponse );
}


/**
* Get a list of the payments (SCT Instant - Payments List API)
*
Expand All @@ -320,7 +440,7 @@ public function getPaymentsList( DateTime $fromDate = null, DateTime $toDate = n
$params['toDate'] = $toDate->format( 'Ymd' );
}

$url = sprintf( '%s/payments/sct/instant/%s/history', $this->ApiBaseUri, $this->Iban );
$url = sprintf( '%s/payments/sct/instant/%s/history', $this->getApiBaseUri(), $this->Iban );

$payments = null;

Expand Down
3 changes: 0 additions & 3 deletions src/Models/Balance.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

use stdClass;

use Shellrent\OpenBanking\Models\GenericModel;


class Balance extends GenericModel {
/**
* @var string
Expand Down
15 changes: 6 additions & 9 deletions src/Models/Collections/PaymentInfos.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@

use DateTime;
use stdClass;

use Shellrent\OpenBanking\Models\Collections\ModelsCollectionInterface;
use Shellrent\OpenBanking\Models\GenericModel;
use Shellrent\OpenBanking\Models\PaymentInfo;


class PaymentInfos extends GenericModel implements ModelsCollectionInterface {
/**
* @var int
Expand All @@ -22,17 +19,17 @@ class PaymentInfos extends GenericModel implements ModelsCollectionInterface {
private $PageSize;

/**
* @var \DateTime
* @var DateTime
*/
private $InquiryFromDate;

/**
* @var \DateTime
* @var DateTime
*/
private $InquiryToDate;

/**
* @var \Shellrent\OpenBanking\Models\PaymentInfo[]
* @var PaymentInfo[]
*/
private $Payments = [];

Expand Down Expand Up @@ -84,23 +81,23 @@ public function getPageSize(): ?int {


/**
* @return \DateTime
* @return DateTime
*/
public function getInquiryFromDate(): ?DateTime {
return $this->InquiryFromDate;
}


/**
* @return \DateTime
* @return DateTime
*/
public function getInquiryToDate(): ?DateTime {
return $this->InquiryToDate;
}


/**
* @return \Shellrent\OpenBanking\Models\PaymentInfo[]
* @return PaymentInfo[]
*/
public function getPayments(): array {
return $this->Payments;
Expand Down
Loading

0 comments on commit 2870b0d

Please sign in to comment.