通过FHIR和EPIC进行对接

说明

Epic是全美最大电子病历供应商。

FHIR (Fast Health Interoperability Resources)旨在实现医疗健康信息的交换。其中包括了临床数据和健康相关的行政管理数据、公共卫生和临床研究数据。既包括了人类和兽医,又适合大多数应用场景——住院、慢病管理、社区护理、健康联盟等。

https://fhir.epic.com/ 中有详细的文档

这里有详细的注册测试账号和沙箱使用的说明。

生成token

调用get_token函数生成token。 

        public static string make_jwt(Option option)
        {
            Dictionary<string, object> h = new Dictionary<string, object>();
            h["alg"] = "RS384";
            h["typ"] = "JWT";
            h["kid"] = option.kid ;
            string header = Newtonsoft.Json.JsonConvert.SerializeObject(h);
            DateTime d1 = DateTime.UtcNow.AddSeconds(60 * 4);
            //1970-01-01T00:00:00Z UTC)
            DateTime d0 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            int exp = ((int)(d1 - d0).TotalSeconds);
            Dictionary<string, object> p = new Dictionary<string, object>();
            p["iss"] = option.client_id;
            p["sub"] = option.client_id;
            p["aud"] = option.oauth_url;
            p["jti"] = Guid.NewGuid().ToString("N");
            p["exp"] = exp;
            string payload = Newtonsoft.Json.JsonConvert.SerializeObject(p);

            //signature = RSA-SHA384(base64urlEncoding(header) + '.' + base64urlEncoding(payload), privatekey)
            byte[] signature_buff = RSASha384Signature.SignData(Base64UrlEncoder.base64urlEncoding(header) + '.' + Base64UrlEncoder.base64urlEncoding(payload), option.privatekey_pem);

            string jwt = Base64UrlEncoder.base64urlEncoding(header) + '.' + Base64UrlEncoder.base64urlEncoding(payload) + '.' + Base64UrlEncoder.Encode(signature_buff);
            return jwt;
        }

        public static string get_token(Option option)
        {
            string jwt = make_jwt(option);
            Dictionary<string, string> postParameters = new Dictionary<string, string>();
            postParameters["grant_type"] = "client_credentials";
            postParameters["client_assertion_type"] = "urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer";
            postParameters["client_assertion"] = jwt;
            Dictionary<string, string> Headers = new Dictionary<string, string>();
            StringBuilder paraStrBuilder = new StringBuilder();
            foreach (string key in postParameters.Keys)
            {
                paraStrBuilder.AppendFormat("{0}={1}&", key, postParameters[key]);
            }
            string para = paraStrBuilder.ToString();
            if (para.EndsWith("&"))
                para = para.Remove(para.Length - 1, 1);
            string result;
            HttpUtils.HttpPostBuff(option.oauth_url, Headers, para, out result, option.proxy_url, option.proxy_port); 
            return result;
        }

使用了RSASha384

    public class RSASha384Signature
    {
        public static byte[] SignData(string data, string privatekey_pem)
        {
            using (var rsa = new RSACryptoServiceProvider())
            {

                RsaPrivateCrtKeyParameters privateKeyParams = ReadPrivateKey(privatekey_pem);
                RSAParameters rsaParams = new RSAParameters();
                rsaParams.Modulus = privateKeyParams.Modulus.ToByteArrayUnsigned();
                rsaParams.Exponent = privateKeyParams.PublicExponent.ToByteArrayUnsigned();
                rsaParams.D = privateKeyParams.Exponent.ToByteArrayUnsigned();
                rsaParams.P = privateKeyParams.P.ToByteArrayUnsigned();
                rsaParams.Q = privateKeyParams.Q.ToByteArrayUnsigned();
                rsaParams.DP = privateKeyParams.DP.ToByteArrayUnsigned();
                rsaParams.DQ = privateKeyParams.DQ.ToByteArrayUnsigned();
                rsaParams.InverseQ = privateKeyParams.QInv.ToByteArrayUnsigned();
                rsa.ImportParameters(rsaParams);
                // 使用SHA384进行签名
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                byte[] signature = rsa.SignData(dataBytes, CryptoConfig.MapNameToOID("SHA384"));
                return signature;
            }
        }
        public static RsaPrivateCrtKeyParameters ReadPrivateKey(string privatekey_pem)
        {
            using (TextReader reader = new StringReader(privatekey_pem))
            {
                var pemReader = new PemReader(reader);
                var keyPair = pemReader.ReadObject() as RsaPrivateCrtKeyParameters;
                if (keyPair != null)
                {
                    return keyPair;
                }

                throw new InvalidDataException("Private key not found in file.");
            }
        }
    }

查询病人

查询病人可以使用 Hl7.Fhir.Rest (主要EPIC的有些接口 使用Hl7.Fhir.Rest  会报错,主要是日期格式)

            try
            {
                FhirClient client = Pub.get_FhirClient();
                SearchParams param = new SearchParams();
                if (textBox_given.Text.Trim() != "")
                    param.Add("given", textBox_given.Text.Trim());
                if (textBox_identifier.Text.Trim() != "")
                    param.Add("identifier", textBox_identifier.Text.Trim());
                if (textBox_family.Text.Trim() != "")
                    param.Add("family", textBox_family.Text.Trim()); 
                
                param.Count = 10; 
                Bundle b = client.Search<Patient>(param);
                display_patient(b);
            }
            catch (Exception err)
            {
                textBox_result.Text = err.Message;
            } 

病人数据

search_by_patient("Appointment"); 

search_by_patient("Condition");

 search_by_patient("Coverage");

 search_by_patient("DiagnosticReport");

search_by_patient("DocumentReference");

search_by_patient("Encounter");

search_by_patient("Immunization");

search_by_patient("InsurancePlan");

search_by_patient("MedicationRequest");

search_by_patient("MedicationStatement");

 search_by_patient("Observation");

search_by_patient("Procedure");

search_by_patient("QuestionnaireResponse");

search_by_patient("ServiceRequest");

search_by_patient("Slot");

private void search_by_patient(string type)
        {
            if (PatientId == "")
            {
                MessageBox.Show("Please select patient");
                return;
            }
            try
            {
               // Pub.get_FhirClient().Get(type + "?patient=" + PatientId);
                string json = Pub.get_RestClient(type + "?patient=" + PatientId);
                json = Pub.check_date(json);
                FhirJsonParser fp = new FhirJsonParser();
                Hl7.Fhir.Model.Bundle b = fp.Parse<Hl7.Fhir.Model.Bundle>(json);
                Form_List frm = new Form_List();
                frm.show_list(b);
                frm.ShowDialog();
                frm.Dispose();
            }
            catch (Exception err)
            {

                textBox_result.Text = err.Message;
            }
           
        }

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月巴月巴白勺合鸟月半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值