2
0

Zend_Gdata_Health.xml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->
  3. <sect1 id="zend.gdata.health">
  4. <title>Using Google Health</title>
  5. <para>
  6. The Google Health Data API is designed to enable developers to do two things:
  7. <itemizedlist>
  8. <listitem>
  9. <para>
  10. Read a user's Google Health profile or query for medical records that match particular criteria and then
  11. use the results to provide personalized functionality based on the data.
  12. </para>
  13. </listitem>
  14. <listitem>
  15. <para>
  16. 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
  17. within the &lt;atom&gt; entry. The library does not provide direct accessors to the object model but it does have helpers for extracting specific fields.
  18. </para>
  19. </listitem>
  20. </itemizedlist>
  21. </para>
  22. <para>
  23. There are three main feeds, each of which requires authentication. Unlike other Google Data APIs, each Google Health feed has a limited set of
  24. HTTP operations you can perform on it, depending on which authentication method you are using (ClientLogin or AuthSub/OAuth).
  25. 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>.
  26. <itemizedlist>
  27. <listitem>
  28. <para>
  29. <firstterm>Profile Feed</firstterm>
  30. use the profile feed to query a user's health profile for specific information.
  31. </para>
  32. </listitem>
  33. <listitem>
  34. <para>
  35. <firstterm>Register Feed</firstterm>
  36. use the register feed to reconcile new CCR data into a profile.
  37. </para>
  38. </listitem>
  39. <listitem>
  40. <para>
  41. <firstterm>Profile List Feed</firstterm>
  42. the profile list feed should be used to determine which of the user's Health profiles to interact with.
  43. This feed is only available when using ClientLogin.
  44. </para>
  45. </listitem>
  46. </itemizedlist>
  47. </para>
  48. <para>
  49. See <ulink url="http://code.google.com/apis/health/">http://code.google.com/apis/health</ulink>
  50. for more information about the Google Health API.
  51. </para>
  52. <sect2 id="zend.gdata.health.connect">
  53. <title>Connect To The Health Service</title>
  54. <para>
  55. 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.
  56. Traffic between a client and the Google Health servers occurs over HTTP and allows for authenticated connections.
  57. </para>
  58. <para>
  59. 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
  60. and binding a <classname>Zend_Gdata_Health</classname> service instance to that client.
  61. </para>
  62. <sect3 id="zend.gdata.health.connect.authentication">
  63. <title>Authentication</title>
  64. <para>
  65. The Google Health API allows programmatic access to a user's Health profile. There are three authentication schemes that are supported by Google Health:
  66. </para>
  67. <itemizedlist>
  68. <listitem>
  69. <para>
  70. <firstterm>ClientLogin</firstterm>
  71. provides direct username/password authentication to the Health servers. Since this method requires that users provide your application
  72. with their password, this authentication scheme is only recommended for installed/desktop applications.
  73. </para>
  74. </listitem>
  75. <listitem>
  76. <para>
  77. <firstterm>AuthSub</firstterm>
  78. allows a user to authorize the sharing of their private data. This provides the same level of convenience as ClientLogin but without the
  79. security risk, making it an ideal choice for web-based applications. For Google Health, AuthSub must be used
  80. in registered and secure mode--meaning that all requests to the API must be digitally signed.
  81. </para>
  82. </listitem>
  83. <listitem>
  84. <para>
  85. <firstterm>OAuth</firstterm>
  86. is an alternative to AuthSub. Although this authentication scheme is not discussed in this document, more information can
  87. be found in the <ulink url="http://code.google.com/apis/health/developers_guide_protocol.html#OAuth">Health Data API Developer's Guide</ulink>.
  88. </para>
  89. </listitem>
  90. </itemizedlist>
  91. <para>
  92. See
  93. <ulink url="http://code.google.com/apis/gdata/auth.html">Authentication Overview in the Google Data API documentation</ulink> for more
  94. information on each authentication method.
  95. </para>
  96. </sect3>
  97. <sect3 id="zend.gdata.health.connect.service">
  98. <title>Create A Health Service Instance</title>
  99. <para>
  100. In order to interact with Google Health, the client library provides the
  101. <classname>Zend_Gdata_Health</classname>
  102. service class. This class provides a common interface to the Google Data and Atom Publishing Protocol models and assists in marshaling
  103. requests to and from the Health API.
  104. </para>
  105. <para>
  106. Once you've decided on an authentication scheme, the next step is to create an instance of
  107. <classname>Zend_Gdata_Health</classname>
  108. . This class should be passed an instance of
  109. <classname>Zend_Gdata_HttpClient</classname>. This provides an interface for AuthSub/OAuth and ClientLogin to create a special
  110. authenticated HTTP client.
  111. </para>
  112. <para>
  113. To test against the H9 Developer's (/h9) instead of Google Health (/health), the
  114. <classname>Zend_Gdata_Health</classname> constructor takes an optional third argument for you to specify the H9 service name 'weaver'.
  115. </para>
  116. <para>
  117. The example below shows how to create a Health service class using ClientLogin authentication:
  118. </para>
  119. <programlisting language="php"><![CDATA[
  120. // Parameters for ClientLogin authentication
  121. $healthServiceName = Zend_Gdata_Health::HEALTH_SERVICE_NAME;
  122. //$h9ServiceName = Zend_Gdata_Health::H9_SANDBOX_SERVICE_NAME;
  123. $user = "user@gmail.com";
  124. $pass = "pa$$w0rd";
  125. // Create an authenticated HTTP client
  126. $client = Zend_Gdata_ClientLogin::getHttpClient($user,
  127. $pass,
  128. $healthServiceName);
  129. // Create an instance of the Health service
  130. $service = new Zend_Gdata_Health($client);
  131. ]]></programlisting>
  132. <para>
  133. A Health service using AuthSub can be created in a similar, though slightly more lengthy fashion. AuthSub is the
  134. recommend interface to communicate with Google Health because each token is directly linked to a specific profile in
  135. the user's account. Unlike other Google Data APIs, it is required that all requests from your application be digitally signed.
  136. </para>
  137. <programlisting language="php"><![CDATA[
  138. /*
  139. * Retrieve the current URL so that the AuthSub server knows where to
  140. * redirect the user after authentication is complete.
  141. */
  142. function getCurrentUrl() {
  143. $phpRequestUri = htmlentities(substr($_SERVER['REQUEST_URI'],
  144. 0,
  145. strcspn($_SERVER['REQUEST_URI'],
  146. "\n\r")),
  147. ENT_QUOTES);
  148. if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
  149. $protocol = 'https://';
  150. } else {
  151. $protocol = 'http://';
  152. }
  153. $host = $_SERVER['HTTP_HOST'];
  154. if ($_SERVER['SERVER_PORT'] != '' &&
  155. (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
  156. ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
  157. $port = ':' . $_SERVER['SERVER_PORT'];
  158. } else {
  159. $port = '';
  160. }
  161. return $protocol . $host . $port . $phpRequestUri;
  162. }
  163. /*
  164. * Redirect a user to AuthSub if they do not have a valid session token.
  165. * If they're coming back from AuthSub with a single-use token, instantiate
  166. * a new HTTP client and exchange the token for a long-lived session token
  167. * instead.
  168. */
  169. function setupClient($singleUseToken = null) {
  170. $client = null;
  171. // Fetch a new AuthSub token?
  172. if (!$singleUseToken) {
  173. $next = getCurrentUrl();
  174. $scope = 'https://www.google.com/health/feeds';
  175. $authSubHandler = 'https://www.google.com/health/authsub';
  176. $secure = 1;
  177. $session = 1;
  178. $authSubURL = Zend_Gdata_AuthSub::getAuthSubTokenUri($next,
  179. $scope,
  180. $secure,
  181. $session,
  182. $authSubHandler);
  183. // 1 - allows posting notices && allows reading profile data
  184. $permission = 1;
  185. $authSubURL .= '&permission=' . $permission;
  186. echo '<a href="' . $authSubURL . '">Your Google Health Account</a>';
  187. } else {
  188. $client = new Zend_Gdata_HttpClient();
  189. // This sets your private key to be used to sign subsequent requests
  190. $client->setAuthSubPrivateKeyFile('/path/to/your/rsa_private_key.pem',
  191. null,
  192. true);
  193. $sessionToken =
  194. Zend_Gdata_AuthSub::getAuthSubSessionToken(trim($singleUseToken),
  195. $client);
  196. // Set the long-lived session token for subsequent requests
  197. $client->setAuthSubToken($sessionToken);
  198. }
  199. return $client;
  200. }
  201. // -> Script execution begins here <-
  202. session_start();
  203. $client = setupClient(@$_GET['token']);
  204. // Create an instance of the Health service
  205. $userH9Sandbox = false;
  206. $healthService = new Zend_Gdata_Health($client,
  207. 'googleInc-MyTestAppName-v1.0',
  208. $userH9Sandbox);
  209. ]]></programlisting>
  210. <para>NOTE: the remainder of this document will assume you are using AuthSub for authentication.</para>
  211. </sect3>
  212. </sect2>
  213. <sect2 id="zend.gdata.health.profilefeed">
  214. <title>Profile Feed</title>
  215. <para>
  216. To query the user's profile feed, make sure your initial AuthSub token was requested with the <code>permission=1</code> parameter set.
  217. The process of extracting data from the profile requires two steps, sending a query and iterating through the resulting feed.
  218. </para>
  219. <sect3 id="zend.gdata.health.profilefeed.query">
  220. <title>Send a Structured Query</title>
  221. <para>
  222. You can send structured queries to retrieve specific records from a user's profile.
  223. </para>
  224. <para>
  225. When retrieving the profile using the Health API, specifically constructed query URLs are used to describe what (CCR) data
  226. should be returned. The <classname>Zend_Gdata_Health_Query</classname> class helps simplify this task by automatically constructing a query
  227. URL based on the parameters you set.
  228. </para>
  229. <sect4 id="zend.gdata.health.profilefeed.query.construct">
  230. <title>Query The Feed</title>
  231. <para>
  232. To execute a query against the profile feed, invoke a new instance of an <classname>Zend_Gdata_Health_Query</classname> and
  233. call the service's <code>getHealthProfileFeed()</code> method:
  234. </para>
  235. <programlisting language="php"><![CDATA[
  236. $healthService = new Zend_Gdata_Health($client);
  237. // example query for the top 10 medications with 2 items each
  238. $query = new Zend_Gdata_Health_Query();
  239. $query->setDigest("true");
  240. $query->setGrouped("true");
  241. $query->setMaxResultsGroup(10);
  242. $query->setMaxResultsInGroup(2);
  243. $query->setCategory("medication");
  244. $profileFeed = $healthService->getHealthProfileFeed($query);
  245. ]]></programlisting>
  246. <para>Using <code>setDigest("true")</code> returns all of user's CCR data in a single Atom <code>&lt;entry&gt;</code>.</para>
  247. <para>The <code>setCategory()</code> helper can be passed an additional parameter to return more specific CCR
  248. information. For example, to return just the medication Lipitor, use <code>setCategory("medication", "Lipitor")</code>. The same
  249. methodology can be applied to other categories such as conditions, allergies, lab results, etc.</para>
  250. <para>
  251. 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>
  252. of the Health API Reference Guide.
  253. </para>
  254. </sect4>
  255. </sect3>
  256. <sect3 id="zend.gdata.health.profilefeed.iterate">
  257. <title>Iterate Through The Profile Entries</title>
  258. <para>
  259. Each Google Health entry contains CCR data, however, using the <code>digest=true</code> query parameter will
  260. consolidate all of the CCR elements (that match your query) into a single Atom <code>&lt;entry&gt;</code>.
  261. </para>
  262. <para>
  263. 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.
  264. That returns a <classname>Zend_Gdata_Health_Extension_CCR</classname>:
  265. </para>
  266. <programlisting language="php"><![CDATA[
  267. $entries = $profileFeed->getEntries();
  268. foreach ($entries as $entry) {
  269. $medications = $entry->getCcr()->getMedications();
  270. //$conditions = $entry->getCcr()->getConditions();
  271. //$immunizations = $entry->getCcr()->getImmunizations();
  272. // print the CCR xml (this will just be the entry's medications)
  273. foreach ($medications as $med) {
  274. $xmlStr = $med->ownerDocument->saveXML($med);
  275. echo "<pre>" . $xmlStr . "</pre>";
  276. }
  277. }
  278. ]]></programlisting>
  279. <para>
  280. Here, the <code>getCcr()</code> method is used in conjunction with a magic helper to drill down and extract just the
  281. medication data from the entry's CCR. The formentioned magic helper takes the form <code>getCATEGORYNAME()</code>, where
  282. <code>CATEGORYNAME</code> is a supported Google Health category. See the
  283. <ulink url="http://code.google.com/apis/health/reference.html#CatQueries">Google Health reference Guide</ulink> for the possible categories.
  284. </para>
  285. <para>
  286. 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:
  287. </para>
  288. <programlisting language="php"><![CDATA[
  289. $query = new Zend_Gdata_Health_Query();
  290. $query->setDigest("true");
  291. $query->setCategory("condition");
  292. $profileFeed = $healthService->getHealthProfileFeed($query);
  293. // Since the query contained digest=true, only one Atom entry is returned
  294. $entry = $profileFeed->entry[0];
  295. $conditions = $entry->getCcr()->getConditions();
  296. // print the CCR xml (this will just be the profile's conditions)
  297. foreach ($conditions as $cond) {
  298. $xmlStr = $cond->ownerDocument->saveXML($cond);
  299. echo "<pre>" . $xmlStr . "</pre>";
  300. }
  301. ]]></programlisting>
  302. </sect3>
  303. </sect2>
  304. <sect2 id="zend.gdata.health.profilelist">
  305. <title>Profile List Feed</title>
  306. <para>NOTE: This feed is only available when using ClientLogin</para>
  307. <para>
  308. Since ClientLogin requires a profile ID with each of its feeds, applications will likely want to query this feed first in order
  309. to select the appropriate profile. The profile list feed returns Atom entries corresponding each profile in the user's
  310. Google Health account. The profile ID is returned in the Atom <code>&lt;content&gt;</code> and the profile name in the
  311. <code>&lt;title&gt;</code> element.
  312. </para>
  313. <sect3 id="zend.gdata.health.profilelist.query">
  314. <title>Query The Feed</title>
  315. <para>
  316. To execute a query against the profile list feed, call the service's <code>getHealthProfileListFeed()</code> method:
  317. </para>
  318. <programlisting language="php"><![CDATA[
  319. $client = Zend_Gdata_ClientLogin::getHttpClient('user@gmail.com',
  320. 'pa$$word',
  321. 'health');
  322. $healthService = new Zend_Gdata_Health($client);
  323. $feed = $healthService->getHealthProfileListFeed();
  324. // print each profile's name and id
  325. $entries = $feed->getEntries();
  326. foreach ($entries as $entry) {
  327. echo '<p>Profile name: ' . $entry->getProfileName() . '<br>';
  328. echo 'profile ID: ' . $entry->getProfileID() . '</p>';
  329. }
  330. ]]></programlisting>
  331. <para>
  332. Once you've determined which profile to use, call <code>setProfileID()</code> with the profileID as an argument.
  333. This will restrict subsequent API requests to be against that particular profile:
  334. </para>
  335. <programlisting language="php"><![CDATA[
  336. // use the first profile
  337. $profileID = $feed->entry[0]->getProfileID();
  338. $healthService->setProfileID($profileID);
  339. $profileFeed = $healthService->getHealthProfileFeed();
  340. $profileID = $healthService->getProfileID();
  341. echo '<p><b>Queried profileID</b>: ' . $profileID . '</p>';
  342. ]]></programlisting>
  343. </sect3>
  344. </sect2>
  345. <sect2 id="zend.gdata.health.notice">
  346. <title>Sending Notices to the Register Feed</title>
  347. <para>
  348. Individual posts to the register feed are known as notices. Notice are sent from third-party applications to inform the user
  349. of a new event. With AuthSub/OAuth, notices are the single means by which your application can add new CCR information
  350. into a user's profile. Notices can contain plain text (including certain XHTML elements), a CCR document, or both. As an example,
  351. notices might be sent to remind users to pick up a prescription, or they might contain lab results in the CCR format.
  352. </para>
  353. <sect3 id="zend.gdata.health.notice.send">
  354. <title>Sending a notice</title>
  355. <para>
  356. Notices can be sent by using the <code>sendHealthNotice()</code> method for the Health service:
  357. </para>
  358. <programlisting language="php"><![CDATA[
  359. $healthService = new Zend_Gdata_Health($client);
  360. $subject = "Title of your notice goes here";
  361. $body = "Notice body can contain <b>html</b> entities";
  362. $ccr = '<ContinuityOfCareRecord xmlns="urn:astm-org:CCR">
  363. <Body>
  364. <Problems>
  365. <Problem>
  366. <DateTime>
  367. <Type><Text>Start date</Text></Type>
  368. <ExactDateTime>2007-04-04T07:00:00Z</ExactDateTime>
  369. </DateTime>
  370. <Description>
  371. <Text>Aortic valve disorders</Text>
  372. <Code>
  373. <Value>410.10</Value>
  374. <CodingSystem>ICD9</CodingSystem>
  375. <Version>2004</Version>
  376. </Code>
  377. </Description>
  378. <Status><Text>Active</Text></Status>
  379. </Problem>
  380. </Problems>
  381. </Body>
  382. </ContinuityOfCareRecord>';
  383. $responseEntry = $healthService->sendHealthNotice($subject,
  384. $body,
  385. "html",
  386. $ccr);
  387. ]]></programlisting>
  388. </sect3>
  389. </sect2>
  390. </sect1>