This article explains the basics of Service Bus communication: why is the communication required and how to implement a minimal version needed to properly implement Connect ID integration. Intended reader is a developer responsible for integrating their Football Management System with Connect ID SDK. Information in this article is valid from version 6.1.267 of the SDK.
One of the intended benefits of FIFA Connect ID Service is that a football player - whether amateur or professional - who changes clubs or even countries (MAs), keeps their FIFA_ID. Knowing the whole football history of a given player is important during transfers and for all the solidarity mechanisms to work correctly. At the same time, Connect ID Service cannot store any personal details of a player or their history - this information stays within local Football Management Systems (FMS) due to data protection regulations. With these constraints, can we somehow know that a person who wants to register at a club, has any football history in our or different MA? And how do we avoid data duplication, that is registering the same player with a new FIFA_ID?
Connect ID provides both the process & infrastructure for duplicate detection and thus prevents re-registering the same player with a new FIFA_ID. We will first look at the process and then explain how to use the existing infrastructure to align with this process at a minimal effort.
Process of duplicate detection
When MA tries to register a player in Connect ID Service (via SDK), the following happens:
- SDK provides name & date of birth of a Person and requests a new FIFA_ID
- Connect ID Service runs a duplicate check based on the name & date of birth alone and if potential duplicates are found...
- Connect ID Service returns the list of FIFA_IDs of potential duplicates and information where (in which MAs) they are registered
- as there is no personal data in the return message from FIFA_ID, a human operator cannot effectively decide whether a record is indeed a duplicate or not. To achieve this, full player details are needed.
- SDK communicates with other MAs (over Service Bus), automatically requesting and receiving person details.
- person details received from other MAs are displayed to human operator who can now decide whether a given person is indeed a duplicate or not.
Note that although this process is fully automated (single register method), it requires every MA to implement a mechanism to receive a request and send back person details. Implementing such a mechanism is a mandatory condition for successfully integrating with Connect ID Service. The second part of this article shows how to do it in the most effective way (single method).
Infrastructure for duplicate detection; implementation
Two MAs communicate with each other using Service Bus architecture, which is focused on queues and messages. That means vendors are not sending messages directly to themselves. Instead, each of them sends message to dedicated Service Bus queue. Then messages from queues are read by vendors and processed. The SDK that we provided, wraps up and makes this functionality easier to use, so there's a feeling of peer-to-peer connection.
Each MA that use PHP version of the SDK needs to implement and set up background listener script (that needs to run constantly and cyclically). It is responsible for getting messages from other MAs as well as for sending messages with person details to other MAs. To see an example of listener script, please open command/sample-listener.php file, which is attached to SDK package. The part responsible for providing person details is placed in ListenerTestPersonDetailsProvider class. In order to provide person details in your solution, you need to implement similar class, starting from implementation of PersonDetailsProviderInterface interface.
Main part of classes that implements mentioned interface is getPersonDetails method. Here you need to fetch person (identified by $request->getUniqueFifaId()) data from your local database and return it in XML format compliant with FIFA Data Standard. Our recommendation here is to use PersonLocalXmlSerializer service, so that creating document is easier and generated output is automatically validated against FIFA Data Standard. See an example below:
/** * Gets detailed information about person with given request. * * @param PersonDetailsRequest $request * @return string|null - the Person Local type from the FIFA Data Standard. * @throws \Fifa\ConnectId\Sdk\Util\ToString\Exception\ToStringException */ public function getPersonDetails(PersonDetailsRequest $request) { // create PersonLocal object with required fields $localLastName = 'Novak'; $gender = Gender::MALE; $nationality = 'IN'; $dateOfBirth = new \DateTime('2000-03-29', new \DateTimeZone('UTC')); $countryOfBirth = 'PL'; $placeOfBirth = 'Kraków'; $localLanguage = 'eng'; $localCountry = 'IN'; $personLocal = new PersonLocal($localLastName, $gender, $nationality, $dateOfBirth, $countryOfBirth, $placeOfBirth, $localLanguage, $localCountry); $personLocal->LocalFirstName = 'John'; // optional field // add player registration $personFIFAId = $request->getUniqueFifaId(); $status = Status::ACTIVE; $organisationFIFAId = '103C3AB'; $registrationValidFrom = new \DateTime('2017-06-01', new \DateTimeZone('UTC')); $level = strtolower(Level::PRO); $discipline = Discipline::BEACH_SOCCER; $registrationNature = RegistrationNature::LOAN; $playerRegistration = new PlayerRegistration($personFIFAId, $status, $organisationFIFAId, $registrationValidFrom, $level, $discipline, $registrationNature); $playerRegistration->setRegistrationValidTo(new \DateTime('2018-05-31', new \DateTimeZone('UTC'))); // optional field $personLocal->addPlayerRegistration($playerRegistration); // serialize object into XML $xmlSerializer = new PersonLocalXmlSerializer(); $xmlContent = null; try { $xmlContent = $xmlSerializer->serialize($personLocal); } catch (XmlSerializationException $e) { // handle serialization exception $this->logger->error(sprintf('Unable to serialize XML for person: %s. Details: %s', $personFIFAId, $e->getMessage())); } return $xmlContent; }
As shown above, first step to serialize data to XML structure is creating PersonLocal instance. All required fields are included in constructor, so object created this way is ready to be serialized. FIFA Data Standard defines lots of optional fields, which can be set by accessing public properties. As for example:
$personLocal->LocalFirstName = 'John';
Each registration type can be included in XML file by adequate methods: addPlayerRegistration(), addTeamOfficialRegistration(), addMatchOfficialRegistration() and addOrganisationOfficialRegistration(). When creating registration instances (i.e. PlayerRegistration) all mandatory fields are required by constructor of the class - same as for it goes for PersonLocal.
PersonLocalXmlSerializer reads string properties and parses them to XML tags or attributes. Because of that, all model classes use string instead of DateTime objects for fields which are storing dates. While it's possible to write values to public properties directly, we recommend to use setter methods that we provide in such cases. See example below:
$validToDate = new \DateTime('2018-05-31', new \DateTimeZone('UTC')); $playerRegistration->setRegistrationValidTo($validToDate);
Usage of PersonLocalXmlSerializer is limited to running method serialize() which takes PersonLocal object as an input. Under the hood, this method creates XML string and executes validation against FIFA Data Standard. In case validation fails, XmlSerializationException will be thrown giving a message with all possible issues that were found during validation. As all of this happens in background listener, you should implement a proper error handling when catching the exception, so to get notified in case when XML response was not generated. Note that in case of exception thrown, MA that was asking for person details, won't receive a correct answer, so it's important to keep data structure valid and try to limit number of exceptions.
For more detailed information please go to SDK documentation - chapter 3.1 Working with PersonLocal.