Java调用DLL对海关申报数据加签

链接:https://pan.baidu.com/s/1zNa42LDPdDHLJceNodZVQw
提取码:cmm5

官方文档

第一章控件使用说明

本控件以dll的方式提供,调用时需链接Sign64.dll。本控件适应于64位操作系统。

第二章接口说明

请注意以下事项:
(1)[in,out]类型的参数既为输入参数也为输出参数,在使用时必须给定参数的初始值,空间会根据该值判断调用者开辟的空间是否够大
(2)字符统一采用BYTE类型,即unsigned char,长度为UINT,即unsigned int,输出的字节流建议根据长度来取
(3)指针与缓冲区由外部调用程序做初始化

基本操作

1. 取卡号
项目说明
函数原型UINT GetCardID(BYTE* szCardID, UINT* nCardIDLen)
使用前提extern “C” _declspec(dllimport) UINT GetCardID(BYTE* szCardID, UINT* nCardIDLen)
功能简介取卡号,卡号至少分配100字节
参数说明【out】szCardID 卡号,以\0结束
【in,out】nCardIDLen 卡号长度(该参数输入时不能等于0,必须是szCardID实际开辟的空间大小)

返回值说明

返回值说明
0取卡号成功
-1卡初始化错
-2取卡号失败
2. 取证书号
项目说明
函数原型UINT GetCertNo(BYTE* szCertNo, UINT* nCertNoLen)
使用前提extern “C” _declspec(dllimport) UINT GetCertNo(BYTE* szCertNo, UINT* nCertNoLen)
功能简介取证书号,证书号至少分配100字节
参数说明【out】szCertNo 证书号,以\0结束
【in,out】nCertNoLen 证书号长度(该参数输入时不能等于0,必须是szCertNo实际开辟的空间大小)

返回值说明

返回值说明
0取证书号成功
-1卡初始化错
-2取证书号失败
3. 加签
项目说明
函数原型UINT Sign(BYTE *src, UINT srcLen, BYTE *sign, UINT signLen, const char * pwd)
使用前提extern “C” _declspec(dllimport) UINT Sign(BYTE *src, UINT srcLen, BYTE sign, UINT signLen, const char * pwd)
功能简介用加密设备传入报文进行加签
参数说明【in】src 待签名的原始数据
【in】srcLen 待签名的原始数据的长度
【out】sign 签名数据,至少分配128字节
【in,out】signLen 签名数据长度,应大于128个字节,输入时应等于szSignData实际分配的空间大小
【in】pwd 进行加签的卡密码
返回值说明
返回值说明
0签名成功
-1卡初始化错
-2卡口令不正确
-3签名失败
-4PEM编码失败

我自己的使用过程

因为我整个web程序使用的是JAVA进行开发,而官方提供的文件是DLL,那么也就意味着我需要用Java去调用DLL,听说过可以使用JNI来调用,但是看了网上的教程,都太复杂了,不太适合我这种只有很短时间用来开发的,后来又发现了一个JNI的框架,名字叫JNA,网上JNA的教程很多,我就不赘述如何使用,主要是记录下我在C++指针踩的坑。

JNA代码

因为一开始没有太理解C++中的指针,所以BYTE*我尝试过很多类型,包括char[] 、String 、byte[],结果都不行,后来使用Memory 来分配一段连续的地址,就类似C语言中的malloc函数。

这个问题倒是解决了,还有个问题是UINT*类型,我一开始想,直接给个int,应该也没啥问题,后来发现,不得行,还是的使用int指针,JNA提供了IntByReference 类表示Int指针,同时JNA还提供了很多常用的指针类型,大概是在com.sun.jna.ptr包中,有需要的可以看看。

好了,问题解决了,那么我附上代码

import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;



	public interface CLibrary extends Library {

		CLibrary INSTANCE = Native.loadLibrary("Sign64", CLibrary.class);

		/**
		 * 取卡号<br>
		 * UINT GetCardID(BYTE* szCardID, UINT* nCardIDLen)
		 * 
		 * @param szCardID
		 *            卡号,以\0结束
		 * @param nCardIDLen
		 *            卡号长度(该参数输入时不能等于0,必须是szCardID实际开辟的空间大小)
		 * @return 0 取卡号成功 -1 卡初始化错 -2 取卡号失败
		 * 
		 */
		int GetCardID(Memory szCardID, IntByReference nCardIDLen);

		/**
		 * 取证书号 <br>
		 * UINT GetCertNo(BYTE* szCertNo, UINT* nCertNoLen)
		 * 
		 * @param szCertNo
		 *            证书号,以\0结束
		 * @param nCardIDLen
		 *            证书号长度(该参数输入时不能等于0,必须是szCertNo实际开辟的空间大小)
		 * @return 0 取证书号成功 -1 卡初始化错 -2 取证书号失败
		 * 
		 */
		int GetCertNo(Memory szCertNo, IntByReference nCardIDLen);

		/**签名
		 * UINT Sign(BYTE *src, UINT srcLen, BYTE *sign, UINT* signLen, const
		 * char * pwd)
		 * 
		 * @param src
		 *            待签名的原始数据
		 * @param srcLen
		 *            待签名的原始数据的长度
		 * @param sign
		 *            签名数据,至少分配128字节
		 * @param signLen
		 *            签名数据长度,应大于128个字节,输入时应等于szSignData实际分配的空间大小
		 * @param pwd
		 *            进行加签的卡密码
		 * @return 0 签名成功 -1 卡初始化错 -2 卡口令不正确 -3 签名失败 -4 PEM编码失败
		 * 
		 */
		int Sign(String src, int srcLen, Memory sign, IntByReference signLen, String pwd);
	}

然后就是我的测试代码

	public static void main(String[] args) {

		Memory memory = new Memory(100);
		IntByReference intby = new IntByReference(100);
		System.out.println("**********************取卡号**********************");
		int getCardID = CLibrary.INSTANCE.GetCardID(memory, intby);
		System.out.println(getCardID);
		System.out.println(intby.getValue());
		System.out.println(new String(memory.getByteArray(0, intby.getValue())));

		Memory memory1 = new Memory(100);
		System.out.println("**********************取证书号**********************");
		int getCertNo = CLibrary.INSTANCE.GetCertNo(memory1, intby);
		System.out.println("获取状态:" + getCertNo);
		System.out.println(intby.getValue());
		System.out.println("证书号:" + new String(memory1.getByteArray(0, intby.getValue())));

		Memory sign = new Memory(100);
		IntByReference intbyReference = new IntByReference(100);
		String src = "testsssssss";
		System.out.println("**********************数据加签**********************");
		int sign2 = CLibrary.INSTANCE.Sign(src, src.length(), sign, intbyReference, "12345678");
		System.out.println(sign2);
		System.out.println(new String(sign.getByteArray(0, intbyReference.getValue())));

	}

Maven

	<dependency>
		<groupId>net.java.dev.jna</groupId>
		<artifactId>jna-platform</artifactId>
		<version>4.5.0</version>
	</dependency>

参考链接

写在最后

如果你跟我一样,如果是在对海关申报数据进行加签的话,那么请一定要将海关总署提供的usercard_cert64文件夹下的所有文件放到合适的位置,不然会产生错误。我一开始也是以为只需要Sign64.dll文件,其实不然,都需要。大概文件目录如下

├─paascloud-master
│ │CPUCard_Client64.dll
│ │epEportBasicApp64.dll
│ │EportSMWConfig.xml -----------------------这个xml文件也有用
│ │IKeyAPI.dll
│ │Sign64.dll
│ │SimpleICAPI.dll
│ │SPSecureAPI64.dll
│ │USBCrw.dll
│ │
│ │

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值