Files
kupshop/class/payments/class.Intrum.php
2025-08-02 16:30:27 +02:00

228 lines
8.8 KiB
PHP

<?php
use Diglin\Intrum\CreditDecision\Request;
use Diglin\Intrum\CreditDecision\Response;
use Diglin\Intrum\CreditDecision\TransportV0017;
use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Util\Compat\SymfonyBridge;
class Intrum extends Payment
{
public static $name = 'Intrum';
public $template = 'payment.Intrum.tpl';
public $class = self::class;
protected $pay_method = Payment::METHOD_INVOICE;
public static $REQUEST_ENQUIRY_CREDIT_ASSESSMENT = 0;
public static $REQUEST_ENQUIRY_BUSINESS_TRANSACTION = 1;
public static $REQUEST_SEND_PAYMENT_TRANSACTION_RECEIPT = 3;
public static $REQUEST_SEND_PAYMENT_TRANSACTION_CANCEL = 6;
public $states = [
1 => 'There are serious negative indicators',
2 => 'All payment methods',
3 => 'Manual post-processing (currently not yet in use)',
4 => 'Postal address is incorrect',
5 => 'Enquiry exceeds the credit limit (the credit limit is specified in the cooperation agreement)',
6 => 'Customer specifications not met (currently not yet in use)',
7 => 'Enquiry exceeds the net credit limit (enquiry amount plus open items exceeds credit limit)',
8 => 'Person queried is not of creditworthy age',
9 => 'Delivery address does not match invoice address (for payment guarantee only)',
10 => 'Household cannot be identified at this address',
11 => 'Country is not supported',
12 => 'Party queried is not a natural person',
13 => 'System is in maintenance mode',
14 => 'Address with high fraud risk',
15 => 'Allowance is too low',
16 => 'Application data incomplete',
17 => 'Send contract documents for external credit check',
18 => 'External credit check in progress',
19 => 'Customer is on client blacklist',
20 => 'Customer is on client whitelist',
21 => 'Customer is on Intrum blacklist',
22 => 'Address is a P.O. box',
23 => 'Address not in residential area',
24 => 'Ordering person not legitimated',
25 => 'IP Address temporarily blacklisted',
50 => 'Blacklist WSNP (NL only)',
51 => 'Blacklist Bankruptcy (NL only)',
52 => 'Blacklist Fraud (NL only)',
];
/**
* @throws Exception
*/
public function check(CartBase $cart)
{
// skip if not last step
$step = end($cart->steps);
if (!($step ?? false) || !($step['selected'] ?? false)) {
return;
}
if (empty($cart->invoice['birthdate'])
|| DateTime::createFromFormat('d-m-Y', $cart->invoice['birthdate']) === false
) {
addUserMessage(replacePlaceholders(translate('checkDataOrChangeDelivery', 'payment'), ['URL' => '/'.$cart->steps['user']['url']]), 'danger');
redirection($cart->steps['delivery']['url']);
}
$hash = $this->createHash(array_merge($cart->invoice, [$cart->totalPricePay->printValue()]));
$oldHash = $cart->getData($this->class.'_hash');
$counter = $cart->getData($this->class.'_counter');
try {
if (isset($oldHash) && $oldHash === $hash) {
$requestID = $cart->getData($this->class.'_enquiryCreditRequest');
$requestResponse = $this->selectSQL('intrum_requests', ['id' => $requestID])->fetch()['response'];
if ($requestResponse) {
$this->checkRawResponse($requestResponse, $requestID);
} else {
$cart->setData($this->class.'_hash', null);
$cart->setData($this->class.'_enquiryCreditRequest', null);
$cart->setData($this->class.'_counter', null);
$cart->setData($this->class.'_counter', 1);
$this->enquiryCreditAssessment($cart, $hash);
}
return;
}
if (!isset($counter) || $counter <= 2) {
$cart->setData($this->class.'_counter', ($counter ?? 0) + 1);
$this->enquiryCreditAssessment($cart, $hash);
} else {
addUserMessage(mb_ucfirst(translate('changePaymentMethod', 'payment')), 'danger');
redirection($cart->steps['delivery']['url']);
}
} catch (RuntimeException $e) {
addUserMessage(replacePlaceholders(translate('checkDataOrChangeDelivery', 'payment'), ['URL' => '/'.$cart->steps['user']['url']]), 'danger');
redirection($cart->steps['delivery']['url']);
}
}
/**
* @return bool TRUE if response status is 2 (All payment methods)
*
* @throws Exception
*/
private function checkRawResponse(string $rawResponse, int $requestID): bool
{
$response = new Response();
$response->setRawResponse($rawResponse);
$response->processResponse();
if ($response->getCustomerRequestStatus() !== 2) {
throw new RuntimeException($this->states[$response->getCustomerRequestStatus()] ?? 'Unknown Intrum error in request '.$requestID.'.');
}
return true;
}
/**
* @throws Exception
*/
private function enquiryCreditAssessment(CartBase $cart, string $hash)
{
$streetArray = explode(' ', $cart->invoice['street']);
$houseNumber = count($streetArray) > 1 ? array_pop($streetArray) : ' ';
$firstLine = join(' ', $streetArray);
$birthdate = DateTime::createFromFormat('d-m-Y', $cart->invoice['birthdate'])->format('Y-m-d');
$data = [
'customer_reference' => 'uid_'.uniqid(),
'person' => [
'first_name' => $cart->invoice['name'],
'last_name' => $cart->invoice['surname'],
'gender' => $cart->invoice['gender'] === 'female' ? 2 : 1,
'date_of_birth' => $birthdate, // YYYY-MM-DD
'current_address' => [
'first_line' => $firstLine,
'house_number' => $houseNumber,
'post_code' => $cart->invoice['zip'],
'country_code' => $cart->invoice['country'],
'town' => $cart->invoice['city'],
],
'communication_numbers' => [
'mobile' => $cart->invoice['phone'],
'email' => $cart->invoice['email'],
],
'extra_info' => [
[
'name' => 'ORDERCLOSED',
'value' => 'NO',
],
[
'name' => 'ORDERAMOUNT',
'value' => $cart->totalPricePay->printValue(2),
],
[
'name' => 'ORDERCURRENCY',
'value' => $cart->invoice['currency'],
],
[
'name' => 'IP',
// 'value' => $_SERVER['REMOTE_ADDR'],
'value' => explode(',', SymfonyBridge::getCurrentRequest()->getClientIp())[0],
],
],
],
];
$uid = uniqid(null, true);
$this->insertSQL('intrum_requests', ['uid' => $uid, 'type' => static::$REQUEST_ENQUIRY_CREDIT_ASSESSMENT]);
$requestID = sqlInsertId();
$dom = new \DOMDocument('1.0', 'UTF-8');
/* @var $request Request */
$request = $dom->appendChild(new Request());
$request->setVersion('1.00');
$request->setClientId($this->config['clientId']);
$request->setUserID($this->config['userID']);
$request->setPassword($this->config['password']);
$request->setEmail($this->config['email']);
$request->setRequestId($uid);
$request->createRequest($data);
$requestXML = $dom->saveXML();
$this->updateSQL('intrum_requests', ['request' => $requestXML], ['id' => $requestID]);
$transport = new TransportV0017();
$transport->setMode($this->config['mode'] ?? 'test');
$responseRequest = $transport->sendRequest($requestXML);
$successful = false;
try {
$successful = $this->checkRawResponse($responseRequest, $requestID);
} finally {
$this->updateSQL('intrum_requests', [
'response' => $responseRequest,
'successful' => $successful,
], ['id' => $requestID]);
$cart->setData($this->class.'_enquiryCreditRequest', $requestID);
$cart->setData($this->class.'_hash', $hash);
}
}
private function createHash(array $data)
{
array_multisort($data);
return md5(json_encode($data));
}
public static function isEnabled($className)
{
$cfg = Config::get();
if (empty($cfg['Modules']['payments'][$className])) {
return false;
}
return true;
}
}