# 未开票收入管理

# 未开票查询

# URL

POST

Content-Type:application/json

http://{HOST}:{PORT}/output-tax/api/invoice-will/result

# 请求体参数

参数 是否必填 类型 描述 说明
lyid String 单据号
djqqlsh String 单据请求流水号 ,单据请求流水号和单据号不能同时为空
orgCode String 组织编码
pageNum int 页码
pageSize String 每页数据数量

# 请求体样例

{
	"lyid":"单据",
	"djqqlsh":"",
	"orgCode":"组织编码",
	"pageNum":1,
	"pageSize":15
}

# 返回结果说明

参数 类型 描述 说明
code String 状态码 详见状态码说明
msg String 信息说明
accountNote String 记账备注
accountStatus String 记账状态:1-未记账 2-已记账
accountTime String 记账日期 yyyy-MM-dd
accountUser String 记账人
accountVoucherNo String 记账凭证号
bz String 备注
djqqlsh String 单据请求流水号
fhr String 复核人
fplx String
gmfDzdh String 购买方地址电话
gmfMc String 购买方名称
gmfNsrsbh String 购买方纳税人识别号
gmfYhzh String 购买方银行账户
hisJe BigDecimal 已开票金额
hisSe BigDecimal 已开票税额
je BigDecimal 单据金额
jshj BigDecimal 单据价税合计
kpr String 开票人
lyid String 单据号
orgName String 组织编码
se BigDecimal 税额
skr String 收款人
unJe BigDecimal 待开票金额
xsfDzdh String 销售方地址电话
xsfMc String 销售方名称
xsfNsrsbh String 销售方纳税人识别号
xsfYhzh String 销售方银行账户
lc Integer 联次 2-二联 3-三联 5-五联
zdrq String 制单日期
dw String 单位
hh String 行号
hisJe BigDecimal 已开票金额
hisJshj BigDecimal 已开票价税合计
se BigDecimal 税额
sl BigDecimal 税率
spbm String 商品编码
spssflbm String 商品税收分类编码
xmje BigDecimal 项目金额
xmjshj BigDecimal 项目价税合计
xmmc String 项目名称
bred String 是否被红冲 Y-被红冲 N-正常
fpDm String 发票代码
fpHm String 发票号码
fplx String 发票类型
fpqqlsh String 开票请求流水号
hh String 行号
se BigDecimal 税额
sl BigDecimal 税率
status String 发票状态 1-待开票 2-开票中 3-开票失败 4-开票成功
xmje BigDecimal 项目金额
xmjshj BigDecimal 项目价税合计
zfbz String 是否作废 Y=已作废,N-未作废,

# 返回样例

{
    "code":"0000",
    "datas":{
        "dtos":[
            {
                "accountNote":"32",
                "accountStatus":"2",
                "accountTime":1592150400000,
                "accountVoucherNo":"32",
                "bz":"",
                "djqqlsh":"1272434265238585345",
                "fhr":"",
                "fplx":"",
                "gmfDzdh":"",
                "gmfMc":"123123",
                "gmfNsrsbh":"",
                "gmfYhzh":"",
                "hisJe":10,
                "hisSe":1,
                "invoiceWillBs":[
                    {
                        "dw":"",
                        "hh":"1",
                        "hisJe":10,
                        "hisJshj":11,
                        "records":[
                            {
                                "bred":"N",
                                "fpDm":"144005044197",
                                "fpHm":"65264302",
                                "fplx":"1",
                                "fpqqlsh":"1272447230817132544",
                                "hh":"0",
                                "se":1,
                                "sl":0.1,
                                "status":"4",
                                "xmje":10,
                                "xmjshj":11,
                                "zfbz":"N"
                            }
                        ],
                        "se":1,
                        "sl":0.1,
                        "spbm":"污水处理费",
                        "spssflbm":"2010300000000000000",
                        "xmje":10,
                        "xmjshj":11,
                        "xmmc":"污水处理费"
                    }
                ],
                "je":10,
                "jshj":11,
                "kpr":"",
                "lyid":"",
                "orgName":"0000ceshi",
                "se":1,
                "skr":"",
                "unJe":0,
                "xsfDzdh":"北京市海淀区北清路68号 010-86396688",
                "xsfMc":"太极计算机股份有限公司",
                "xsfNsrsbh":"111222333456111",
                "xsfYhzh":"一",
                "zdrq":"2020-06"
            }
        ],
        "totalCount":1
    },
    "msg":"SUCCESS"
}

# 未开票管理新增单据

# URL

POST

Content-Type:application/json; charset=UTF-8

http://{HOST}:{PORT}/output-tax/api/invoice-will/save

# 请求体

{
    "lyid":"单据",
    "lydjh":"来源单据号",
    "djqqlsh":"单据请求流水号",
    "orgCode":"组织编码",
    "gmfMc":"购买方名称",
    "gmfDzdh":"",
    "gmfDz":"购买方地址", (数电专用字段)
    "gmfDh":"购买方电话", (数电专用字段)
    "gmfNsrsbh":"",    (发票类型31数电专票,购买方纳税人识别号必填)
    "gmfYhzh":"",
    "gmfYh":"购买方银行",(数电专用字段)
    "gmfZh":"购买方账号",(数电专用字段)
    "revphone":"联系人手机号",
    "revemail":"联系人邮箱",
    "lc":"",
    "bz":"",
    "fplx":"", (发票类型31数电专票,发票类型32数电普票,发票类型是数电发票,购买方地址电话和银行账号需要分开传值。)
    "zdrq ":"",
	"revurl1":"开票、作废回调地址",
    "invoiceWillBs":[{
        "xmmc":"项目(商品)名称",
        "xmjshj":"价税合计",
        "hh":"行号",
        "spbm":"商品编码",
        "xmhsdj":"商品含税单价",
        "xmsl":"商品数量",
        "se":"税额", 
        "spssflbm":"商品税收分类编码",(商品税收分类编码必填)
        "sl":"税率",
        "dw":"计量单位",
        "ggxh":"规格型号"
    }]
}

# 请求体参数

参数 是否必填 类型 描述 说明
lyid String 单据号
lydjh String 来源单据号
djqqlsh String 单据请求流水号
orgCode String 组织编码
gmfMc String 购买方名称
gmfDzdh String 购买方地址电话
gmfDz String 购买方地址
gmfdh String 购买方电话
gmfNsrsbh String 购买方纳税人识别号
gmfYhzh String 购买方银行账户
gmfYh String 购买方银行
gmfzh String 购买方账户
revphone String 联系人手机号
revemail String 联系人邮箱
lc String 联次
bz String 联次
fplx String 发票类型
xmmc String 商品名称 匹配商品档案,档案中商品名称不唯一,
spbm String 商品编码 匹配商品档案,档案中商品编码唯一
xmjshj BigDecimal 项目价税合计
hh String 行号
xmhsdj BigDecimal 商品含税单价
xmsl BigDecimal 商品数量
se BigDecimal 税额
spssflbm String 商品税收分类编码
sl BigDecimal 税率
dw String 计量单位
ggxh String 规格型号
zdrq String 制单日期 格式为yyyy-MM-dd
revurl1 String 待开票明细结果回传地址 合法url地址

# 返回结果说明

参数 类型 描述 说明
code String 状态码 详见状态码说明
msg String 信息说明

# 返回样例

{
    "code":"0000",
    "msg":"success"
}

# 待开票明细回传结果样例

[{
"data":"{\"djqqlsh\":\"2023033101480035\",\"corpId\":\"um86vloe\",\"orgId\":1467284815433695241,\"orgName\":\"百望888开票点\",\"code\":\"1641688270826569728\",\"fplx\":\"3\",\"xsfNsrsbh\":\"111222333456888\",\"xsfMc\":\"用友税务云\",\"xsfDzdh\":\"测试地址和电话 13144445555\",\"xsfYhzh\":\"北京啦啦啦 345677890098990\",\"gmfNsrsbh\":\"1QAZ2WSX3EDC4RF\",\"gmfMc\":\"htt0331003\",\"gmfDzdh\":\"北清路68号13141422677\",\"gmfYhzh\":\"北京银行6345678987655678\",\"kpr\":\"111\",\"skr\":\"htt收款222\",\"fhr\":\"htt复核人\",\"zdybz\":\"自定义备注写了100字以内呢哈哈哈哈\",\"lylx\":\"2\",\"zdzfbz\":\"N\",\"lyid\":\"2237227707797763\",\"lydjh\":\"NBJS20221122120801\",\"creator\":\"348af872-f245-4eed-ab16-ed36f6cf5e37\",\"zdrq\":\"2023-03-23\",\"accountStatus\":\"1\",\"je\":400.00,\"jshj\":800.00,\"createTime\":1680243960000,\"ts\":1680246797000,\"isBilling\":\"1\",\"sqr\":\"北京人\",\"sqbm\":\"北京部门我访问的哦文件啦啦队冷冻机房了安家费了98698哦肌司研……%*&……(\",\"gmfDz\":\"北清路68号\",\"gmfDh\":\"13141422677\",\"gmfYh\":\"北京银行\",\"gmfZh\":\"6345678987655678\",\"se\":400.00,\"hisJe\":3.00,\"unJe\":397.00,\"hisSe\":0.00,\"redInfos\":[],\"enableRed\":false,\"invoiceWillBs\":[{\"id\":1692594719821922312,\"hh\":\"1\",\"spbm\":\"06000001\",\"xmmc\":\"餐费\",\"spssflbm\":\"3070401000000000000\",\"ggxh\":\"千克*箱\",\"dw\":\"套\",\"xmhsdj\":100.0000000000,\"xmsl\":2.0000000000,\"xmje\":200.00,\"sl\":0.000000,\"se\":0.00,\"xmjshj\":200.00,\"hisJe\":3.00,\"hisJshj\":3.00,\"hisZke\":0.00,\"hisSpsl\":0.0300000000,\"taxclassname\":\"餐饮服务\",\"taxclassjc\":\"餐饮服务\",\"createTime\":1680243960000,\"lymxid\":\"2237227707797771\",\"lyid\":\"2237227707797770\",\"ts\":1680246792000,\"isBilling\":\"1\",\"records\":[{\"fplx\":\"3\",\"hh\":\"1\",\"fpqqlsh\":\"1641700152848969728\",\"fpDm\":\"780000000000\",\"fpHm\":\"70000061\",\"kprq\":\"2023-03-31 15:13:15\",\"kprq4DMDB\":1680246795000,\"xmsl\":0.0100000000,\"xmhsdj\":100.0000000000,\"xmje\":1.00,\"xmjshj\":1.00,\"se\":0.00,\"sl\":0.000000,\"status\":\"4\",\"zfbz\":\"N\",\"bred\":\"N\",\"czrq\":\"2023-03-31\",\"createTime\":\"2023-03-31 03:13:12\",\"ts\":1680246796000,\"bid\":1692594719821922312},{\"fplx\":\"3\",\"hh\":\"2\",\"fpqqlsh\":\"1641700152848969728\",\"fpDm\":\"780000000000\",\"fpHm\":\"70000061\",\"kprq\":\"2023-03-31 15:13:15\",\"kprq4DMDB\":1680246795000,\"xmsl\":0.0200000000,\"xmhsdj\":100.0000000000,\"xmje\":2.00,\"xmjshj\":2.00,\"se\":0.00,\"sl\":0.000000,\"status\":\"4\",\"zfbz\":\"N\",\"bred\":\"N\",\"czrq\":\"2023-03-31\",\"createTime\":\"2023-03-31 03:13:12\",\"ts\":1680246796000,\"bid\":1692594719821922312}],\"lslbs\":\"1\",\"fphxz\":0},{\"hh\":\"2\",\"spbm\":\"JF01000216\",\"xmmc\":\"糯米糍粑\",\"spssflbm\":\"1030201020000000000\",\"ggxh\":\"千克*箱\",\"xmhsdj\":300.5000000000,\"xmsl\":2.0000000000,\"xmje\":200.00,\"sl\":0.000000,\"se\":400.00,\"xmjshj\":600.00,\"hisJe\":0.00,\"hisJshj\":0.00,\"zke\":1.00,\"hisZke\":0.00,\"hisSpsl\":0E-10,\"taxclassjc\":\"焙烤食品\",\"createTime\":1680243960000,\"lymxid\":\"2237227707797771\",\"lyid\":\"2237227707797770\",\"ts\":1680243960000,\"lslbs\":\"3\",\"fphxz\":0,\"zkhbs\":\"Y\"}]}",
"code":"0000",
"msg":"开票成功",
"fpqqlsh":"2023033101480035",
"corpid":"um86vloe"
}]

# 待开票明细回传参数说明

参数 类型 描述 说明
code String 开票信息码 0000代表成功
msg String 开票失败信息
fpqqlsh String 发票请求流水号
corpid String 租户id
data String 发票详细信息

# 待开票明细回传data说明

参数 类型 描述 说明
code String 状态码 详见状态码说明
msg String 信息说明
accountNote String 记账备注
accountStatus String 记账状态:1-未记账 2-已记账
accountTime String 记账日期 yyyy-MM-dd
accountUser String 记账人
accountVoucherNo String 记账凭证号
bz String 备注
djqqlsh String 单据请求流水号
fhr String 复核人
fplx String
gmfDzdh String 购买方地址电话
gmfMc String 购买方名称
gmfNsrsbh String 购买方纳税人识别号
gmfYhzh String 购买方银行账户
hisJe BigDecimal 已开票金额
hisSe BigDecimal 已开票税额
je BigDecimal 单据金额
jshj BigDecimal 单据价税合计
kpr String 开票人
lyid String 单据号
orgName String 组织编码
se BigDecimal 税额
skr String 收款人
unJe BigDecimal 待开票金额
xsfDzdh String 销售方地址电话
xsfMc String 销售方名称
xsfNsrsbh String 销售方纳税人识别号
xsfYhzh String 销售方银行账户
lc Integer 联次 2-二联 3-三联 5-五联
zdrq String 制单日期
dw String 单位
hh String 行号
hisJe BigDecimal 已开票金额
hisJshj BigDecimal 已开票价税合计
se BigDecimal 税额
sl BigDecimal 税率
spbm String 商品编码
spssflbm String 商品税收分类编码
xmje BigDecimal 项目金额
xmjshj BigDecimal 项目价税合计
xmmc String 项目名称
bred String 是否被红冲 Y-被红冲 N-正常
fpDm String 发票代码
fpHm String 发票号码
fplx String 发票类型
fpqqlsh String 开票请求流水号
hh String 行号
se BigDecimal 税额
sl BigDecimal 税率
status String 发票状态 1-待开票 2-开票中 3-开票失败 4-开票成功
xmje BigDecimal 项目金额
xmjshj BigDecimal 项目价税合计
zfbz String 是否作废 Y=已作废,N-未作废,

# URL

POST

Content-Type:application/x-www-form-urlencoded

http://{HOST}:{PORT}/output-tax/api/invoiceApply/queryInvoiceStatus

# 请求体参数

参数 类型 长度 是否必填 默认值 描述 说明
fpqqlsh String 20 发票请求流水号

# 请求样例

表单参数如下

fpqqlsh=12345678901234567890

# 返回结果说明

参数 类型 描述 说明
fpqqlsh String 发票请求流水号
code String 状态码 详见返回状态码说明
msg String 信息说明
statuscode String 开票状态码 1-待开票(需要开票员确认开票);2-开票中;3-开票失败;4-开票成功
status String 开票状态 待开票;开票中;开票失败;开票成功
errmsg String 开票失败明细 开票状态为失败时,此处为明细信息
data String 开票内容 回调内容与开票回调相同

# 返回样例

    样例1(开票中)
    {
	    "fpqqlsh": "12345678901234567890",
		"code": "0000",
	    "msg": "查询成功",
	    "statuscode": "1",
		"status": "待开票"
	}

    样例2(开票失败)
    {
	    "fpqqlsh": "12345678901234567890",
		"code": "0000",
	    "msg": "查询成功",
	    "statuscode": "3",
		"status": "开票失败",
		"errmsg":"税控设备错误"
    }

# 未开票记录变更查询

# URL

POST

Content-Type:application/json; charset=UTF-8

http://{HOST}:{PORT}/output-tax/api/invoice-will/changes

# 请求体参数

参数 类型 长度 是否必填 默认值 描述
beginTime String 20 查询未开票变更开始时间 时间格式yyyyMMdd hh:mm:ss
orgCode String 20 查询组织编码非必填 不填写则查询全部开票组织的未开票记录在变更时间之后的
pageNum Integer - 页数
pageSize Integer - 每页条数
endTime String 20 查询未开票变更结束时间 时间格式yyyyMMdd hh:mm:ss

# 请求样例

{
     "pageSize" : 15,
     "pageNum" : 2,
     "beginTime":"2020-10-24 16:31:15",
     "endTime":"2020-12-24 16:31:15"
}

# 返回结果说明

参数 类型 描述 说明
djqqlsh String 单据请求流水号 单据请求流水号可用于查询该单据的开票明细信息
code String 状态码 详见返回状态码说明
msg String 信息说明
orgCode String 组织编码 此单据对应的组织编码
totalCount Integer 总条数 查询变更的总的记录数

返回样例

{
    "code": "0000",
    "datas": {
        "invoiceWillChangeList": [
            {
                "djqqlsh": "1331153392887709697",
                "orgCode": "ceshiview"
            },
            {
                "djqqlsh": "1331153932052905985",
                "orgCode": "ceshiview"
            }
        ],
        "totalCount": 2
    },
    "msg": "SUCCESS"
}

# 附录

# 样例代码

# Java(适用于JDK1.6及其更高版本)

# Maven配置文件依赖

依赖配置如下

		<!-- httpclient,发送HTTP请求 -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5</version>
		</dependency>
		<!-- gson,json转换工具 -->
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.7</version>
		</dependency>
		<!-- jjwt,Java Web Token签名工具包 -->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.6.0</version>
		</dependency>
# API调用代码
import com.google.gson.GsonBuilder;
import com.yonyou.einvoice.einvoiceApply.JwtParamBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.compression.CompressionCodecs;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.util.io.pem.PemReader;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @date 2018/5/25
 * <p>
 * 扫码开票接口测试代码,适用于JDK1.6及更高版本,jdk1.6版本需要对签名方法稍做修改,修改方法在签名方法内已经写明
 * 请求参数的注意事项也在参数构建的过程中写明,请详细阅读样例代码。
 */

public class InsertForQRInvoice {

    //测试环境有测试appid和证书,正式环境有正式appid和证书,请务必对应使用
    //测试环境appid就用这个,正式环境需要替换成正式的
    private static String APPID = "commontesterCA";
    //这个是测试环境的域名,正式环境为https://fapiao.yonyoucloud.com
    private static String DOMAIN = "https://yesfp.yonyoucloud.com";
    private static String URL = DOMAIN + "/input-tax/api/pit/report/import?appid=" + APPID;
    //pro22.pfx为测试环境通讯证书,正式环境需要替换成正式的
    private static String KEYPATH = "src/main/resources/certificate/pro22.pfx";
    //证书密码
    private static String PASSWORD = "password";

    public static void main(String[] args) {
        try {
            new InsertForQRInvoice().callQRInvoiceApply();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();

            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

    public void callQRInvoiceApply() throws Exception {
//        提供两种构建HttpClient实例的方法,如果使用被注释掉的方法构建实例报证书不被信任的错误,那么请使用未被注释的构建方法
//        HttpClient httpClient = HttpClients.custom().build();
        HttpClient httpClient = createSSLClientDefault();    //信任所有https证书
        HttpPost httpPost = new HttpPost(URL);

        // 构造POST请求体
        String body = this.buildRequestDatas();
        // 签名
        String sign = this.sign(body);
        httpPost.addHeader("sign", sign);
        httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
        StringEntity se = new StringEntity(body.toString(), "UTF-8");
        se.setContentType("text/json");
        se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
        httpPost.setEntity(se);
        // 发送http post请求,并得到响应结果
        HttpResponse response = httpClient.execute(httpPost);
        String result = "";
        if (response != null) {
            HttpEntity resEntity = response.getEntity();
            if (resEntity != null) {
                result = EntityUtils.toString(resEntity, "UTF-8");
                System.out.println(result);
            }
        }
    }


    /**
     * 签名
     *
     * @param paramsMap 表单参数
     * @return 签名值
     * @throws Exception
     */
    private String sign(String paramsMap) throws Exception {

        // 读取CA证书与PEM格式证书需要根据实际证书使用情况而定,目前这两种都支持
        PrivateKey privateKey = loadPrivateKeyOfCA();
        // PrivateKey privateKey = loadPrivateKeyOfPem();

        Map<String, Object> claims =
                JwtParamBuilder.build().setSubject("tester").setIssuer("einvoice").setAudience("einvoice")
                        .addJwtId().addIssuedAt().setExpirySeconds(300).setNotBeforeSeconds(300).getClaims();
        // 此签名数据必须存在,否则在验证签名时会不通过。
        claims.put("requestdatas", getMD5(paramsMap));
        // 使用jdk1.6版本时,删除下面代码的中.compressWith(CompressionCodecs.DEFLATE)
        String compactJws = Jwts.builder().signWith(SignatureAlgorithm.RS512, privateKey)
                .setClaims(claims).compressWith(CompressionCodecs.DEFLATE).compact();

        return compactJws;
    }


    /**
     * 计算MD5
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    private String getMD5(String str) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        byte[] buf = null;
        buf = str.getBytes("utf-8");
        MessageDigest md5 = null;
        md5 = MessageDigest.getInstance("MD5");
        md5.update(buf);
        byte[] tmp = md5.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : tmp) {
            sb.append(String.format("%02x", b & 0xff));
        }
        return sb.toString();
    }


    /**
     * 读取证书私钥
     *
     * @return
     * @throws UnrecoverableKeyException
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws CertificateException
     * @throws IOException
     */
    protected PrivateKey loadPrivateKeyOfCA() throws UnrecoverableKeyException, KeyStoreException,
            NoSuchAlgorithmException, CertificateException, IOException {
        FileInputStream in = new FileInputStream(KEYPATH);
        KeyStore ks = KeyStore.getInstance("pkcs12");
        ks.load(in, PASSWORD.toCharArray());
        String alias = ks.aliases().nextElement();
        PrivateKey caprk = (PrivateKey) ks.getKey(alias, PASSWORD.toCharArray());
        return caprk;
    }


    /**
     * 构造请求的json数据
     *
     * @return
     */
    private String buildRequestDatas() {
       
        return "这应该是一个json格式字符串";
    }

# API相关工具类
package com.yonyou.einvoice.test;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


/**
 * @author wangweir
 *
 */
public class JwtParamBuilder {

  /** JWT {@code Issuer} claims parameter name: <code>"iss"</code> */
  public static final String ISSUER = "iss";

  /** JWT {@code Subject} claims parameter name: <code>"sub"</code> */
  public static final String SUBJECT = "sub";

  /** JWT {@code Audience} claims parameter name: <code>"aud"</code> */
  public static final String AUDIENCE = "aud";

  /** JWT {@code Expiration} claims parameter name: <code>"exp"</code> */
  public static final String EXPIRATION = "exp";

  /** JWT {@code Not Before} claims parameter name: <code>"nbf"</code> */
  public static final String NOT_BEFORE = "nbf";

  /** JWT {@code Issued At} claims parameter name: <code>"iat"</code> */
  public static final String ISSUED_AT = "iat";

  /** JWT {@code JWT ID} claims parameter name: <code>"jti"</code> */
  public static final String ID = "jti";

  private Map<String, Object> claims;

  private final long now;

  private JwtParamBuilder() {
    claims = new HashMap<>();
    now = System.currentTimeMillis() / 1000l;
  }

  public static JwtParamBuilder build() {
    return new JwtParamBuilder();
  }

  public JwtParamBuilder addIssuedAt() {
    claims.put(ISSUED_AT, now);
    return this;
  }

  public JwtParamBuilder setExpirySeconds(final Integer expirySeconds) {
    claims.put(EXPIRATION, now + expirySeconds);
    return this;
  }

  public JwtParamBuilder setNotBeforeSeconds(final Integer beforeSeconds) {
    claims.put(NOT_BEFORE, now - beforeSeconds);
    return this;
  }

  public JwtParamBuilder setSubject(String sub) {
    addOneClaim(SUBJECT, sub);
    return this;
  }

  public JwtParamBuilder setIssuer(String iss) {
    addOneClaim(ISSUER, iss);
    return this;
  }

  public JwtParamBuilder setAudience(String aud) {
    addOneClaim(AUDIENCE, aud);
    return this;
  }

  public JwtParamBuilder addJwtId() {
    return setJwtId(UUID.randomUUID().toString());
  }

  public JwtParamBuilder setJwtId(String jwtid) {
    addOneClaim(ID, UUID.randomUUID().toString());
    return this;
  }

  public JwtParamBuilder claim(String name, Object value) {
    if (value == null) {
      this.claims.remove(name);
    } else {
      this.claims.put(name, value);
    }
    return this;
  }

  private void addOneClaim(String key, String value) {
    if (value != null && value.length() > 0) {
      claims.put(key, value);
    }
  }


  /**
   * @return the claims
   */
  public Map<String, Object> getClaims() {
    return claims;
  }


}

Last Updated: 11/23/2023, 10:04:29 AM