| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.gdata.health">
- <title>Using Google Health</title>
- <para>
- The Google Health Data API is designed to enable developers to do two things:
- <itemizedlist>
- <listitem>
- <para>
- Read a user's Google Health profile or query for medical records that match particular criteria and then
- use the results to provide personalized functionality based on the data.
- </para>
- </listitem>
- <listitem>
- <para>
- Add new medical records to a user's profile by including CCR data when sending a notice to a user's profile. Note: The CCR data is stored as an XML blob
- within the <atom> entry. The library does not provide direct accessors to the object model but it does have helpers for extracting specific fields.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- There are three main feeds, each of which requires authentication. Unlike other Google Data APIs, each Google Health feed has a limited set of
- HTTP operations you can perform on it, depending on which authentication method you are using (ClientLogin or AuthSub/OAuth).
- For a list of permitted operations, see <ulink url="http://code.google.com/apis/health/reference.html#Authentication">http://code.google.com/apis/health/reference.html#Authentication</ulink>.
- <itemizedlist>
- <listitem>
- <para>
- <firstterm>Profile Feed</firstterm>
- use the profile feed to query a user's health profile for specific information.
- </para>
- </listitem>
- <listitem>
- <para>
- <firstterm>Register Feed</firstterm>
- use the register feed to reconcile new CCR data into a profile.
- </para>
- </listitem>
- <listitem>
- <para>
- <firstterm>Profile List Feed</firstterm>
- the profile list feed should be used to determine which of the user's Health profiles to interact with.
- This feed is only available when using ClientLogin.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- See <ulink url="http://code.google.com/apis/health/">http://code.google.com/apis/health</ulink>
- for more information about the Google Health API.
- </para>
- <sect2 id="zend.gdata.health.connect">
- <title>Connect To The Health Service</title>
- <para>
- The Google Health API, like all Google Data APIs, is based off of the Atom Publishing Protocol (APP), an XML based format for managing web-based resources.
- Traffic between a client and the Google Health servers occurs over HTTP and allows for authenticated connections.
- </para>
- <para>
- Before any transactions can occur, a connection needs to be made. Creating a connection to the Health servers involves two steps: creating an HTTP client
- and binding a <classname>Zend_Gdata_Health</classname> service instance to that client.
- </para>
- <sect3 id="zend.gdata.health.connect.authentication">
- <title>Authentication</title>
- <para>
- The Google Health API allows programmatic access to a user's Health profile. There are three authentication schemes that are supported by Google Health:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <firstterm>ClientLogin</firstterm>
- provides direct username/password authentication to the Health servers. Since this method requires that users provide your application
- with their password, this authentication scheme is only recommended for installed/desktop applications.
- </para>
- </listitem>
- <listitem>
- <para>
- <firstterm>AuthSub</firstterm>
- allows a user to authorize the sharing of their private data. This provides the same level of convenience as ClientLogin but without the
- security risk, making it an ideal choice for web-based applications. For Google Health, AuthSub must be used
- in registered and secure mode--meaning that all requests to the API must be digitally signed.
- </para>
- </listitem>
- <listitem>
- <para>
- <firstterm>OAuth</firstterm>
- is an alternative to AuthSub. Although this authentication scheme is not discussed in this document, more information can
- be found in the <ulink url="http://code.google.com/apis/health/developers_guide_protocol.html#OAuth">Health Data API Developer's Guide</ulink>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- See
- <ulink url="http://code.google.com/apis/gdata/auth.html">Authentication Overview in the Google Data API documentation</ulink> for more
- information on each authentication method.
- </para>
- </sect3>
- <sect3 id="zend.gdata.health.connect.service">
- <title>Create A Health Service Instance</title>
- <para>
- In order to interact with Google Health, the client library provides the
- <classname>Zend_Gdata_Health</classname>
- service class. This class provides a common interface to the Google Data and Atom Publishing Protocol models and assists in marshaling
- requests to and from the Health API.
- </para>
- <para>
- Once you've decided on an authentication scheme, the next step is to create an instance of
- <classname>Zend_Gdata_Health</classname>
- . This class should be passed an instance of
- <classname>Zend_Gdata_HttpClient</classname>. This provides an interface for AuthSub/OAuth and ClientLogin to create a special
- authenticated HTTP client.
- </para>
- <para>
- To test against the H9 Developer's (/h9) instead of Google Health (/health), the
- <classname>Zend_Gdata_Health</classname> constructor takes an optional third argument for you to specify the H9 service name 'weaver'.
- </para>
- <para>
- The example below shows how to create a Health service class using ClientLogin authentication:
- </para>
- <programlisting language="php"><![CDATA[
- // Parameters for ClientLogin authentication
- $healthServiceName = Zend_Gdata_Health::HEALTH_SERVICE_NAME;
- //$h9ServiceName = Zend_Gdata_Health::H9_SANDBOX_SERVICE_NAME;
- $user = "user@gmail.com";
- $pass = "pa$$w0rd";
- // Create an authenticated HTTP client
- $client = Zend_Gdata_ClientLogin::getHttpClient($user,
- $pass,
- $healthServiceName);
- // Create an instance of the Health service
- $service = new Zend_Gdata_Health($client);
- ]]></programlisting>
- <para>
- A Health service using AuthSub can be created in a similar, though slightly more lengthy fashion. AuthSub is the
- recommend interface to communicate with Google Health because each token is directly linked to a specific profile in
- the user's account. Unlike other Google Data APIs, it is required that all requests from your application be digitally signed.
- </para>
- <programlisting language="php"><![CDATA[
- /*
- * Retrieve the current URL so that the AuthSub server knows where to
- * redirect the user after authentication is complete.
- */
- function getCurrentUrl() {
- $phpRequestUri = htmlentities(substr($_SERVER['REQUEST_URI'],
- 0,
- strcspn($_SERVER['REQUEST_URI'],
- "\n\r")),
- ENT_QUOTES);
- if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
- $protocol = 'https://';
- } else {
- $protocol = 'http://';
- }
- $host = $_SERVER['HTTP_HOST'];
- if ($_SERVER['SERVER_PORT'] != '' &&
- (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
- ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
- $port = ':' . $_SERVER['SERVER_PORT'];
- } else {
- $port = '';
- }
- return $protocol . $host . $port . $phpRequestUri;
- }
- /*
- * Redirect a user to AuthSub if they do not have a valid session token.
- * If they're coming back from AuthSub with a single-use token, instantiate
- * a new HTTP client and exchange the token for a long-lived session token
- * instead.
- */
- function setupClient($singleUseToken = null) {
- $client = null;
- // Fetch a new AuthSub token?
- if (!$singleUseToken) {
- $next = getCurrentUrl();
- $scope = 'https://www.google.com/health/feeds';
- $authSubHandler = 'https://www.google.com/health/authsub';
- $secure = 1;
- $session = 1;
- $authSubURL = Zend_Gdata_AuthSub::getAuthSubTokenUri($next,
- $scope,
- $secure,
- $session,
- $authSubHandler);
- // 1 - allows posting notices && allows reading profile data
- $permission = 1;
- $authSubURL .= '&permission=' . $permission;
- echo '<a href="' . $authSubURL . '">Your Google Health Account</a>';
- } else {
- $client = new Zend_Gdata_HttpClient();
- // This sets your private key to be used to sign subsequent requests
- $client->setAuthSubPrivateKeyFile('/path/to/your/rsa_private_key.pem',
- null,
- true);
- $sessionToken =
- Zend_Gdata_AuthSub::getAuthSubSessionToken(trim($singleUseToken),
- $client);
- // Set the long-lived session token for subsequent requests
- $client->setAuthSubToken($sessionToken);
- }
- return $client;
- }
- // -> Script execution begins here <-
- session_start();
- $client = setupClient(@$_GET['token']);
- // Create an instance of the Health service
- $userH9Sandbox = false;
- $healthService = new Zend_Gdata_Health($client,
- 'googleInc-MyTestAppName-v1.0',
- $userH9Sandbox);
- ]]></programlisting>
- <para>NOTE: the remainder of this document will assume you are using AuthSub for authentication.</para>
- </sect3>
- </sect2>
- <sect2 id="zend.gdata.health.profilefeed">
- <title>Profile Feed</title>
- <para>
- To query the user's profile feed, make sure your initial AuthSub token was requested with the <code>permission=1</code> parameter set.
- The process of extracting data from the profile requires two steps, sending a query and iterating through the resulting feed.
- </para>
- <sect3 id="zend.gdata.health.profilefeed.query">
- <title>Send a Structured Query</title>
- <para>
- You can send structured queries to retrieve specific records from a user's profile.
- </para>
- <para>
- When retrieving the profile using the Health API, specifically constructed query URLs are used to describe what (CCR) data
- should be returned. The <classname>Zend_Gdata_Health_Query</classname> class helps simplify this task by automatically constructing a query
- URL based on the parameters you set.
- </para>
- <sect4 id="zend.gdata.health.profilefeed.query.construct">
- <title>Query The Feed</title>
- <para>
- To execute a query against the profile feed, invoke a new instance of an <classname>Zend_Gdata_Health_Query</classname> and
- call the service's <code>getHealthProfileFeed()</code> method:
- </para>
- <programlisting language="php"><![CDATA[
- $healthService = new Zend_Gdata_Health($client);
- // example query for the top 10 medications with 2 items each
- $query = new Zend_Gdata_Health_Query();
- $query->setDigest("true");
- $query->setGrouped("true");
- $query->setMaxResultsGroup(10);
- $query->setMaxResultsInGroup(2);
- $query->setCategory("medication");
- $profileFeed = $healthService->getHealthProfileFeed($query);
- ]]></programlisting>
- <para>Using <code>setDigest("true")</code> returns all of user's CCR data in a single Atom <code><entry></code>.</para>
- <para>The <code>setCategory()</code> helper can be passed an additional parameter to return more specific CCR
- information. For example, to return just the medication Lipitor, use <code>setCategory("medication", "Lipitor")</code>. The same
- methodology can be applied to other categories such as conditions, allergies, lab results, etc.</para>
- <para>
- A full list of supported query parameters is available in the <ulink url="http://code.google.com/apis/health/reference.html#Parameters">query parameters section</ulink>
- of the Health API Reference Guide.
- </para>
- </sect4>
- </sect3>
- <sect3 id="zend.gdata.health.profilefeed.iterate">
- <title>Iterate Through The Profile Entries</title>
- <para>
- Each Google Health entry contains CCR data, however, using the <code>digest=true</code> query parameter will
- consolidate all of the CCR elements (that match your query) into a single Atom <code><entry></code>.
- </para>
- <para>
- To retrieve the full CCR information from an entry, make a call to the <classname>Zend_Gdata_Health_ProfileEntry</classname> class's <code>getCcr()</code> method.
- That returns a <classname>Zend_Gdata_Health_Extension_CCR</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- $entries = $profileFeed->getEntries();
- foreach ($entries as $entry) {
- $medications = $entry->getCcr()->getMedications();
- //$conditions = $entry->getCcr()->getConditions();
- //$immunizations = $entry->getCcr()->getImmunizations();
- // print the CCR xml (this will just be the entry's medications)
- foreach ($medications as $med) {
- $xmlStr = $med->ownerDocument->saveXML($med);
- echo "<pre>" . $xmlStr . "</pre>";
- }
- }
- ]]></programlisting>
- <para>
- Here, the <code>getCcr()</code> method is used in conjunction with a magic helper to drill down and extract just the
- medication data from the entry's CCR. The formentioned magic helper takes the form <code>getCATEGORYNAME()</code>, where
- <code>CATEGORYNAME</code> is a supported Google Health category. See the
- <ulink url="http://code.google.com/apis/health/reference.html#CatQueries">Google Health reference Guide</ulink> for the possible categories.
- </para>
- <para>
- To be more efficient, you can also use category queries to only return the necessary CCR from the Google Health servers. Then, iterate through those results:
- </para>
- <programlisting language="php"><![CDATA[
- $query = new Zend_Gdata_Health_Query();
- $query->setDigest("true");
- $query->setCategory("condition");
- $profileFeed = $healthService->getHealthProfileFeed($query);
- // Since the query contained digest=true, only one Atom entry is returned
- $entry = $profileFeed->entry[0];
- $conditions = $entry->getCcr()->getConditions();
- // print the CCR xml (this will just be the profile's conditions)
- foreach ($conditions as $cond) {
- $xmlStr = $cond->ownerDocument->saveXML($cond);
- echo "<pre>" . $xmlStr . "</pre>";
- }
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="zend.gdata.health.profilelist">
- <title>Profile List Feed</title>
- <para>NOTE: This feed is only available when using ClientLogin</para>
- <para>
- Since ClientLogin requires a profile ID with each of its feeds, applications will likely want to query this feed first in order
- to select the appropriate profile. The profile list feed returns Atom entries corresponding each profile in the user's
- Google Health account. The profile ID is returned in the Atom <code><content></code> and the profile name in the
- <code><title></code> element.
- </para>
- <sect3 id="zend.gdata.health.profilelist.query">
- <title>Query The Feed</title>
- <para>
- To execute a query against the profile list feed, call the service's <code>getHealthProfileListFeed()</code> method:
- </para>
- <programlisting language="php"><![CDATA[
- $client = Zend_Gdata_ClientLogin::getHttpClient('user@gmail.com',
- 'pa$$word',
- 'health');
- $healthService = new Zend_Gdata_Health($client);
- $feed = $healthService->getHealthProfileListFeed();
- // print each profile's name and id
- $entries = $feed->getEntries();
- foreach ($entries as $entry) {
- echo '<p>Profile name: ' . $entry->getProfileName() . '<br>';
- echo 'profile ID: ' . $entry->getProfileID() . '</p>';
- }
- ]]></programlisting>
- <para>
- Once you've determined which profile to use, call <code>setProfileID()</code> with the profileID as an argument.
- This will restrict subsequent API requests to be against that particular profile:
- </para>
- <programlisting language="php"><![CDATA[
- // use the first profile
- $profileID = $feed->entry[0]->getProfileID();
- $healthService->setProfileID($profileID);
- $profileFeed = $healthService->getHealthProfileFeed();
- $profileID = $healthService->getProfileID();
- echo '<p><b>Queried profileID</b>: ' . $profileID . '</p>';
- ]]></programlisting>
- </sect3>
- </sect2>
- <sect2 id="zend.gdata.health.notice">
- <title>Sending Notices to the Register Feed</title>
- <para>
- Individual posts to the register feed are known as notices. Notice are sent from third-party applications to inform the user
- of a new event. With AuthSub/OAuth, notices are the single means by which your application can add new CCR information
- into a user's profile. Notices can contain plain text (including certain XHTML elements), a CCR document, or both. As an example,
- notices might be sent to remind users to pick up a prescription, or they might contain lab results in the CCR format.
- </para>
- <sect3 id="zend.gdata.health.notice.send">
- <title>Sending a notice</title>
- <para>
- Notices can be sent by using the <code>sendHealthNotice()</code> method for the Health service:
- </para>
- <programlisting language="php"><![CDATA[
- $healthService = new Zend_Gdata_Health($client);
- $subject = "Title of your notice goes here";
- $body = "Notice body can contain <b>html</b> entities";
- $ccr = '<ContinuityOfCareRecord xmlns="urn:astm-org:CCR">
- <Body>
- <Problems>
- <Problem>
- <DateTime>
- <Type><Text>Start date</Text></Type>
- <ExactDateTime>2007-04-04T07:00:00Z</ExactDateTime>
- </DateTime>
- <Description>
- <Text>Aortic valve disorders</Text>
- <Code>
- <Value>410.10</Value>
- <CodingSystem>ICD9</CodingSystem>
- <Version>2004</Version>
- </Code>
- </Description>
- <Status><Text>Active</Text></Status>
- </Problem>
- </Problems>
- </Body>
- </ContinuityOfCareRecord>';
- $responseEntry = $healthService->sendHealthNotice($subject,
- $body,
- "html",
- $ccr);
- ]]></programlisting>
- </sect3>
- </sect2>
- </sect1>
|