diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsOrdersRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsOrdersRequest.java new file mode 100644 index 000000000..1819b328c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsOrdersRequest.java @@ -0,0 +1,568 @@ +package com.github.binarywang.wxpay.bean.mipay; + +import com.github.binarywang.wxpay.bean.mipay.enums.CashAddTypeEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.CashReduceTypeEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.MixPayTypeEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.OrderTypeEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.UserCardTypeEnum; +import com.github.binarywang.wxpay.v3.SpecEncrypt; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 医保自费混合收款下单请求 + *

+ * 从业机构调用该接口向微信医保后台下单 + * 文档地址:https://pay.weixin.qq.com/doc/v3/partner/4012503131 + * @author xgl + * @date 2025/12/19 14:37 + */ +@Data +@Builder(builderMethodName = "newBuilder") +@NoArgsConstructor +@AllArgsConstructor +public class MedInsOrdersRequest { + + /** + *

+   * 字段名:混合支付类型
+   * 变量名:mix_pay_type
+   * 必填:是
+   * 类型:string
+   * 描述:
+   *   混合支付类型可选取值:
+   *   - UNKNOWN_MIX_PAY_TYPE: 未知的混合支付类型,会被拦截
+   *   - CASH_ONLY: 只向微信支付下单,没有向医保局下单
+   *   - INSURANCE_ONLY: 只向医保局下单,没有向微信支付下单
+   *   - CASH_AND_INSURANCE: 向医保局下单,也向微信支付下单
+   * 
+ */ + @SerializedName("mix_pay_type") + public MixPayTypeEnum mixPayType; + + /** + *
+   * 字段名:订单类型
+   * 变量名:order_type
+   * 必填:是
+   * 类型:string
+   * 描述:
+   *   订单类型可选取值:
+   *   - UNKNOWN_ORDER_TYPE: 未知类型,会被拦截
+   *   - REG_PAY: 挂号支付
+   *   - DIAG_PAY: 诊间支付
+   *   - COVID_EXAM_PAY: 新冠检测费用(核酸)
+   *   - IN_HOSP_PAY: 住院费支付
+   *   - PHARMACY_PAY: 药店支付
+   *   - INSURANCE_PAY: 保险费支付
+   *   - INT_REG_PAY: 互联网医院挂号支付
+   *   - INT_RE_DIAG_PAY: 互联网医院复诊支付
+   *   - INT_RX_PAY: 互联网医院处方支付
+   *   - COVID_ANTIGEN_PAY: 新冠抗原检测
+   *   - MED_PAY: 药费支付
+   * 
+ */ + @SerializedName("order_type") + public OrderTypeEnum orderType; + + /** + *
+   * 字段名:从业机构/服务商的公众号ID
+   * 变量名:appid
+   * 必填:是
+   * 类型:string(32)
+   * 描述:从业机构/服务商的公众号ID
+   * 
+ */ + @SerializedName("appid") + public String appid; + + /** + *
+   * 字段名:医疗机构的公众号ID
+   * 变量名:sub_appid
+   * 必填:是
+   * 类型:string(32)
+   * 描述:医疗机构的公众号ID
+   * 
+ */ + @SerializedName("sub_appid") + public String subAppid; + + /** + *
+   * 字段名:医疗机构的商户号
+   * 变量名:sub_mchid
+   * 必填:是
+   * 类型:string(32)
+   * 描述:医疗机构的商户号
+   * 
+ */ + @SerializedName("sub_mchid") + public String subMchid; + + /** + *
+   * 字段名:用户在appid下的唯一标识
+   * 变量名:openid
+   * 必填:否
+   * 类型:string(128)
+   * 描述:openid与sub_openid二选一,传入openid时需要使用appid调起医保自费混合支付
+   * 
+ */ + @SerializedName("openid") + public String openid; + + /** + *
+   * 字段名:用户在sub_appid下的唯一标识
+   * 变量名:sub_openid
+   * 必填:否
+   * 类型:string(128)
+   * 描述:openid与sub_openid二选一,传入sub_openid时需要使用sub_appid调起医保自费混合支付
+   * 
+ */ + @SerializedName("sub_openid") + public String subOpenid; + + /** + *
+   * 字段名:支付人身份信息
+   * 变量名:payer
+   * 必填:是
+   * 类型:object
+   * 描述:支付人身份信息
+   * 
+ */ + @SerializedName("payer") + @SpecEncrypt + public PersonIdentification payer; + + /** + *
+   * 字段名:是否代亲属支付
+   * 变量名:pay_for_relatives
+   * 必填:否
+   * 类型:boolean
+   * 描述:不传默认替本人支付
+   *   - true: 代亲属支付
+   *   - false: 本人支付
+   * 
+ */ + @SerializedName("pay_for_relatives") + public Boolean payForRelatives; + + /** + *
+   * 字段名:亲属身份信息
+   * 变量名:relative
+   * 必填:否
+   * 类型:object
+   * 描述:pay_for_relatives为true时,该字段必填
+   * 
+ */ + @SerializedName("relative") + @SpecEncrypt + public PersonIdentification relative; + + /** + *
+   * 字段名:从业机构订单号
+   * 变量名:out_trade_no
+   * 必填:是
+   * 类型:string(64)
+   * 描述:从业机构/服务商需要调两次接口:从业机构/服务商向微信支付下单获取微信支付凭证,请求中会带上out_trade_no。下单成功后,从业机构/服务商调用混合下单的接口(即该接口),请求中也会带上out_trade_no。
+   * 
+ */ + @SerializedName("out_trade_no") + public String outTradeNo; + + /** + *
+   * 字段名:医疗机构订单号
+   * 变量名:serial_no
+   * 必填:是
+   * 类型:string(40)
+   * 描述:例如医院HIS系统订单号。传与费用明细上传中medOrgOrd字段一样的值,局端会校验,不一致将会返回错误
+   * 
+ */ + @SerializedName("serial_no") + public String serialNo; + + /** + *
+   * 字段名:支付订单号
+   * 变量名:pay_order_id
+   * 必填:否
+   * 类型:string
+   * 描述:支付订单号
+   * 
+ */ + @SerializedName("pay_order_id") + public String payOrderId; + + /** + *
+   * 字段名:支付授权号
+   * 变量名:pay_auth_no
+   * 必填:否
+   * 类型:string
+   * 描述:支付授权号
+   * 
+ */ + @SerializedName("pay_auth_no") + public String payAuthNo; + + /** + *
+   * 字段名:地理位置
+   * 变量名:geo_location
+   * 必填:否
+   * 类型:string
+   * 描述:地理位置
+   * 
+ */ + @SerializedName("geo_location") + public String geoLocation; + + /** + *
+   * 字段名:城市ID
+   * 变量名:city_id
+   * 必填:否
+   * 类型:string
+   * 描述:城市ID
+   * 
+ */ + @SerializedName("city_id") + public String cityId; + + /** + *
+   * 字段名:医疗机构名称
+   * 变量名:med_inst_name
+   * 必填:否
+   * 类型:string
+   * 描述:医疗机构名称
+   * 
+ */ + @SerializedName("med_inst_name") + public String medInstName; + + /** + *
+   * 字段名:医疗机构编号
+   * 变量名:med_inst_no
+   * 必填:否
+   * 类型:string
+   * 描述:医疗机构编号
+   * 
+ */ + @SerializedName("med_inst_no") + public String medInstNo; + + /** + *
+   * 字段名:医保订单创建时间
+   * 变量名:med_ins_order_create_time
+   * 必填:否
+   * 类型:string
+   * 描述:医保订单创建时间
+   * 
+ */ + @SerializedName("med_ins_order_create_time") + public String medInsOrderCreateTime; + + /** + *
+   * 字段名:总金额
+   * 变量名:total_fee
+   * 必填:否
+   * 类型:long
+   * 描述:总金额
+   * 
+ */ + @SerializedName("total_fee") + public Long totalFee; + + /** + *
+   * 字段名:医保统筹基金支付金额
+   * 变量名:med_ins_gov_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保统筹基金支付金额
+   * 
+ */ + @SerializedName("med_ins_gov_fee") + public Long medInsGovFee; + + /** + *
+   * 字段名:医保个人账户支付金额
+   * 变量名:med_ins_self_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保个人账户支付金额
+   * 
+ */ + @SerializedName("med_ins_self_fee") + public Long medInsSelfFee; + + /** + *
+   * 字段名:医保其他基金支付金额
+   * 变量名:med_ins_other_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保其他基金支付金额
+   * 
+ */ + @SerializedName("med_ins_other_fee") + public Long medInsOtherFee; + + /** + *
+   * 字段名:医保现金支付金额
+   * 变量名:med_ins_cash_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保现金支付金额
+   * 
+ */ + @SerializedName("med_ins_cash_fee") + public Long medInsCashFee; + + /** + *
+   * 字段名:微信支付现金支付金额
+   * 变量名:wechat_pay_cash_fee
+   * 必填:否
+   * 类型:long
+   * 描述:微信支付现金支付金额
+   * 
+ */ + @SerializedName("wechat_pay_cash_fee") + public Long wechatPayCashFee; + + /** + *
+   * 字段名:现金增加明细
+   * 变量名:cash_add_detail
+   * 必填:否
+   * 类型:list
+   * 描述:现金增加明细
+   * 
+ */ + @SerializedName("cash_add_detail") + public List cashAddDetail; + + /** + *
+   * 字段名:现金减少明细
+   * 变量名:cash_reduce_detail
+   * 必填:否
+   * 类型:list
+   * 描述:现金减少明细
+   * 
+ */ + @SerializedName("cash_reduce_detail") + public List cashReduceDetail; + + /** + *
+   * 字段名:回调URL
+   * 变量名:callback_url
+   * 必填:否
+   * 类型:string
+   * 描述:回调URL
+   * 
+ */ + @SerializedName("callback_url") + public String callbackUrl; + + /** + *
+   * 字段名:预支付交易会话标识
+   * 变量名:prepay_id
+   * 必填:否
+   * 类型:string
+   * 描述:预支付交易会话标识
+   * 
+ */ + @SerializedName("prepay_id") + public String prepayId; + + /** + *
+   * 字段名:透传请求内容
+   * 变量名:passthrough_request_content
+   * 必填:否
+   * 类型:string
+   * 描述:透传请求内容
+   * 
+ */ + @SerializedName("passthrough_request_content") + public String passthroughRequestContent; + + /** + *
+   * 字段名:扩展字段
+   * 变量名:extends
+   * 必填:否
+   * 类型:string
+   * 描述:扩展字段
+   * 
+ */ + @SerializedName("extends") + public String _extends; + + /** + *
+   * 字段名:附加数据
+   * 变量名:attach
+   * 必填:否
+   * 类型:string
+   * 描述:附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
+   * 
+ */ + @SerializedName("attach") + public String attach; + + /** + *
+   * 字段名:渠道编号
+   * 变量名:channel_no
+   * 必填:否
+   * 类型:string
+   * 描述:渠道编号
+   * 
+ */ + @SerializedName("channel_no") + public String channelNo; + + /** + *
+   * 字段名:医保测试环境标识
+   * 变量名:med_ins_test_env
+   * 必填:否
+   * 类型:boolean
+   * 描述:医保测试环境标识
+   * 
+ */ + @SerializedName("med_ins_test_env") + public Boolean medInsTestEnv; + + /** + *
+   * 支付人身份信息
+   * 
+ */ + public static class PersonIdentification { + /** + *
+     * 字段名:姓名
+     * 变量名:name
+     * 必填:是
+     * 类型:string
+     * 描述:姓名,需加密
+     * 
+ */ + @SerializedName("name") + @SpecEncrypt + public String name; + + /** + *
+     * 字段名:身份证摘要
+     * 变量名:id_digest
+     * 必填:是
+     * 类型:string
+     * 描述:身份证摘要,需加密
+     * 
+ */ + @SerializedName("id_digest") + @SpecEncrypt + public String idDigest; + + /** + *
+     * 字段名:证件类型
+     * 变量名:card_type
+     * 必填:是
+     * 类型:string
+     * 描述:证件类型
+     * 
+ */ + @SerializedName("card_type") + public UserCardTypeEnum cardType; + } + + /** + *
+   * 现金增加明细实体
+   * 
+ */ + public static class CashAddEntity { + /** + *
+     * 字段名:现金增加金额
+     * 变量名:cash_add_fee
+     * 必填:是
+     * 类型:long
+     * 描述:现金增加金额
+     * 
+ */ + @SerializedName("cash_add_fee") + public Long cashAddFee; + + /** + *
+     * 字段名:现金增加类型
+     * 变量名:cash_add_type
+     * 必填:是
+     * 类型:string
+     * 描述:现金增加类型
+     * 
+ */ + @SerializedName("cash_add_type") + public CashAddTypeEnum cashAddType; + } + + /** + *
+   * 现金减少明细实体
+   * 
+ */ + public static class CashReduceEntity { + /** + *
+     * 字段名:现金减少金额
+     * 变量名:cash_reduce_fee
+     * 必填:是
+     * 类型:long
+     * 描述:现金减少金额
+     * 
+ */ + @SerializedName("cash_reduce_fee") + public Long cashReduceFee; + + /** + *
+     * 字段名:现金减少类型
+     * 变量名:cash_reduce_type
+     * 必填:是
+     * 类型:string
+     * 描述:现金减少类型
+     * 
+ */ + @SerializedName("cash_reduce_type") + public CashReduceTypeEnum cashReduceType; + } + + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsOrdersResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsOrdersResult.java new file mode 100644 index 000000000..4fc68e279 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsOrdersResult.java @@ -0,0 +1,497 @@ +package com.github.binarywang.wxpay.bean.mipay; + +import com.github.binarywang.wxpay.bean.mipay.enums.MedInsPayStatusEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.MixPayStatusEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.MixPayTypeEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.OrderTypeEnum; +import com.github.binarywang.wxpay.bean.mipay.enums.SelfPayStatusEnum; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; + +/** + * 医保自费混合收款下单响应 + *

+ * 从业机构调用医保自费混合收款下单接口后返回的结果 + * 文档地址:https://pay.weixin.qq.com/doc/v3/partner/4012503131 + * @author xgl + * @date 2025/12/19 14:37 + */ +@Data +public class MedInsOrdersResult { + /** + *

+   * 字段名:混合交易订单号
+   * 变量名:mix_trade_no
+   * 必填:是
+   * 类型:string
+   * 描述:微信支付生成的混合交易订单号
+   * 
+ */ + @SerializedName("mix_trade_no") + public String mixTradeNo; + + /** + *
+   * 字段名:混合支付状态
+   * 变量名:mix_pay_status
+   * 必填:是
+   * 类型:string
+   * 描述:混合支付整体状态
+   * 
+ */ + @SerializedName("mix_pay_status") + public MixPayStatusEnum mixPayStatus; + + /** + *
+   * 字段名:自费支付状态
+   * 变量名:self_pay_status
+   * 必填:是
+   * 类型:string
+   * 描述:自费部分支付状态
+   * 
+ */ + @SerializedName("self_pay_status") + public SelfPayStatusEnum selfPayStatus; + + /** + *
+   * 字段名:医保支付状态
+   * 变量名:med_ins_pay_status
+   * 必填:是
+   * 类型:string
+   * 描述:医保部分支付状态
+   * 
+ */ + @SerializedName("med_ins_pay_status") + public MedInsPayStatusEnum medInsPayStatusEnum; + + /** + *
+   * 字段名:支付完成时间
+   * 变量名:paid_time
+   * 必填:否
+   * 类型:string
+   * 描述:支付完成时间,格式为yyyyMMddHHmmss
+   * 
+ */ + @SerializedName("paid_time") + public String paidTime; + + /** + *
+   * 字段名:透传响应内容
+   * 变量名:passthrough_response_content
+   * 必填:否
+   * 类型:string
+   * 描述:透传响应内容
+   * 
+ */ + @SerializedName("passthrough_response_content") + public String passthroughResponseContent; + + /** + *
+   * 字段名:混合支付类型
+   * 变量名:mix_pay_type
+   * 必填:是
+   * 类型:string
+   * 描述:
+   *   混合支付类型可选取值:
+   *   - UNKNOWN_MIX_PAY_TYPE: 未知的混合支付类型,会被拦截
+   *   - CASH_ONLY: 只向微信支付下单,没有向医保局下单
+   *   - INSURANCE_ONLY: 只向医保局下单,没有向微信支付下单
+   *   - CASH_AND_INSURANCE: 向医保局下单,也向微信支付下单
+   * 
+ */ + @SerializedName("mix_pay_type") + public MixPayTypeEnum mixPayType; + + /** + *
+   * 字段名:订单类型
+   * 变量名:order_type
+   * 必填:是
+   * 类型:string
+   * 描述:
+   *   订单类型可选取值:
+   *   - UNKNOWN_ORDER_TYPE: 未知类型,会被拦截
+   *   - REG_PAY: 挂号支付
+   *   - DIAG_PAY: 诊间支付
+   *   - COVID_EXAM_PAY: 新冠检测费用(核酸)
+   *   - IN_HOSP_PAY: 住院费支付
+   *   - PHARMACY_PAY: 药店支付
+   *   - INSURANCE_PAY: 保险费支付
+   *   - INT_REG_PAY: 互联网医院挂号支付
+   *   - INT_RE_DIAG_PAY: 互联网医院复诊支付
+   *   - INT_RX_PAY: 互联网医院处方支付
+   *   - COVID_ANTIGEN_PAY: 新冠抗原检测
+   *   - MED_PAY: 药费支付
+   * 
+ */ + @SerializedName("order_type") + public OrderTypeEnum orderType; + + /** + *
+   * 字段名:从业机构/服务商的公众号ID
+   * 变量名:appid
+   * 必填:是
+   * 类型:string(32)
+   * 描述:从业机构/服务商的公众号ID
+   * 
+ */ + @SerializedName("appid") + public String appid; + + /** + *
+   * 字段名:医疗机构的公众号ID
+   * 变量名:sub_appid
+   * 必填:是
+   * 类型:string(32)
+   * 描述:医疗机构的公众号ID
+   * 
+ */ + @SerializedName("sub_appid") + public String subAppid; + + /** + *
+   * 字段名:医疗机构的商户号
+   * 变量名:sub_mchid
+   * 必填:是
+   * 类型:string(32)
+   * 描述:医疗机构的商户号
+   * 
+ */ + @SerializedName("sub_mchid") + public String subMchid; + + /** + *
+   * 字段名:用户在appid下的唯一标识
+   * 变量名:openid
+   * 必填:否
+   * 类型:string(128)
+   * 描述:openid与sub_openid二选一,传入openid时需要使用appid调起医保自费混合支付
+   * 
+ */ + @SerializedName("openid") + public String openid; + + /** + *
+   * 字段名:用户在sub_appid下的唯一标识
+   * 变量名:sub_openid
+   * 必填:否
+   * 类型:string(128)
+   * 描述:openid与sub_openid二选一,传入sub_openid时需要使用sub_appid调起医保自费混合支付
+   * 
+ */ + @SerializedName("sub_openid") + public String subOpenid; + + /** + *
+   * 字段名:是否代亲属支付
+   * 变量名:pay_for_relatives
+   * 必填:否
+   * 类型:boolean
+   * 描述:不传默认替本人支付
+   *   - true: 代亲属支付
+   *   - false: 本人支付
+   * 
+ */ + @SerializedName("pay_for_relatives") + public Boolean payForRelatives; + + /** + *
+   * 字段名:从业机构订单号
+   * 变量名:out_trade_no
+   * 必填:是
+   * 类型:string(64)
+   * 描述:从业机构/服务商需要调两次接口:从业机构/服务商向微信支付下单获取微信支付凭证,请求中会带上out_trade_no。下单成功后,从业机构/服务商调用混合下单的接口(即该接口),请求中也会带上out_trade_no。
+   * 
+ */ + @SerializedName("out_trade_no") + public String outTradeNo; + + /** + *
+   * 字段名:医疗机构订单号
+   * 变量名:serial_no
+   * 必填:是
+   * 类型:string(40)
+   * 描述:例如医院HIS系统订单号。传与费用明细上传中medOrgOrd字段一样的值,局端会校验,不一致将会返回错误
+   * 
+ */ + @SerializedName("serial_no") + public String serialNo; + + /** + *
+   * 字段名:支付订单号
+   * 变量名:pay_order_id
+   * 必填:否
+   * 类型:string
+   * 描述:支付订单号
+   * 
+ */ + @SerializedName("pay_order_id") + public String payOrderId; + + /** + *
+   * 字段名:支付授权号
+   * 变量名:pay_auth_no
+   * 必填:否
+   * 类型:string
+   * 描述:支付授权号
+   * 
+ */ + @SerializedName("pay_auth_no") + public String payAuthNo; + + /** + *
+   * 字段名:地理位置
+   * 变量名:geo_location
+   * 必填:否
+   * 类型:string
+   * 描述:地理位置
+   * 
+ */ + @SerializedName("geo_location") + public String geoLocation; + + /** + *
+   * 字段名:城市ID
+   * 变量名:city_id
+   * 必填:否
+   * 类型:string
+   * 描述:城市ID
+   * 
+ */ + @SerializedName("city_id") + public String cityId; + + /** + *
+   * 字段名:医疗机构名称
+   * 变量名:med_inst_name
+   * 必填:否
+   * 类型:string
+   * 描述:医疗机构名称
+   * 
+ */ + @SerializedName("med_inst_name") + public String medInstName; + + /** + *
+   * 字段名:医疗机构编号
+   * 变量名:med_inst_no
+   * 必填:否
+   * 类型:string
+   * 描述:医疗机构编号
+   * 
+ */ + @SerializedName("med_inst_no") + public String medInstNo; + + /** + *
+   * 字段名:医保订单创建时间
+   * 变量名:med_ins_order_create_time
+   * 必填:否
+   * 类型:string
+   * 描述:医保订单创建时间
+   * 
+ */ + @SerializedName("med_ins_order_create_time") + public String medInsOrderCreateTime; + + /** + *
+   * 字段名:总金额
+   * 变量名:total_fee
+   * 必填:否
+   * 类型:long
+   * 描述:总金额
+   * 
+ */ + @SerializedName("total_fee") + public Long totalFee; + + /** + *
+   * 字段名:医保统筹基金支付金额
+   * 变量名:med_ins_gov_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保统筹基金支付金额
+   * 
+ */ + @SerializedName("med_ins_gov_fee") + public Long medInsGovFee; + + /** + *
+   * 字段名:医保个人账户支付金额
+   * 变量名:med_ins_self_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保个人账户支付金额
+   * 
+ */ + @SerializedName("med_ins_self_fee") + public Long medInsSelfFee; + + /** + *
+   * 字段名:医保其他基金支付金额
+   * 变量名:med_ins_other_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保其他基金支付金额
+   * 
+ */ + @SerializedName("med_ins_other_fee") + public Long medInsOtherFee; + + /** + *
+   * 字段名:医保现金支付金额
+   * 变量名:med_ins_cash_fee
+   * 必填:否
+   * 类型:long
+   * 描述:医保现金支付金额
+   * 
+ */ + @SerializedName("med_ins_cash_fee") + public Long medInsCashFee; + + /** + *
+   * 字段名:微信支付现金支付金额
+   * 变量名:wechat_pay_cash_fee
+   * 必填:否
+   * 类型:long
+   * 描述:微信支付现金支付金额
+   * 
+ */ + @SerializedName("wechat_pay_cash_fee") + public Long wechatPayCashFee; + + /** + *
+   * 字段名:现金增加明细
+   * 变量名:cash_add_detail
+   * 必填:否
+   * 类型:list
+   * 描述:现金增加明细
+   * 
+ */ + @SerializedName("cash_add_detail") + public List cashAddDetail; + + /** + *
+   * 字段名:现金减少明细
+   * 变量名:cash_reduce_detail
+   * 必填:否
+   * 类型:list
+   * 描述:现金减少明细
+   * 
+ */ + @SerializedName("cash_reduce_detail") + public List cashReduceDetail; + + /** + *
+   * 字段名:回调URL
+   * 变量名:callback_url
+   * 必填:否
+   * 类型:string
+   * 描述:回调URL
+   * 
+ */ + @SerializedName("callback_url") + public String callbackUrl; + + /** + *
+   * 字段名:预支付交易会话标识
+   * 变量名:prepay_id
+   * 必填:否
+   * 类型:string
+   * 描述:预支付交易会话标识
+   * 
+ */ + @SerializedName("prepay_id") + public String prepayId; + + /** + *
+   * 字段名:透传请求内容
+   * 变量名:passthrough_request_content
+   * 必填:否
+   * 类型:string
+   * 描述:透传请求内容
+   * 
+ */ + @SerializedName("passthrough_request_content") + public String passthroughRequestContent; + + /** + *
+   * 字段名:扩展字段
+   * 变量名:extends
+   * 必填:否
+   * 类型:string
+   * 描述:扩展字段
+   * 
+ */ + @SerializedName("extends") + public String _extends; + + /** + *
+   * 字段名:附加数据
+   * 变量名:attach
+   * 必填:否
+   * 类型:string
+   * 描述:附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
+   * 
+ */ + @SerializedName("attach") + public String attach; + + /** + *
+   * 字段名:渠道编号
+   * 变量名:channel_no
+   * 必填:否
+   * 类型:string
+   * 描述:渠道编号
+   * 
+ */ + @SerializedName("channel_no") + public String channelNo; + + /** + *
+   * 字段名:医保测试环境标识
+   * 变量名:med_ins_test_env
+   * 必填:否
+   * 类型:boolean
+   * 描述:医保测试环境标识
+   * 
+ */ + @SerializedName("med_ins_test_env") + public Boolean medInsTestEnv; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsRefundNotifyRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsRefundNotifyRequest.java new file mode 100644 index 000000000..b6e15a364 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/MedInsRefundNotifyRequest.java @@ -0,0 +1,116 @@ +package com.github.binarywang.wxpay.bean.mipay; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 医保退款通知请求 + *

+ * 从业机构调用该接口向微信医保后台通知医保订单的退款成功结果 + * 文档地址:https://pay.weixin.qq.com/doc/v3/partner/4012166534 + * @author xgl + * @date 2025/12/20 + */ +@Data +@Builder(builderMethodName = "newBuilder") +@NoArgsConstructor +@AllArgsConstructor +public class MedInsRefundNotifyRequest { + + /** + *

+   * 字段名:医保自费混合订单号
+   * 必填:是
+   * 类型:string(32)
+   * 描述:医保自费混合订单号
+   * 
+ */ + private String mixTradeNo; + + /** + *
+   * 字段名:医疗机构的商户号
+   * 变量名:sub_mchid
+   * 必填:是
+   * 类型:string(32)
+   * 描述:医疗机构的商户号
+   * 
+ */ + @SerializedName("sub_mchid") + private String subMchid; + + /** + *
+   * 字段名:医保退款的总金额
+   * 变量名:med_refund_total_fee
+   * 必填:是
+   * 类型:integer
+   * 描述:单位分,医保退款的总金额。
+   * 
+ */ + @SerializedName("med_refund_total_fee") + private Integer medRefundTotalFee; + + /** + *
+   * 字段名:医保统筹退款金额
+   * 变量名:med_refund_gov_fee
+   * 必填:是
+   * 类型:integer
+   * 描述:单位分,医保统筹退款金额。
+   * 
+ */ + @SerializedName("med_refund_gov_fee") + private Integer medRefundGovFee; + + /** + *
+   * 字段名:医保个账退款金额
+   * 变量名:med_refund_self_fee
+   * 必填:是
+   * 类型:integer
+   * 描述:单位分,医保个账退款金额。
+   * 
+ */ + @SerializedName("med_refund_self_fee") + private Integer medRefundSelfFee; + + /** + *
+   * 字段名:医保其他退款金额
+   * 变量名:med_refund_other_fee
+   * 必填:是
+   * 类型:integer
+   * 描述:单位分,医保其他退款金额。
+   * 
+ */ + @SerializedName("med_refund_other_fee") + private Integer medRefundOtherFee; + + /** + *
+   * 字段名:医保退款成功时间
+   * 变量名:refund_time
+   * 必填:是
+   * 类型:string(64)
+   * 描述:遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE。
+   * 
+ */ + @SerializedName("refund_time") + private String refundTime; + + /** + *
+   * 字段名:从业机构\服务商退款单号
+   * 变量名:out_refund_no
+   * 必填:是
+   * 类型:string(64)
+   * 描述:有自费单时,从业机构\服务商应填与自费退款申请处一致的out_refund_no。否则从业机构透传医疗机构退款单号即可。
+   * 
+ */ + @SerializedName("out_refund_no") + private String outRefundNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/CashAddTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/CashAddTypeEnum.java new file mode 100644 index 000000000..b935f2041 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/CashAddTypeEnum.java @@ -0,0 +1,29 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 现金增加类型枚举 + *

+ * 描述医保自费混合支付中现金增加的类型 + * + * @author xgl + * @date 2025/12/20 + */ +public enum CashAddTypeEnum { + /** + * 默认增加类型 + */ + @SerializedName("DEFAULT_ADD_TYPE") + DEFAULT_ADD_TYPE, + /** + * 运费 + */ + @SerializedName("FREIGHT") + FREIGHT, + /** + * 其他医疗费用 + */ + @SerializedName("OTHER_MEDICAL_EXPENSES") + OTHER_MEDICAL_EXPENSES +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/CashReduceTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/CashReduceTypeEnum.java new file mode 100644 index 000000000..4f90b8500 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/CashReduceTypeEnum.java @@ -0,0 +1,44 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 现金减少类型枚举 + *

+ * 描述医保自费混合支付中现金减少的类型 + * + * @author xgl + * @date 2025/12/20 + */ +public enum CashReduceTypeEnum { + /** + * 默认减少类型 + */ + @SerializedName("DEFAULT_REDUCE_TYPE") + DEFAULT_REDUCE_TYPE, + /** + * 医院减免 + */ + @SerializedName("HOSPITAL_REDUCE") + HOSPITAL_REDUCE, + /** + * 药店折扣 + */ + @SerializedName("PHARMACY_DISCOUNT") + PHARMACY_DISCOUNT, + /** + * 折扣优惠 + */ + @SerializedName("DISCOUNT") + DISCOUNT, + /** + * 预付费抵扣 + */ + @SerializedName("PRE_PAYMENT") + PRE_PAYMENT, + /** + * 押金扣除 + */ + @SerializedName("DEPOSIT_DEDUCTION") + DEPOSIT_DEDUCTION +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MedInsPayStatusEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MedInsPayStatusEnum.java new file mode 100644 index 000000000..324530f0f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MedInsPayStatusEnum.java @@ -0,0 +1,44 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 医保支付状态枚举 + *

+ * 描述医保自费混合支付中医保部分的支付状态 + * + * @author xgl + * @date 2025/12/20 + */ +public enum MedInsPayStatusEnum { + /** + * 未知的医保支付状态 + */ + @SerializedName("UNKNOWN_MED_INS_PAY_STATUS") + UNKNOWN_MED_INS_PAY_STATUS, + /** + * 医保支付已创建 + */ + @SerializedName("MED_INS_PAY_CREATED") + MED_INS_PAY_CREATED, + /** + * 医保支付成功 + */ + @SerializedName("MED_INS_PAY_SUCCESS") + MED_INS_PAY_SUCCESS, + /** + * 医保支付已退款 + */ + @SerializedName("MED_INS_PAY_REFUND") + MED_INS_PAY_REFUND, + /** + * 医保支付失败 + */ + @SerializedName("MED_INS_PAY_FAIL") + MED_INS_PAY_FAIL, + /** + * 无需医保支付 + */ + @SerializedName("NO_MED_INS_PAY") + NO_MED_INS_PAY +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MixPayStatusEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MixPayStatusEnum.java new file mode 100644 index 000000000..736070498 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MixPayStatusEnum.java @@ -0,0 +1,39 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 混合支付状态枚举 + *

+ * 描述医保自费混合支付的整体状态 + * + * @author xgl + * @date 2025/12/20 + */ +public enum MixPayStatusEnum { + /** + * 未知的混合支付状态 + */ + @SerializedName("UNKNOWN_MIX_PAY_STATUS") + UNKNOWN_MIX_PAY_STATUS, + /** + * 混合支付已创建 + */ + @SerializedName("MIX_PAY_CREATED") + MIX_PAY_CREATED, + /** + * 混合支付成功 + */ + @SerializedName("MIX_PAY_SUCCESS") + MIX_PAY_SUCCESS, + /** + * 混合支付已退款 + */ + @SerializedName("MIX_PAY_REFUND") + MIX_PAY_REFUND, + /** + * 混合支付失败 + */ + @SerializedName("MIX_PAY_FAIL") + MIX_PAY_FAIL +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MixPayTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MixPayTypeEnum.java new file mode 100644 index 000000000..ad62d50a6 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/MixPayTypeEnum.java @@ -0,0 +1,41 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 混合支付类型枚举 + *

+ * 描述医保自费混合支付的类型 + * 文档地址:https://pay.weixin.qq.com/doc/v3/partner/4012503131 + * + * @author xgl + * @date 2025/12/20 09:21 + */ +public enum MixPayTypeEnum { + + /** + * 未知的混合支付类型,会被拦截。 + */ + @SerializedName("UNKNOWN_MIX_PAY_TYPE") + UNKNOWN_MIX_PAY_TYPE, + + /** + * 只向微信支付下单,没有向医保局下单。包括没有向医保局上传费用明细、预结算。 + */ + @SerializedName("CASH_ONLY") + CASH_ONLY, + + /** + * 只向医保局下单,没有向微信支付下单。如果医保局分账结果中有自费部份,但由于有减免抵扣,没有向微信支付下单,也是纯医保。 + */ + @SerializedName("INSURANCE_ONLY") + INSURANCE_ONLY, + + /** + * 向医保局下单,也向微信支付下单。如果医保预结算全部需自费,也属于混合类型。 + */ + @SerializedName("CASH_AND_INSURANCE") + CASH_AND_INSURANCE + + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/OrderTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/OrderTypeEnum.java new file mode 100644 index 000000000..749b1276e --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/OrderTypeEnum.java @@ -0,0 +1,87 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 订单类型枚举 + *

+ * 描述医保自费混合支付的订单类型 + * 文档地址:https://pay.weixin.qq.com/doc/v3/partner/4012503131 + * + * @author xgl + * @date 2025/12/20 + */ +public enum OrderTypeEnum { + + /** + * 未知类型,会被拦截 + */ + @SerializedName("UNKNOWN_ORDER_TYPE") + UNKNOWN_ORDER_TYPE, + + /** + * 挂号支付 + */ + @SerializedName("REG_PAY") + REG_PAY, + + /** + * 诊间支付 + */ + @SerializedName("DIAG_PAY") + DIAG_PAY, + + /** + * 新冠检测费用(核酸) + */ + @SerializedName("COVID_EXAM_PAY") + COVID_EXAM_PAY, + + /** + * 住院费支付 + */ + @SerializedName("IN_HOSP_PAY") + IN_HOSP_PAY, + + /** + * 药店支付 + */ + @SerializedName("PHARMACY_PAY") + PHARMACY_PAY, + + /** + * 保险费支付 + */ + @SerializedName("INSURANCE_PAY") + INSURANCE_PAY, + + /** + * 互联网医院挂号支付 + */ + @SerializedName("INT_REG_PAY") + INT_REG_PAY, + + /** + * 互联网医院复诊支付 + */ + @SerializedName("INT_RE_DIAG_PAY") + INT_RE_DIAG_PAY, + + /** + * 互联网医院处方支付 + */ + @SerializedName("INT_RX_PAY") + INT_RX_PAY, + + /** + * 新冠抗原检测 + */ + @SerializedName("COVID_ANTIGEN_PAY") + COVID_ANTIGEN_PAY, + + /** + * 药费支付 + */ + @SerializedName("MED_PAY") + MED_PAY +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/SelfPayStatusEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/SelfPayStatusEnum.java new file mode 100644 index 000000000..a7014b9e1 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/SelfPayStatusEnum.java @@ -0,0 +1,44 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 自费支付状态枚举 + *

+ * 描述医保自费混合支付中自费部分的支付状态 + * + * @author xgl + * @date 2025/12/20 + */ +public enum SelfPayStatusEnum { + /** + * 未知的自费支付状态 + */ + @SerializedName("UNKNOWN_SELF_PAY_STATUS") + UNKNOWN_SELF_PAY_STATUS, + /** + * 自费支付已创建 + */ + @SerializedName("SELF_PAY_CREATED") + SELF_PAY_CREATED, + /** + * 自费支付成功 + */ + @SerializedName("SELF_PAY_SUCCESS") + SELF_PAY_SUCCESS, + /** + * 自费支付已退款 + */ + @SerializedName("SELF_PAY_REFUND") + SELF_PAY_REFUND, + /** + * 自费支付失败 + */ + @SerializedName("SELF_PAY_FAIL") + SELF_PAY_FAIL, + /** + * 无需自费支付 + */ + @SerializedName("NO_SELF_PAY") + NO_SELF_PAY +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/UserCardTypeEnum.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/UserCardTypeEnum.java new file mode 100644 index 000000000..1bf97b762 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/mipay/enums/UserCardTypeEnum.java @@ -0,0 +1,54 @@ +package com.github.binarywang.wxpay.bean.mipay.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * 用户证件类型枚举 + *

+ * 描述医保自费混合支付中用户的证件类型 + * + * @author xgl + * @date 2025/12/20 + */ +public enum UserCardTypeEnum { + /** + * 未知的用户证件类型 + */ + @SerializedName("UNKNOWN_USER_CARD_TYPE") + UNKNOWN_USER_CARD_TYPE, + /** + * 居民身份证 + */ + @SerializedName("ID_CARD") + ID_CARD, + /** + * 户口本 + */ + @SerializedName("HOUSEHOLD_REGISTRATION") + HOUSEHOLD_REGISTRATION, + /** + * 外国护照 + */ + @SerializedName("FOREIGNER_PASSPORT") + FOREIGNER_PASSPORT, + /** + * 台湾居民来往大陆通行证 + */ + @SerializedName("MAINLAND_TRAVEL_PERMIT_FOR_TW") + MAINLAND_TRAVEL_PERMIT_FOR_TW, + /** + * 澳门居民来往大陆通行证 + */ + @SerializedName("MAINLAND_TRAVEL_PERMIT_FOR_MO") + MAINLAND_TRAVEL_PERMIT_FOR_MO, + /** + * 香港居民来往大陆通行证 + */ + @SerializedName("MAINLAND_TRAVEL_PERMIT_FOR_HK") + MAINLAND_TRAVEL_PERMIT_FOR_HK, + /** + * 外国人永久居留身份证 + */ + @SerializedName("FOREIGN_PERMANENT_RESIDENT") + FOREIGN_PERMANENT_RESIDENT +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/MiPayNotifyV3Result.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/MiPayNotifyV3Result.java new file mode 100644 index 000000000..a0641379f --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/MiPayNotifyV3Result.java @@ -0,0 +1,265 @@ +package com.github.binarywang.wxpay.bean.notify; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * 医保混合收款成功通知结果
+ * 文档地址:https://pay.weixin.qq.com/doc/v3/partner/4012165722
+ * 
+ * + * @author xgl + * @date 2025/12/20 + */ +@Data +@NoArgsConstructor +public class MiPayNotifyV3Result implements Serializable, WxPayBaseNotifyV3Result { + + /** + * 源数据 + */ + private OriginNotifyResponse rawData; + + /** + * 解密后的数据 + */ + private DecryptNotifyResult result; + + @Data + @NoArgsConstructor + public static class DecryptNotifyResult implements Serializable { + private static final long serialVersionUID = 1L; + + /** + *
+         * 字段名:应用ID
+         * 变量名:appid
+         * 是否必填:是
+         * 类型:string(32)
+         * 描述:
+         *   从业机构/服务商的公众号ID
+         * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+         * 字段名:医疗机构的公众号ID
+         * 变量名:sub_appid
+         * 是否必填:是
+         * 类型:string(32)
+         * 描述:
+         *   医疗机构的公众号ID
+         * 
+ */ + @SerializedName(value = "sub_appid") + private String subAppid; + + /** + *
+         * 字段名:医疗机构的商户号
+         * 变量名:sub_mchid
+         * 是否必填:是
+         * 类型:string(32)
+         * 描述:
+         *   医疗机构的商户号
+         * 
+ */ + @SerializedName(value = "sub_mchid") + private String subMchid; + + /** + *
+         * 字段名:从业机构订单号
+         * 变量名:out_trade_no
+         * 是否必填:是
+         * 类型:string(64)
+         * 描述:
+         *   从业机构/服务商订单号
+         * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+         * 字段名:医保自费混合订单号
+         * 变量名:mix_trade_no
+         * 是否必填:是
+         * 类型:string(32)
+         * 描述:
+         *   微信支付系统生成的医保自费混合订单号
+         * 
+ */ + @SerializedName(value = "mix_trade_no") + private String mixTradeNo; + + /** + *
+         * 字段名:微信支付订单号
+         * 变量名:transaction_id
+         * 是否必填:是
+         * 类型:string(32)
+         * 描述:
+         *   微信支付系统生成的订单号
+         * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+         * 字段名:医保订单创建时间
+         * 变量名:med_ins_order_create_time
+         * 是否必填:是
+         * 类型:string(64)
+         * 描述:
+         *   医保订单创建时间,遵循rfc3339标准格式
+         * 
+ */ + @SerializedName(value = "med_ins_order_create_time") + private String medInsOrderCreateTime; + + /** + *
+         * 字段名:医保订单完成时间
+         * 变量名:med_ins_order_finish_time
+         * 是否必填:是
+         * 类型:string(64)
+         * 描述:
+         *   医保订单完成时间,遵循rfc3339标准格式
+         * 
+ */ + @SerializedName(value = "med_ins_order_finish_time") + private String medInsOrderFinishTime; + + /** + *
+         * 字段名:总金额
+         * 变量名:total_fee
+         * 是否必填:否
+         * 类型:long
+         * 描述:
+         *   总金额,单位为分
+         * 
+ */ + @SerializedName(value = "total_fee") + private Long totalFee; + + /** + *
+         * 字段名:医保统筹基金支付金额
+         * 变量名:med_ins_gov_fee
+         * 是否必填:否
+         * 类型:long
+         * 描述:
+         *   医保统筹基金支付金额,单位为分
+         * 
+ */ + @SerializedName(value = "med_ins_gov_fee") + private Long medInsGovFee; + + /** + *
+         * 字段名:医保个人账户支付金额
+         * 变量名:med_ins_self_fee
+         * 是否必填:否
+         * 类型:long
+         * 描述:
+         *   医保个人账户支付金额,单位为分
+         * 
+ */ + @SerializedName(value = "med_ins_self_fee") + private Long medInsSelfFee; + + /** + *
+         * 字段名:医保其他基金支付金额
+         * 变量名:med_ins_other_fee
+         * 是否必填:否
+         * 类型:long
+         * 描述:
+         *   医保其他基金支付金额,单位为分
+         * 
+ */ + @SerializedName(value = "med_ins_other_fee") + private Long medInsOtherFee; + + /** + *
+         * 字段名:医保现金支付金额
+         * 变量名:med_ins_cash_fee
+         * 是否必填:否
+         * 类型:long
+         * 描述:
+         *   医保现金支付金额,单位为分
+         * 
+ */ + @SerializedName(value = "med_ins_cash_fee") + private Long medInsCashFee; + + /** + *
+         * 字段名:微信支付现金支付金额
+         * 变量名:wechat_pay_cash_fee
+         * 是否必填:否
+         * 类型:long
+         * 描述:
+         *   微信支付现金支付金额,单位为分
+         * 
+ */ + @SerializedName(value = "wechat_pay_cash_fee") + private Long wechatPayCashFee; + + /** + *
+         * 字段名:附加数据
+         * 变量名:attach
+         * 是否必填:否
+         * 类型:string(128)
+         * 描述:
+         *   附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
+         * 
+ */ + @SerializedName(value = "attach") + private String attach; + + /** + *
+         * 字段名:支付状态
+         * 变量名:trade_state
+         * 是否必填:是
+         * 类型:string(32)
+         * 描述:
+         *   交易状态,枚举值:
+         *   SUCCESS:支付成功
+         *   REFUND:转入退款
+         *   NOTPAY:未支付
+         *   CLOSED:已关闭
+         *   REVOKED:已撤销
+         *   USERPAYING:用户支付中
+         *   PAYERROR:支付失败
+         * 
+ */ + @SerializedName(value = "trade_state") + private String tradeState; + + /** + *
+         * 字段名:支付状态描述
+         * 变量名:trade_state_desc
+         * 是否必填:是
+         * 类型:string(256)
+         * 描述:
+         *   交易状态描述
+         * 
+ */ + @SerializedName(value = "trade_state_desc") + private String tradeStateDesc; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MiPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MiPayService.java new file mode 100644 index 000000000..83b75ad40 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/MiPayService.java @@ -0,0 +1,94 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.mipay.MedInsOrdersRequest; +import com.github.binarywang.wxpay.bean.mipay.MedInsOrdersResult; +import com.github.binarywang.wxpay.bean.mipay.MedInsRefundNotifyRequest; +import com.github.binarywang.wxpay.bean.notify.MiPayNotifyV3Result; +import com.github.binarywang.wxpay.bean.notify.SignatureHeader; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + * 医保相关接口 + * 医保相关接口 + * @author xgl + * @date 2025/12/20 + */ +public interface MiPayService { + + /** + *
+   * 医保自费混合收款下单
+   *
+   * 从业机构调用该接口向微信医保后台下单
+   *
+   * 文档地址:医保自费混合收款下单
+   * 
+ * + * @param request 下单参数 + * @return ReservationTransferNotifyResult 下单结果 + * @throws WxPayException the wx pay exception + */ + MedInsOrdersResult medInsOrders(MedInsOrdersRequest request) throws WxPayException; + + /** + *
+   * 使用医保自费混合订单号查看下单结果
+   *
+   * 从业机构使用混合下单订单号,通过该接口主动查询订单状态,完成下一步的业务逻辑。
+   *
+   * 文档地址:使用医保自费混合订单号查看下单结果
+   * 
+ * + * @param mixTradeNo 医保自费混合订单号 + * @param subMchid 医疗机构的商户号 + * @return MedInsOrdersResult 下单结果 + * @throws WxPayException the wx pay exception + */ + MedInsOrdersResult getMedInsOrderByMixTradeNo(String mixTradeNo, String subMchid) throws WxPayException; + + /** + *
+   * 使用从业机构订单号查看下单结果
+   *
+   * 从业机构使用从业机构订单号、医疗机构商户号,通过该接口主动查询订单状态,完成下一步的业务逻辑。
+   *
+   * 文档地址:使用从业机构订单号查看下单结果
+   * 
+ * + * @param outTradeNo 从业机构订单号 + * @param subMchid 医疗机构的商户号 + * @return MedInsOrdersResult 下单结果 + * @throws WxPayException the wx pay exception + */ + MedInsOrdersResult getMedInsOrderByOutTradeNo(String outTradeNo, String subMchid) throws WxPayException; + + /** + *
+   * 解析医保混合收款成功通知
+   *
+   * 微信支付会通过POST请求向商户设置的回调URL推送医保混合收款成功通知,商户需要接收处理该消息,并返回应答。
+   *
+   * 文档地址:医保混合收款成功通知
+   * 
+ * + * @param notifyData 通知数据字符串 + * @return MiPayNotifyV3Result 医保混合收款成功通知结果 + * @throws WxPayException the wx pay exception + */ + MiPayNotifyV3Result parseMiPayNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException; + + /** + *
+   * 医保退款通知
+   *
+   * 从业机构调用该接口向微信医保后台通知医保订单的退款成功结果
+   *
+   * 文档地址:医保退款通知
+   * 
+ * + * @param request 医保退款通知请求参数 + * @throws WxPayException the wx pay exception + */ + void medInsRefundNotify(MedInsRefundNotifyRequest request) throws WxPayException; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 93da0d133..cfb2479ae 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -1706,4 +1706,12 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri * @return the partner pay score sign plan service */ PartnerPayScoreSignPlanService getPartnerPayScoreSignPlanService(); + + /** + * 获取医保支付服务类 + * + * @return the merchant transfer service + */ + MiPayService getMiPayService(); + } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index ba3dc3714..f2e343df2 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -1,17 +1,21 @@ package com.github.binarywang.wxpay.service.impl; -import com.github.binarywang.utils.qrcode.QrcodeUtils; -import com.github.binarywang.wxpay.bean.WxPayApiData; +import static com.github.binarywang.wxpay.constant.WxPayConstants.QUERY_COMMENT_DATE_FORMAT; +import static com.github.binarywang.wxpay.constant.WxPayConstants.TarType; import com.github.binarywang.wxpay.bean.coupon.*; import com.github.binarywang.wxpay.bean.notify.*; +import com.github.binarywang.wxpay.bean.request.*; +import com.github.binarywang.wxpay.bean.result.*; +import com.github.binarywang.wxpay.service.*; +import java.util.*; +import com.github.binarywang.wxpay.bean.result.enums.GlobalTradeTypeEnum; +import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; +import com.github.binarywang.utils.qrcode.QrcodeUtils; +import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; -import com.github.binarywang.wxpay.bean.request.*; -import com.github.binarywang.wxpay.bean.result.*; -import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; -import com.github.binarywang.wxpay.bean.result.enums.GlobalTradeTypeEnum; import com.github.binarywang.wxpay.bean.transfer.TransferBillsNotifyResult; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.config.WxPayConfigHolder; @@ -19,7 +23,6 @@ import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.exception.WxSignTestException; -import com.github.binarywang.wxpay.service.*; import com.github.binarywang.wxpay.util.SignUtils; import com.github.binarywang.wxpay.util.XmlConfig; import com.github.binarywang.wxpay.util.ZipUtils; @@ -29,14 +32,6 @@ import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import me.chanjar.weixin.common.error.WxRuntimeException; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.reflect.ConstructorUtils; -import org.apache.http.entity.ContentType; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -45,12 +40,15 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.security.GeneralSecurityException; -import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.zip.ZipException; - -import static com.github.binarywang.wxpay.constant.WxPayConstants.QUERY_COMMENT_DATE_FORMAT; -import static com.github.binarywang.wxpay.constant.WxPayConstants.TarType; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxRuntimeException; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.ConstructorUtils; +import org.apache.http.entity.ContentType; /** *
@@ -139,6 +137,9 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
   @Getter
   private final BusinessOperationTransferService businessOperationTransferService = new BusinessOperationTransferServiceImpl(this);
 
+  @Getter
+  private final MiPayService miPayService = new MiPayServiceImpl(this);
+
   protected Map configMap = new ConcurrentHashMap<>();
 
   @Override
diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MiPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MiPayServiceImpl.java
new file mode 100644
index 000000000..3063d7731
--- /dev/null
+++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/MiPayServiceImpl.java
@@ -0,0 +1,68 @@
+package com.github.binarywang.wxpay.service.impl;
+
+import com.github.binarywang.wxpay.bean.mipay.MedInsOrdersRequest;
+import com.github.binarywang.wxpay.bean.mipay.MedInsOrdersResult;
+import com.github.binarywang.wxpay.bean.mipay.MedInsRefundNotifyRequest;
+import com.github.binarywang.wxpay.bean.notify.MiPayNotifyV3Result;
+import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.MiPayService;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.security.cert.X509Certificate;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * 医保相关接口
+ * 医保相关接口
+ * @author xgl
+ * @date 2025/12/20
+ */
+@RequiredArgsConstructor
+public class MiPayServiceImpl implements MiPayService {
+
+  private final WxPayService payService;
+  private static final Gson GSON = new GsonBuilder().create();
+
+
+  @Override
+  public MedInsOrdersResult medInsOrders(MedInsOrdersRequest request) throws WxPayException {
+
+    String url = String.format("%s/v3/med-ins/orders", this.payService.getPayBaseUrl());
+    X509Certificate validCertificate = this.payService.getConfig().getVerifier().getValidCertificate();
+
+    RsaCryptoUtil.encryptFields(request, validCertificate);
+
+    String result = this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request));
+    return GSON.fromJson(result, MedInsOrdersResult.class);
+  }
+
+  @Override
+  public MedInsOrdersResult getMedInsOrderByMixTradeNo(String mixTradeNo, String subMchid) throws WxPayException {
+    String url = String.format("%s/v3/med-ins/orders/mix-trade-no/%s?sub_mchid=%s", this.payService.getPayBaseUrl(), mixTradeNo, subMchid);
+    String result = this.payService.getV3(url);
+    return GSON.fromJson(result, MedInsOrdersResult.class);
+  }
+
+  @Override
+  public MedInsOrdersResult getMedInsOrderByOutTradeNo(String outTradeNo, String subMchid) throws WxPayException {
+    String url = String.format("%s/v3/med-ins/orders/out-trade-no/%s?sub_mchid=%s", this.payService.getPayBaseUrl(), outTradeNo, subMchid);
+    String result = this.payService.getV3(url);
+    return GSON.fromJson(result, MedInsOrdersResult.class);
+  }
+
+  @Override
+  public MiPayNotifyV3Result parseMiPayNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
+    return this.payService.baseParseOrderNotifyV3Result(notifyData, header, MiPayNotifyV3Result.class, MiPayNotifyV3Result.DecryptNotifyResult.class);
+  }
+
+  @Override
+  public void medInsRefundNotify(MedInsRefundNotifyRequest request) throws WxPayException {
+    String url = String.format("%s/v3/med-ins/refunds/notify?mix_trade_no=%s", this.payService.getPayBaseUrl(), request.getMixTradeNo());
+    this.payService.postV3(url, GSON.toJson(request));
+  }
+
+
+}
diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MiPayServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MiPayServiceImplTest.java
new file mode 100644
index 000000000..23c3c5681
--- /dev/null
+++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MiPayServiceImplTest.java
@@ -0,0 +1,148 @@
+package com.github.binarywang.wxpay.service.impl;
+
+import com.github.binarywang.wxpay.bean.mipay.MedInsOrdersRequest;
+import com.github.binarywang.wxpay.bean.mipay.MedInsOrdersResult;
+import com.github.binarywang.wxpay.bean.mipay.MedInsRefundNotifyRequest;
+import com.github.binarywang.wxpay.bean.notify.MiPayNotifyV3Result;
+import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.MiPayService;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.testbase.ApiTestModule;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+/**
+ * 医保接口测试
+ * @author xgl
+ * @date 2025/12/20 10:04
+ */
+@Slf4j
+@Test
+@Guice(modules = ApiTestModule.class)
+public class MiPayServiceImplTest {
+
+  @Inject
+  private WxPayService wxPayService;
+
+  private static final Gson GSON = new GsonBuilder().create();
+
+
+  /**
+   * 医保自费混合收款下单测试
+   * @throws WxPayException
+   */
+  @Test
+  public void medInsOrders() throws WxPayException {
+    String requestParamStr = "{\"mix_pay_type\":\"CASH_AND_INSURANCE\",\"order_type\":\"REG_PAY\",\"appid\":\"wxdace645e0bc2cXXX\",\"sub_appid\":\"wxdace645e0bc2cXXX\",\"sub_mchid\":\"1900008XXX\",\"openid\":\"o4GgauInH_RCEdvrrNGrntXDuXXX\",\"sub_openid\":\"o4GgauInH_RCEdvrrNGrntXDuXXX\",\"payer\":{\"name\":\"张三\",\"id_digest\":\"09eb26e839ff3a2e3980352ae45ef09e\",\"card_type\":\"ID_CARD\"},\"pay_for_relatives\":false,\"relative\":{\"name\":\"张三\",\"id_digest\":\"09eb26e839ff3a2e3980352ae45ef09e\",\"card_type\":\"ID_CARD\"},\"out_trade_no\":\"202204022005169952975171534816\",\"serial_no\":\"1217752501201\",\"pay_order_id\":\"ORD530100202204022006350000021\",\"pay_auth_no\":\"AUTH530100202204022006310000034\",\"geo_location\":\"102.682296,25.054260\",\"city_id\":\"530100\",\"med_inst_name\":\"北大医院\",\"med_inst_no\":\"1217752501201407033233368318\",\"med_ins_order_create_time\":\"2015-05-20T13:29:35+08:00\",\"total_fee\":202000,\"med_ins_gov_fee\":100000,\"med_ins_self_fee\":45000,\"med_ins_other_fee\":5000,\"med_ins_cash_fee\":50000,\"wechat_pay_cash_fee\":42000,\"cash_add_detail\":[{\"cash_add_fee\":2000,\"cash_add_type\":\"FREIGHT\"}],\"cash_reduce_detail\":[{\"cash_reduce_fee\":10000,\"cash_reduce_type\":\"DEFAULT_REDUCE_TYPE\"}],\"callback_url\":\"https://www.weixin.qq.com/wxpay/pay.php\",\"prepay_id\":\"wx201410272009395522657a690389285100\",\"passthrough_request_content\":\"{\\\"payAuthNo\\\":\\\"AUTH****\\\",\\\"payOrdId\\\":\\\"ORD****\\\",\\\"setlLatlnt\\\":\\\"118.096435,24.485407\\\"}\",\"extends\":\"{}\",\"attach\":\"{}\",\"channel_no\":\"AAGN9uhZc5EGyRdairKW7Qnu\",\"med_ins_test_env\":false}";
+
+    MedInsOrdersRequest request = GSON.fromJson(requestParamStr, MedInsOrdersRequest.class);
+
+    MiPayService miPayService = wxPayService.getMiPayService();
+
+    MedInsOrdersResult result = miPayService.medInsOrders(request);
+
+    log.info(result.toString());
+  }
+
+  /**
+   * 使用医保自费混合订单号查看下单结果测试
+   * @throws WxPayException
+   */
+  @Test
+  public void getMedInsOrderByMixTradeNo() throws WxPayException {
+    // 测试用的医保自费混合订单号和医疗机构商户号
+    String mixTradeNo = "202204022005169952975171534816";
+    String subMchid = "1900000109";
+
+    MiPayService miPayService = wxPayService.getMiPayService();
+
+    MedInsOrdersResult result = miPayService.getMedInsOrderByMixTradeNo(mixTradeNo, subMchid);
+
+    log.info(result.toString());
+  }
+
+  /**
+   * 使用从业机构订单号查看下单结果测试
+   * @throws WxPayException
+   */
+  @Test
+  public void getMedInsOrderByOutTradeNo() throws WxPayException {
+    // 测试用的从业机构订单号和医疗机构商户号
+    String outTradeNo = "202204022005169952975171534816";
+    String subMchid = "1900000109";
+
+    MiPayService miPayService = wxPayService.getMiPayService();
+
+    MedInsOrdersResult result = miPayService.getMedInsOrderByOutTradeNo(outTradeNo, subMchid);
+
+    log.info(result.toString());
+  }
+
+  /**
+   * 解析医保混合收款成功通知测试
+   * @throws WxPayException
+   */
+  @Test
+  public void parseMiPayNotifyV3Result() throws WxPayException {
+    // 模拟的医保混合收款成功通知数据
+    String notifyData = "{\"id\":\"EV-202401011234567890\",\"create_time\":\"2024-01-01T12:34:56+08:00\",\"event_type\":\"MEDICAL_INSURANCE.SUCCESS\",\"summary\":\"医保混合收款成功\",\"resource_type\":\"encrypt-resource\",\"resource\":{\"algorithm\":\"AEAD_AES_256_GCM\",\"ciphertext\":\"encrypted_data\",\"associated_data\":\"\",\"nonce\":\"random_string\"}}";
+
+    // 模拟的签名信息
+    String signature = "test_signature";
+    String timestamp = "1234567890";
+    String nonce = "test_nonce";
+    String serial = "test_serial";
+
+    MiPayService miPayService = wxPayService.getMiPayService();
+
+    SignatureHeader header = SignatureHeader.builder()
+      .signature(signature)
+      .timeStamp(timestamp)
+      .nonce(nonce)
+      .serial(serial)
+      .build();
+
+    try {
+      // 调用解析方法,预期会失败,因为是模拟数据
+      MiPayNotifyV3Result result = miPayService.parseMiPayNotifyV3Result(notifyData, header);
+      log.info("解析结果:{}", result);
+    } catch (WxPayException e) {
+      // 预期会抛出异常,因为是模拟数据,签名验证和解密都会失败
+      log.info("预期的异常:{}", e.getMessage());
+    }
+  }
+
+  /**
+   * 医保退款通知测试
+   * @throws WxPayException
+   */
+  @Test
+  public void medInsRefundNotify() throws WxPayException {
+    // 测试用的医保自费混合订单号
+    String mixTradeNo = "202204022005169952975171534816";
+
+    // 模拟的医保退款通知请求数据
+    String requestParamStr = "{\"sub_mchid\":\"1900008XXX\",\"med_refund_total_fee\":45000,\"med_refund_gov_fee\":45000,\"med_refund_self_fee\":45000,\"med_refund_other_fee\":45000,\"refund_time\":\"2015-05-20T13:29:35+08:00\",\"out_refund_no\":\"R202204022005169952975171534816\"}";
+
+    // 解析请求参数
+    MedInsRefundNotifyRequest request = GSON.fromJson(requestParamStr, MedInsRefundNotifyRequest.class);
+    request.setMixTradeNo(mixTradeNo);
+
+    MiPayService miPayService = wxPayService.getMiPayService();
+
+    try {
+      // 调用医保退款通知方法,预期会失败,因为是模拟数据
+      miPayService.medInsRefundNotify(request);
+      log.info("医保退款通知调用成功");
+    } catch (WxPayException e) {
+      // 预期会抛出异常,因为是模拟数据
+      log.info("预期的异常:{}", e.getMessage());
+    }
+  }
+
+}