فهرست منبع

航信电子发票SDK

skyline 3 روز پیش
والد
کامیت
253e1c57db
24فایلهای تغییر یافته به همراه1263 افزوده شده و 0 حذف شده
  1. 270 0
      huapiaoer-sdk/README.md
  2. 20 0
      huapiaoer-sdk/pom.xml
  3. 140 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/HuapiaoerClient.java
  4. 12 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/HuapiaoerConfig.java
  5. 15 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/HuapiaoerException.java
  6. 14 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/enums/InvoiceQueryType.java
  7. 14 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/enums/InvoiceType.java
  8. 26 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/enums/PayType.java
  9. 13 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/AuthorizeOrderRequest.java
  10. 8 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/DrawerListRequest.java
  11. 8 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/EnterpriseSearchRequest.java
  12. 37 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/InvoiceQrcodeRequest.java
  13. 9 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/InvoiceQueryRequest.java
  14. 57 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/OpenBlueInvoiceRequest.java
  15. 8 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/OpenRedInvoiceRequest.java
  16. 10 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/SendMailRequest.java
  17. 15 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/AuthorizeOrderResponse.java
  18. 9 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/DrawerInfo.java
  19. 14 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/EnterpriseInfo.java
  20. 15 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/HuapiaoerResponse.java
  21. 26 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/InvoiceInfo.java
  22. 11 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/OpenInvoiceResponse.java
  23. 9 0
      huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/QrcodeResponse.java
  24. 503 0
      huapiaoer-sdk/src/main/resources/电子发票API_航信乐企版_v5.1.md

+ 270 - 0
huapiaoer-sdk/README.md

@@ -0,0 +1,270 @@
+# 航信电子发票 SDK (huapiaoer-sdk)
+
+基于航信(票慧通)乐企版 v5.1 的电子发票 Java SDK,封装了发票开具、红冲、查询、发送邮件等全部接口。
+
+## 引入依赖
+
+```xml
+<dependency>
+    <groupId>com.kym</groupId>
+    <artifactId>huapiaoer-sdk</artifactId>
+    <version>5.1.0</version>
+</dependency>
+```
+
+## 快速开始
+
+```java
+// 1. 创建配置
+HuapiaoerConfig config = HuapiaoerConfig.builder()
+        .appSecret("你的票慧通 appsecret")
+        .build();
+
+// 2. 创建客户端
+HuapiaoerClient client = new HuapiaoerClient(config);
+
+// 3. 调用接口
+List<DrawerInfo> drawers = client.getDrawerIdList("915001*******460R");
+```
+
+## 配置参数
+
+| 参数 | 类型 | 必填 | 默认值 | 说明 |
+|------|------|------|--------|------|
+| `appSecret` | String | 是 | — | 票慧通提供的密钥 |
+| `baseUrl` | String | 否 | `https://erp.huapiaoer.com` | API 正式环境地址 |
+
+> `appSecret` 由 SDK 自动注入到所有请求中,无需手动设置。
+
+---
+
+## API 参考
+
+### 1. 查询开票人列表
+
+查询当前企业下所有开票人。
+
+```java
+List<DrawerInfo> getDrawerIdList(String nsrsbh)
+```
+
+| 参数 | 类型 | 说明 |
+|------|------|------|
+| `nsrsbh` | String | 开票方税号(商家税号) |
+
+---
+
+### 2. 授权订单号
+
+微信支付商户授权,在发起开票前调用。
+
+```java
+AuthorizeOrderResponse getAuthorizeOrderId(AuthorizeOrderRequest request)
+```
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `omsoutputorderid` | String | 是 | 订单号(企业号 + 流水号) |
+| `appid` | String | 是 | 商户 AppID |
+| `openid` | String | 是 | 微信 OpenID |
+| `source` | String | 否 | `WEB` / `MINIPROGRAM` |
+
+---
+
+### 3. 发票开具
+
+开具蓝字发票。
+
+```java
+OpenInvoiceResponse openBlueInvoice(OpenBlueInvoiceRequest request)
+```
+
+请求核心字段:
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `issuerid` | String | 否 | 开票人 ID |
+| `tradeinfo.payType` | String | 是 | 支付渠道编码,见 `PayType` 枚举 |
+| `tradeinfo.outTradeNo` | String | 是 | 支付流水号 |
+| `head.kpje` | String | 是 | 开票总金额 |
+| `head.orderId` | String | 是 | 开票订单号 |
+| `head.b2cshopid` | String | 是 | 商家税号 |
+| `head.invoicetitle` | String | 是 | 购方抬头 |
+| `head.invoiceTypeCode` | String | 是 | 发票类型,见 `InvoiceType` 枚举 |
+| `head.registrationnumber` | String | 否 | 购方税号 |
+| `head.companyaddress` | String | 否 | 购方地址 |
+| `head.mobilenumber` | String | 否 | 购方手机号 |
+| `head.openaccountbank` | String | 否 | 银行名称 |
+| `head.bankaccount` | String | 否 | 银行账号 |
+| `head.remark` | String | 否 | 发票备注 |
+| `head.recmail` | String | 否 | 接收邮箱 |
+| `details` | List | 是 | 商品明细 |
+
+商品明细 (`DetailInfo`):
+
+| 字段 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `goodsname` | String | 是 | 商品名称 |
+| `price` | Double | 是 | 商品单价(元) |
+| `sl` | Double | 是 | 数量 |
+| `goodscategory` | String | 否 | 商品大类(与 taxcode/tax 二选一) |
+| `taxcode` | String | 否 | 税目编码(与 goodscategory 二选一) |
+| `tax` | String | 否 | 税率(与 goodscategory 二选一) |
+| `attributes` | String | 否 | 规格型号 |
+| `unitname` | String | 否 | 单位 |
+| `discount` | Double | 否 | 折扣金额(元) |
+
+使用示例:
+
+```java
+OpenInvoiceResponse resp = client.openBlueInvoice(
+    new OpenBlueInvoiceRequest()
+        .setIssuerid("1868914789939154946")
+        .setTradeinfo(new TradeInfo()
+            .setPayType(PayType.WECHAT_PAY.getCode())
+            .setOutTradeNo("WX20240410000001"))
+        .setHead(new HeadInfo()
+            .setOrderId("1019000000000001")
+            .setB2cshopid("914403008888888888")
+            .setKpje("1.00")
+            .setInvoicetitle("深圳柯适科技有限公司")
+            .setRegistrationnumber("91440300MA5FB8A214")
+            .setInvoiceTypeCode(InvoiceType.DIGITAL_NORMAL.getCode())
+            .setRecmail("test@qq.com"))
+        .setDetails(List.of(
+            new DetailInfo()
+                .setGoodsname("充电服务费")
+                .setPrice(1.0)
+                .setSl(1.0)
+                .setTaxcode("1030302000000000xxx")
+                .setTax("0.13")
+        ))
+);
+// resp.getCode()        → "200"
+// resp.getData()         → "订单生成成功!请让用户授权。"
+// resp.getOrderId()      → "1019000000000001"
+// resp.getAuthorizeQRCode() → "https://image.huapiaoer.com/xxx.png"
+```
+
+---
+
+### 4. 发票红冲
+
+冲红已开具的发票。
+
+```java
+HuapiaoerResponse<String> openRedInvoice(String orderId)
+```
+
+| 参数 | 类型 | 说明 |
+|------|------|------|
+| `orderId` | String | 发票订单号 |
+
+---
+
+### 5. 发票查询
+
+查询发票开票结果。
+
+```java
+InvoiceInfo getInvoice(String orderId, int invoicetype)
+```
+
+| 参数 | 类型 | 说明 |
+|------|------|------|
+| `orderId` | String | 航信订单号 |
+| `invoicetype` | int | `1` 蓝票,`2` 红票,见 `InvoiceQueryType` |
+
+返回 `InvoiceInfo` 包含:`invoicenumber`(发票号码)、`invoicecode`(发票代码)、`invoiceurl`(PDF 地址)、`ofdurl`(OFD 地址)、`xmlurl`(XML 地址)、`ticketTotalAmountHasTax`(金额)等。
+
+---
+
+### 6. 发送邮件
+
+将发票发送到指定邮箱。
+
+```java
+HuapiaoerResponse<String> sendMail(String orderId, int invoiceType, String email)
+```
+
+| 参数 | 类型 | 说明 |
+|------|------|------|
+| `orderId` | String | 订单号 |
+| `invoiceType` | int | `1` 蓝票,`2` 红票 |
+| `email` | String | 目标邮箱 |
+
+---
+
+### 7. 生成开票二维码
+
+生成自助开票二维码,用户扫码填写抬头开票。
+
+```java
+HuapiaoerResponse<QrcodeResponse> getInvoiceQrcode(InvoiceQrcodeRequest request)
+```
+
+| 参数 | 类型 | 必填 | 说明 |
+|------|------|------|------|
+| `head.orderId` | String | 是 | 开票订单号 |
+| `head.b2cshopid` | String | 是 | 商家税号 |
+| `head.invoiceTypeCode` | String | 是 | 发票类型 |
+| `head.remark` | String | 否 | 发票备注 |
+| `details` | List | 是 | 商品明细(不含 discount) |
+
+---
+
+### 8. 企业搜索
+
+根据企业简称查询企业基本信息。
+
+```java
+List<EnterpriseInfo> searchEnterprise(String enterpriseName)
+```
+
+| 参数 | 类型 | 说明 |
+|------|------|------|
+| `enterpriseName` | String | 公司简称(4 个字符起生效) |
+
+---
+
+## 枚举常量
+
+### InvoiceType 发票类型
+
+| 枚举 | 编码 | 说明 |
+|------|------|------|
+| `DIGITAL_SPECIAL` | `"081"` | 数电专票 |
+| `DIGITAL_NORMAL` | `"082"` | 数电普票 |
+
+### InvoiceQueryType 查询类型
+
+| 枚举 | 值 | 说明 |
+|------|-----|------|
+| `BLUE` | `1` | 蓝票 |
+| `RED` | `2` | 红票 |
+
+### PayType 支付渠道
+
+| 枚举 | 编码 | 说明 |
+|------|------|------|
+| `CASH` | `"01"` | 现金 |
+| `BANK_TRANSFER` | `"02"` | 银行转账 |
+| `ALIPAY` | `"09"` | 支付宝 |
+| `WECHAT_PAY` | `"10"` | 微信支付 |
+| `UNIONPAY_QUICK` | `"11"` | 云闪付 |
+| ... | ... | 共 14 种支付渠道 |
+
+---
+
+## 异常处理
+
+所有接口在 `code != "200"` 或网络异常时抛出 `HuapiaoerException`:
+
+```java
+try {
+    List<DrawerInfo> drawers = client.getDrawerIdList("...");
+} catch (HuapiaoerException e) {
+    // e.getCode()    — 状态码
+    // e.getMessage() — 错误描述
+}
+```

+ 20 - 0
huapiaoer-sdk/pom.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.kym</groupId>
+        <artifactId>charge</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>huapiaoer-sdk</artifactId>
+
+    <properties>
+        <maven.compiler.source>21</maven.compiler.source>
+        <maven.compiler.target>21</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+</project>

+ 140 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/HuapiaoerClient.java

@@ -0,0 +1,140 @@
+package com.kym.huapiaoer;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.TypeReference;
+import com.kym.huapiaoer.model.request.*;
+import com.kym.huapiaoer.model.response.*;
+import okhttp3.*;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class HuapiaoerClient {
+
+    private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
+
+    private final HuapiaoerConfig config;
+    private final OkHttpClient httpClient;
+
+    public HuapiaoerClient(HuapiaoerConfig config) {
+        this.config = config;
+        this.httpClient = new OkHttpClient.Builder()
+                .connectTimeout(10, TimeUnit.SECONDS)
+                .readTimeout(30, TimeUnit.SECONDS)
+                .writeTimeout(30, TimeUnit.SECONDS)
+                .build();
+    }
+
+    // ==================== 3.1 查询开票人列表 ====================
+
+    public List<DrawerInfo> getDrawerIdList(String nsrsbh) {
+        JSONObject body = new JSONObject();
+        body.put("nsrsbh", nsrsbh);
+        body.put("appsecret", config.getAppSecret());
+        String json = post("/ewy_weberp/api/huapiaoer/outopenapis/getDrawerIdList", body);
+        return parseStandardResponse(json, new TypeReference<List<DrawerInfo>>() {}.getType());
+    }
+
+    // ==================== 3.2 授权订单号 ====================
+
+    public AuthorizeOrderResponse getAuthorizeOrderId(AuthorizeOrderRequest request) {
+        JSONObject body = buildBody(request);
+        String json = post("/ewy_weberp/api/wechatPay/getWechatShopAuthorizeOrderId", body);
+        return JSONObject.parseObject(json, AuthorizeOrderResponse.class);
+    }
+
+    // ==================== 3.3 发票开具 ====================
+
+    public OpenInvoiceResponse openBlueInvoice(OpenBlueInvoiceRequest request) {
+        JSONObject body = buildBody(request);
+        String json = post("/ewy_weberp/api/huapiaoer/outopenapis/openBlueInvoice", body);
+        return JSONObject.parseObject(json, OpenInvoiceResponse.class);
+    }
+
+    // ==================== 3.4 发票红冲 ====================
+
+    public HuapiaoerResponse<String> openRedInvoice(String orderId) {
+        JSONObject body = new JSONObject();
+        body.put("orderId", orderId);
+        body.put("appsecret", config.getAppSecret());
+        String json = post("/ewy_weberp/api/huapiaoer/outopenapis/openRedInvoice", body);
+        return JSONObject.parseObject(json, new TypeReference<HuapiaoerResponse<String>>() {});
+    }
+
+    // ==================== 3.5 发票通知、查询 ====================
+
+    public InvoiceInfo getInvoice(String orderId, int invoicetype) {
+        JSONObject body = new JSONObject();
+        body.put("orderId", orderId);
+        body.put("invoicetype", invoicetype);
+        body.put("appsecret", config.getAppSecret());
+        String json = post("/ewy_weberp/api/huapiaoer/outopenapis/getInvoice", body);
+        return parseStandardResponse(json, InvoiceInfo.class);
+    }
+
+    // ==================== 3.6 发送邮件 ====================
+
+    public HuapiaoerResponse<String> sendMail(String orderId, int invoiceType, String email) {
+        JSONObject body = new JSONObject();
+        body.put("orderId", orderId);
+        body.put("invoiceType", invoiceType);
+        body.put("email", email);
+        body.put("appsecret", config.getAppSecret());
+        String json = post("/ewy_weberp/api/huapiaoer/outopenapis/sendMail", body);
+        return JSONObject.parseObject(json, new TypeReference<HuapiaoerResponse<String>>() {});
+    }
+
+    // ==================== 3.7 生成开票二维码 ====================
+
+    public HuapiaoerResponse<QrcodeResponse> getInvoiceQrcode(InvoiceQrcodeRequest request) {
+        JSONObject body = buildBody(request);
+        String json = post("/ewy_weberp/api/huapiaoer/outopenapis/getInvoiceQrcode", body);
+        return JSONObject.parseObject(json, new TypeReference<HuapiaoerResponse<QrcodeResponse>>() {});
+    }
+
+    // ==================== 4.1 企业搜索 ====================
+
+    public List<EnterpriseInfo> searchEnterprise(String enterpriseName) {
+        JSONObject body = new JSONObject();
+        body.put("enterpriseName", enterpriseName);
+        body.put("appsecret", config.getAppSecret());
+        String json = post("/ewy_weberp/api/piaotong/platform/getInvoiceHeaderInquiry", body);
+        return parseStandardResponse(json, new TypeReference<List<EnterpriseInfo>>() {}.getType());
+    }
+
+    // ==================== 内部方法 ====================
+
+    private String post(String path, JSONObject body) {
+        String url = config.getBaseUrl() + path;
+        RequestBody requestBody = RequestBody.create(body.toJSONString(), JSON_MEDIA_TYPE);
+        Request request = new Request.Builder().url(url).post(requestBody).build();
+        try (Response response = httpClient.newCall(request).execute()) {
+            if (!response.isSuccessful()) {
+                throw new HuapiaoerException(String.valueOf(response.code()), "HTTP " + response.code());
+            }
+            return response.body() != null ? response.body().string() : "";
+        } catch (IOException e) {
+            throw new HuapiaoerException("500", "网络请求异常: " + e.getMessage());
+        }
+    }
+
+    private JSONObject buildBody(Object request) {
+        JSONObject body = (JSONObject) JSON.toJSON(request);
+        body.put("appsecret", config.getAppSecret());
+        return body;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T> T parseStandardResponse(String responseBody, Type dataType) {
+        JSONObject json = JSONObject.parseObject(responseBody);
+        String code = json.getString("code");
+        if (!"200".equals(code)) {
+            String msg = json.getString("data");
+            throw new HuapiaoerException(code, msg != null ? msg : "请求失败");
+        }
+        return (T) json.getObject("data", dataType);
+    }
+}

+ 12 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/HuapiaoerConfig.java

@@ -0,0 +1,12 @@
+package com.kym.huapiaoer;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class HuapiaoerConfig {
+    @Builder.Default
+    private String baseUrl = "https://erp.huapiaoer.com";
+    private String appSecret;
+}

+ 15 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/HuapiaoerException.java

@@ -0,0 +1,15 @@
+package com.kym.huapiaoer;
+
+public class HuapiaoerException extends RuntimeException {
+
+    private final String code;
+
+    public HuapiaoerException(String code, String message) {
+        super(message);
+        this.code = code;
+    }
+
+    public String getCode() {
+        return code;
+    }
+}

+ 14 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/enums/InvoiceQueryType.java

@@ -0,0 +1,14 @@
+package com.kym.huapiaoer.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum InvoiceQueryType {
+    BLUE(1, "蓝票"),
+    RED(2, "红票");
+
+    private final int code;
+    private final String desc;
+}

+ 14 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/enums/InvoiceType.java

@@ -0,0 +1,14 @@
+package com.kym.huapiaoer.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum InvoiceType {
+    DIGITAL_SPECIAL("081", "数电专票"),
+    DIGITAL_NORMAL("082", "数电普票");
+
+    private final String code;
+    private final String desc;
+}

+ 26 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/enums/PayType.java

@@ -0,0 +1,26 @@
+package com.kym.huapiaoer.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum PayType {
+    CASH("01", "现金"),
+    BANK_TRANSFER("02", "银行转账"),
+    BILL("03", "票据"),
+    DEBIT_CARD("04", "借记卡"),
+    CREDIT_CARD("05", "信用卡"),
+    SHOPPING_CARD("06", "购物卡/券"),
+    COUPON("07", "优惠券"),
+    MALL_POINTS("08", "商场积分"),
+    ALIPAY("09", "支付宝"),
+    WECHAT_PAY("10", "微信支付"),
+    UNIONPAY_QUICK("11", "云闪付"),
+    APPLE_PAY("12", "Apple Pay"),
+    SAMSUNG_PAY("13", "Samsung Pay"),
+    OTHER("99", "其他");
+
+    private final String code;
+    private final String desc;
+}

+ 13 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/AuthorizeOrderRequest.java

@@ -0,0 +1,13 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@Accessors(chain = true)
+public class AuthorizeOrderRequest {
+    private String omsoutputorderid;
+    private String source;
+    private String appid;
+    private String openid;
+}

+ 8 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/DrawerListRequest.java

@@ -0,0 +1,8 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+
+@Data
+public class DrawerListRequest {
+    private String nsrsbh;
+}

+ 8 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/EnterpriseSearchRequest.java

@@ -0,0 +1,8 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+
+@Data
+public class EnterpriseSearchRequest {
+    private String enterpriseName;
+}

+ 37 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/InvoiceQrcodeRequest.java

@@ -0,0 +1,37 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+public class InvoiceQrcodeRequest {
+
+    private HeadInfo head;
+
+    private List<DetailInfo> details;
+
+    @Data
+    @Accessors(chain = true)
+    public static class HeadInfo {
+        private String orderId;
+        private String b2cshopid;
+        private String remark;
+        private String invoiceTypeCode;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DetailInfo {
+        private String goodscategory;
+        private String taxcode;
+        private String tax;
+        private String goodsname;
+        private Double price;
+        private Double sl;
+        private String attributes;
+        private String unitname;
+    }
+}

+ 9 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/InvoiceQueryRequest.java

@@ -0,0 +1,9 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+
+@Data
+public class InvoiceQueryRequest {
+    private String orderId;
+    private Integer invoicetype;
+}

+ 57 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/OpenBlueInvoiceRequest.java

@@ -0,0 +1,57 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Data
+@Accessors(chain = true)
+public class OpenBlueInvoiceRequest {
+    private String issuerid;
+
+    private TradeInfo tradeinfo;
+
+    private HeadInfo head;
+
+    private List<DetailInfo> details;
+
+    @Data
+    @Accessors(chain = true)
+    public static class TradeInfo {
+        private String payType;
+        private String outTradeNo;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class HeadInfo {
+        private String companyid;
+        private String kpje;
+        private String orderId;
+        private String b2cshopid;
+        private String invoicetitle;
+        private String registrationnumber;
+        private String companyaddress;
+        private String mobilenumber;
+        private String openaccountbank;
+        private String bankaccount;
+        private String remark;
+        private String recmail;
+        private String invoiceTypeCode;
+    }
+
+    @Data
+    @Accessors(chain = true)
+    public static class DetailInfo {
+        private String goodscategory;
+        private String taxcode;
+        private String tax;
+        private String goodsname;
+        private Double price;
+        private Double sl;
+        private String attributes;
+        private String unitname;
+        private Double discount;
+    }
+}

+ 8 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/OpenRedInvoiceRequest.java

@@ -0,0 +1,8 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+
+@Data
+public class OpenRedInvoiceRequest {
+    private String orderId;
+}

+ 10 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request/SendMailRequest.java

@@ -0,0 +1,10 @@
+package com.kym.huapiaoer.model.request;
+
+import lombok.Data;
+
+@Data
+public class SendMailRequest {
+    private String orderId;
+    private Integer invoiceType;
+    private String email;
+}

+ 15 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/AuthorizeOrderResponse.java

@@ -0,0 +1,15 @@
+package com.kym.huapiaoer.model.response;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+@Data
+public class AuthorizeOrderResponse {
+    private Boolean wechatshop;
+
+    @JSONField(name = "miniprogram_user_name")
+    private String miniprogramUserName;
+
+    @JSONField(name = "miniprogram_appid")
+    private String miniprogramAppid;
+}

+ 9 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/DrawerInfo.java

@@ -0,0 +1,9 @@
+package com.kym.huapiaoer.model.response;
+
+import lombok.Data;
+
+@Data
+public class DrawerInfo {
+    private String issuerid;
+    private String name;
+}

+ 14 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/EnterpriseInfo.java

@@ -0,0 +1,14 @@
+package com.kym.huapiaoer.model.response;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+@Data
+public class EnterpriseInfo {
+    private String bankAccount;
+    private String address;
+    private String telephone;
+    private String bankName;
+    private String taxpayerNum;
+    private String enterpriseName;
+}

+ 15 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/HuapiaoerResponse.java

@@ -0,0 +1,15 @@
+package com.kym.huapiaoer.model.response;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+@Data
+public class HuapiaoerResponse<T> {
+    private String code;
+    private T data;
+
+    @JSONField(serialize = false)
+    public boolean isSuccess() {
+        return "200".equals(code);
+    }
+}

+ 26 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/InvoiceInfo.java

@@ -0,0 +1,26 @@
+package com.kym.huapiaoer.model.response;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+@Data
+public class InvoiceInfo {
+    @JSONField(name = "invoice_type_code")
+    private String invoiceTypeCode;
+    private String mobilenumber;
+    private String invoicenature;
+    @JSONField(name = "ticket_date")
+    private String ticketDate;
+    private String openaccountbank;
+    private String bankaccount;
+    private String registrationnumber;
+    private String companyaddress;
+    private String invoicetitle;
+    private String invoiceurl;
+    private String ofdurl;
+    private String xmlurl;
+    @JSONField(name = "ticket_total_amount_has_tax")
+    private String ticketTotalAmountHasTax;
+    private String invoicecode;
+    private String invoicenumber;
+}

+ 11 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/OpenInvoiceResponse.java

@@ -0,0 +1,11 @@
+package com.kym.huapiaoer.model.response;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class OpenInvoiceResponse extends HuapiaoerResponse<String> {
+    private String orderId;
+    private String authorizeQRCode;
+}

+ 9 - 0
huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response/QrcodeResponse.java

@@ -0,0 +1,9 @@
+package com.kym.huapiaoer.model.response;
+
+import lombok.Data;
+
+@Data
+public class QrcodeResponse {
+    private String imgUrl;
+    private String orderId;
+}

+ 503 - 0
huapiaoer-sdk/src/main/resources/电子发票API_航信乐企版_v5.1.md

@@ -0,0 +1,503 @@
+# 电子发票 API(航信乐企版 v5.1)
+
+## 1. 调用方式
+
+- 正式环境:`https://erp.huapiaoer.com`
+- 通信协议:HTTPS
+- 请求方法:`POST`
+- Content-Type:`application/json`
+- 编码:UTF-8
+
+---
+
+## 2. 公共约定
+
+### 2.1 公共请求参数
+
+以下参数在多个接口中出现,此处统一说明。
+
+| 参数名称 | 类型 | 必填 | 描述 | 适用接口 |
+|---|---|---|---|---|
+| `appsecret` | String | 是 | 票慧通提供 | 全部接口 |
+
+> 注意:发票开具和生成开票二维码接口中,`b2cshopid` 位于 `head` 对象内(`head.b2cshopid`)。
+
+---
+
+### 2.2 公共响应格式
+
+除授权订单号接口外,统一返回:
+
+```json
+{
+  "code": "200",
+  "data": {}
+}
+```
+
+| 字段 | 类型 | 说明 |
+|---|---|---|
+| `code` | String | `"200"` 成功,`"400"` 失败 |
+| `data` | String / Object | 业务数据 |
+
+---
+
+### 2.3 商品明细(details)结构
+
+适用接口:
+
+- 发票开具
+- 生成开票二维码
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `details.goodscategory` | String | 否 | 商品大类(传值时不填 `taxcode`、`tax`) |
+| `details.taxcode` | String | 否 | 税目编码(传值时不填 `goodscategory`) |
+| `details.tax` | String | 否 | 税率(传值时不填 `goodscategory`) |
+| `details.goodsname` | String | 是 | 商品名称 |
+| `details.price` | Double | 是 | 商品单价(元) |
+| `details.sl` | Double | 是 | 商品数量 |
+| `details.attributes` | String | 否 | 商品规格型号 |
+| `details.unitname` | String | 否 | 商品单位 |
+| `details.discount` | Double | 否 | 折扣金额(元) |
+
+> 生成开票二维码接口暂不支持 `discount`
+
+---
+
+### 2.4 发票类型编码
+
+| 编码 | 发票类型 |
+|---|---|
+| `081` | 数电专票 |
+| `082` | 数电普票 |
+
+---
+
+### 2.5 支付渠道编码
+
+| 编码 | 支付渠道 |
+|---|---|
+| `01` | 现金 |
+| `02` | 银行转账 |
+| `03` | 票据 |
+| `04` | 借记卡 |
+| `05` | 信用卡 |
+| `06` | 购物卡/券 |
+| `07` | 优惠券 |
+| `08` | 商场积分 |
+| `09` | 支付宝 |
+| `10` | 微信支付 |
+| `11` | 云闪付 |
+| `12` | Apple Pay |
+| `13` | Samsung Pay |
+| `99` | 其他 |
+
+---
+
+### 2.6 业务状态码汇总
+
+| 接口 | code=200 | code=400 |
+|---|---|---|
+| 发票开具 | 开票中请稍等 | 开票失败 |
+| 发票红冲 | 红冲中请稍等 | 红冲失败 |
+| 发票通知、查询 | 订单查询成功 | 未查询到对应订单信息 |
+| 发送邮件 | 发送成功 | 发送失败 |
+| 生成开票二维码 | 成功 | 失败 |
+| 企业搜索 | 成功 | 失败 |
+| 查询开票人列表 | 成功 | 失败 |
+
+> 授权订单号接口响应格式不同,不包含 `code` 字段。
+
+---
+
+# 3. 开票核心
+
+## 3.1 查询开票人列表
+
+### 接口地址
+
+```text
+/ewy_weberp/api/huapiaoer/outopenapis/getDrawerIdList
+```
+
+### 说明
+
+查询当前企业下所有开票人列表。
+
+### 请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `nsrsbh` | String | 是 | 开票方税号(商家税号) |
+
+### 请求示例
+
+```json
+{
+  "nsrsbh": "915001*******460R"
+}
+```
+
+### 响应示例
+
+```json
+{
+  "code": "200",
+  "data": [
+    {
+      "issuerid": "186891*******4946",
+      "name": "游* 2921"
+    },
+    {
+      "issuerid": "186891*******5074",
+      "name": "袁** 3713"
+    }
+  ]
+}
+```
+
+---
+
+## 3.2 授权订单号
+
+### 接口地址
+
+```text
+/ewy_weberp/api/wechatPay/getWechatShopAuthorizeOrderId
+```
+
+### 说明
+
+微信支付商户授权接口,在发起开票前调用。
+
+> 注意:该接口响应格式不同于其他接口。
+
+### 请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `omsoutputorderid` | String | 是 | 订单号(企业号 + 流水号) |
+| `source` | String | 否 | 来源:`WEB` / `MINIPROGRAM` |
+| `appid` | String | 是 | 商户 AppID |
+| `openid` | String | 是 | 微信 OpenID |
+
+### 请求示例
+
+```json
+{
+  "omsoutputorderid": "1019000000000001",
+  "appid": "wxa889d1c7e87524bd",
+  "openid": "ozjEW5X1T2h9QK9omRUKD7Ij9X4Y"
+}
+```
+
+### 响应示例
+
+```json
+{
+  "wechatshop": true,
+  "miniprogram_user_name": "gh_3610de7f9728",
+  "miniprogram_appid": "wx1af4f6aa3a537c1a"
+}
+```
+
+---
+
+## 3.3 发票开具
+
+### 接口地址
+
+```text
+/ewy_weberp/api/huapiaoer/outopenapis/openBlueInvoice
+```
+
+### 说明
+
+开具蓝字发票。
+
+### 核心请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `issuerid` | String | 否 | 开票人 ID |
+| `tradeinfo.payType` | String | 是 | 支付渠道编码 |
+| `tradeinfo.outTradeNo` | String | 是 | 支付流水号 |
+| `head.companyid` | String | 否 | 企业号 |
+| `head.kpje` | String | 是 | 开票总金额 |
+| `head.orderId` | String | 是 | 开票订单号 |
+| `head.b2cshopid` | String | 是 | 商家税号 |
+| `head.invoicetitle` | String | 是 | 购方抬头 |
+| `head.registrationnumber` | String | 否 | 购方税号 |
+| `head.companyaddress` | String | 否 | 购方地址 |
+| `head.mobilenumber` | String | 否 | 购方手机号 |
+| `head.openaccountbank` | String | 否 | 银行名称 |
+| `head.bankaccount` | String | 否 | 银行账号 |
+| `head.remark` | String | 否 | 发票备注 |
+| `head.recmail` | String | 否 | 接收邮箱 |
+| `head.invoiceTypeCode` | String | 是 | 发票类型 |
+| `details` | List | 是 | 商品明细 |
+
+### 请求示例
+
+```json
+{
+  "appsecret": "123456789",
+  "issuerid": "1868914789939154946",
+  "head": {
+    "orderId": "1019000000000001",
+    "b2cshopid": "914403008888888888",
+    "invoicetitle": "深圳柯适科技有限公司",
+    "registrationnumber": "91440300MA5FB8A214",
+    "companyaddress": "深圳市 xxx 区 xxx 街道 xxx",
+    "mobilenumber": "18888888888",
+    "openaccountbank": "招商银行 xxx 支行",
+    "bankaccount": "755944788888888",
+    "remark": "结算方式 xxxxxx,合同编号 xxxxxx",
+    "recmail": "1888888888@qq.com",
+    "invoiceTypeCode": "082"
+  },
+  "details": [
+    {
+      "taxcode": "1030302000000000xxx",
+      "tax": "0.13",
+      "goodsname": "电子发票",
+      "price": "1",
+      "sl": 1,
+      "attributes": "标准版",
+      "unitname": "年"
+    }
+  ]
+}
+```
+
+### 响应示例
+
+```json
+{
+  "code": "200",
+  "data": "订单生成成功!请让用户授权。",
+  "orderId": "1019000000000001",
+  "authorizeQRCode": "https://image.huapiaoer.com/xxx.png"
+}
+```
+
+---
+
+## 3.4 发票红冲
+
+### 接口地址
+
+```text
+/ewy_weberp/api/huapiaoer/outopenapis/openRedInvoice
+```
+
+### 请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `orderId` | String | 是 | 发票订单号 |
+
+### 请求示例
+
+```json
+{
+  "appsecret": "123456789",
+  "orderId": "1019000000000001"
+}
+```
+
+### 响应示例
+
+```json
+{
+  "code": "200",
+  "data": "红冲中请稍等"
+}
+```
+
+---
+
+## 3.5 发票通知、查询
+
+### 接口地址
+
+```text
+/ewy_weberp/api/huapiaoer/outopenapis/getInvoice
+```
+
+### 请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `orderId` | String | 是 | 航信订单号 |
+| `invoicetype` | int | 是 | 1=蓝票,2=红票 |
+
+### 响应字段
+
+| 字段 | 说明 |
+|---|---|
+| `invoice_type_code` | 发票类型 |
+| `mobilenumber` | 企业电话 |
+| `invoicenature` | 抬头类型 |
+| `ticket_date` | 开票日期 |
+| `openaccountbank` | 开户行 |
+| `bankaccount` | 开户账号 |
+| `registrationnumber` | 税号 |
+| `companyaddress` | 地址 |
+| `invoicetitle` | 发票抬头 |
+| `invoiceurl` | PDF 地址 |
+| `ofdurl` | OFD 地址 |
+| `xmlurl` | XML 地址 |
+| `ticket_total_amount_has_tax` | 金额 |
+| `invoicecode` | 发票代码 |
+| `invoicenumber` | 发票号码 |
+
+### 请求示例
+
+```json
+{
+  "orderId": "1019000000000001",
+  "invoicetype": 1
+}
+```
+
+---
+
+## 3.6 发送邮件
+
+### 接口地址
+
+```text
+/ewy_weberp/api/huapiaoer/outopenapis/sendMail
+```
+
+### 请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `orderId` | String | 是 | 订单号 |
+| `invoiceType` | int | 是 | 1=蓝票,2=红票 |
+| `email` | String | 是 | 目标邮箱 |
+
+### 请求示例
+
+```json
+{
+  "orderId": "1019000000000001",
+  "invoiceType": 1,
+  "email": "1888888888@qq.com"
+}
+```
+
+### 响应示例
+
+```json
+{
+  "code": "200",
+  "data": "ok"
+}
+```
+
+---
+
+## 3.7 生成开票二维码
+
+### 接口地址
+
+```text
+/ewy_weberp/api/huapiaoer/outopenapis/getInvoiceQrcode
+```
+
+### 请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `head.orderId` | String | 是 | 开票订单号 |
+| `head.b2cshopid` | String | 是 | 商家税号 |
+| `head.remark` | String | 否 | 发票备注 |
+| `head.invoiceTypeCode` | String | 是 | 发票类型 |
+| `details` | List | 是 | 商品明细 |
+
+### 响应字段
+
+| 字段 | 说明 |
+|---|---|
+| `data.imgUrl` | 二维码图片地址 |
+| `data.orderId` | 订单号 |
+
+### 请求示例
+
+```json
+{
+  "appsecret": "123456789",
+  "head": {
+    "orderId": "20240410000001",
+    "b2cshopid": "91440300MA5FN0xxxx",
+    "remark": "发票备注",
+    "invoiceTypeCode": "082"
+  }
+}
+```
+
+### 响应示例
+
+```json
+{
+  "code": "200",
+  "data": {
+    "imgUrl": "https://image.huapiaoer.com/xxxx.png",
+    "orderId": "20240410000001"
+  }
+}
+```
+
+---
+
+# 4. 辅助功能
+
+## 4.1 企业搜索
+
+### 接口地址
+
+```text
+/ewy_weberp/api/piaotong/platform/getInvoiceHeaderInquiry
+```
+
+### 说明
+
+查询企业基本信息。
+
+> 注意:官方文档说明“数据存在错误,仅供辅助”。
+
+### 请求参数
+
+| 参数名称 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `enterpriseName` | String | 是 | 公司简称(4 个字符起生效) |
+
+### 请求示例
+
+```json
+{
+  "enterpriseName": "维克多信息"
+}
+```
+
+### 响应示例
+
+```json
+{
+  "code": "200",
+  "data": [
+    {
+      "bankAccount": "4562878487282",
+      "address": "深圳市南山区粤海街道海珠社区海德三道1236号大成基金总部大厦201",
+      "telephone": "18070830426",
+      "bankName": "中国银行",
+      "taxpayerNum": "91440300MA5FB8A214",
+      "enterpriseName": "深圳柯适科技有限公司"
+    }
+  ]
+}
+```