diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 72f6064..1958b9d 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -22,6 +22,7 @@ public function getConfigTreeBuilder() $rootNode ->children() + ->booleanNode('sandbox_mode')->defaultValue(false)->end() ->booleanNode('debug_mode')->defaultValue(false)->end() ->scalarNode('client_id')->isRequired()->end() ->scalarNode('client_password')->isRequired()->end() diff --git a/DependencyInjection/TroopersMangopayExtension.php b/DependencyInjection/TroopersMangopayExtension.php index 72f8511..d045c35 100644 --- a/DependencyInjection/TroopersMangopayExtension.php +++ b/DependencyInjection/TroopersMangopayExtension.php @@ -25,7 +25,8 @@ public function load(array $configs, ContainerBuilder $container) $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); - $container->setParameter('troopers_mangopay.debug_mode', $config['debug_mode'] === true); + $container->setParameter('troopers_mangopay.sandbox_mode', $config['sandbox_mode']); + $container->setParameter('troopers_mangopay.debug_mode', $config['debug_mode']); $container->setParameter('troopers_mangopay.client_id', $config['client_id']); $container->setParameter('troopers_mangopay.client_password', $config['client_password']); $container->setParameter('troopers_mangopay.base_url', $config['base_url']); diff --git a/Entity/BankInformationInterface.php b/Entity/BankInformationInterface.php index 1dac2e0..8c6987c 100644 --- a/Entity/BankInformationInterface.php +++ b/Entity/BankInformationInterface.php @@ -11,42 +11,42 @@ interface BankInformationInterface /** * BankInformation address. * - * @var string + * @return string */ public function getBankInformationStreetAddress(); /** * BankInformation address. * - * @var string + * @return string */ public function getBankInformationAdditionalStreetAddress(); /** * BankInformation address. * - * @var string + * @return string */ public function getBankInformationCity(); /** * BankInformation address. * - * @var string + * @return string */ public function getBankInformationPostalCode(); /** * BankInformation address. * - * @var string + * @return string */ public function getBankInformationCountry(); /** * BankInformation name. * - * @var string + * @return string */ public function getBankInformationFullName(); @@ -54,18 +54,20 @@ public function getBankInformationFullName(); * It represents the amount debited on the bank account of the Author.In cents so 100€ will be written like « Amount » : 10000 * DebitedFunds – Fees = CreditedFunds (amount received on wallet). * - * @var string + * @return string */ public function getIban(); /** * The user bank informations belongs to * - * @var UserInterface + * @return UserInterface */ public function getUser(); public function getMangoBankAccountId(); public function setMangoBankAccountId($mangoBankAccountId); + public function setMangoMandateId($mangoMandateId); + public function setMangoMandateUrl($mangoMandateUrl); } diff --git a/Entity/LegalUserInterface.php b/Entity/LegalUserInterface.php index 0aa39f9..7339ce5 100644 --- a/Entity/LegalUserInterface.php +++ b/Entity/LegalUserInterface.php @@ -140,6 +140,7 @@ public function getCompanyNumber(); * behalf of the legal entity */ public function getLegalRepresentativeProofOfIdentityId(); + public function setLegalRepresentativeProofOfIdentityId($id); /** * @var string @@ -147,6 +148,7 @@ public function getLegalRepresentativeProofOfIdentityId(); * the following information is mentioned: business name, activity, registered address, shareholding… */ public function getStatuteId(); + public function setStatuteId($id); /** * @var string @@ -155,12 +157,14 @@ public function getStatuteId(); * authority */ public function getProofOfRegistrationId(); + public function setProofOfRegistrationId($id); /** * @var string * Shareholder declaration (as https://www.mangopay.com/terms/shareholder-declaration/Shareholder_Declaration-EN.pdf) */ public function getShareholderDeclarationId(); + public function setShareholderDeclarationId($id); /** * @var File diff --git a/Entity/NaturalUserInterface.php b/Entity/NaturalUserInterface.php index 478b99f..a6a76f4 100644 --- a/Entity/NaturalUserInterface.php +++ b/Entity/NaturalUserInterface.php @@ -60,7 +60,7 @@ public function getPostalCode(); * @var \DateTime * User’s birthdate. */ - public function getBirthday() :?\DateTime; + public function getBirthday(); /** * @var string diff --git a/Entity/UserInterface.php b/Entity/UserInterface.php index 1e828eb..ade8d5b 100644 --- a/Entity/UserInterface.php +++ b/Entity/UserInterface.php @@ -23,19 +23,28 @@ public function getEmail(); * @var int */ public function getMangoUserId(); + public function setMangoUserId($id); /** * @var int */ public function getMangoWalletId(); + public function setMangoWalletId($id); /** * @var int */ public function getMangoCardId(); + public function setMangoCardId($id); /** * @var int */ public function getMangoBankAccountId(); + public function setMangoBankAccountId($id); + + /** + * @var int + */ + public function getBankInformation(); } diff --git a/Helper/BankInformationHelper.php b/Helper/BankInformationHelper.php index 30caa29..bfa22f5 100644 --- a/Helper/BankInformationHelper.php +++ b/Helper/BankInformationHelper.php @@ -13,11 +13,13 @@ class BankInformationHelper { private $mangopayHelper; private $userHelper; + private $mangopaySandbox; - public function __construct(MangopayHelper $mangopayHelper, UserHelper $userHelper) + public function __construct(MangopayHelper $mangopayHelper, UserHelper $userHelper, $mangopaySandbox) { $this->mangopayHelper = $mangopayHelper; $this->userHelper = $userHelper; + $this->mangopaySandbox = $mangopaySandbox; } /** @@ -67,7 +69,12 @@ public function createBankAccount(BankInformationInterface $bankInformation) $bankAccount->OwnerAddress = $address; $bankAccountDetailsIban = new BankAccountDetailsIBAN(); - $bankAccountDetailsIban->IBAN = $bankInformation->getIban(); + + $iban = $bankInformation->getIban(); + if ($this->mangopaySandbox) { + $iban = "FR7611808009101234567890147"; + } + $bankAccountDetailsIban->IBAN = $iban; $bankAccount->Details = $bankAccountDetailsIban; @@ -77,4 +84,46 @@ public function createBankAccount(BankInformationInterface $bankInformation) return $bankAccount; } + + /** + * @param BankInformationInterface $bankInformation + * @return BankAccount + * @throws \Exception + */ + public function updateBankAccount(BankInformationInterface $bankInformation) + { + /** @var UserInterface $user */ + $user = $bankInformation->getUser(); + $bankAccount = $this->mangopayHelper->Users->GetBankAccount($user->getMangoUserId(), $bankInformation->getMangoBankAccountId()); + + $bankAccount->OwnerName = $bankInformation->getBankInformationFullName(); + $bankAccount->UserId = $user->getMangoUserId(); + $bankAccount->Type = 'IBAN'; + + $address = new \MangoPay\Address(); + $userAddress = $bankInformation->getBankInformationStreetAddress(); + $city = $bankInformation->getBankInformationCity(); + $postalCode = $bankInformation->getBankInformationPostalCode(); + if (null == $userAddress || null == $city || null == $postalCode) { + throw new NotFoundHttpException(sprintf('address, city or postalCode missing for BankInformation of User id : %s', $user->getId())); + } + $address->AddressLine1 = $userAddress; + $address->AddressLine2 = $bankInformation->getBankInformationAdditionalStreetAddress(); + $address->City = $city; + $address->Country = $bankInformation->getBankInformationCountry(); + $address->PostalCode = $postalCode; + $bankAccount->OwnerAddress = $address; + + if ($bankInformation->getIban() !== $bankAccount->Details->IBAN) { + $iban = $bankInformation->getIban(); + if ($this->mangopaySandbox) { + $iban = "FR7611808009101234567890147"; + } + $bankAccount->Details->IBAN = $iban; + } + + $bankAccount = $this->mangopayHelper->Users->UpdateBankAccount($mangoUser->Id, $bankAccount); + + return $bankAccount; + } } diff --git a/Helper/KYCHelper.php b/Helper/KYCHelper.php index 5fefcb3..8b3bef6 100644 --- a/Helper/KYCHelper.php +++ b/Helper/KYCHelper.php @@ -39,7 +39,7 @@ public function createDocument(File $file) { $page = new KycPage(); - if (false === $file = @file_get_contents($value->getPathname(), FILE_BINARY)) { + if (false === $file = @file_get_contents($file->getPathname(), FILE_BINARY)) { throw new TransformationFailedException(sprintf('Unable to read the "%s" file', $value->getPathname())); } diff --git a/Helper/MandateHelper.php b/Helper/MandateHelper.php new file mode 100644 index 0000000..7e95338 --- /dev/null +++ b/Helper/MandateHelper.php @@ -0,0 +1,75 @@ +mangopayHelper = $mangopayHelper; + } + + /** + * @param BankInformationInterface $user + * + * @return Mandate + */ + public function findOrCreateMandate(BankInformationInterface $bankInformation, $returnUrl = 'http://example.com/') + { + $bankInformationId = $bankInformation->getMangoBankAccountId(); + $userId = $bankInformation->getUser()->getMangoUserId(); + $pagination = null; + $mandates = $this->mangopayHelper->Users->GetMandatesForBankAccount($userId, $bankInformationId, $pagination, (new Sorting())->AddField('CreationDate', 'DESC')); + + if (empty($mandates)) { + $mandate = $this->createMandateForBankInformation($bankInformation, $returnUrl); + // else, create a new mango user + } else { + $mandate = array_shift($mandates); + } + + return $mandate; + } + + public function createMandateForBankInformation(BankInformationInterface $bankInformation, $returnUrl = 'http://example.com/') + { + $bankInformationId = $bankInformation->getMangoBankAccountId(); + $userId = $bankInformation->getUser()->getMangoUserId(); + + $mandate = new Mandate(); + $mandate->BankAccountId = $bankInformationId; + $user = $bankInformation->getUser(); + if ($user instanceof LegalUserInterface) { + $culture = $user->getLegalRepresentativeNationality(); + } else { + $culture = $user->getNationality(); + } + $mandate->Culture = $culture; + $mandate->ReturnURL = $returnUrl; + $mangoMandate = $this->mangopayHelper->Mandates->Create($mandate, md5(json_encode([ + 'bankInformation' => $bankInformationId, + 'user' => $userId, + ]))); + + $bankInformation->setMangoMandateId($mandate->Id); + $bankInformation->setMangoMandateUrl($mandate->RedirectURL); + + return $mangoMandate; + } +} diff --git a/Helper/PaymentDirectDebitHelper.php b/Helper/PaymentDirectDebitHelper.php new file mode 100644 index 0000000..57ca25c --- /dev/null +++ b/Helper/PaymentDirectDebitHelper.php @@ -0,0 +1,73 @@ +mangopayHelper = $mangopayHelper; + $this->mandateHelper = $mandateHelper; + } + + /** + * @param UserInterface $userDebited + * @param UserInterface $userCredited + * @param int $amount + * @param int $fees + * @param string|null $statementDescriptor + * @return PayIn + */ + public function createDirectDebitPayin(UserInterface $userDebited, UserInterface $userCredited, $amount, $fees, $statementDescriptor = null) + { + $mandate = $this->mandateHelper->findOrCreateMandate($userDebited->getBankInformation()); + + $payin = new PayIn(); + $payin->AuthorId = $userDebited->getMangoUserId(); + $payin->CreditedUserId = $userCredited->getMangoUserId(); + $payin->CreditedWalletId = $userCredited->getMangoWalletId(); + + $debitedFunds = new Money(); + $debitedFunds->Currency = 'EUR'; + $debitedFunds->Amount = $amount; + + $mangoFees = new Money(); + $mangoFees->Currency = 'EUR'; + $mangoFees->Amount = $fees; + + $payin->DebitedFunds = $debitedFunds; + $payin->Fees = $mangoFees; + + $payin->PaymentDetails = new PayInPaymentDetailsDirectDebit(); + $payin->PaymentDetails->MandateId = $mandate->Id; + $payin->PaymentDetails->StatementDescriptor = $statementDescriptor; + + $payin->ExecutionDetails = new PayInExecutionDetailsDirect(); + + return $this->mangopayHelper->PayIns->Create($payin); + } + + public function getPayin($payinId) + { + return $this->mangopayHelper->PayIns->Get($payinId); + } + + public function getPayout($payoutId) + { + return $this->mangopayHelper->PayOuts->Get($payoutId); + } +} diff --git a/Helper/PaymentOutHelper.php b/Helper/PaymentOutHelper.php index 3ecbbb2..e7a945f 100644 --- a/Helper/PaymentOutHelper.php +++ b/Helper/PaymentOutHelper.php @@ -23,7 +23,7 @@ public function __construct(MangopayHelper $mangopayHelper) public function buildPayOutPaymentDetailsBankWire(UserInterface $user) { $meanOfPaymentDetails = new PayOutPaymentDetailsBankWire(); - if (null == $bankAccountId = $user->getBankAccountId()) { + if (null == $bankAccountId = $user->getMangoBankAccountId()) { throw new NotFoundHttpException(sprintf('bankAccount not found for id : %s', $user->getId())); } $meanOfPaymentDetails->BankAccountId = $bankAccountId; @@ -42,17 +42,15 @@ public function buildMoney($amount = '0', $currency = 'EUR') public function createPayOutForUser(UserInterface $user, $debitedFunds, $fees = '0') { - $debitedFunds = $this->buildMoney($debitedFunds); - $fees = $this->buildMoney($fees); $meanOfPaymentDetails = $this->buildPayOutPaymentDetailsBankWire($user); $payOut = new PayOut(); $payOut->AuthorId = $user->getMangoUserId(); $payOut->DebitedWalletId = $user->getMangoWalletId(); $payOut->PaymentType = 'BANK_WIRE'; - $payOut->DebitedFunds = $debitedFunds; + $payOut->DebitedFunds = $this->buildMoney($debitedFunds); $payOut->MeanOfPaymentDetails = $meanOfPaymentDetails; - $payOut->fees = $fees; + $payOut->fees = $this->buildMoney($fees); return $this->mangopayHelper->PayOuts->Create($payOut); } diff --git a/Helper/User/LegalUserHelper.php b/Helper/User/LegalUserHelper.php index b056bcb..7022784 100644 --- a/Helper/User/LegalUserHelper.php +++ b/Helper/User/LegalUserHelper.php @@ -3,7 +3,10 @@ namespace Troopers\MangopayBundle\Helper\User; use Doctrine\ORM\EntityManager; +use MangoPay\KycDocument; +use MangoPay\KycDocumentStatus; use MangoPay\KycLevel; +use MangoPay\KycPage; use MangoPay\User; use MangoPay\UserLegal; use MangoPay\UserNatural; @@ -18,21 +21,24 @@ use Troopers\MangopayBundle\Helper\MangopayHelper; use MangoPay\BankAccount; use MangoPay\BankAccountDetailsIBAN; +use MangoPay\KycDocumentType; class LegalUserHelper { private $mangopayHelper; private $dispatcher; private $KYCHelper; + private $mangopaySandbox; - public function __construct(MangopayHelper $mangopayHelper, EventDispatcherInterface $dispatcher, KYCHelper $KYCHelper) + public function __construct(MangopayHelper $mangopayHelper, EventDispatcherInterface $dispatcher, KYCHelper $KYCHelper, $mangopaySandbox) { $this->mangopayHelper = $mangopayHelper; $this->dispatcher = $dispatcher; $this->KYCHelper = $KYCHelper; + $this->mangopaySandbox = $mangopaySandbox; } - public function createMangoUser(LegalUserInterface $user) + public function createMangoUser(UserInterface $user) { $birthday = null; if ($user->getLegalRepresentativeBirthday() instanceof \Datetime) { @@ -44,7 +50,11 @@ public function createMangoUser(LegalUserInterface $user) $mangoUser->LegalPersonType = $user->getLegalPersonType(); $mangoUser->Name = $user->getName(); $mangoUser->Email = $user->getEmail(); - $mangoUser->LegalRepresentativeFirstName = $user->getLegalRepresentativeFirstName(); + $legalRepresentativeFirstName = $user->getLegalRepresentativeFirstName(); + if ($this->mangopaySandbox) { + $legalRepresentativeFirstName = "Successful"; + } + $mangoUser->LegalRepresentativeFirstName = $legalRepresentativeFirstName; $mangoUser->LegalRepresentativeLastName = $user->getLegalRepresentativeLastName(); $mangoUser->LegalRepresentativeBirthday = $birthday ? $birthday->getTimestamp() : null; $mangoUser->LegalRepresentativeNationality = $user->getLegalRepresentativeNationality(); @@ -72,21 +82,27 @@ public function createMangoUser(LegalUserInterface $user) $user->setMangoUserId($mangoUser->Id); if (null !== $document = $user->getProofOfRegistration()) { - $mangoDocument = $this->createDocument($document, $user); + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::RegistrationProof); $mangoUser->ProofOfRegistration = $mangoDocument->Id; - $user->getProofOfRegistrationId($mangoDocument->Id); + $user->setProofOfRegistrationId($mangoDocument->Id); } if (null !== $document = $user->getLegalRepresentativeProofOfIdentity()) { - $mangoDocument = $this->createDocument($document, $user); + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::IdentityProof); $mangoUser->LegalRepresentativeProofOfIdentity = $mangoDocument->Id; - $user->getLegalRepresentativeProofOfIdentityId($mangoDocument->Id); + $user->setLegalRepresentativeProofOfIdentityId($mangoDocument->Id); } if (null !== $document = $user->getStatute()) { - $mangoDocument = $this->createDocument($document, $user); + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::ArticlesOfAssociation); $mangoUser->Statute = $mangoDocument->Id; - $user->getStatuteId($mangoDocument->Id); + $user->setStatuteId($mangoDocument->Id); + } + + if (null !== $document = $user->getShareholderDeclaration()) { + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::ShareholderDeclaration); + $mangoUser->ShareholderDeclaration = $mangoDocument->Id; + $user->setShareholderDeclarationId($mangoDocument->Id); } $event = new UserEvent($user, $mangoUser); @@ -95,8 +111,9 @@ public function createMangoUser(LegalUserInterface $user) return $mangoUser; } - public function updateMangoUser(LegalUserInterface $user) + public function updateMangoUser(UserInterface $user) { + $birthday = null; if ($user->getLegalRepresentativeBirthday() instanceof \Datetime) { $birthday = $user->getLegalRepresentativeBirthday()->getTimestamp(); } @@ -122,25 +139,25 @@ public function updateMangoUser(LegalUserInterface $user) if (null !== $document = $user->getProofOfRegistration()) { - $mangoDocument = $this->createDocument($document, $user); + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::RegistrationProof); $mangoUser->ProofOfRegistration = $mangoDocument->Id; $user->setProofOfRegistrationId($mangoDocument->Id); } if (null !== $document = $user->getLegalRepresentativeProofOfIdentity()) { - $mangoDocument = $this->createDocument($document, $user); + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::IdentityProof); $mangoUser->LegalRepresentativeProofOfIdentity = $mangoDocument->Id; $user->setLegalRepresentativeProofOfIdentityId($mangoDocument->Id); } if (null !== $document = $user->getStatute()) { - $mangoDocument = $this->createDocument($document, $user); + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::ArticlesOfAssociation); $mangoUser->Statute = $mangoDocument->Id; $user->setStatuteId($mangoDocument->Id); } if (null !== $document = $user->getShareholderDeclaration()) { - $mangoDocument = $this->createDocument($document, $user); + $mangoDocument = $this->createDocument($document, $user, KycDocumentType::ShareholderDeclaration); $mangoUser->ShareholderDeclaration = $mangoDocument->Id; $user->setShareholderDeclarationId($mangoDocument->Id); } @@ -150,10 +167,20 @@ public function updateMangoUser(LegalUserInterface $user) return $mangoUser; } - protected function createDocument(File $file, UserInterface $user) + protected function createDocument($fileContent, UserInterface $user, $type) { - $document = $this->KYCHelper->createDocument($file); - $document = $this->mangopayHelper->Users->CreateKycDocument($user->getMangoUserId(), $document); + $kycDocument = new KycDocument(); + $kycDocument->UserId = $user->getMangoUserId(); + $kycDocument->Type = $type; + $kycDocument->Status = KycDocumentStatus::ValidationAsked; + + $document = $this->mangopayHelper->Users->CreateKycDocument($user->getMangoUserId(), $kycDocument); + + $page = new KycPage(); + $page->File = $fileContent; + + $this->mangopayHelper->Users->CreateKycPage($user->getMangoUserId(), $document->Id, $page); + return $document; } diff --git a/Helper/User/NaturalUserHelper.php b/Helper/User/NaturalUserHelper.php index 5e56392..9d85d32 100644 --- a/Helper/User/NaturalUserHelper.php +++ b/Helper/User/NaturalUserHelper.php @@ -18,14 +18,16 @@ class NaturalUserHelper { private $mangopayHelper; private $dispatcher; + private $mangopaySandbox; - public function __construct(MangopayHelper $mangopayHelper, EventDispatcherInterface $dispatcher) + public function __construct(MangopayHelper $mangopayHelper, EventDispatcherInterface $dispatcher, $mangopaySandbox) { $this->mangopayHelper = $mangopayHelper; $this->dispatcher = $dispatcher; + $this->mangopaySandbox = $mangopaySandbox; } - public function createMangoUser(NaturalUserInterface $user) + public function createMangoUser(UserInterface $user) { $birthday = null; if ($user->getBirthday() instanceof \Datetime) { @@ -35,7 +37,11 @@ public function createMangoUser(NaturalUserInterface $user) } $mangoUser = new UserNatural(); $mangoUser->Email = $user->getEmail(); - $mangoUser->FirstName = $user->getFirstName(); + $firstname = $user->getFirstName(); + if ($this->mangopaySandbox) { + $firstname = "Successful"; + } + $mangoUser->FirstName = $firstname; $mangoUser->LastName = $user->getLastName(); $mangoUser->Birthday = $birthday ? $birthday->getTimestamp() : null; $mangoUser->Nationality = $user->getNationality(); @@ -53,16 +59,22 @@ public function createMangoUser(NaturalUserInterface $user) public function updateMangoUser(NaturalUserInterface $user) { + $birthday = null; if ($user->getBirthday() instanceof \Datetime) { - $birthdate = $user->getBirthday()->getTimestamp(); + $birthday = $user->getBirthday()->getTimestamp(); } $mangoUserId = $user->getMangoUserId(); $mangoUser = $this->mangopayHelper->Users->get($mangoUserId); $mangoUser->Email = $user->getEmail(); - $mangoUser->FirstName = $user->getFirstname(); + + $firstname = $user->getFirstName(); + if ($this->mangopaySandbox) { + $firstname = "Successful"; + } + $mangoUser->FirstName = $firstname; $mangoUser->LastName = $user->getLastname(); - $mangoUser->Birthday = $birthdate; + $mangoUser->Birthday = $birthday; $mangoUser->Nationality = $user->getNationality(); $mangoUser->CountryOfResidence = $user->getCountry(); $mangoUser->Tag = $user->getId(); diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 1dc5ed9..512c413 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,4 +1,7 @@ services: + _defaults: + bind: + $mangopaySandbox: '%troopers_mangopay.sandbox_mode%' Troopers\MangopayBundle\: autowire: true @@ -13,6 +16,10 @@ services: - "%troopers_mangopay.base_url%" - "%troopers_mangopay.debug_mode%" - "@event_dispatcher" + calls: + - method: setLogger + arguments: + - '@logger' troopers_mangopay.mango_api: - alias: Troopers\MangopayBundle\Helper\MangopayHelper \ No newline at end of file + alias: Troopers\MangopayBundle\Helper\MangopayHelper diff --git a/composer.json b/composer.json index 2bd7083..05c71e7 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ } ], "require": { - "php": "~5.3|~7", + "php": "~5.5|~7", "symfony/framework-bundle": "~3.4|~4", "mangopay/php-sdk-v2": ">=2.0", "stof/doctrine-extensions-bundle": "~1.2",