.. title: How to change the status of a CiviCRM event participant by scanning a bar code .. slug: how-to-change-the-status-of-a-civicrm-event-participant-by-scanning-a-bar-code .. date: 2016-05-27 22:12:09 UTC+02:00 .. tags: civicrm,api,howto .. link: .. description: Here is the POC I promised at CiviCon NWEurope 2016. .. type: text Yesterday I was at `Civicon NWEurope 2016 `_. I was talking to Yves, who was searching for a system that would enable him to scan some kind of bar code of participants turning up at an event, and then automatically change the participants's status to 'Attended' in CiviCRM. .. TEASER_END I thought this would not be too difficult, and I promised to create a simple proof of concept. So here it is. I will just show that it is possible, in the most simple way. I created a PHP application that reads participant ID's using a web form. It calls CiviCRM using the API to change the status of those participants to 'attended'. I chose to write a PHP application, because I assume that people who use CiviCRM will understand PHP. But you can use this with any programming language that can do curl-like web requests. So what you have to do, is send each participant a personalised letter or e-mail with their participant ID in a bar code font (more details on this later on). So with a scanner and the PHP app, we can change the participant status. This example works for if your CiviCRM runs on top of Drupal. But I guess it can be changed for other platforms. What to do in CiviCRM? ====================== To make this work, you need to create a Drupal user on your CiviCRM site, and make sure that this user has the following permissions in CiviCRM: * Access CiviCRM * Access CiviEvent * Edit Event Participants * View all CiviCRM contacts (The last one is not strictly necessary, but my demo application shows the names of the participants. If you want this, you need that permission.) Your Drupal user will have a corresponding CiviCRM contact. You need to `create an API key `_ for this contact. The PHP client application ========================== Here is the code for the application. You do not need to run it on your CiviCRM server; it uses the HTTP-api to communicate with your CiviCRM instance. .. code-block:: php SITE_KEY, 'api_key' => API_KEY, 'sequential' => 1, 'entity' => $entity, 'action' => $action, 'json' => json_encode($params), ); $opts = array( CURLOPT_URL => $url, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $rest_params, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_SSL_VERIFYPEER => FALSE, ); curl_setopt_array($curl, $opts); $result = curl_exec($curl); curl_close($curl); $result = json_decode($result, true); // You should probably handle HTTP errors here. return $result; } if (isset($_POST['participantId'])) { $participantId = $_POST['participantId']; // avoid script injection. is_numeric($participantId) or die('Prutser!'); // TODO: check whether the participant exists. (We are lucky, // because the API call will fail if the ID does not exist.) $params = array( // update participant with 'id' => $participantId, // change status to 'attended' 'status_id' => STATUS_ATTENDED, // Use chained call to get contact name 'api.Contact.getsingle' => array( 'id' => '$value.contact_id', 'return' => 'display_name' ), // Use another chained call to get event title 'api.Event.getsingle' => array( 'id' => '$value.event_id', 'return' => 'title', ), ); $result = _civicrm_http_api('Participant', 'create', $params); if ($result['is_error'] || $result['count'] != 1) { print "Something went wrong:
"; print $result['error_message'] . "
"; } else { $participant = $result['values'][0]; print "Participant: " . $participant['api.Contact.getsingle']['display_name'] . "
"; print "Event: " . $participant['api.Event.getsingle']['title'] . "
"; } } ?>
You need to change the values of ``CIVI_URL``, ``SITE_KEY`` and ``API_KEY`` for your site. And again: this is just a demo. Do not put it on the public internet, because it writes to your CiviCRM instance! Generating the bar codes ======================== Now you still need to provide each of your participants with a bar code. Easy. Just create a PDF letter for your participants, and use the ``{participant.participant_id}`` token. The bad news is that CiviCRM does not provide tokens for participants (`CRM-16734 `_). The good news is that `a patch exists `_. (Not sure how to apply a patch? See :doc:`How to apply a patch `.) If you have applied the patch, you can use the ``{participant.participant_id}`` token, but you'll have to type it into your template, because it is not available from the drop down list. Then you should figure out how to use a barcode font in your PDF letter. I have not looked into this yet, but I guess it should be doable. Thoughts ======== I cannot repeat enough that this is just a proof of concept. It reads participant IDs, and changes statuses, that's all. Do not use this to prevent people from entering your event without paying; it is very easy to spoof the bar code by guessing other participant ID's. As Alain suggested, you cold add a hash to the bar code, and check that hash in the client program. If you do not want to patch CiviCRM, you can also generate a bar code based on contact ID and event ID. You will have to adapt your API calls, but it will not be too hard. I wanted to use the participant ID because it keeps things simple, and of course I also wanted to promote `CRM-16734 `_ ;-)