// Package prescription 处方平台 package prescription import ( "bytes" "context" "encoding/json" "errors" "fmt" "hospital-admin-api/config" "hospital-admin-api/global" "hospital-admin-api/utils" "io" "net/http" "time" ) // 获取token请求值 type getTokeRequest struct { ClientId string `json:"clientId"` ClientSecret string `json:"clientSecret"` } // 通知处方平台订单取消 type noticePreOrderCancelRequest struct { OrgCode string `json:"orgCode"` // 机构编码 OrderNo string `json:"orderNo"` // 院内订单编号 OptCode string `json:"optCode"` // 操作状态 } // 通知处方平台订单取消返回数据 type noticePreOrderCancelResponse struct { ResultCode string `json:"resultCode"` // 操作编码 ResultDesc string `json:"resultDesc"` // 描述 } // ReportPreRequest 上报处方请求值-基础数据 type ReportPreRequest struct { TerminalCode string `json:"terminalCode"` // 终端代码 OrderNo string `json:"orderNo"` // 订单编号 TransactNo string `json:"transactNo"` // 流水单号 PayDate string `json:"payDate"` // 支付时间 Money float64 `json:"money"` // 订单金额 Freight float64 `json:"freight"` // 运费(单位:元) TakeTypeCode int `json:"takeTypeCode"` // 取货方式 1 自提 2 快递,目前只支持快递,传固定值 2 BuyerName string `json:"buyerName"` // 收货人姓名 BuyerPhone string `json:"buyerPhone"` // 收货人联系方式 BuyerAddress string `json:"buyerAddress"` // 收货人地址 ProvinceCode string `json:"provinceCode"` // 收货地址(省) 编码 ProvinceName string `json:"provinceName"` // 收货地址(省) 名称 CityCode string `json:"cityCode"` // 收货地址(市) 编码 CityName string `json:"cityName"` // 收货地址(市) 名称 DistrictCode string `json:"districtCode"` // 收货地址(区 县)编码 DistrictName string `json:"districtName"` // 收货地址(区 县)名称 PresList []PresRequest `json:"presList"` // 处方列表 } // PresRequest 上报处方请求值-处方数据 type PresRequest struct { PrescriptionNo string `json:"prescriptionNo"` // 处方编号 PrescriptionSubType int `json:"prescriptionSubType"` // 处方类型 0:无类型 1:普通处方 2:儿科处方 PatientName string `json:"patientName"` // 就诊人姓名 PatientPhone string `json:"patientPhone"` // 就诊人联系方式 IdCard string `json:"idCard"` // 身份证号 Advice string `json:"advice"` // 医嘱 DiagnosisName string `json:"diagnosisName"` // 诊断 ThirdDoctorName string `json:"thirdDoctorName"` // 开方医生姓名 ThirdDeptName string `json:"thirdDeptName"` // 开方科室名称 ThirdDoctorNameImg string `json:"thirdDoctorNameImg"` // 开方医生签名链接 PrescriptionTime string `json:"prescriptionTime"` // 开方时间 ThirdFirstPharmacist string `json:"thirdFirstPharmacist"` // 初审药师姓名 ThirdFirstPharmacistImg string `json:"thirdFirstPharmacistImg"` // 初审药师签名链接 ThirdFirstTime string `json:"thirdFirstTime"` // 初审时间 ThirdLastPharmacist string `json:"thirdLastPharmacist"` // 终审药师姓名 ThirdLastPharmacistImg string `json:"thirdLastPharmacistImg"` // 终审药师签名链接 ThirdLastTime string `json:"ThirdLastTime"` // 终审时间 ThirdSignImg string `json:"thirdSignImg"` // 处方签章链接 ReferenceCharge float64 `json:"referenceCharge"` // 处方费用(不包含运费) ChiefComplaint string `json:"chiefComplaint"` // 主诉 HistoryPresent string `json:"historyPresent"` // 现病史 PastHistory string `json:"pastHistory"` // 既往史 PhysicalExamination string `json:"physicalExamination"` // 体格检查 SupplementaryExamination string `json:"supplementaryExamination"` // 辅助检查 AllergicHistory string `json:"allergicHistory"` // 过敏史 DrugList []DrugListRequest `json:"drugList"` // 药品列表 OrderDrugList []OrderDrugListRequest `json:"orderDrugList"` // 订单药品列表 } // DrugListRequest 上报处方请求值-药品数据1 type DrugListRequest struct { DrugCode string `json:"drugCode"` // 药品编码 ApprovalNumber string `json:"approvalNumber"` // 批准文号 DrugName string `json:"drugName"` // 药品名称 Specifications string `json:"specifications"` // 药品规格 Price float64 `json:"price"` // 药品单价 PackingCount int `json:"packingCount"` // 药品数量 SurplusPackingCount int `json:"surplusPackingCount"` // 处方药品剩余使用数量 PackingUnit string `json:"packingUnit"` // 药品单位 SingleDosage int `json:"singleDosage"` // 单次用量 SingleDosageUnit string `json:"singleDosageUnit"` // 单次用量单位 UseName string `json:"useName"` // 用法名称 FrequencyName string `json:"frequencyName"` // 频次名称 UseDays int `json:"useDays"` // 使用天数 } // OrderDrugListRequest 上报处方请求值-药品数据2 type OrderDrugListRequest struct { DrugCode string `json:"drugCode"` // 药品编码 ApprovalNumber string `json:"approvalNumber"` // 批准文号 DrugName string `json:"drugName"` // 药品名称 Specifications string `json:"specifications"` // 药品规格 Price float64 `json:"price"` // 药品单价 DrugCount int `json:"drugCount"` // 药品数量 PackingUnit string `json:"packingUnit"` // 药品单位 ActualSellingPrice float64 `json:"actual_product_price"` // 药品实际销售单价 } // GetProdStockRequest 获取商品库存请求值 type GetProdStockRequest struct { PharmacyCode string `json:"pharmacyCode"` // 药房编码 DrugCode string `json:"drugCode"` // 三方药房药品编码 } // 上报处方返回数据 type reportPreResponse struct { ResultCode string `json:"resultCode"` // 操作编码 ResultDesc string `json:"resultDesc"` // 描述 } // 获取商品库存返回数据 type getProdStockResponse struct { ResultCode string `json:"resultCode"` // 操作编码 ResultDesc string `json:"resultDesc"` // 描述 Data []GetProdStockDataResponse `json:"data"` // 具体内容 } type GetProdStockDataResponse struct { Quantity string `json:"quantity"` // 库存 Threshold string `json:"threshold"` // 库存阈值 } // GetToken 获取token func GetToken() (string, error) { // 准备要发送的 JSON 数据 requestData := getTokeRequest{ ClientId: config.C.Pre.PrePlatClientId, ClientSecret: config.C.Pre.PrePlatClientSecret, } // 将 JSON 数据编码为字节数组 jsonData, err := json.Marshal(requestData) if err != nil { return "", err } // 准备请求体 requestBody := bytes.NewBuffer(jsonData) // 设置请求 URL url := config.C.Pre.PrePlatAppUrl + "v1/user_thrid/token" // 创建 POST 请求 req, err := http.NewRequest("POST", url, requestBody) if err != nil { return "", err } // 设置请求头 req.Header.Set("Content-Type", "application/json") // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { return "", err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) // 检查响应状态码 if resp.StatusCode != 200 { return "", errors.New("返回数据错误") } // 读取响应体 var response map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return "", errors.New("返回数据错误") } // 获取 result 字段 result, ok := response["data"].(map[string]interface{})["result"].(map[string]interface{}) if !ok { return "", errors.New("返回数据错误2") } // 获取 token 值 token, ok := result["token"].(string) if !ok { return "", errors.New("返回数据错误3") } // 添加缓存 _, err = global.Redis.Set(context.Background(), "prescription_token", token, (60*60*1.5)*time.Second).Result() if err != nil { return "", errors.New("添加缓存失败") } return token, nil } // NoticePreOrderCancel 通知处方平台订单取消 func NoticePreOrderCancel(orderNo string) (bool, error) { // 准备要发送的 JSON 数据 data := noticePreOrderCancelRequest{ OrgCode: config.C.Pre.PrePlatPharmacyCode, OrderNo: orderNo, OptCode: "EVTDOD-04", } // 将 JSON 数据编码为字节数组 jsonData, err := json.Marshal(data) if err != nil { return false, err } // 准备请求体 requestBody := bytes.NewBuffer(jsonData) // 设置请求 URL url := config.C.Pre.PrePlatAppUrl + "v1/preOrder/changeOrderByOrg" // 创建 POST 请求 req, err := http.NewRequest("POST", url, requestBody) if err != nil { return false, err } // 设置请求头,指定 Content-Type 为 application/json req.Header.Set("Content-Type", "application/json") token, _ := global.Redis.Get(context.Background(), "prescription_token").Result() if token == "" { token, err = GetToken() if err != nil { return false, err } } req.Header.Set("Authorization", "Bearer "+token) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { return false, err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) // 检查响应状态码 if resp.StatusCode != 200 { return false, errors.New("返回数据错误") } var response noticePreOrderCancelResponse err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return false, err } fmt.Println(response) if response.ResultCode != "1000" { if response.ResultDesc != "" { return false, errors.New(response.ResultDesc) } return false, errors.New("取消处方平台订单失败") } return true, nil } // ReportPre 上报处方 func (r ReportPreRequest) ReportPre() (bool, error) { jsonData, err := json.Marshal(r) if err != nil { return false, err } utils.LogJsonInfo("上报处方平台:", jsonData) // 准备请求体 requestBody := bytes.NewBuffer(jsonData) // 设置请求 URL url := config.C.Pre.PrePlatAppUrl + "v1/preOrder/receivePreOrder" // 创建 POST 请求 req, err := http.NewRequest("POST", url, requestBody) if err != nil { return false, err } // 设置请求头,指定 Content-Type 为 application/json req.Header.Set("Content-Type", "application/json") token, _ := global.Redis.Get(context.Background(), "prescription_token").Result() if token == "" { token, err = GetToken() if err != nil { return false, err } } req.Header.Set("Authorization", "Bearer "+token) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { return false, err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) // 检查响应状态码 if resp.StatusCode != 200 { return false, errors.New("返回数据错误") } var response reportPreResponse err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return false, err } if response.ResultCode != "1000" { if response.ResultDesc != "" { return false, errors.New(response.ResultDesc) } return false, errors.New("上报处方平台失败") } return true, nil } // GetProdStock 获取商品库存 func (r GetProdStockRequest) GetProdStock() (*GetProdStockDataResponse, error) { r.PharmacyCode = config.C.Pre.PrePlatPharmacyCode jsonData, err := json.Marshal(r) if err != nil { return nil, err } // 准备请求体 requestBody := bytes.NewBuffer(jsonData) // 设置请求 URL url := config.C.Pre.PrePlatAppUrl + "v1/pharmacy/pharmacyInventory" // 创建 POST 请求 req, err := http.NewRequest("POST", url, requestBody) if err != nil { return nil, err } // 设置请求头,指定 Content-Type 为 application/json req.Header.Set("Content-Type", "application/json") token, _ := global.Redis.Get(context.Background(), "prescription_token").Result() if token == "" { token, err = GetToken() if err != nil { return nil, err } } req.Header.Set("Authorization", "Bearer "+token) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) // 检查响应状态码 if resp.StatusCode != 200 { return nil, errors.New("返回数据错误") } var response getProdStockResponse err = json.NewDecoder(resp.Body).Decode(&response) if err != nil { return nil, err } if response.ResultCode != "1000" { if response.ResultDesc != "" { return nil, errors.New(response.ResultDesc) } return nil, errors.New("获取商品库存失败") } return &response.Data[0], nil }