微信后端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
18 KiB

package com.ynxbd.ali.helper;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayCommerceMedicalAuthinfoAuthQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AuthExtendParams;
import com.alipay.api.domain.MedicalNationalPayAuthInfo;
import com.alipay.api.request.AlipayCommerceMedicalAuthinfoAuthQueryRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayCommerceMedicalAuthinfoAuthQueryResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.ynxbd.ali.config.AliConfig;
import com.ynxbd.ali.config.AliMIConfig;
import com.ynxbd.common.bean.pay.Order;
import com.ynxbd.common.helper.common.DateHelper;
import com.ynxbd.common.helper.common.ErrorHelper;
import com.ynxbd.common.helper.common.JsonHelper;
import com.ynxbd.common.result.ServiceException;
import com.ynxbd.wx.wxfactory.bean.OrderMIEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.*;
@Slf4j
public class AliMedicalHelper {
/**
* 国家医保局线上业务身份核验信息授权查询接口[alipay_commerce_medical_authinfo_auth_query_response]
*
* @param openId openId
* @param accessToken accessToken
* @param patientName 用户姓名
* @param patientCardNo 用户证件号
* @param callUrl 回调地址
* @return info
*/
public static MedicalNationalPayAuthInfo queryMIAuth(String openId, String accessToken, String patientName, String patientCardNo, String reqBizNo, String callUrl) throws Exception {
// 初始化SDK
AlipayClient alipayClient = new DefaultAlipayClient(AliConfig.getAlipayConfig());
// 构造请求参数以调用接口
AlipayCommerceMedicalAuthinfoAuthQueryRequest request = new AlipayCommerceMedicalAuthinfoAuthQueryRequest();
AlipayCommerceMedicalAuthinfoAuthQueryModel model = new AlipayCommerceMedicalAuthinfoAuthQueryModel();
// 设置用户标识
if (AliConfig.IS_NEW_USER_ID_VERSION) { // 新版
// model.setOpenId("074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5");
model.setOpenId(openId);
} else {
// uid参数未来计划废弃,存量商户可继续使用,新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
model.setAlipayUserId(openId);
}
// 设置商户请求流水号
model.setReqBizNo(ObjectUtils.isEmpty(reqBizNo) ? UUID.randomUUID().toString() : reqBizNo);
// 设置机构编码-固定为NATHSA
model.setInsCode("NATHSA");
// 设置线上业务类型编码
model.setOlBizTypeCode("04107");
// 设置授权回调地址{url}?resultCode=SUCCESS&openapiAppId=2021**3&reqBizNo=20230***
model.setCallUrl(callUrl);
// 设置olBizTypeCode=04107(医保移动支付业务)时必传
model.setOrgAppId(AliMIConfig.ORG_APP_ID);
// 设置机构渠道认证编码
model.setOrgChnlCrtfCode(AliMIConfig.ORG_CHNL_CRTF_CODG);
// 设置定点医药机构代码
model.setOrgCode(AliMIConfig.ORG_NO);
// 设置扩展信息-亲情账户支付场景增加
AuthExtendParams extendParams = new AuthExtendParams();
// 系统商签约协议的PID
extendParams.setSysServiceProviderId(AliConfig.ISV_PARTNER_ID);
// 就诊人证件类型
extendParams.setPatientCertType("01");
// 就诊人真实姓名
extendParams.setPatientName(patientName);
// 就诊人证件号
extendParams.setPatientCertNo(patientCardNo);
model.setExtendParams(extendParams);
// 设置线上购药渠道ID
// odel.setOnlineDrugChnlAppId("1DBHJRS5I01E0F34A8C00000B959FA87");
request.setBizModel(model);
// 第三方代调用模式下请设置app_auth_token
// request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
// 设置auth_token,同access_token(用户访问令牌)
request.putOtherTextParam("auth_token", accessToken);
log.info("[支付宝]国家医保局线上业务身份核验信息授权查询接口-入参{}", JsonHelper.toJsonString(request));
AlipayCommerceMedicalAuthinfoAuthQueryResponse response = alipayClient.execute(request);
log.info("[支付宝]国家医保局线上业务身份核验信息授权查询接口-调用{} {}", response.isSuccess() ? "[成功]" : "[失败]", response.getBody());
if (response.isSuccess()) {
return response.getData();
}
// 异常:商户未上线(白名单未添加或已过期-10到15天,会自动下架)
throw new ServiceException(response.getErrorMessage());
// sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
// String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
// System.out.println(diagnosisUrl);
}
// public static AlipayClient getGBKAliClient() {
// return new DefaultAlipayClient(AliConfig.SERVICE_URL, AliConfig.APP_ID, AliConfig.APP_PRIVATE_KEY, "json", "GBK", AliConfig.ALI_PUBLIC_KEY, "RSA2");
// }
/**
* 5.2.2.4 APP支付接口alipay.trade.app.pay
*
* @param orderMIEnum 医保订单类型
* @param openid openid
* @param outTradeNo 商户订单号
* @param medOrgOrd HIS医院订单号
* @param payOrdId 医保订单id
* @param payAuthNo 医保授权
* @param totalAmount 总金额
* @param cashFee 现金部分
* @param subject 订单标题
* @param notifyUrl 携带了业务类型用于区分挂号和处方缴费
* @param notifyType 业务类型
* @param familyType 保卡类型"1":亲情支付"0":"本人支付"为空默认本人支付
* @param familyName 家属姓名
* @param familyCardNo 家属卡号
* @param medicalCardInstId 医保电子凭证机构编号默认位NATHSA
* @param medicalCardId 医保电子凭证授权码 获取线上医保业务授权接口返回medicalCardId参数"6638aabe-7b4d-4d10-bdf0-b44804da3dab"
* @return map
*/
public static Map<String, Object> createOrder(OrderMIEnum orderMIEnum, String openid, String outTradeNo, String medOrgOrd, String payOrdId, String payAuthNo, BigDecimal totalAmount, BigDecimal cashFee, String subject, String notifyUrl, String notifyType, String familyType, String familyName, String familyCardNo, String medicalCardInstId, String medicalCardId) {
try {
AlipayClient alipayClient = new DefaultAlipayClient(AliConfig.getAlipayConfig());
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl(notifyUrl);
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", outTradeNo);
// 订单总金额
bizContent.put("total_amount", totalAmount.toString());
// 订单标题
bizContent.put("subject", subject);
bizContent.put("product_code", "QUICK_MSECURITY_PAY"); // JSAPI_PAY|QUICK_MSECURITY_PAY
// 亲情账户增加 start
bizContent.put("query_options", new String[]{"medical_insurance_info"});
// 亲情账户增加 end
JSONObject extendParams = new JSONObject();
extendParams.put("sys_service_provider_id", AliConfig.ISV_PARTNER_ID);
extendParams.put("IS_INSURANCE_PAY", "T"); // 是否使用医保支付
extendParams.put("medical_card_inst_id", ObjectUtils.isEmpty(medicalCardInstId) ? "NATHSA" : medicalCardInstId); //医保电子凭证机构号 获取线上医保业务授权接口返回medicalCardInstId参数。
extendParams.put("medical_card_id", medicalCardId); //医保电子凭证授权码 获取线上医保业务授权接口返回medicalCardId参数。
JSONObject medicalRequestContent = new JSONObject(); // 医保参数透传体,没有需传空对象串
extendParams.put("medical_request_content", JSONObject.toJSONString(medicalRequestContent));
JSONObject medicalRequestExt = new JSONObject(); //医保扩展参数
medicalRequestExt.put("gmt_out_create", DateHelper.getCurDateTime()); // 医疗机构下单时间
medicalRequestExt.put("out_trade_no", medOrgOrd); // 商户网站唯一订单号 医院订单号medOrgOrd
medicalRequestExt.put("serial_no", payOrdId); // 移动支付中心订单号payOrdId
medicalRequestExt.put("bill_no", payOrdId); // 移动支付中心订单号payOrdId
medicalRequestExt.put("pay_auth_no", payAuthNo); // 移动支付中心返回授权编号 获取线上医保业务授权接口返回payAuthNo参数
//
medicalRequestExt.put("org_no", AliMIConfig.ORG_NO); // 医药机构编号
medicalRequestExt.put("org_name", AliMIConfig.ORG_HOSPITAL_NAME); // 医药机构名称
medicalRequestExt.put("payment_city_code", AliMIConfig.CITY_CODE); // 医保结算地城市编码(国标)
//
medicalRequestExt.put("industry", "HOSPITAL"); // 行业标识 医院:HOSPITAL
medicalRequestExt.put("chinfo", "gjydzf"); // 渠道标识-默认为gjydzf
medicalRequestExt.put("scene", "TREATMENT"); //使用场景
medicalRequestExt.put("insurance_pay_scene", orderMIEnum.ALI_MI_CODE); // 医保结算场景 是 医保结算场景:OUTPATIENT - 门诊;INPATIENT - 住院;APPOINTMENT- 挂号;DRUGSTORE- 药店
// if (isZeroCash) { // 额外支付金额
// // 同时需要增加医保补充计算字段 extend_params.medical_request_ex.insurance_subsidy_mode:involve。示例为:
// // {"insurance_subsidy_mode":"involve","insurance_subsidy_amount":"0.01","insurance_subsidy_type":"OTHER"}
// medicalRequestExt.put("insurance_subsidy_mode", "involve");
// medicalRequestExt.put("insurance_subsidy_type", "OTHER");
// medicalRequestExt.put("insurance_subsidy_amount", "0.01"); // (如自费部分增加10元运费)
// }
extendParams.put("medical_request_ext", JSONObject.toJSONString(medicalRequestExt));
// // 如需补充资产,如院内预交金等 begin
// if (isZeroCash) { // 0元义诊-需上报医保
// // 文档(特别注意1:当出现义诊等纯0元订单,又需要完成医保登记场景)
// // 示例为:"preset_pay_tool": "{\"MERCHANTCARD_ZKT\":[{\"amount\":\"0.01\",\"templateId\":\"2023062500391002246600208318\",\"forceUse\":\"Y\"}]}"。
// JSONArray merchantCardZkt = new JSONArray();
// JSONObject zkt = new JSONObject();
// zkt.put("amount", "0.01"); // 总金额
// zkt.put("forceUse", "Y"); // 固定为Y
// zkt.put("templateId", "2023062500391002246600208318");
// merchantCardZkt.add(zkt);
// JSONObject presetPayTool = new JSONObject();
// presetPayTool.put("MERCHANTCARD_ZKT", merchantCardZkt);
// extendParams.put("preset_pay_tool", JSONObject.toJSONString(presetPayTool));
//// extendParams.put("scene", "PLATFORM_DRUG_STORE"); // 场景(有三方购药渠道场景使用)
// }
// // 如需补充资产,如院内预交金等 end
bizContent.put("extend_params", extendParams);
request.setBizContent(JSONObject.toJSONString(bizContent));
log.info("[支付宝]医保下单-入参 {}", JSONObject.toJSONString(request));
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
log.info("[支付宝]医保下单-返回 orderStr={}", response.getBody());
if (response.isSuccess()) {
Map<String, Object> map = new HashMap<>();
map.put("orderStr", response.getBody());
map.put("outTradeNo", outTradeNo);
return map;
}
} catch (AlipayApiException e) {
ErrorHelper.println(e);
}
return null;
}
// 5.2.2.5 线下交易查询alipay.trade.query
public static Order queryTrade(String outTradeNo, String tradeNo) {
Order order = new Order();
try {
AlipayClient alipayClient = new DefaultAlipayClient(AliConfig.getAlipayConfig());
// 构造请求参数以调用接口
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
// 设置订单支付时传入的商户订单号
model.setOutTradeNo(outTradeNo);
// 设置支付宝交易号
model.setTradeNo(tradeNo);
// 设置查询选项
List<String> queryOptions = new ArrayList<>();
queryOptions.add("trade_settle_info");
queryOptions.add("fund_bill_list");
queryOptions.add("medical_insurance_info");
model.setQueryOptions(queryOptions);
request.setBizModel(model);
log.info("[支付宝][医保]线下交易查询-入参 {}", JSONObject.toJSONString(request));
AlipayTradeQueryResponse response = alipayClient.execute(request);
log.info("[支付宝][医保]线下交易查询-返回 {}", JsonHelper.toJsonString(response));
if (response.isSuccess()) {
if ("TRADE_SUCCESS".equals(response.getTradeStatus())) {
order.setSuccess(true);
}
order.setInfo(response.getBody());
order.setTradeState(response.getTradeStatus());
order.setTradeNo(response.getTradeNo());
order.setBankTransNo(response.getTradeNo());
order.setOutTradeNo(response.getOutTradeNo());
order.setTotalFee(new BigDecimal(response.getTotalAmount()));
} else {
order.setErrorMsg(response.getMsg());
}
} catch (AlipayApiException e) {
ErrorHelper.println(e);
}
return order;
}
// 5.2.2.6 交易退款接口alipay.trade.refund.apply
public static String refundTrade(String outTradeNo, String outRefundNo, String tradeNo, BigDecimal refundAmount, String refundReason) {
try {
AlipayClient alipayClient = new DefaultAlipayClient(AliConfig.getAlipayConfig());
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
JSONObject bizContent = new JSONObject();
bizContent.put("trade_no", tradeNo);
bizContent.put("out_trade_no", outTradeNo);
bizContent.put("refund_amount", refundAmount.toString());
bizContent.put("out_request_no", outRefundNo); // 退款请求号-如需部分退款,则此参数必传
// 退款原因说明
bizContent.put("refund_reason", refundReason);
//亲情账户增加 end
JSONObject extendParams = new JSONObject();
extendParams.put("cancel_serial_no", outRefundNo);
extendParams.put("cancel_bill_no", outRefundNo);
bizContent.put("extend_params", extendParams);
request.setBizContent(JSONObject.toJSONString(bizContent));
log.info("[支付宝][医保]交易退款接口-入参 {}", JSONObject.toJSONString(request));
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
log.info("[支付宝][医保]交易退款接口-返回 {}", response.getBody());
if (response.isSuccess()) {
return response.getBody();
}
} catch (AlipayApiException e) {
ErrorHelper.println(e);
}
return null;
}
// 5.2.2.7 交易退款查询alipay.trade.fastpay.refund.query
public static String queryRefund(String outRefundNo, String outTradeNo, String tradeNo) {
try {
AlipayClient alipayClient = new DefaultAlipayClient(AliConfig.getAlipayConfig());
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
JSONObject bizContent = new JSONObject();
bizContent.put("out_request_no", outRefundNo);
bizContent.put("trade_no", tradeNo);
bizContent.put("out_trade_no", outTradeNo);
bizContent.put("query_options", new String[]{"refund_detail_item_list"}); // 查询本次交易用户付款的支付渠道和亲情账户关系
request.setBizContent(JSONObject.toJSONString(bizContent));
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
log.info("[支付宝]交易退款查询-返回 {}", response.getBody());
if (response.isSuccess()) {
return response.getBody();
}
} catch (AlipayApiException e) {
ErrorHelper.println(e);
}
return null;
}
// 数据转换
private static String formatOrderInfo(String data) {
try {
if (ObjectUtils.isEmpty(data)) {
return null;
}
String decode = URLDecoder.decode(data, "UTF-8");
if (ObjectUtils.isEmpty(decode)) {
return null;
}
String[] pairs = decode.split("&");
Map<String, Object> map = new HashMap<>();
for (String pair : pairs) {
if (ObjectUtils.isEmpty(pair)) {
continue;
}
String[] keyValue = pair.split("=");
if (keyValue.length == 2) {
map.put(keyValue[0], keyValue[1]);
}
}
return null;
} catch (Exception e) {
ErrorHelper.println(e);
return null;
}
}
}