windows 用JAVA如何对接微信刷脸支付的SDK,附有完整流程,方法代码以及常见错误处理

1、文档序列:

1、微信支付的文档:刷脸支付文档

2、微信支付SDK模式文档:SDK模式

2、SDK了解

提供的SDK为C动态链接库dll,入口函数原型是用C语言写的,文档里是使用C# 导入DLL声明的方法来调用的。
在这里插入图片描述
在这里插入图片描述
SDK下载后的目录如下:

3、JAVA开发中如何使用

1)下载Windows SDK ,安装并加载Dll文件

现在下载的版本是v1.28.100,目录如下:
在这里插入图片描述
安装目录中的exe文件,安装后会产生一个“刷脸应用”的快捷方式,在调用SDK前需要双击启用;
在这里插入图片描述

在下载目录,\SDK\x86\lib或者\SDK\x64\lib目录下,找到符合自己windows设备下的WxpayFaceSDK.dll文件放到C:\Windows\System32目录下,或者是放到自己的JDK安装的bin目录下;这样才可以在JAVA代码运行的时候找到并加载
在这里插入图片描述
在这里插入图片描述
以上方式二选一即可

2)查询windows设备的序列号,复制为serial.txt文件放到C盘

我的电脑上是win11,找到序列号的方式:>

打开“注册表编辑”:
“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform”,点击最后一个 SoftwareProtectionPlatform 文件夹,然后在右侧的界面中找到“BackupProductKeyDefault”文件,在文件的后方数据一栏就可以看见 Windows 11 产品密钥

3)JAVA使用JNA动态加载dll文件并实现调用

Java中加载DLL动态链接库,主要是JNI【Java官方提供的一种机制,允许Java代码调用其他语言编写的本地代码】、JNA【一种更简便的Java调用本地库的方式,无需编写额外的C/C++代码】

dll中的代码是这样的:
在这里插入图片描述

(1)加载dll动态链路,java中需要使用到JNA,在pom.xml中加载依赖

那我肯定使用更简便的方式,使用JNA调用DLL的步骤如下:

 <!--添加JNA库-->
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
            <version>5.5.0</version>
        </dependency>

(2)定义接口:创建一个继承自 com.sun.jna.Library 的接口,描述DLL中的方法
在这里插入图片描述
注意:加载的“WxpayFaceSDK”名字要与复制到C:\Windows\System32目录下或JDK安装bin目录下的WxpayFaceSDK.dll文件的名称一致

描述DLL中的方法代码:

public interface WxpayFaceSDK extends Library {

    WxpayFaceSDK INSTANCE = (WxpayFaceSDK) Native.load("WxpayFaceSDK", WxpayFaceSDK.class);


    /**
     * 调用人脸服务
     *  注意:这里的方法签名需要与DLL中的C函数签名一致
     *  req和resp都是JSON字符串,需要转换为Pointer类型
     *  char * -->String; char ** -->String[]
     *  int -->int; int* --> IntByReference
     * @param reqBuf 	请求参数(JSON字符串)
     * @param reqSize 	请求参数长度
     * @param pRespBuf	用来接收响应结果(JSON字符串)的char**指针
     * @param pRespSize 用来接收响应结果长度的unsigned int*指针
     * @return 如果成功返回0,失败则返回非0
     */ 
    //int wxpayCallFaceService(String reqBuf, int reqSize, String[] pRespBuf, IntByReference pRespSize);
    int wxpayCallFaceService(String reqBuf, int reqSize, long[] pRespBuf, int[] pRespSize);


    /**
     *  char ** -->String[]
     * 释放人脸服务的响应字符串,调用wxpayCallFaceService成功后务必调用此函数释放内存
     * @param pRespBuf	指向响应结果(JSON字符串)的指针
     */
    void wxpayReleaseResponse(String[] pRespBuf);
}

我在这里卡了很久,主要的问题就是参数类型的设置与dll中的对接不上,具体内容可以去看官网
在这里插入图片描述
我一开始的wxpayCallFaceService方法使用的注释掉使用String[]类型接收返回值,但返回值里一直是null值,后来想到返回值可能是一个内存地址,才改用了long[],试了很多种方法才试通。

(2)定义接口:组装出请求数据,接收数据来调用SDK。代码如下

 /**
     * 调用微信刷脸服务
     * @param reqJson 请求数据
     * @param respJson 响应数据
     * @return
     */
    @Override
    public String callWxpayFaceService(String reqJson, List<String> respJson)  {
        //组装请求数据
        Pointer reqPointer = new Memory(reqJson.length() + 1);
        reqPointer.setString(0, reqJson);
        //请求数据长度
        int reqSize = reqPointer.getString(0).length();
        System.out.println("-----------调用微信刷脸请求数据----------"+reqPointer.getString(0));

        //接收响应
        long[] pRespBuf = new long[1];
        int[]  respSize = new int[1];
        String resStr = new String();

        // 调用本地方法
        int result = WxpayFaceSDK.INSTANCE.wxpayCallFaceService(reqPointer.getString(0), reqSize, pRespBuf, respSize);
        if (result == 0) {
            Pointer pointer = new Pointer(pRespBuf[0]);
            byte[] byteArray = pointer.getByteArray(0, respSize[0]);
            resStr = new String(byteArray, StandardCharsets.UTF_8);

            System.out.println("-----------调用人脸服务成功结果: " + resStr);
            //释放
            WxpayFaceSDK.INSTANCE.wxpayReleaseResponse(new String[2]);
        } else {
            Pointer pointer = new Pointer(pRespBuf[0]);
            byte[] byteArray = pointer.getByteArray(0, respSize[0]);
            resStr = new String(byteArray, StandardCharsets.UTF_8);
            System.err.println("-----------调用人脸服务失败: " +resStr);
        }
        return resStr;
    }

(3)调用接口

定义了一个实体来定义请求体,名为WxFacePayReq
在这里插入图片描述
在这里插入图片描述

定义一个实体来接收详响应,名为WxFacePayResp
在这里插入图片描述

在这里插入图片描述

定义具体调用方法:使用jackson方式处理JSON数据与实体之间的转换

   public WxFacePayResp doWxPayMethod(WxFacePayReq wxFacePayReq) throws JsonProcessingException {
        // 构建请求参数的JSON字符串
        ObjectMapper mapper = new ObjectMapper();
        String req = mapper.writeValueAsString(wxFacePayReq);

        // 创建一个Pointer来接收响应
        List<String> pResp= new ArrayList<>();
        String result = this.callWxpayFaceService(req,pResp);

        //响应结果
        WxFacePayResp wxFacePayResp = mapper.readValue(result, WxFacePayResp.class);
        return  wxFacePayResp;
    }

(4)调用测试

1、程序启动时初始化 initWxpayface
文档:初始化

官网示例
在这里插入图片描述
实际调用
在这里插入图片描述
2、获取数据 getWxpayfaceRawdata
文档:获取数据

官网示例
在这里插入图片描述
实际调用
在这里插入图片描述

extern "C" int wxpayCallFaceService(const char *reqBuf, unsigned int reqSize, char **pRespBuf, unsigned int *pRespSize);

(5)常见错误记录

我在调dll的WxpayFaceSDK中的wxpayCallFaceService方法的时候遇到很多问题;主要是
(1)报错:

Error occurred during initialization of VM
Unable to load native library: Can’t load this .dll (machine code=0x0) on a AMD 64-bit platform

原因:项目JDK版本与module版本不一致
处理方法:修改项目module的JDK版本与项目版本一致

(2)报错:Invalid memory access
原因:dll加载失败;数据类型不对应:

char * -->String; char ** -->String[]
int -->int; int* --> IntByReference

(3)不报错但是返回-1失败,却不知道原因,查了之后发现是int*类型不可以使用int,改成IntByReference后成功;改之后返回0

(4)返回值为空值,然后考虑到可能的是内存地址,把返回值改为 long[] pRespBuf, int[] pRespSize,然后将long类型的地址转换为字符串

Pointer pointer = new Pointer(pRespBuf[0]);
byte[] byteArray = pointer.getByteArray(0, respSize[0]);
resStr = new String(byteArray, StandardCharsets.UTF_8);

以上就是我的使用过程啦,因为之前没有对接过,中间遇到了很多问题,也发现网上很少能找到能参考的文章,于是记录下来为大家提供一点点参考。

如果记录中有什么问题的话,欢迎在评论中提出来共同交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值