Pārlūkot izejas kodu

添加java和c#版

master
洪普君 pirms 5 gadiem
revīzija
e54eb5c53d
31 mainītis faili ar 10836 papildinājumiem un 0 dzēšanām
  1. 6
    0
      .gitignore
  2. 22
    0
      cs/einv-demo-order-cs.sln
  3. 196
    0
      cs/einv-demo-order-cs/Program.cs
  4. 36
    0
      cs/einv-demo-order-cs/Properties/AssemblyInfo.cs
  5. 34
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/OrderFacade.cs
  6. 133
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/OrderFacadeAgent.cs
  7. 183
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/Invoice.cs
  8. 82
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/InvoiceItem.cs
  9. 14
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/InvoiceResult.cs
  10. 156
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/Order.cs
  11. 41
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/OrderBase.cs
  12. 69
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/OrderItem.cs
  13. 17
    0
      cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/Result.cs
  14. 85
    0
      cs/einv-demo-order-cs/einv-demo-order-cs.csproj
  15. 6
    0
      cs/einv-demo-order-cs/einv-demo-order-cs.csproj.user
  16. Binārs
      cs/einv-demo-order-cs/lib/Newtonsoft.Json.dll
  17. Binārs
      cs/einv-demo-order-cs/lib/Newtonsoft.Json.pdb
  18. 6982
    0
      cs/einv-demo-order-cs/lib/Newtonsoft.Json.xml
  19. Binārs
      java/lib/fastjson-1.2.47.jar
  20. 191
    0
      java/src/Main.java
  21. 36
    0
      java/src/com/chinaeinv/einv/order/OrderFacade.java
  22. 92
    0
      java/src/com/chinaeinv/einv/order/OrderFacadeAgent.java
  23. 454
    0
      java/src/com/chinaeinv/einv/order/dto/Invoice.java
  24. 203
    0
      java/src/com/chinaeinv/einv/order/dto/InvoiceItem.java
  25. 22
    0
      java/src/com/chinaeinv/einv/order/dto/InvoiceResult.java
  26. 387
    0
      java/src/com/chinaeinv/einv/order/dto/Order.java
  27. 72
    0
      java/src/com/chinaeinv/einv/order/dto/OrderBase.java
  28. 174
    0
      java/src/com/chinaeinv/einv/order/dto/OrderItem.java
  29. 32
    0
      java/src/com/chinaeinv/einv/order/dto/Result.java
  30. 888
    0
      java/src/com/chinaeinv/einv/util/CertificateUtils.java
  31. 223
    0
      java/src/com/chinaeinv/einv/util/HttpUtil.java

+ 6
- 0
.gitignore Parādīt failu

@@ -0,0 +1,6 @@

.DS_Store
java/.idea/
java/out/
java/*.iml
cs/.vs/

+ 22
- 0
cs/einv-demo-order-cs.sln Parādīt failu

@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "einv-demo-order-cs", "einv-demo-order-cs\einv-demo-order-cs.csproj", "{EB51574C-DA86-4CBE-BC6B-1FCA249B0D6A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EB51574C-DA86-4CBE-BC6B-1FCA249B0D6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB51574C-DA86-4CBE-BC6B-1FCA249B0D6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB51574C-DA86-4CBE-BC6B-1FCA249B0D6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB51574C-DA86-4CBE-BC6B-1FCA249B0D6A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

+ 196
- 0
cs/einv-demo-order-cs/Program.cs Parādīt failu

@@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using com.chinaeinv.einv.order;
using com.chinaeinv.einv.order.dto;
using System.Collections;

namespace einv_demo_order_cs
{
class Program
{
// 由电子发票平台分配的appCode
private static string appCode = "请向瑞宏网工作人员索取";
// 证书文件路径
private static string keyStorePath = "请向瑞宏网工作人员索取";
// 证书密码
private static string password = "请向瑞宏网工作人员索取";
// 接口URL
private static string apiUrl = "https://www.chinaeinv.com:943/igs/api/orderApi.jspa";
// 销售方纳税人识别号
private static string testTaxpayerCode = "请向瑞宏网工作人员索取";

private static OrderFacade orderFacade = new OrderFacadeAgent(appCode, keyStorePath, password, apiUrl);

static void Main(string[] args)
{
// (异步)开具蓝字发票
TestKpAsync();

// (异步)开具红字发票
//TestChAsync();

// (异步)对开票失败的订单重新开票
//TestRetryKpAsync();

// (同步)取消订单
//TestCancel();

// (同步)根据订单编号查询发票
//TestCxByOrderNo();

Console.WriteLine("按回车键退出。");
Console.ReadLine(); //等待用户按一个回车
return; //可选,按下回车后关闭
}

/**
* (异步)开具蓝字发票
*/
private static void TestKpAsync()
{
Order order = new Order();
// 订单编号
order.orderNo = "OrderNo-007";
// 销货方纳税人识别号
order.taxpayerCode = testTaxpayerCode;
// 用户扫码key
order.scanCodeKey = Guid.NewGuid().ToString();
// 店铺
order.shopName = "第198店";
// 店铺编号
order.shopCode = "198";
// 订单时间(yyyy-MM-dd HH:mm:ss)
order.orderTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
// 联系人
order.contact = "小明";
// 联系电话
order.contactTel = "18000000000";
// 邮箱
order.contactMail = "test@chinaeinv.cn";
// 配送地址
order.shippingAddress = "火星北路1024号";
// 购货方名称,即发票抬头
order.customerName = "小明";
// 是否自动开票
order.autoBilling = true;
// 开票人
order.drawer = "张三";
// 收款人
order.payee = "李四";
// 复核人
order.reviewer = "王五";
// 开票金额
order.totalAmount = "24000";
// 发票备注
order.remark = "软件系统维护期限为2018年1月1日至2019年12月31日。";

// 发票明细1
OrderItem orderItem1 = new OrderItem();
//商品编码
orderItem1.code = "001";
//商品名称
orderItem1.name = "软件开发";
//规格型号
orderItem1.spec = "无";
//税率
orderItem1.taxRate = "0.06";
//税价合计金额
orderItem1.amount = "10000";
//商品分类编码
orderItem1.catalogCode = "3040203000000000000";

// 发票明细2
OrderItem orderItem2 = new OrderItem();
//商品编码
orderItem2.code = "002";
//商品名称
orderItem2.name = "软件系统维护";
//规格型号
orderItem2.spec = "无";
//商品单价
orderItem2.price = "8000";
//数量
orderItem2.quantity = "2";
//单位
orderItem2.uom = "年";
//税率
orderItem2.taxRate = "0.06";
//税价合计金额
orderItem2.amount = "16000";
//折扣金额
orderItem2.discountAmount = "2000";
//商品分类编码
orderItem2.catalogCode = "3040203000000000000";

// 发票明细
order.orderItems = new List<OrderItem>();
order.orderItems.Add(orderItem1);
order.orderItems.Add(orderItem2);

// 扩展参数
order.extendedParams = new Hashtable();
order.extendedParams.Add("testExtendedNo1", "12345678");
order.extendedParams.Add("testExtendedNo2", "87654321");

// 调用接口方法
orderFacade.KpAsync(order);
}

/**
* (异步)开具红字发票
*/
private static void TestChAsync()
{
Order order = new Order();
// 订单编号
order.orderNo = "OrderNo-006";
// 销货方纳税人识别号
order.taxpayerCode = testTaxpayerCode;
// 冲红原因
order.reason = "开票信息有误。";

// 调用接口方法
orderFacade.ChAsync(order);
}

/**
* (异步)对开票失败的订单重新开票
*/
private static void TestRetryKpAsync()
{
OrderBase order = new OrderBase();
// 订单编号
order.orderNo = "OrderNo-004";
// 销货方纳税人识别号
order.taxpayerCode = testTaxpayerCode;

// 调用接口方法
orderFacade.RetryKpAsync(order);
}

/**
* (同步)取消订单
*/
private static void TestCancel()
{
OrderBase order = new OrderBase();
// 订单编号
order.orderNo = "OrderNo-004";
// 销货方纳税人识别号
order.taxpayerCode = testTaxpayerCode;

// 调用接口方法
orderFacade.Cancel(order);
}

/**
* (同步)根据订单编号查询发票
*/
private static void TestCxByOrderNo()
{
OrderBase orderBase = new OrderBase("OrderNo-006", testTaxpayerCode);
// 调用接口方法
orderFacade.CxByOrderNo(orderBase);
}
}
}

+ 36
- 0
cs/einv-demo-order-cs/Properties/AssemblyInfo.cs Parādīt failu

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("einv-demo-order-cs")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("einv-demo-order-cs")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

//将 ComVisible 设置为 false 将使此程序集中的类型
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]

// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("eb51574c-da86-4cbe-bc6b-1fca249b0d6a")]

// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”: :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 34
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/OrderFacade.cs Parādīt failu

@@ -0,0 +1,34 @@
using com.chinaeinv.einv.order.dto;

namespace com.chinaeinv.einv.order
{
/**
* 订单接口
*/
public interface OrderFacade {
/**
* (异步)开具蓝字发票异步方法
*/
Result KpAsync(Order order);

/**
* (异步)开具红字发票异步方法
*/
Result ChAsync(Order order);

/**
* (异步)对开票失败的订单重新开票异步方法
*/
Result RetryKpAsync(OrderBase orderBase);

/**
* (同步)取消订单
*/
Result Cancel(OrderBase orderBase);

/**
* (同步)根据订单编号查询发票
*/
InvoiceResult CxByOrderNo(OrderBase orderBase);
}
}

+ 133
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/OrderFacadeAgent.cs Parādīt failu

@@ -0,0 +1,133 @@
using System;
using System.Net;
using System.Text;
using System.Web;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

using com.chinaeinv.einv.order.dto;
using Newtonsoft.Json;

namespace com.chinaeinv.einv.order
{
/**
* 订单接口代理实现
*/
public class OrderFacadeAgent : OrderFacade {
private string appCode, keyStorePath, password, apiUrl;

/**
* 构造方法
* @param appCode 由电子发票平台分配的appCode
* @param keyStorePath 密钥库文件路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @param apiUrl 接口URL
*/
public OrderFacadeAgent(string appCode, string keyStorePath, string password, string apiUrl) {
this.appCode = appCode;
this.keyStorePath = keyStorePath;
this.password = password;
this.apiUrl = apiUrl;
}

/**
* (异步)开具蓝字发票
*/
public Result KpAsync(Order order) {
return Exec<Result, Order>(order, "chinaeinv.api.order.v11.kp_async");
}

/**
* (异步)开具红字发票
*/
public Result ChAsync(Order order) {
return Exec<Result, Order>(order, "chinaeinv.api.order.v11.ch_async");
}

/**
* (异步)对开票失败的订单重新开票
*/
public Result RetryKpAsync(OrderBase orderBase) {
return Exec<Result, OrderBase>(orderBase, "chinaeinv.api.order.v11.retryKp_async");
}

/**
* (同步)取消订单
*/
public Result Cancel(OrderBase orderBase) {
return Exec<Result, OrderBase>(orderBase, "chinaeinv.api.order.v11.cancel");
}

/**
* (同步)根据订单编号查询发票
*/
public InvoiceResult CxByOrderNo(OrderBase orderBase) {
return Exec<InvoiceResult, OrderBase>(orderBase, "chinaeinv.api.order.v11.cx.orderNo");
}

/**
* 调用接口
* @param order 请求数据
* @return 响应数据
* @throws Exception
*/
private T Exec<T,O>(O order, string cmdName) {
// 将Order对象转为json
string requestJson = JsonConvert.SerializeObject(order, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Console.WriteLine("方法名称: " + cmdName + ", 请求报文: " + requestJson);

// 生成签名
string sign = GetSign(requestJson);
Console.WriteLine("方法名称: " + cmdName + ", 签名: " + sign);

// 调用接口
string responseJson;
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
client.QueryString.Add("appCode", appCode);
client.QueryString.Add("cmdName", cmdName);
client.QueryString.Add("sign", UrlEncode(UrlEncode(sign, Encoding.UTF8), Encoding.UTF8)); // C#中需要进行两次UrlEncode,不然发送请求时加号会变空格,导致验签失败。
responseJson = client.UploadString(apiUrl, requestJson);
}
Console.WriteLine("方法名称: " + cmdName + ", 响应报文: " + responseJson);

// 将响应json转为对象
return JsonConvert.DeserializeObject<T>(responseJson);
}

/**
* 数字签名
*/
private string GetSign(string kpParams)
{
X509Certificate2 x = new X509Certificate2(keyStorePath, password, X509KeyStorageFlags.Exportable);
RSACryptoServiceProvider rsa = x.PrivateKey as RSACryptoServiceProvider;
byte[] data = Encoding.UTF8.GetBytes(kpParams);
RSACryptoServiceProvider privateKey1 = new RSACryptoServiceProvider();
privateKey1.ImportParameters(rsa.ExportParameters(true));
byte[] sign = privateKey1.SignData(data, "MD5");
return Convert.ToBase64String(sign);
}

private string UrlEncode(string temp, Encoding encoding)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < temp.Length; i++)
{
string t = temp[i].ToString();
string k = HttpUtility.UrlEncode(t, encoding);
if (t == k)
{
stringBuilder.Append(t);
}
else
{
stringBuilder.Append(k.ToUpper());
}
}
return stringBuilder.ToString();
}
}
}

+ 183
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/Invoice.cs Parādīt failu

@@ -0,0 +1,183 @@
using System.Collections.Generic;

namespace com.chinaeinv.einv.order.dto
{
/**
* 开票请求中的发票信息
*/
public class Invoice
{
/**
* 订单编号
*/
public string orderNo { get; set; }

/**
* 子订单编号
*/
public string subOrderNo { get; set; }

/**
* 店铺名称
*/
public string shopName { get; set; }

/**
* 店铺编号
*/
public string shopCode { get; set; }

/**
* 销货方纳税人识别号
*/
public string taxpayerCode { get; set; }

/**
* 销货方名称
*/
public string taxpayerName { get; set; }

/**
* 销货方地址
*/
public string taxpayerAddress { get; set; }

/**
* 销货方电话
*/
public string taxpayerTel { get; set; }

/**
* 销货方开户银行
*/
public string taxpayerBankName { get; set; }

/**
* 销货方银行账号
*/
public string taxpayerBankAccount { get; set; }

/**
* 购货方纳税人识别号
*/
public string customerCode { get; set; }

/**
* 购货方名称,即发票抬头
*/
public string customerName { get; set; }

/**
* 购货方地址
*/
public string customerAddress { get; set; }

/**
* 购货方电话
*/
public string customerTel { get; set; }

/**
* 购货方开户银行
*/
public string customerBankName { get; set; }

/**
* 购货方银行账号
*/
public string customerBankAccount { get; set; }

/**
* 发票代码+发票号码
*/
public string code { get; set; }

/**
* 校验码
*/
public string checkCode { get; set; }

/**
* 税控码
*/
public string fiscalCode { get; set; }

/**
* 发票状态
* 正常:1
* 红冲:3
* 被红冲:4
*/
public string status { get; set; }

/**
* 生成时间
*/
public string generateTime { get; set; }

/**
* 税价合计金额
*/
public string totalAmount { get; set; }

/**
* 不含税金额
*/
public string noTaxAmount { get; set; }

/**
* 税额
*/
public string taxAmount { get; set; }

/**
* 开票人
*/
public string drawer { get; set; }

/**
* 收款人
*/
public string payee { get; set; }

/**
* 复核人
*/
public string reviewer { get; set; }

/**
* 发票备注
*/
public string remark { get; set; }

/**
* 未签名PDF下载URL
*/
public string pdfUnsignedUrl { get; set; }

/**
* 查看URL
*/
public string viewUrl { get; set; }

/**
* 关联发票编号
*/
public string relatedCode { get; set; }

/**
* 作废/红冲原因
*/
public string validReason { get; set; }

/**
* 作废/红冲时间
*/
public string validTime { get; set; }

/**
* 项目明细
*/
public List<InvoiceItem> items { get; set; }
}
}

+ 82
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/InvoiceItem.cs Parādīt failu

@@ -0,0 +1,82 @@
namespace com.chinaeinv.einv.order.dto
{
/**
* 发票项目明细
*/
public class InvoiceItem {
/**
* 发票行性质 0 正常行、1 折扣行、2 被折扣行
*/
public string type { get; set; }

/**
* 商品编码
*/
public string code { get; set; }

/**
* 商品名称
*/
public string name { get; set; }

/**
* 规格型号
*/
public string spec { get; set; }

/**
* 含税商品单价
*/
public string price { get; set; }

/**
* 数量
*/
public string quantity { get; set; }

/**
* 单位
*/
public string uom { get; set; }

/**
* 税率
*/
public string taxRate { get; set; }

/**
* 税价合计金额
*/
public string amount { get; set; }

/**
* 不含税金额
*/
public string noTaxAmount { get; set; }

/**
* 税额
*/
public string taxAmount { get; set; }

/**
* 商品分类编码
*/
public string catalogCode { get; set; }

/**
* 优惠政策标识
*/
public string preferentialPolicyFlg { get; set; }

/**
* 增值税特殊管理
*/
public string addedValueTaxFlg { get; set; }

/**
* 零税率标识
*/
public string zeroTaxRateFlg { get; set; }
}
}

+ 14
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/InvoiceResult.cs Parādīt failu

@@ -0,0 +1,14 @@
using System.Collections.Generic;

namespace com.chinaeinv.einv.order.dto
{
/**
* “根据订单编号查询发票”方法响应和回调数据
*/
public class InvoiceResult : Result {
/**
* 发票列表
*/
public List<Invoice> invoices { get; set; }
}
}

+ 156
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/Order.cs Parādīt failu

@@ -0,0 +1,156 @@
using System.Collections.Generic;
using System.Collections;
using System;

namespace com.chinaeinv.einv.order.dto
{
/**
* 订单详细信息
*/
public class Order : OrderBase {
/**
* 用户扫码key
*/
public string scanCodeKey { get; set; }

/**
* 店铺
*/
public string shopName { get; set; }

/**
* 店铺编号
*/
public string shopCode { get; set; }

/**
* 订单时间(yyyy-MM-dd HH:mm:ss)
*/
public string orderTime { get; set; }

/**
* 联系人
*/
public string contact { get; set; }

/**
* 联系电话
*/
public string contactTel { get; set; }

/**
* 邮箱
*/
public string contactMail { get; set; }

/**
* 配送地址
*/
public string shippingAddress { get; set; }

/**
* 销货方名称
*/
public string taxpayerName { get; set; }

/**
* 销货方地址
*/
public string taxpayerAddress { get; set; }

/**
* 销货方电话
*/
public string taxpayerTel { get; set; }

/**
* 销货方开户银行
*/
public string taxpayerBankName { get; set; }

/**
* 销货方银行账号
*/
public string taxpayerBankAccount { get; set; }

/**
* 购货方名称,即发票抬头
*/
public string customerName { get; set; }

/**
* 购货方纳税人识别号
*/
public string customerCode { get; set; }

/**
* 购货方地址
*/
public string customerAddress { get; set; }

/**
* 购货方电话
*/
public string customerTel { get; set; }

/**
* 购货方开户银行
*/
public string customerBankName { get; set; }

/**
* 购货方银行账号
*/
public string customerBankAccount { get; set; }

/**
* 是否自动开票
*/
public Boolean autoBilling { get; set; }

/**
* 开票人
*/
public string drawer { get; set; }

/**
* 收款人
*/
public string payee { get; set; }

/**
* 复核人
*/
public string reviewer { get; set; }

/**
* 开票金额
*/
public string totalAmount { get; set; }

/**
* 发票备注
*/
public string remark { get; set; }

/**
* 冲红原因
*/
public string reason { get; set; }

/**
* 订单明细
*/
public List<OrderItem> orderItems { get; set; }

/**
* 扩展参数
*/
public Hashtable extendedParams { get; set; }

/**
* 动态参数
*/
public Hashtable dynamicParams { get; set; }
}
}

+ 41
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/OrderBase.cs Parādīt failu

@@ -0,0 +1,41 @@
namespace com.chinaeinv.einv.order.dto
{
/**
* 订单基本信息
*/
public class OrderBase {
/**
* 订单编号
*/
public string orderNo { get; set; }

/**
* 子订单编号
*/
public string subOrderNo { get; set; }

/**
* 销货方纳税人识别号
*/
public string taxpayerCode { get; set; }

/**
* 发票类型
*/
public string invoiceType { get; set; }

public OrderBase() {
}

public OrderBase(string orderNo, string taxpayerCode) {
this.orderNo = orderNo;
this.taxpayerCode = taxpayerCode;
}

public OrderBase(string orderNo, string subOrderNo, string taxpayerCode) {
this.orderNo = orderNo;
this.subOrderNo = subOrderNo;
this.taxpayerCode = taxpayerCode;
}
}
}

+ 69
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/OrderItem.cs Parādīt failu

@@ -0,0 +1,69 @@
namespace com.chinaeinv.einv.order.dto
{
public class OrderItem {
/**
* 商品编码
*/
public string code { get; set; }

/**
* 商品名称
*/
public string name { get; set; }

/**
* 规格型号
*/
public string spec { get; set; }

/**
* 商品单价
*/
public string price { get; set; }

/**
* 数量
*/
public string quantity { get; set; }

/**
* 单位
*/
public string uom { get; set; }

/**
* 税率
*/
public string taxRate { get; set; }

/**
* 税价合计金额
*/
public string amount { get; set; }

/**
* 折扣金额
*/
public string discountAmount { get; set; }

/**
* 商品分类编码
*/
public string catalogCode { get; set; }

/**
* 优惠政策标识
*/
public string preferentialPolicyFlg { get; set; }

/**
* 增值税特殊管理
*/
public string addedValueTaxFlg { get; set; }

/**
* 零税率标识
*/
public string zeroTaxRateFlg { get; set; }
}
}

+ 17
- 0
cs/einv-demo-order-cs/com/chinaeinv/einv/order/dto/Result.cs Parādīt failu

@@ -0,0 +1,17 @@
namespace com.chinaeinv.einv.order.dto
{
/**
* 异步方法响应和“取消订单”方法响应
*/
public class Result {
/**
* 处理结果代码
*/
public string code { get; set; }

/**
* 处理结果消息
*/
public string message { get; set; }
}
}

+ 85
- 0
cs/einv-demo-order-cs/einv-demo-order-cs.csproj Parādīt failu

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EB51574C-DA86-4CBE-BC6B-1FCA249B0D6A}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>einv_demo_order_cs</RootNamespace>
<AssemblyName>einv-demo-order-cs</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=4.0.3.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>lib\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="com\chinaeinv\einv\order\dto\Invoice.cs" />
<Compile Include="com\chinaeinv\einv\order\dto\InvoiceItem.cs" />
<Compile Include="com\chinaeinv\einv\order\dto\InvoiceResult.cs" />
<Compile Include="com\chinaeinv\einv\order\dto\Order.cs" />
<Compile Include="com\chinaeinv\einv\order\dto\OrderBase.cs" />
<Compile Include="com\chinaeinv\einv\order\dto\OrderItem.cs" />
<Compile Include="com\chinaeinv\einv\order\dto\Result.cs" />
<Compile Include="com\chinaeinv\einv\order\OrderFacade.cs" />
<Compile Include="com\chinaeinv\einv\order\OrderFacadeAgent.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="lib\Newtonsoft.Json.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="lib\Newtonsoft.Json.pdb">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="lib\Newtonsoft.Json.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Include="PTTEST17.pfx" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 6
- 0
cs/einv-demo-order-cs/einv-demo-order-cs.csproj.user Parādīt failu

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
</Project>

Binārs
cs/einv-demo-order-cs/lib/Newtonsoft.Json.dll Parādīt failu


Binārs
cs/einv-demo-order-cs/lib/Newtonsoft.Json.pdb Parādīt failu


+ 6982
- 0
cs/einv-demo-order-cs/lib/Newtonsoft.Json.xml
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


Binārs
java/lib/fastjson-1.2.47.jar Parādīt failu


+ 191
- 0
java/src/Main.java Parādīt failu

@@ -0,0 +1,191 @@
import com.chinaeinv.einv.order.OrderFacade;
import com.chinaeinv.einv.order.OrderFacadeAgent;
import com.chinaeinv.einv.order.dto.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class Main {
// 由电子发票平台分配的appCode
private static final String appCode = "请向瑞宏网工作人员索取";
// 密钥库文件路径
private static final String keyStorePath = "请向瑞宏网工作人员索取";
// 密钥库别名
private static final String alias = "请向瑞宏网工作人员索取";
// 密钥库密码
private static final String password = "请向瑞宏网工作人员索取";
// 接口URL
private static final String apiUrl = "https://www.chinaeinv.com:943/igs/api/orderApi.jspa";
// 销售方纳税人识别号
private static final String testTaxpayerCode = "请向瑞宏网工作人员索取";

private static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

private static OrderFacade orderFacade = new OrderFacadeAgent(appCode, keyStorePath, alias, password, apiUrl);

private static String orderNo = UUID.randomUUID().toString();

public static void main(String[] args) throws Exception {
System.out.println("订单编号:" + orderNo);

// (异步)开具蓝字发票
testKpAsync();

// (异步)开具红字发票
//testChAsync();

// (异步)对开票失败的订单重新开票
//testRetryKpAsync();

// (同步)取消订单
//testCancel();

// (同步)根据订单编号查询发票
testCxByOrderNo();
}

/**
* (异步)开具蓝字发票
*/
private static void testKpAsync() throws Exception {
Order order = new Order();
// 订单编号
order.setOrderNo(orderNo);
// 销货方纳税人识别号
order.setTaxpayerCode(testTaxpayerCode);
// 用户扫码key
order.setScanCodeKey(UUID.randomUUID().toString());
// 店铺
order.setShopName("第198店");
// 店铺编号
order.setShopCode("198");
// 订单时间(yyyy-MM-dd HH:mm:ss)
order.setOrderTime(LocalDateTime.now().format(df));
// 联系人
order.setContact("小小明222");
// 联系电话
order.setContactTel("18000000000");
// 邮箱
order.setContactMail("test@chinaeinv.cn");
// 配送地址
order.setShippingAddress("火星北路1024号");
// 购货方名称,即发票抬头
order.setCustomerName(UUID.randomUUID().toString().replace("-",""));
order.setCustomerCode("");
// 是否自动开票
order.setAutoBilling(true);
// 开票人
order.setDrawer("张三");
// 收款人
order.setPayee("李四");
// 复核人
order.setReviewer("王五");
// 开票金额
order.setTotalAmount(new BigDecimal("24000"));
// 发票备注
order.setRemark("软件系统维护期限为2018年1月1日至2019年12月31日。");

// 发票明细1
OrderItem orderItem1 = new OrderItem();
//商品编码
orderItem1.setCode("001");
//商品名称
orderItem1.setName("软件开发");
//规格型号
orderItem1.setSpec("无");
//税率
orderItem1.setTaxRate(new BigDecimal("0.06"));
//税价合计金额
orderItem1.setAmount(new BigDecimal("10000"));
//商品分类编码
orderItem1.setCatalogCode("3040203000000000000");

// 发票明细2
OrderItem orderItem2 = new OrderItem();
//商品编码
orderItem2.setCode("002");
//商品名称
orderItem2.setName("软件系统维护");
//规格型号
orderItem2.setSpec("无");
//商品单价
orderItem2.setPrice(new BigDecimal("8000"));
//数量
orderItem2.setQuantity(new BigDecimal("2"));
//单位
orderItem2.setUom("年");
//税率
orderItem2.setTaxRate(new BigDecimal("0.06"));
//税价合计金额
orderItem2.setAmount(new BigDecimal("16000"));
//折扣金额
orderItem2.setDiscountAmount(new BigDecimal("2000"));
//商品分类编码
orderItem2.setCatalogCode("3040203000000000000");

// 发票明细
order.setOrderItems(Arrays.asList(orderItem1, orderItem2));

// 扩展参数
order.setExtendedParams(Collections.singletonMap("testExtendedNo", "12345678"));

// 调用接口方法
orderFacade.kpAsync(order);
}

/**
* (异步)开具红字发票
*/
private static void testChAsync() throws Exception {
Order order = new Order();
// 订单编号
order.setOrderNo("OrderNo-105");
// 销货方纳税人识别号
order.setTaxpayerCode(testTaxpayerCode);
// 冲红原因
order.setReason("开票信息有误。");

// 调用接口方法
orderFacade.chAsync(order);
}

/**
* (异步)对开票失败的订单重新开票
*/
private static void testRetryKpAsync() throws Exception {
Order order = new Order();
// 订单编号
order.setOrderNo("OrderNo-001");
// 销货方纳税人识别号
order.setTaxpayerCode(testTaxpayerCode);

// 调用接口方法
orderFacade.retryKpAsync(order);
}

/**
* (同步)取消订单
*/
private static void testCancel() throws Exception {
Order order = new Order();
// 订单编号
order.setOrderNo("OrderNo-001");
// 销货方纳税人识别号
order.setTaxpayerCode(testTaxpayerCode);

// 调用接口方法
orderFacade.cancel(order);
}

/**
* (同步)根据订单编号查询发票
*/
private static void testCxByOrderNo() throws Exception {
OrderBase orderBase = new OrderBase(orderNo, testTaxpayerCode);

// 调用接口方法
orderFacade.cxByOrderNo(orderBase);
}
}

+ 36
- 0
java/src/com/chinaeinv/einv/order/OrderFacade.java Parādīt failu

@@ -0,0 +1,36 @@
package com.chinaeinv.einv.order;

import com.chinaeinv.einv.order.dto.InvoiceResult;
import com.chinaeinv.einv.order.dto.Order;
import com.chinaeinv.einv.order.dto.OrderBase;
import com.chinaeinv.einv.order.dto.Result;

/**
* 订单接口
*/
public interface OrderFacade {
/**
* (异步)开具蓝字发票异步方法
*/
Result kpAsync(Order order) throws Exception;

/**
* (异步)开具红字发票异步方法
*/
Result chAsync(Order order) throws Exception;

/**
* (异步)对开票失败的订单重新开票异步方法
*/
Result retryKpAsync(OrderBase orderBase) throws Exception;

/**
* (同步)取消订单
*/
Result cancel(OrderBase orderBase) throws Exception;

/**
* (同步)根据订单编号查询发票
*/
InvoiceResult cxByOrderNo(OrderBase orderBase) throws Exception;
}

+ 92
- 0
java/src/com/chinaeinv/einv/order/OrderFacadeAgent.java Parādīt failu

@@ -0,0 +1,92 @@
package com.chinaeinv.einv.order;

import com.alibaba.fastjson.JSON;
import com.chinaeinv.einv.order.dto.*;
import com.chinaeinv.einv.util.CertificateUtils;
import com.chinaeinv.einv.util.HttpUtil;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
* 订单接口代理实现
*/
public class OrderFacadeAgent implements OrderFacade {
private String appCode, keyStorePath, alias, password, apiUrl;

/**
* 构造方法
* @param appCode 由电子发票平台分配的appCode
* @param keyStorePath 密钥库文件路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @param apiUrl 接口URL
*/
public OrderFacadeAgent(String appCode, String keyStorePath, String alias, String password, String apiUrl) {
this.appCode = appCode;
this.keyStorePath = keyStorePath;
this.alias = alias;
this.password = password;
this.apiUrl = apiUrl;
}

/**
* (异步)开具蓝字发票
*/
public Result kpAsync(Order order) throws Exception {
return exec(order, "chinaeinv.api.order.v11.kp_async", Result.class);
}

/**
* (异步)开具红字发票
*/
public Result chAsync(Order order) throws Exception {
return exec(order, "chinaeinv.api.order.v11.ch_async", Result.class);
}

/**
* (异步)对开票失败的订单重新开票
*/
public Result retryKpAsync(OrderBase orderBase) throws Exception {
return exec(orderBase, "chinaeinv.api.order.v11.retryKp_async", Result.class);
}

/**
* (同步)取消订单
*/
public Result cancel(OrderBase orderBase) throws Exception {
return exec(orderBase, "chinaeinv.api.order.v11.cancel", Result.class);
}

/**
* (同步)根据订单编号查询发票
*/
public InvoiceResult cxByOrderNo(OrderBase orderBase) throws Exception {
return exec(orderBase, "chinaeinv.api.order.v11.cx.orderNo", InvoiceResult.class);
}

/**
* 调用接口
* @param order 请求数据
* @return 响应数据
* @throws Exception
*/
private <T> T exec(OrderBase order, String cmdName, Class<T> resultType) throws Exception {
// 将Order对象转为json
String requestJson = JSON.toJSONString(order);
System.out.println("方法名称: " + cmdName + ", 请求报文: " + requestJson);
// 生成签名
String sign = CertificateUtils.signToBase64(requestJson.getBytes("UTF-8"), keyStorePath, alias, password);
System.out.println("方法名称: " + cmdName + ", 签名: " + sign);
// 调用接口
Map<String, String> params = new HashMap<>();
params.put("appCode", appCode);
params.put("cmdName", cmdName);
params.put("sign", URLEncoder.encode(sign,"UTF-8"));
String responseJson = HttpUtil.doPost(apiUrl, params, requestJson);
System.out.println("方法名称: " + cmdName + ", 响应报文: " + responseJson);

return JSON.parseObject(responseJson, resultType);
}
}

+ 454
- 0
java/src/com/chinaeinv/einv/order/dto/Invoice.java Parādīt failu

@@ -0,0 +1,454 @@
package com.chinaeinv.einv.order.dto;

import java.math.BigDecimal;
import java.util.List;

/**
* 开票请求中的发票信息
*/
public class Invoice {
/**
* 订单编号
*/
private String orderNo;

/**
* 子订单编号
*/
private String subOrderNo;

/**
* 店铺名称
*/
private String shopName;

/**
* 店铺编号
*/
private String shopCode;

/**
* 销货方纳税人识别号
*/
private String taxpayerCode;

/**
* 销货方名称
*/
private String taxpayerName;

/**
* 销货方地址
*/
private String taxpayerAddress;

/**
* 销货方电话
*/
private String taxpayerTel;

/**
* 销货方开户银行
*/
private String taxpayerBankName;

/**
* 销货方银行账号
*/
private String taxpayerBankAccount;

/**
* 购货方纳税人识别号
*/
private String customerCode;

/**
* 购货方名称,即发票抬头
*/
private String customerName;

/**
* 购货方地址
*/
private String customerAddress;

/**
* 购货方电话
*/
private String customerTel;

/**
* 购货方开户银行
*/
private String customerBankName;

/**
* 购货方银行账号
*/
private String customerBankAccount;

/**
* 发票代码+发票号码
*/
private String code;

/**
* 校验码
*/
private String checkCode;

/**
* 税控码
*/
private String fiscalCode;

/**
* 发票状态
* 正常:1
* 红冲:3
* 被红冲:4
*/
private String status;

/**
* 生成时间
*/
private String generateTime;

/**
* 税价合计金额
*/
private BigDecimal totalAmount;

/**
* 不含税金额
*/
private BigDecimal noTaxAmount;

/**
* 税额
*/
private BigDecimal taxAmount;

/**
* 开票人
*/
private String drawer;

/**
* 收款人
*/
private String payee;

/**
* 复核人
*/
private String reviewer;

/**
* 发票备注
*/
private String remark;

/**
* 未签名PDF下载URL
*/
private String pdfUnsignedUrl;

/**
* 查看URL
*/
private String viewUrl;

/**
* 关联发票编号
*/
private String relatedCode;

/**
* 作废/红冲原因
*/
private String validReason;

/**
* 作废/红冲时间
*/
private String validTime;

/**
* 项目明细
*/
private List<InvoiceItem> items;

public String getOrderNo() {
return orderNo;
}

public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}

public String getSubOrderNo() {
return subOrderNo;
}

public void setSubOrderNo(String subOrderNo) {
this.subOrderNo = subOrderNo;
}

public String getShopName() {
return shopName;
}

public void setShopName(String shopName) {
this.shopName = shopName;
}

public String getShopCode() {
return shopCode;
}

public void setShopCode(String shopCode) {
this.shopCode = shopCode;
}

public String getTaxpayerCode() {
return taxpayerCode;
}

public void setTaxpayerCode(String taxpayerCode) {
this.taxpayerCode = taxpayerCode;
}

public String getTaxpayerName() {
return taxpayerName;
}

public void setTaxpayerName(String taxpayerName) {
this.taxpayerName = taxpayerName;
}

public String getTaxpayerAddress() {
return taxpayerAddress;
}

public void setTaxpayerAddress(String taxpayerAddress) {
this.taxpayerAddress = taxpayerAddress;
}

public String getTaxpayerTel() {
return taxpayerTel;
}

public void setTaxpayerTel(String taxpayerTel) {
this.taxpayerTel = taxpayerTel;
}

public String getTaxpayerBankName() {
return taxpayerBankName;
}

public void setTaxpayerBankName(String taxpayerBankName) {
this.taxpayerBankName = taxpayerBankName;
}

public String getTaxpayerBankAccount() {
return taxpayerBankAccount;
}

public void setTaxpayerBankAccount(String taxpayerBankAccount) {
this.taxpayerBankAccount = taxpayerBankAccount;
}

public String getCustomerCode() {
return customerCode;
}

public void setCustomerCode(String customerCode) {
this.customerCode = customerCode;
}

public String getCustomerName() {
return customerName;
}

public void setCustomerName(String customerName) {
this.customerName = customerName;
}

public String getCustomerAddress() {
return customerAddress;
}

public void setCustomerAddress(String customerAddress) {
this.customerAddress = customerAddress;
}

public String getCustomerTel() {
return customerTel;
}

public void setCustomerTel(String customerTel) {
this.customerTel = customerTel;
}

public String getCustomerBankName() {
return customerBankName;
}

public void setCustomerBankName(String customerBankName) {
this.customerBankName = customerBankName;
}

public String getCustomerBankAccount() {
return customerBankAccount;
}

public void setCustomerBankAccount(String customerBankAccount) {
this.customerBankAccount = customerBankAccount;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getCheckCode() {
return checkCode;
}

public void setCheckCode(String checkCode) {
this.checkCode = checkCode;
}

public String getFiscalCode() {
return fiscalCode;
}

public void setFiscalCode(String fiscalCode) {
this.fiscalCode = fiscalCode;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public String getGenerateTime() {
return generateTime;
}

public void setGenerateTime(String generateTime) {
this.generateTime = generateTime;
}

public BigDecimal getTotalAmount() {
return totalAmount;
}

public void setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
}

public BigDecimal getNoTaxAmount() {
return noTaxAmount;
}

public void setNoTaxAmount(BigDecimal noTaxAmount) {
this.noTaxAmount = noTaxAmount;
}

public BigDecimal getTaxAmount() {
return taxAmount;
}

public void setTaxAmount(BigDecimal taxAmount) {
this.taxAmount = taxAmount;
}

public String getDrawer() {
return drawer;
}

public void setDrawer(String drawer) {
this.drawer = drawer;
}

public String getPayee() {
return payee;
}

public void setPayee(String payee) {
this.payee = payee;
}

public String getReviewer() {
return reviewer;
}

public void setReviewer(String reviewer) {
this.reviewer = reviewer;
}

public String getRemark() {
return remark;
}

public void setRemark(String remark) {
this.remark = remark;
}

public String getPdfUnsignedUrl() {
return pdfUnsignedUrl;
}

public void setPdfUnsignedUrl(String pdfUnsignedUrl) {
this.pdfUnsignedUrl = pdfUnsignedUrl;
}

public String getViewUrl() {
return viewUrl;
}

public void setViewUrl(String viewUrl) {
this.viewUrl = viewUrl;
}

public String getRelatedCode() {
return relatedCode;
}

public void setRelatedCode(String relatedCode) {
this.relatedCode = relatedCode;
}

public String getValidReason() {
return validReason;
}

public void setValidReason(String validReason) {
this.validReason = validReason;
}

public String getValidTime() {
return validTime;
}

public void setValidTime(String validTime) {
this.validTime = validTime;
}

public List<InvoiceItem> getItems() {
return items;
}

public void setItems(List<InvoiceItem> items) {
this.items = items;
}
}

+ 203
- 0
java/src/com/chinaeinv/einv/order/dto/InvoiceItem.java Parādīt failu

@@ -0,0 +1,203 @@
package com.chinaeinv.einv.order.dto;

import java.math.BigDecimal;

/**
* 发票项目明细
*/
public class InvoiceItem {
/**
* 发票行性质 0 正常行、1 折扣行、2 被折扣行
*/
private String type;

/**
* 商品编码
*/
private String code;

/**
* 商品名称
*/
private String name;

/**
* 规格型号
*/
private String spec;

/**
* 含税商品单价
*/
private BigDecimal price;

/**
* 数量
*/
private BigDecimal quantity;

/**
* 单位
*/
private String uom;

/**
* 税率
*/
private BigDecimal taxRate;

/**
* 税价合计金额
*/
private BigDecimal amount;

/**
* 不含税金额
*/
private BigDecimal noTaxAmount;

/**
* 税额
*/
private BigDecimal taxAmount;

/**
* 商品分类编码
*/
private String catalogCode;

/**
* 优惠政策标识
*/
private String preferentialPolicyFlg;

/**
* 增值税特殊管理
*/
private String addedValueTaxFlg;

/**
* 零税率标识
*/
private String zeroTaxRateFlg;

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSpec() {
return spec;
}

public void setSpec(String spec) {
this.spec = spec;
}

public BigDecimal getPrice() {
return price;
}

public void setPrice(BigDecimal price) {
this.price = price;
}

public BigDecimal getQuantity() {
return quantity;
}

public void setQuantity(BigDecimal quantity) {
this.quantity = quantity;
}

public String getUom() {
return uom;
}

public void setUom(String uom) {
this.uom = uom;
}

public BigDecimal getTaxRate() {
return taxRate;
}

public void setTaxRate(BigDecimal taxRate) {
this.taxRate = taxRate;
}

public BigDecimal getAmount() {
return amount;
}

public void setAmount(BigDecimal amount) {
this.amount = amount;
}

public BigDecimal getNoTaxAmount() {
return noTaxAmount;
}

public void setNoTaxAmount(BigDecimal noTaxAmount) {
this.noTaxAmount = noTaxAmount;
}

public BigDecimal getTaxAmount() {
return taxAmount;
}

public void setTaxAmount(BigDecimal taxAmount) {
this.taxAmount = taxAmount;
}

public String getCatalogCode() {
return catalogCode;
}

public void setCatalogCode(String catalogCode) {
this.catalogCode = catalogCode;
}

public String getPreferentialPolicyFlg() {
return preferentialPolicyFlg;
}

public void setPreferentialPolicyFlg(String preferentialPolicyFlg) {
this.preferentialPolicyFlg = preferentialPolicyFlg;
}

public String getAddedValueTaxFlg() {
return addedValueTaxFlg;
}

public void setAddedValueTaxFlg(String addedValueTaxFlg) {
this.addedValueTaxFlg = addedValueTaxFlg;
}

public String getZeroTaxRateFlg() {
return zeroTaxRateFlg;
}

public void setZeroTaxRateFlg(String zeroTaxRateFlg) {
this.zeroTaxRateFlg = zeroTaxRateFlg;
}
}

+ 22
- 0
java/src/com/chinaeinv/einv/order/dto/InvoiceResult.java Parādīt failu

@@ -0,0 +1,22 @@
package com.chinaeinv.einv.order.dto;

import java.util.List;
import java.util.Map;

/**
* “根据订单编号查询发票”方法响应和回调数据
*/
public class InvoiceResult extends Result {
/**
* 发票列表
*/
private List<Invoice> invoices;

public List<Invoice> getInvoices() {
return invoices;
}

public void setInvoices(List<Invoice> invoices) {
this.invoices = invoices;
}
}

+ 387
- 0
java/src/com/chinaeinv/einv/order/dto/Order.java Parādīt failu

@@ -0,0 +1,387 @@
package com.chinaeinv.einv.order.dto;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
* 订单详细信息
*/
public class Order extends OrderBase {
/**
* 用户扫码key
*/
private String scanCodeKey;

/**
* 店铺
*/
private String shopName;

/**
* 店铺编号
*/
private String shopCode;

/**
* 订单时间(yyyy-MM-dd HH:mm:ss)
*/
private String orderTime;

/**
* 联系人
*/
private String contact;

/**
* 联系电话
*/
private String contactTel;

/**
* 邮箱
*/
private String contactMail;

/**
* 配送地址
*/
private String shippingAddress;

/**
* 销货方名称
*/
private String taxpayerName;

/**
* 销货方地址
*/
private String taxpayerAddress;

/**
* 销货方电话
*/
private String taxpayerTel;

/**
* 销货方开户银行
*/
private String taxpayerBankName;

/**
* 销货方银行账号
*/
private String taxpayerBankAccount;

/**
* 购货方名称,即发票抬头
*/
private String customerName;

/**
* 购货方纳税人识别号
*/
private String customerCode;

/**
* 购货方地址
*/
private String customerAddress;

/**
* 购货方电话
*/
private String customerTel;

/**
* 购货方开户银行
*/
private String customerBankName;

/**
* 购货方银行账号
*/
private String customerBankAccount;

/**
* 是否自动开票
*/
private boolean autoBilling;

/**
* 开票人
*/
private String drawer;

/**
* 收款人
*/
private String payee;

/**
* 复核人
*/
private String reviewer;

/**
* 开票金额
*/
private BigDecimal totalAmount;

/**
* 发票备注
*/
private String remark;

/**
* 冲红原因
*/
private String reason;

/**
* 订单明细
*/
private List<OrderItem> orderItems;

/**
* 扩展参数
*/
private Map<String, String> extendedParams;

/**
* 动态参数
*/
private Map<String, String> dynamicParams;

public String getScanCodeKey() {
return scanCodeKey;
}

public void setScanCodeKey(String scanCodeKey) {
this.scanCodeKey = scanCodeKey;
}

public String getShopName() {
return shopName;
}

public void setShopName(String shopName) {
this.shopName = shopName;
}

public String getShopCode() {
return shopCode;
}

public void setShopCode(String shopCode) {
this.shopCode = shopCode;
}

public String getOrderTime() {
return orderTime;
}

public void setOrderTime(String orderTime) {
this.orderTime = orderTime;
}

public String getContact() {
return contact;
}

public void setContact(String contact) {
this.contact = contact;
}

public String getContactTel() {
return contactTel;
}

public void setContactTel(String contactTel) {
this.contactTel = contactTel;
}

public String getContactMail() {
return contactMail;
}

public void setContactMail(String contactMail) {
this.contactMail = contactMail;
}

public String getShippingAddress() {
return shippingAddress;
}

public void setShippingAddress(String shippingAddress) {
this.shippingAddress = shippingAddress;
}

public String getTaxpayerName() {
return taxpayerName;
}

public void setTaxpayerName(String taxpayerName) {
this.taxpayerName = taxpayerName;
}

public String getTaxpayerAddress() {
return taxpayerAddress;
}

public void setTaxpayerAddress(String taxpayerAddress) {
this.taxpayerAddress = taxpayerAddress;
}

public String getTaxpayerTel() {
return taxpayerTel;
}

public void setTaxpayerTel(String taxpayerTel) {
this.taxpayerTel = taxpayerTel;
}

public String getTaxpayerBankName() {
return taxpayerBankName;
}

public void setTaxpayerBankName(String taxpayerBankName) {
this.taxpayerBankName = taxpayerBankName;
}

public String getTaxpayerBankAccount() {
return taxpayerBankAccount;
}

public void setTaxpayerBankAccount(String taxpayerBankAccount) {
this.taxpayerBankAccount = taxpayerBankAccount;
}

public String getCustomerName() {
return customerName;
}

public void setCustomerName(String customerName) {
this.customerName = customerName;
}

public String getCustomerCode() {
return customerCode;
}

public void setCustomerCode(String customerCode) {
this.customerCode = customerCode;
}

public String getCustomerAddress() {
return customerAddress;
}

public void setCustomerAddress(String customerAddress) {
this.customerAddress = customerAddress;
}

public String getCustomerTel() {
return customerTel;
}

public void setCustomerTel(String customerTel) {
this.customerTel = customerTel;
}

public String getCustomerBankName() {
return customerBankName;
}

public void setCustomerBankName(String customerBankName) {
this.customerBankName = customerBankName;
}

public String getCustomerBankAccount() {
return customerBankAccount;
}

public void setCustomerBankAccount(String customerBankAccount) {
this.customerBankAccount = customerBankAccount;
}

public boolean isAutoBilling() {
return autoBilling;
}

public void setAutoBilling(boolean autoBilling) {
this.autoBilling = autoBilling;
}

public String getDrawer() {
return drawer;
}

public void setDrawer(String drawer) {
this.drawer = drawer;
}

public String getPayee() {
return payee;
}

public void setPayee(String payee) {
this.payee = payee;
}

public String getReviewer() {
return reviewer;
}

public void setReviewer(String reviewer) {
this.reviewer = reviewer;
}

public BigDecimal getTotalAmount() {
return totalAmount;
}

public void setTotalAmount(BigDecimal totalAmount) {
this.totalAmount = totalAmount;
}

public String getRemark() {
return remark;
}

public void setRemark(String remark) {
this.remark = remark;
}

public String getReason() {
return reason;
}

public void setReason(String reason) {
this.reason = reason;
}

public List<OrderItem> getOrderItems() {
return orderItems;
}

public void setOrderItems(List<OrderItem> orderItems) {
this.orderItems = orderItems;
}

public Map<String, String> getExtendedParams() {
return extendedParams;
}

public void setExtendedParams(Map<String, String> extendedParams) {
this.extendedParams = extendedParams;
}

public Map<String, String> getDynamicParams() {
return dynamicParams;
}

public void setDynamicParams(Map<String, String> dynamicParams) {
this.dynamicParams = dynamicParams;
}
}

+ 72
- 0
java/src/com/chinaeinv/einv/order/dto/OrderBase.java Parādīt failu

@@ -0,0 +1,72 @@
package com.chinaeinv.einv.order.dto;

/**
* 订单基本信息
*/
public class OrderBase {
/**
* 订单编号
*/
private String orderNo;

/**
* 子订单编号
*/
private String subOrderNo;

/**
* 销货方纳税人识别号
*/
private String taxpayerCode;

/**
* 发票类型
*/
private String invoiceType;

public OrderBase() {
}

public OrderBase(String orderNo, String taxpayerCode) {
this.orderNo = orderNo;
this.taxpayerCode = taxpayerCode;
}

public OrderBase(String orderNo, String subOrderNo, String taxpayerCode) {
this.orderNo = orderNo;
this.subOrderNo = subOrderNo;
this.taxpayerCode = taxpayerCode;
}

public String getOrderNo() {
return orderNo;
}

public void setOrderNo(String orderNo) {
this.orderNo = orderNo;
}

public String getSubOrderNo() {
return subOrderNo;
}

public void setSubOrderNo(String subOrderNo) {
this.subOrderNo = subOrderNo;
}

public String getTaxpayerCode() {
return taxpayerCode;
}

public void setTaxpayerCode(String taxpayerCode) {
this.taxpayerCode = taxpayerCode;
}

public String getInvoiceType() {
return invoiceType;
}

public void setInvoiceType(String invoiceType) {
this.invoiceType = invoiceType;
}
}

+ 174
- 0
java/src/com/chinaeinv/einv/order/dto/OrderItem.java Parādīt failu

@@ -0,0 +1,174 @@
package com.chinaeinv.einv.order.dto;

import java.math.BigDecimal;

public class OrderItem {
/**
* 商品编码
*/
private String code;

/**
* 商品名称
*/
private String name;

/**
* 规格型号
*/
private String spec;

/**
* 商品单价
*/
private BigDecimal price;

/**
* 数量
*/
private BigDecimal quantity;

/**
* 单位
*/
private String uom;

/**
* 税率
*/
private BigDecimal taxRate;

/**
* 税价合计金额
*/
private BigDecimal amount;

/**
* 折扣金额
*/
private BigDecimal discountAmount;

/**
* 商品分类编码
*/
private String catalogCode;

/**
* 优惠政策标识
*/
private String preferentialPolicyFlg;

/**
* 增值税特殊管理
*/
private String addedValueTaxFlg;

/**
* 零税率标识
*/
private String zeroTaxRateFlg;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSpec() {
return spec;
}

public void setSpec(String spec) {
this.spec = spec;
}

public BigDecimal getPrice() {
return price;
}

public void setPrice(BigDecimal price) {
this.price = price;
}

public BigDecimal getQuantity() {
return quantity;
}

public void setQuantity(BigDecimal quantity) {
this.quantity = quantity;
}

public String getUom() {
return uom;
}

public void setUom(String uom) {
this.uom = uom;
}

public BigDecimal getTaxRate() {
return taxRate;
}

public void setTaxRate(BigDecimal taxRate) {
this.taxRate = taxRate;
}

public BigDecimal getAmount() {
return amount;
}

public void setAmount(BigDecimal amount) {
this.amount = amount;
}

public BigDecimal getDiscountAmount() {
return discountAmount;
}

public void setDiscountAmount(BigDecimal discountAmount) {
this.discountAmount = discountAmount;
}

public String getCatalogCode() {
return catalogCode;
}

public void setCatalogCode(String catalogCode) {
this.catalogCode = catalogCode;
}

public String getPreferentialPolicyFlg() {
return preferentialPolicyFlg;
}

public void setPreferentialPolicyFlg(String preferentialPolicyFlg) {
this.preferentialPolicyFlg = preferentialPolicyFlg;
}

public String getAddedValueTaxFlg() {
return addedValueTaxFlg;
}

public void setAddedValueTaxFlg(String addedValueTaxFlg) {
this.addedValueTaxFlg = addedValueTaxFlg;
}

public String getZeroTaxRateFlg() {
return zeroTaxRateFlg;
}

public void setZeroTaxRateFlg(String zeroTaxRateFlg) {
this.zeroTaxRateFlg = zeroTaxRateFlg;
}
}

+ 32
- 0
java/src/com/chinaeinv/einv/order/dto/Result.java Parādīt failu

@@ -0,0 +1,32 @@
package com.chinaeinv.einv.order.dto;

/**
* 异步方法响应和“取消订单”方法响应
*/
public class Result {
/**
* 处理结果代码
*/
private String code;

/**
* 处理结果消息
*/
private String message;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}

+ 888
- 0
java/src/com/chinaeinv/einv/util/CertificateUtils.java Parādīt failu

@@ -0,0 +1,888 @@
package com.chinaeinv.einv.util;

import javax.crypto.Cipher;
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Date;

/**
* <p>
* 数字签名/加密解密工具包
* </p>
*/
public class CertificateUtils {

/**
* Java密钥库(Java 密钥库,JKS)KEY_STORE
*/
public static final String KEY_STORE = "JKS";

public static final String X509 = "X.509";
/**
* 文件读取缓冲区大小
*/
private static final int CACHE_SIZE = 2048;
/**
* 最大文件加密块
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* 最大文件解密块
*/
private static final int MAX_DECRYPT_BLOCK = 128;

/**
* <p>
* 根据密钥库获得私钥
* </p>
*
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
static PrivateKey getPrivateKey(String keyStorePath, String alias, String password)
throws Exception {
KeyStore keyStore = getKeyStore(keyStorePath, password);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
return privateKey;
}
/**
* <p>
* 获得密钥库
* </p>
*
* @param keyStorePath 密钥库存储路径
* @param password 密钥库密码
* @return
* @throws Exception
*/
private static KeyStore getKeyStore(String keyStorePath, String password)
throws Exception {
FileInputStream in = new FileInputStream(keyStorePath);
KeyStore keyStore = KeyStore.getInstance(KEY_STORE);
keyStore.load(in, password.toCharArray());
in.close();
return keyStore;
}

/**
* <p>
* 根据证书获得公钥
* </p>
*
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
static PublicKey getPublicKey(String certificatePath) throws CertificateException, IOException {
Certificate certificate = getCertificate(certificatePath);
PublicKey publicKey = certificate.getPublicKey();
return publicKey;
}

/**
* <p>
* 根据证书获得公钥
* </p>
*
* @param certificateInStream 证书输入流
* @return
* @throws Exception
*/
static PublicKey getPublicKey(InputStream certificateInStream) throws CertificateException, IOException {
Certificate certificate = getCertificate(certificateInStream);
PublicKey publicKey = certificate.getPublicKey();
return publicKey;
}

/**
* <p>
* 获得证书
* </p>
*
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
private static Certificate getCertificate(String certificatePath) throws CertificateException, IOException {
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
FileInputStream in = new FileInputStream(certificatePath);
Certificate certificate = certificateFactory.generateCertificate(in);
in.close();
return certificate;
}

/**
* <p>
* 获得证书
* </p>
*
* @param certificateInStream 证书输入流
* @return
* @throws Exception
*/
private static Certificate getCertificate(InputStream certificateInStream) throws CertificateException, IOException {
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
Certificate certificate = certificateFactory.generateCertificate(certificateInStream);
certificateInStream.close();
return certificate;
}

/**
* <p>
* 根据密钥库获得证书
* </p>
*
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
private static Certificate getCertificate(String keyStorePath, String alias, String password)
throws Exception {
KeyStore keyStore = getKeyStore(keyStorePath, password);
Certificate certificate = keyStore.getCertificate(alias);
return certificate;
}

/**
* <p>
* 私钥加密
* </p>
*
* @param data 源数据
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath, String alias, String password)
throws Exception {
// 取得私钥
PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
System.out.print("\n=========="+privateKey.getAlgorithm()+"\n==========");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/**
* <p>
* 文件私钥加密
* </p>
* <p>
* 过大的文件可能会导致内存溢出
* </>
*
* @param filePath 文件路径
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
public static byte[] encryptFileByPrivateKey(String filePath, String keyStorePath, String alias, String password)
throws Exception {
byte[] data = fileToByte(filePath);
return encryptByPrivateKey(data, keyStorePath, alias, password);
}
/**
* <p>
* 文件加密
* </p>
*
* @param srcFilePath 源文件
* @param destFilePath 加密后文件
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @throws Exception
*/
public static void encryptFileByPrivateKey(String srcFilePath, String destFilePath, String keyStorePath, String alias, String password)
throws Exception {
// 取得私钥
PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
File srcFile = new File(srcFilePath);
FileInputStream in = new FileInputStream(srcFile);
File destFile = new File(destFilePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] data = new byte[MAX_ENCRYPT_BLOCK];
byte[] encryptedData; // 加密块
while (in.read(data) != -1) {
encryptedData = cipher.doFinal(data);
out.write(encryptedData, 0, encryptedData.length);
out.flush();
}
out.close();
in.close();
}

/**
* <p>
* 文件加密成BASE64编码的字符串
* </p>
*
* @param filePath 文件路径
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
// public static String encryptFileToBase64ByPrivateKey(String filePath, String keyStorePath, String alias, String password)
// throws Exception {
// byte[] encryptedData = encryptFileByPrivateKey(filePath, keyStorePath, alias, password);
// return Base64Utils.encode(encryptedData);
// }
/**
* <p>
* 私钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String keyStorePath, String alias, String password)
throws Exception {
// 取得私钥
PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// 解密byte数组最大长度限制: 128
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}

/**
* <p>
* 公钥加密
* </p>
*
* @param data 源数据
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String certificatePath)
throws Exception {
// 取得公钥
PublicKey publicKey = getPublicKey(certificatePath);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}

/**
* <p>
* 公钥解密
* </p>
*
* @param encryptedData 已加密数据
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData, String certificatePath)
throws Exception {
PublicKey publicKey = getPublicKey(certificatePath);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/**
* <p>
* 文件解密
* </p>
*
* @param srcFilePath 源文件
* @param destFilePath 目标文件
* @param certificatePath 证书存储路径
* @throws Exception
*/
public static void decryptFileByPublicKey(String srcFilePath, String destFilePath, String certificatePath)
throws Exception {
PublicKey publicKey = getPublicKey(certificatePath);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
File srcFile = new File(srcFilePath);
FileInputStream in = new FileInputStream(srcFile);
File destFile = new File(destFilePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] data = new byte[MAX_DECRYPT_BLOCK];
byte[] decryptedData; // 解密块
while (in.read(data) != -1) {
decryptedData = cipher.doFinal(data);
out.write(decryptedData, 0, decryptedData.length);
out.flush();
}
out.close();
in.close();
}
/**
* <p>
* 生成数据签名
* </p>
*
* @param data 源数据
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
public static byte[] sign(byte[] data, String keyStorePath, String alias, String password)
throws Exception {
// 获得证书
X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath, alias, password);
// 获取私钥
KeyStore keyStore = getKeyStore(keyStorePath, password);
// 取得私钥
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
// 构建签名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
/**
* <p>
* 生成数据签名并以BASE64编码
* </p>
*
* @param data 源数据
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
public static String signToBase64(byte[] data, String keyStorePath, String alias, String password)
throws Exception {
return Base64.getEncoder().encodeToString(sign(data, keyStorePath, alias, password));
}
/**
* <p>
* 生成文件数据签名(BASE64)
* </p>
* <p>
* 需要先将文件私钥加密,再根据加密后的数据生成签名(BASE64),适用于小文件
* </p>
*
* @param filePath 源文件
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
public static String signFileToBase64WithEncrypt(String filePath, String keyStorePath, String alias, String password)
throws Exception {
byte[] encryptedData = encryptFileByPrivateKey(filePath, keyStorePath, alias, password);
return signToBase64(encryptedData, keyStorePath, alias, password);
}
/**
* <p>
* 生成文件签名
* </p>
* <p>
* 注意:<br>
* 方法中使用了FileChannel,其巨大Bug就是不会释放文件句柄,导致签名的文件无法操作(移动或删除等)<br>
* 该方法已被generateFileSign取代
* </p>
*
* @param filePath 文件路径
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
* @throws Exception
*/
@Deprecated
public static byte[] signFile(String filePath, String keyStorePath, String alias, String password)
throws Exception {
byte[] sign = new byte[0];
// 获得证书
X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath, alias, password);
// 获取私钥
KeyStore keyStore = getKeyStore(keyStorePath, password);
// 取得私钥
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
// 构建签名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
signature.initSign(privateKey);
File file = new File(filePath);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
FileChannel fileChannel = in.getChannel();
MappedByteBuffer byteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
signature.update(byteBuffer);
fileChannel.close();
in.close();
sign = signature.sign();
}
return sign;
}
/**
* <p>
* 生成文件数字签名
* </p>
*
* @param filePath
* @param keyStorePath
* @param alias
* @param password
* @return
* @throws Exception
*/
public static byte[] generateFileSign(String filePath, String keyStorePath, String alias, String password)
throws Exception {
byte[] sign = new byte[0];
// 获得证书
X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath, alias, password);
// 获取私钥
KeyStore keyStore = getKeyStore(keyStorePath, password);
// 取得私钥
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
// 构建签名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
signature.initSign(privateKey);
File file = new File(filePath);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
signature.update(cache, 0, nRead);
}
in.close();
sign = signature.sign();
}
return sign;
}
/**
* <p>
* 文件签名成BASE64编码字符串
* </p>
*
* @param filePath
* @param keyStorePath
* @param alias
* @param password
* @return
* @throws Exception
*/
public static String signFileToBase64(String filePath, String keyStorePath, String alias, String password)
throws Exception {
return Base64.getEncoder().encodeToString(generateFileSign(filePath, keyStorePath, alias, password));
}
/**
* <p>
* 验证签名
* </p>
*
* @param data 已加密数据
* @param sign 数据签名[BASE64]
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static boolean verifySign(byte[] data, String sign, String certificatePath)
throws Exception {
// 获得证书
X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
// 获得公钥
PublicKey publicKey = x509Certificate.getPublicKey();
// 构建签名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(Base64.getDecoder().decode(sign));
}

/**
* <p>
* 验证签名
* </p>
*
* @param data 已加密数据
* @param sign 数据签名[BASE64]
* @param certificate 证书
* @return
* @throws Exception
*/
public static boolean verifySign(byte[] data, String sign, byte[] certificate)
throws Exception {
// 获得证书
X509Certificate x509Certificate = (X509Certificate) getCertificate(new ByteArrayInputStream(certificate));
// 获得公钥
PublicKey publicKey = x509Certificate.getPublicKey();
// 构建签名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(Base64.getDecoder().decode(sign));
}
/**
* <p>
* 校验文件签名
* </p>
*
* @param filePath
* @param sign
* @param certificatePath
* @return
* @throws Exception
*/
// public static boolean validateFileSign(String filePath, String sign, String certificatePath)
// throws Exception {
// boolean result = false;
// // 获得证书
// X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
// // 获得公钥
// PublicKey publicKey = x509Certificate.getPublicKey();
//// System.out.print("测试私钥");
//// System.out.print(publicKey);
//// System.out.print("测试私钥");
//// System.out.print("\n");
//
// // 构建签名
// Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
// signature.initVerify(publicKey);
// File file = new File(filePath);
// if (file.exists()) {
// byte[] decodedSign = Base64Utils.decode(sign);
// FileInputStream in = new FileInputStream(file);
// byte[] cache = new byte[CACHE_SIZE];
// int nRead = 0;
// while ((nRead = in.read(cache)) != -1) {
// signature.update(cache, 0, nRead);
// }
// in.close();
// result = signature.verify(decodedSign);
// }
// return result;
// }
/**
* <p>
* BASE64解码->签名校验
* </p>
*
* @param base64String BASE64编码字符串
* @param sign 数据签名[BASE64]
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
// public static boolean verifyBase64Sign(String base64String, String sign, String certificatePath)
// throws Exception {
// byte[] data = Base64Utils.decode(base64String);
// return verifySign(data, sign, certificatePath);
// }
/**
* <p>
* BASE64解码->公钥解密-签名校验
* </p>
*
*
* @param base64String BASE64编码字符串
* @param sign 数据签名[BASE64]
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
// public static boolean verifyBase64SignWithDecrypt(String base64String, String sign, String certificatePath)
// throws Exception {
// byte[] encryptedData = Base64Utils.decode(base64String);
// byte[] data = decryptByPublicKey(encryptedData, certificatePath);
// return verifySign(data, sign, certificatePath);
// }
/**
* <p>
* 文件公钥解密->签名校验
* </p>
*
* @param encryptedFilePath 加密文件路径
* @param sign 数字证书[BASE64]
* @param certificatePath
* @return
* @throws Exception
*/
// public static boolean verifyFileSignWithDecrypt(String encryptedFilePath, String sign, String certificatePath)
// throws Exception {
// byte[] encryptedData = fileToByte(encryptedFilePath);
// byte[] data = decryptByPublicKey(encryptedData, certificatePath);
// return verifySign(data, sign, certificatePath);
// }

/**
* <p>
* 校验证书当前是否有效
* </p>
*
* @param certificate 证书
* @return
*/
public static boolean verifyCertificate(Certificate certificate) {
return verifyCertificate(new Date(), certificate);
}
/**
* <p>
* 验证证书是否过期或无效
* </p>
*
* @param date 日期
* @param certificate 证书
* @return
*/
public static boolean verifyCertificate(Date date, Certificate certificate) {
boolean isValid = true;
try {
X509Certificate x509Certificate = (X509Certificate) certificate;
x509Certificate.checkValidity(date);
} catch (Exception e) {
isValid = false;
}
return isValid;
}
/**
* <p>
* 验证数字证书是在给定的日期是否有效
* </p>
*
* @param date 日期
* @param certificatePath 证书存储路径
* @return
*/
public static boolean verifyCertificate(Date date, String certificatePath) {
Certificate certificate;
try {
certificate = getCertificate(certificatePath);
return verifyCertificate(certificate);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* <p>
* 验证数字证书是在给定的日期是否有效
* </p>
*
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
*/
public static boolean verifyCertificate(Date date, String keyStorePath, String alias, String password) {
Certificate certificate;
try {
certificate = getCertificate(keyStorePath, alias, password);
return verifyCertificate(certificate);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

/**
* <p>
* 验证数字证书当前是否有效
* </p>
*
* @param keyStorePath 密钥库存储路径
* @param alias 密钥库别名
* @param password 密钥库密码
* @return
*/
public static boolean verifyCertificate(String keyStorePath, String alias, String password) {
return verifyCertificate(new Date(), keyStorePath, alias, password);
}
/**
* <p>
* 验证数字证书当前是否有效
* </p>
*
* @param certificatePath 证书存储路径
* @return
*/
public static boolean verifyCertificate(String certificatePath) {
return verifyCertificate(new Date(), certificatePath);
}
/**
* <p>
* 文件转换为byte数组
* </p>
*
* @param filePath 文件路径
* @return
* @throws Exception
*/
public static byte[] fileToByte(String filePath) throws Exception {
byte[] data = new byte[0];
File file = new File(filePath);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
data = out.toByteArray();
}
return data;
}
/**
* <p>
* 二进制数据写文件
* </p>
*
* @param bytes 二进制数据
* @param filePath 文件生成目录
*/
public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
InputStream in = new ByteArrayInputStream(bytes);
File destFile = new File(filePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
}

}

+ 223
- 0
java/src/com/chinaeinv/einv/util/HttpUtil.java Parādīt failu

@@ -0,0 +1,223 @@
package com.chinaeinv.einv.util;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Map.Entry;

/**
* 进行http访问的基本类
*/
public class HttpUtil {

private static final String DEFAULT_CHARSET = "UTF-8";

private static final String METHOD_POST = "POST";

private static final String METHOD_GET = "GET";

private static final int CONNECTTIMEOUT = 5000;

private static final int READTIMEOUT = 5000;

private static class DefaultTrustManager implements X509TrustManager {

public X509Certificate[] getAcceptedIssuers() {
return null;
}

public void checkClientTrusted(X509Certificate[] cert, String oauthType)
throws java.security.cert.CertificateException {
}

public void checkServerTrusted(X509Certificate[] cert, String oauthType)
throws java.security.cert.CertificateException {
}
}

private static HttpURLConnection getConnection(URL url, String method)
throws IOException {

HttpURLConnection conn;
if ("https".equals(url.getProtocol())) {
SSLContext ctx;
try {
ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[] { new DefaultTrustManager() },
new SecureRandom());
} catch (Exception e) {
throw new IOException(e);
}
HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection();
connHttps.setSSLSocketFactory(ctx.getSocketFactory());
connHttps.setHostnameVerifier(new HostnameVerifier() {

public boolean verify(String hostname, SSLSession session) {
return true;// 默认都认证通过
}
});
conn = connHttps;
} else {
conn = (HttpURLConnection) url.openConnection();
}
conn.setRequestMethod(method);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
conn.setRequestProperty("Connection", "Keep-Alive");
return conn;

}

/**
* 通过get方法访问
*
* @param url 访问的url地址
* @param urlParams 请求需要的参数
* @return 返回请求响应的数据
* @throws IOException
*/
public static String doGet(String url, Map<String, String> urlParams)
throws IOException {
if (isEmpty(url)) {
throw new IllegalArgumentException("The parameter 'url' can not be null or blank.");
}
url += buildQuery(urlParams, DEFAULT_CHARSET);
HttpURLConnection conn = getConnection(new URL(url), METHOD_GET);
String s = getResponseAsString(conn);
return s;
}

/**
*
* @param url api请求的权路径url地址
* @param urlParams 请求的参数
* @param requestJson 请求报文
* @return 请求响应
* @throws IOException
*/
public static String doPost(String url, Map<String, String> urlParams, String requestJson) throws IOException {
return doPost(url, urlParams, requestJson, CONNECTTIMEOUT, READTIMEOUT);
}

/**
*
* 通过post方法请求数据
*
* @param url 请求的url地址
* @param urlParams 请求的参数
* @param requestJson 请求报文
* @param connectTimeOut 请求连接过期时间
* @param readTimeOut 请求读取过期时间
* @return 请求响应
* @throws IOException
*/
public static String doPost(String url, Map<String, String> urlParams, String requestJson,
int connectTimeOut, int readTimeOut) throws IOException {
if (isEmpty(url)) {
throw new IllegalArgumentException("The parameter 'url' can not be null or blank.");
}
url += buildQuery(urlParams, DEFAULT_CHARSET);
HttpURLConnection conn = getConnection(new URL(url), METHOD_POST);
conn.setConnectTimeout(connectTimeOut);
conn.setReadTimeout(readTimeOut);
conn.getOutputStream().write(requestJson.getBytes(DEFAULT_CHARSET));
String s = getResponseAsString(conn);
return s;
}

/**
*
* @param params 请求参数
* @return 构建query
*/
public static String buildQuery(Map<String, String> params, String charset) throws UnsupportedEncodingException {
if (params == null || params.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
boolean first = true;
for (Entry<String, String> entry : params.entrySet()) {
if (first) {
sb.append("?");
first = false;
} else {
sb.append("&");
}
String key = entry.getKey();
String value = entry.getValue();
if (areNotEmpty(key, value)) {
sb.append(key).append("=").append(URLEncoder.encode(value, charset));
}
}
return sb.toString();

}

private static String getResponseAsString(HttpURLConnection conn) throws IOException {
InputStream es = conn.getErrorStream();
if (es == null) {
return getStreamAsString(conn.getInputStream(), DEFAULT_CHARSET);
} else {
String msg = getStreamAsString(es, DEFAULT_CHARSET);
if (isEmpty(msg)) {
throw new IOException(conn.getResponseCode() + " : " + conn.getResponseMessage());
} else {
throw new IOException(msg);
}
}

}

private static String getStreamAsString(InputStream input, String charset) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader bf = null;
try {
bf = new BufferedReader(new InputStreamReader(input, charset));
String str;
while ((str = bf.readLine()) != null) {
sb.append(str);
}
return sb.toString();
} finally {
if (bf != null) {
bf.close();
}
}

}

/**
* 判断字符串为空
*
* @param str 字符串信息
* @return true or false
*/
private static boolean isEmpty(String str) {
return str == null || str.trim().length() == 0;
}

/**
* 判断字符数组,不为空
*
* @param values 字符数组
* @return true or false
*/
public static boolean areNotEmpty(String... values) {
if (values == null || values.length == 0) {
return false;
}

for (String value : values) {
if (isEmpty(value)) {
return false;
}
}
return true;
}
}

Notiek ielāde…
Atcelt
Saglabāt