美文网首页
java人行超网加签验签代码

java人行超网加签验签代码

作者: dinel | 来源:发表于2020-08-11 22:08 被阅读0次
package com.kayak.trade.api.branch.util;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.druid.util.StringUtils;
import com.kayak.gray.api.exception.BizException;
import com.kayak.gray.api.options.Options;
import com.kayak.trade.api.branch.annotation.SignatureAnotation_15;
import com.kayak.trade.api.branch.annotation.SignatureAnotation_16;
import com.kayak.trade.api.branch.annotation.SignatureClassAnotation;
import com.kayak.trade.api.branch.annotation.SignatureResultAnotation;
import com.kayak.trade.api.branch.code.IbpsBizErrorCode;
import com.union.dsignApi.UnionCertAppAPI;
import com.union.dsignApi.UnionCertInfo;

/**   
 * @ClassName:  AutographUtil   
 * @Description: 对ibps报文进行加签及解签
 * @author: qiran
 * @date:   2018年7月13日 下午9:01:09   
 * 方法说明:1.getSignatureComnons 
 *          作用: 初始化加签规则
 *          2.sign
 *          作用: 加签
 *          3.relieveSign
 *          作用:验签
 *          4.unionAppUpdateCert
 *          作用 :更新证书
 * 
 * 重点说明: 该工具类 只支持 1层list加签验签处理,多层集合需要自主调用加签验签类自行处理
 *  
 */
public class SignatureUtil {
    
    private static final Logger log = LoggerFactory.getLogger(SignatureUtil.class);
    
    protected static  Options options = new Options();
    /**
     * 加签解签类  同包及私有类能够访问
     */
    protected static UnionCertAppAPI   UNION_CERTAPP_API= null;

    /**
     * 加签解签规则 1.5版本
     */
    public  static  final Map<Class<?>,Map<Integer,Field>>  SIGNATURE_CACHE_15 = new ConcurrentHashMap<>();
    
    /**
     * 加签解签规则 1.6版本
     */
    public  static  final Map<Class<?>,Map<Integer,Field>>  SIGNATURE_CACHE_16 = new ConcurrentHashMap<>();
    /**
     * 加签结果参数
     */
    private static Map<Class<?>,Field > SignatureResultCache = new ConcurrentHashMap<>();
    
    /**
     * 裸签加签类  所有包都可以访问  该对象需要以参数传递给  SignatureUtil.sign( bean,unionAppRawSign)
     */
    public  static  final UnionAppRawSign  UNION_APPRAW_SIGN = new UnionAppRawSign();
    
    /**
     * 裸签验签方法  所有包都可以访问   该对象需要以参数传递给  SignatureUtil.relieveSign( bean,UnionAppRawVerify)
     */
    public static final UnionAppRawVerify  UNION_APPRAW_VERIFY= new UnionAppRawVerify();
    
    /**
     * PKCS7签名 加签类 所有包都可以访问 该对象需要以参数传递给  SignatureUtil.sign( bean,unionAppDetachedSign)
     *  作废说明: 由于初始设计 与实际不符  注释该静态类  不外放使用 
     */
    
    public static final UnionAppDetachedSign  UNION_APPDETACHED_SIGN = new UnionAppDetachedSign();

    /**
     * PKCS7签名  所有包都可以访问 该对象需要以参数传递给  SignatureUtil.relieveSign( bean,UnionAppRawVerify)
     * 作废说明: 由于初始设计 与实际不符  注释该静态类  不外放使用 
     */
    //public static final UnionAppDetachedVerify  UNION_APPDETACHED_VERIFY = new UnionAppDetachedVerify();

    public static boolean  signFlag= true;
    static {

        /**
         * 1.读取加签服务器配置文件
         *     用于初始化加签API
         */
        //UNION_CERTAPP_API = new UnionCertAppAPI("conf"+File.separator+"sys"+File.separator+"srj1401Hsm.conf");
        
        //由于加签服务器 目前不支持上面的方式 先使用ip 端口方式访问
        //UNION_CERTAPP_API = new UnionCertAppAPI("21.129.12.2",1818, 0);
        log.info("初始化加签配置文件成功!");
        try {
            
            /**
             * 2.读取加签方式配置文件
             *   用于配置加签方式
             *   注意 :读取的是当前项目的配置 并非 kayak-trade-base
             */
            options.load(new File("conf"+File.separator+"sys"+File.separator+"sign.conf"));
            signFlag =options.get("sign.test");
            
            UNION_CERTAPP_API = new UnionCertAppAPI();
        } catch (Exception e) {
            log.error("读取加签验签异常,请确认配置文件是否存在:",e);
        }
    }
    
    /**   
     * @MethodName: getSignatureComnons
     * @Description:  对加签的bean 参数加签规则进行初始化
     * @param T clazz 需要被加签的bean
     *        Map<Class<?>,Map<Integer,Field>>  signAtureMap  传入的保存加签规则的静态Map 内中保存加签规则
     *                                                          固定为  SignatureUtil.SIGNATURE_CACHE_15   超网 1.5版本
     *                                                              SignatureUtil.SIGNATURE_CACHE_16   超网1.6版本
     *       annotaion 加签参数的实际注解    SignatureAnotation_15.class   超网 1.5版本
     *                                      SignatureAnotation_16.class      超网 1.6版本
     *                  annotaion 与 signAtureMap 为 一对一关系 如 增加 annotaion 需要在 SignatureUtil 增加 静态 Map保存 加签规则
     *                  annotaion  中必须实现 index() ,nameSpace() 方法
     *      SignatureClassAnotation  加签类 内部写死
     *      SignatureResultAnotation 加签结果参数  注解写死
     *      SignatureResultCache 加签结果Map 此处同一个Class 只能由一个加签结果参数
     *      
     * @author: qiran
     * @date:   2018年7月3日 下午3:24:19   
     * 调用者  beanToSignString  (T t,Map<Class<?>,Map<Integer,Field>> signAtureMap, Class< ? extends Annotation>  annotaion)
     */
    private static <T>  void getSignatureComnons(T t,Map<Class<?>,Map<Integer,Field>>  signAtureMap, Class< ? extends Annotation>  annotaion) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{ 
        

        if(signAtureMap.get(t.getClass())==null){
            
            log.info("初始化加签规则类 : {}   注解标识:{} ",t.getClass(),annotaion.getName());
            //判断类是否需要加签 不需要加签直接返回
            SignatureClassAnotation signatureClassAnotation= t.getClass().getDeclaredAnnotation(SignatureClassAnotation.class);
            
            //考虑性能 增加类注解 判断是否循环 类变量
            if(signatureClassAnotation == null){
                return;
            }
            
            //循环所有参数查询加签解签参数
            Field[]  fields= t.getClass().getDeclaredFields();
            Map<Integer,Field> map = new HashMap<Integer,Field>(18);
            for(Field field :fields){
                Annotation   signatureAnotation = field.getDeclaredAnnotation(annotaion);
                
                if(signatureAnotation!=null){
                    
                    //如果参数为集合 循环子类查询 加签参数  将子类重新定义加签规则
                    if(field.getType().isAssignableFrom(java.util.List.class)){

                        ParameterizedType parameterizedTypeSon = (ParameterizedType)field.getGenericType();
                        @SuppressWarnings("rawtypes")
                        Class clazzSon = (Class)parameterizedTypeSon.getActualTypeArguments()[0];
                        Field[] fieldSons =  clazzSon.getDeclaredFields();
                        
                        Map<Integer,Field> mapSon = new HashMap<Integer,Field>(18);
                        for(Field fieldSon :fieldSons){
                        
                            Annotation signatureAnotationSon = fieldSon.getDeclaredAnnotation(annotaion);
                            if(signatureAnotationSon!=null){
                                
                                mapSon.put((Integer) signatureAnotationSon.annotationType().getMethod("index").invoke(signatureAnotationSon),fieldSon);
                            }
                        }
                        signAtureMap.put((Class<?>) parameterizedTypeSon.getActualTypeArguments()[0], mapSon);
                    
                    }
                    
                    //保存加签解签参数
                    map.put((Integer) signatureAnotation.annotationType().getMethod("index").invoke(signatureAnotation),field);

                }
                //保存加签结果参数
                SignatureResultAnotation signatureResultAnotation = field.getDeclaredAnnotation(SignatureResultAnotation.class);
                if(signatureResultAnotation!=null){
                    SignatureResultCache.put(t.getClass(),field);
                }
            }
            signAtureMap.put(t.getClass(), map);
        }else{
            log.info("加签类规则已初始化无需初始化 : {}  注解标识:{} ",t.getClass(),annotaion.getName());
        }
    }
    
    /**   
     * @MethodName: beanToSignString
     * @Description:   对bean 中参数进行解析获取对应的加签字符串  并初始化加签规则    以及加签结果参数初始化
     * @param T clazz 需要被加签的bean
     *        Map<Class<?>,Map<Integer,Field>>  signAtureMap  传入的保存加签规则的静态Map 内中保存加签规则
     *                                                          固定为  SignatureUtil.SIGNATURE_CACHE_15   超网 1.5版本
     *                                                              SignatureUtil.SIGNATURE_CACHE_16   超网1.6版本
     *       annotaion 加签参数的实际注解    SignatureAnotation_15.class   超网 1.5版本
     *                                      SignatureAnotation_16.class      超网 1.6版本
     *                  annotaion 与 signAtureMap 为 一对一关系 如 增加 annotaion 需要在 SignatureUtil 增加 静态 Map保存 加签规则
     *                  annotaion  中必须实现 index() ,nameSpace() 方法
     *      
     * @author: qiran
     * @date:   2018年7月3日 下午3:24:19  
     * @调用者   1.sign15(T t,Function<byte[],String> fun)  超网1.5加签版本
     *        2.sign16(T t,Function<byte[],String> fun)  超网1.6加签版本
     *        3.relieveSign15(T t,Function<Map<String,Object>,Integer> fun) 超网1.5验签版本
     *        4.relieveSign16(T t,Function<Map<String,Object>,Integer> fun) 超网1.6验签版本
     *           或者  beanToSignString (T t, SignatureUtil 中新增的保存加签规则的Map, 自定义的 Annotation)  
     *          之后调用        SignatureUtil.UNION_APPRAW_SIGN.apply("".getBytes());   自定义 裸加签
     *                          SignatureUtil.UNION_APPRAW_VERIFY.apply(msg,signedData);  自定义 裸验签
     *                          SignatureUtil.UNION_APPDETACHED_SIGN.apply("".getBytes()); 自定义 证书加签
     *                          SignatureUtil.UNION_APPDETACHED_VERIFY.apply(msg,signedData);  自定义 证书验签
     * 
     */
    public static <T>  String  beanToSignString(T t,Map<Class<?>,Map<Integer,Field>> signAtureMap, Class< ? extends Annotation>  annotaion) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{ 

        //1.初始化加签规则方法
        getSignatureComnons(t,signAtureMap,annotaion);
        
        //2.获取加签的规则
        Map<Integer,Field> mapSignature = signAtureMap.get(t.getClass());

        //如果没有加签直接返回
        if(mapSignature==null||mapSignature.size()<=0){
            return null;
        }
        
        log.info("开始拼装加签串...");
        StringBuffer sb = new StringBuffer();
        //3.根据加签规则进行加签
        for (int i = 0; i < mapSignature.size(); i++) {
            
            Field field = mapSignature.get(i);
            field.setAccessible(true);
            
            //3.1 判断类中参数是否为集合形式
            if(field.getType().isAssignableFrom(java.util.List.class)){
                
                ParameterizedType parameterizedTypeSon = (ParameterizedType)field.getGenericType();
                
                //获取list的泛型类并 获取对应的加签规则
                List<?> objSons = (List<?>) field.get(t);
                Map<Integer,Field> mapSignatureSon = signAtureMap.get((Class<?>)parameterizedTypeSon.getActualTypeArguments()[0]);
                
                if(objSons!=null){
                //3.2 对类中存在的集合进行加签处理      以list的size进行处理
                    for(Object obj: objSons){
                        for (int j = 0; j < mapSignatureSon.size(); j++) {
                            Field fieldSon = mapSignatureSon.get(j);
                            fieldSon.setAccessible(true);
                            
                            //3.3 如果集合中参数 不为空才进行加签
                            if(fieldSon.get(obj)!=null&&!"".equals(fieldSon.get(obj).toString())){
                                
                                //为解决金额加签问题 追加命名空间
                                Annotation signatureAnotation= fieldSon.getAnnotation(annotaion);
                                
                                // 处理币种 也可以在前面添加其他内容
                                sb.append(signatureAnotation.annotationType().getMethod("nameSpace").invoke(signatureAnotation));
                                //组装加签串
                                String signature = fieldSon.get(obj).toString();
                                sb.append(signature);
    
                                sb.append("|");
                            }
                        }
                    }
                }
                
            //3.4 判断类中参数是否为集合形式
            }else{
                //3.5 如果集合中参数 不为空才进行加签
                if(field.get(t)!=null&&!"".equals(field.get(t).toString())){
                    
                    //为解决金额加签问题 追加命名空间
                    Annotation signatureAnotation = field.getAnnotation(annotaion);
                                    
                    //处理币种 也可以在前面添加其他内容
                    sb.append(signatureAnotation.annotationType().getMethod("nameSpace").invoke(signatureAnotation));
                    
                    //组装加签串
                    String signature = field.get(t).toString();
                    sb.append(signature);
                    //币种
                    sb.append("|");
                }
            }
        }
        log.info("加签串拼装结果为:[{}]", sb.toString());
        return sb.toString();
    }
    
    
    /**   
     * @MethodName: addSignature
     * @Description:  对业务流转的bean加签参数进行加签 1.5 版本 该方法会读取bean中 SignatureAnotation_15的注解
     * @param T clazz 需要被加签的bean Function fun 
     * @return T 加签结果bean
     * @author: qiran
     * @throws SecurityException 
     * @throws NoSuchFieldException 
     * @throws NoSuchMethodException 
     * @throws InvocationTargetException 
     * @throws BizException 
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public static <T> T sign15(T t,Function<byte[],String> fun) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InvocationTargetException, NoSuchMethodException, BizException{
        
        //1.根据加签规则 获取需验签的字符串  bean中1.5版本的注解
        String msg= beanToSignString(t,SIGNATURE_CACHE_15,SignatureAnotation_15.class);
        
        if(msg == null){
            log.info("该接口无需加签,未做加签操作!");
            return null;
        }
        
        //4.调用加签接口进行加签操作
        String unionAppRawSign = null;
        try {
            unionAppRawSign = fun.apply(msg.getBytes());
        } catch (Exception e) {
            log.error("加签出错,出错原因为:{}", e);
            throw new BizException(IbpsBizErrorCode.BR400001_加签失败,"加签失败,失败原因为:["+ e.getMessage() + "]");
        }
        
        log.info("加签成功,加签结果为:[{}]", unionAppRawSign);
        
        //5.将加签结果参数添加值
        Field fieldResult = SignatureResultCache.get(t.getClass());
        fieldResult.setAccessible(true);
        fieldResult.set(t, unionAppRawSign);
        
        return t;
    }
    
    /**   
     * @MethodName: addSignature
     * @Description:  对业务流转的bean加签参数进行加签 1.6 版本 该方法会读取bean中 SignatureAnotation_16的注解
     * @param T clazz 需要被加签的bean Function fun 
     * @return T 加签结果bean
     * @author: qiran
     * @throws SecurityException 
     * @throws NoSuchFieldException 
     * @throws NoSuchMethodException 
     * @throws InvocationTargetException 
     * @throws BizException 
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public static <T> T sign16(T t,Function<byte[],String> fun) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, InvocationTargetException, NoSuchMethodException, BizException{
        
        //1.根据加签规则 获取需验签的字符串  bean中1.5版本的注解
        String msg= beanToSignString(t,SIGNATURE_CACHE_16,SignatureAnotation_16.class);
        
        if(msg == null){
            log.info("该接口无需加签,未做加签操作!");
            return null;
        }
        
        //4.调用加签接口进行加签操作
        String unionAppRawSign = null;
        try {
            unionAppRawSign = fun.apply(msg.getBytes());
        } catch (Exception e) {
            log.error("加签出错,出错原因为:{}", e);
            throw new BizException(IbpsBizErrorCode.BR400001_加签失败,"加签失败,失败原因为:["+ e.getMessage() + "]");
        }
        
        log.info("加签成功,加签结果为:[{}]", unionAppRawSign);
        
        //5.将加签结果参数添加值
        Field fieldResult = SignatureResultCache.get(t.getClass());
        fieldResult.setAccessible(true);
        fieldResult.set(t, unionAppRawSign);
        
        return t;
    }
    
    /**   
     * @MethodName: signString
     * @Description:  对传入参数参数进行加签  
     * @param T clazz 需要被加签的bean Function fun 
     * @return String 加签结果
     * @author: qiran
     * @throws BizException 
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public static String signString(String signMsg,Function<byte[],String> fun) throws  BizException{
        
        log.info("加签串内容 :[{}]",signMsg);
        if(StringUtils.isEmpty(signMsg)){
            log.info("加签字符串为空,无需加签!");
            return null;
        }
        
        //调用加签接口进行加签操作
        String unionAppRawSign = null;
        try {
            unionAppRawSign = fun.apply(signMsg.getBytes());
        } catch (Exception e) {
            log.error("加签出错,出错原因为:{}", e);
            throw new BizException(IbpsBizErrorCode.BR400001_加签失败,"加签失败,失败原因为:["+ e.getMessage() + "]");
        }
        
        log.info("加签成功,加签结果为:[{}]", unionAppRawSign);
        
        //5.将加签结果返回
        return unionAppRawSign;
        
    }
    
    /**   
     *  
     * @MethodName: addSignature
     * @Description:  对业务流转的bean加签参数进行加签  该方法会读取bean中 SignatureAnotation_15的注解
     * @param T clazz 需要被加签的bean
     * @return T 加签结果bean
     * @author: qiran
     * @throws BizException 
     * @throws SecurityException 
     * @throws NoSuchMethodException 
     * @throws InvocationTargetException 
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public static <T> boolean relieveSign15(T t,Function<Map<String,Object>,Integer> fun,String bankId) throws IllegalArgumentException, IllegalAccessException, BizException, InvocationTargetException, NoSuchMethodException, SecurityException {
        
        //1.根据加签规则 获取需验签的字符串  bean中1.5版本的注解
        String msg= beanToSignString(t,SIGNATURE_CACHE_15,SignatureAnotation_15.class);

        if(msg == null){
            log.info("该接口无需验签,无需进行验签操作!");
            return true;
        }
        
//      if(!signFlag){
//          log.debug("----------验签开关关闭,无需验签------------");
//          return true;
//      }
        
        //5.将加签结果参数添加值
        Field fieldResult = SignatureResultCache.get(t.getClass());
        fieldResult.setAccessible(true);
        String signedData =fieldResult.get(t).toString();
        
        Map<String,Object> map =new HashMap<String,Object>(18);
        map.put("signedData", signedData);
        map.put("msg", msg);
        map.put("bankId", bankId);
        log.info("验签直参行行号为:[{}]",bankId);
        log.info("验签加签结果为:[{}]", signedData);
        Integer signatureResult =  fun.apply(map);
    
        log.info("验签返回结果为:[{}]!",signatureResult);
        
        if(signatureResult!=0){
            
            if(signFlag){
                
                log.error("超网1.6接口版本报文验签失败!");
                throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"参数验签错误" );
            }else{
                log.info("----------验签开关关闭,无需验签------------");
                return true;
            }
        }else{
            log.info("[超网1.5接口版本报文验签成功]");
        }
        
        return true;
    }

    /**   
     * 
     * @MethodName: addSignature
     * @Description:  对业务流转的bean加签参数进行加签   该方法会读取bean中 SignatureAnotation_16的注解
     * @param T clazz 需要被加签的bean
     * @return T 加签结果bean
     * @author: qiran
     * @throws BizException 
     * @throws SecurityException 
     * @throws NoSuchMethodException 
     * @throws InvocationTargetException 
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public static <T> boolean relieveSign16(T t,Function<Map<String,Object>,Integer> fun,String bankId) throws IllegalArgumentException, IllegalAccessException, BizException, InvocationTargetException, NoSuchMethodException, SecurityException {
        
        //1.根据加签规则 获取需验签的字符串  bean中1.6版本的注解
        String msg= beanToSignString(t,SIGNATURE_CACHE_16,SignatureAnotation_16.class);
        
        if(msg == null){
            log.info("该接口无需验签,无需进行验签操作!");
            return true;
        }
        
//      if(!signFlag){
//          log.info("----------验签开关关闭,无需验签------------");
//          return true;
//      }
        
        //2.将加签结果参数添加值
        Field fieldResult = SignatureResultCache.get(t.getClass());
        fieldResult.setAccessible(true);
        String signedData =fieldResult.get(t).toString();
        
        Map<String,Object> map =new HashMap<String,Object>(18);
        map.put("signedData", signedData);
        map.put("msg", msg);
        map.put("bankId", bankId);
        log.info("验签直参行行号为:[{}]",bankId);
        log.info("验签加签结果为:[{}]", signedData);
        Integer signatureResult =  fun.apply(map);
        log.info("验签返回结果为:[{}]",signatureResult);
        
        if(signatureResult!=0){
            
            if(signFlag){
                
                log.error("超网1.6接口版本报文验签失败!");
                throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"参数验签错误" );
            }else{
                log.info("----------验签开关关闭,无需验签------------");
                return true;
            }

        }else{
            log.info("[超网1.6接口版本报文验签成功]");
        }
        
        return true;
    }

    /**   
     *  
     * @MethodName: relieveSignString
     * @Description:  对 参数进行 验签
     * @param signMsg 待验签 的拼接字符串结果
     *          fun   验签方法
     *          bankId 发送行行号
     *          signedData 对手方发送的加签串
     * @return  boolean 验签结果
     * @author: qiran
     * @throws BizException 
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public static  boolean relieveSignString(String signMsg,Function<Map<String,Object>,Integer> fun,
                                    String bankId,String signedData) throws BizException {
        
//      if(!signFlag){
//          log.info("----------验签开关关闭,无需验签------------");
//          return true;
//      }
        
        if(StringUtils.isEmpty(signMsg)){
            log.info("验签字符串为空,无需验签!");
            return true;
        }
        
        log.info("验签字符串:[{}]",signMsg);
        log.info("验签直参行行号:[{}]",bankId);
        Map<String,Object> map =new HashMap<String,Object>(18);
        map.put("signedData", signedData);
        map.put("msg", signMsg);
        map.put("bankId", bankId);
        Integer signatureResult =  fun.apply(map);
        log.info("验签返回结果为:[{}]",signatureResult);
        
        //验签返回不为0 并且 验签开关为 true   false 不进行验签  
        if(signatureResult!=0){
            
            if(signFlag){
                
                log.error("超网1.6接口版本报文验签失败!");
                throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"参数验签错误" );
            }else{
                log.info("----------验签开关关闭,无需验签------------");
                return true;
            }
        }else{
            log.info("[报文验签成功]");
        }
        
        return true;
    }
    
    /**   
     * @MethodName: unionAppUpdateCert
     * @Description:  对他行证书进行上传
     * @param  bankId: 对手行行号
     *          cert:公钥证书(base64格式)
     * @return 返回参数值:false 上传失败  true  上传成功
     * @author: qiran
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public static boolean unionAppUpdateCert(String bankId, String cert){

        String appName = SignatureUtil.options.get("unionAppRawVerify.appId")+bankId+SignatureUtil.options.get("unionAppRawVerify.appVer");
        log.info("开始将公钥证书上传至加签服务器 appName:[{}]",appName);
        int result = UNION_CERTAPP_API.UnionAppUpdateCert(appName,cert);
        if(result!=0){
            log.info("公钥证书上传失败,错误码为:[]", result);
            return false;
        }else{
            log.info("[公钥证书上传成功]");
            return true;
        }
        
    }
    
    /**   
     * @MethodName: UnionAppDetachedVerify
     * @Description:  证书验签
     * @param  T t 需要 证书验签的bean 
     * @return String Base64Cert 加签服务器对手行的公钥信息
     * @author: qiran 
     * @date:   2018年7月3日 下午3:24:19   
     *   
     */
    public  static <T> String  UnionAppDetachedVerify(T t) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException, BizException{
        
        String msg= beanToSignString(t,SIGNATURE_CACHE_15,SignatureAnotation_15.class);

        if(msg == null){
            log.info("该接口无需验签,无需进行验签操作!");
            return null;
        }
        
        //5.将加签结果参数添加值
        Field fieldResult = SignatureResultCache.get(t.getClass());
        fieldResult.setAccessible(true);
        String signedData =fieldResult.get(t).toString();
        
        UnionCertInfo unionCertInfo = SignatureUtil.UNION_CERTAPP_API.UnionAppDetachedVerify(msg.getBytes(),signedData);
        
        //由于 调用方法 以 0为成功 方法 所以 此处修改为返回0
        if(unionCertInfo==null){
            log.error("903证书验签错误!");
            //throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"903证书验签错误");
        }
        if(StringUtils.isEmpty(unionCertInfo.getBase64Cert())){
            log.error("903证书验签错误,未获取到公钥信息!");
        //  throw new BizException(IbpsBizErrorCode.BR999999_验签失败,"903证书验签错误,未获取到公钥信息!");
        }
        String  Base64Cert= unionCertInfo.getBase64Cert();
        
        log.info("证书 Ser_number : "+unionCertInfo.getSer_number());
        log.info("证书 Base64Cert : "+unionCertInfo.getBase64Cert());
        log.info("证书验签已成功 ");
        return Base64Cert;
    }
    
    public static void main(String[] args) throws Exception {
        
        String signedData = "MEYCIQDn4x0W0iReQNNkiuHgxvxGbAU91MNUpmXeLKi8r3PijgIhAJDF9kbVuyLA+nU/L/rI7HpKML4etrkRSBWofCsYkMnW";
        String signMsg = "0000000000012018110815073363|2018-11-08T17:38:40|0000|323241000016|323241000016|3232410000162018110800026420|ibps.101.001.01|PR09|IB1O4001|2018-11-08|";
        String bankId = "313770000016";
        Map<String,Object> map =new HashMap<String,Object>(18);
        map.put("signedData", signedData);
        map.put("msg", signMsg);
        map.put("bankId", bankId);
        Integer signatureResult =  UNION_APPRAW_VERIFY.apply(map);
        System.out.println("验签返回结果为:" + signatureResult);
        if(signatureResult!=0){
            System.out.println("报文验签失败!");
        }else{
            System.out.println("[报文验签成功]");
        }
        
//      Ibps805Model model = new Ibps805Model();
//      
//      model.setMsgid("3232410000162018072459718890");
//      model.setCreDtTm("2018-07-24T19:33:21");
//      model.setSendBank("323241000016");
//      model.setRecvBank("0000");
//      model.setOperationType("OT00");
//      
//      UNION_CERTAPP_API = new UnionCertAppAPI("21.129.12.2",1818, 0);
//      
//      System.out.println("裸签加签前:"+model.toString());
//      SignatureUtil.sign(model,SignatureUtil.UNION_APPRAW_SIGN);
//      System.out.println("裸签加签后:"+model.toString());
////        
//      Ibps805Model model = new Ibps805Model();
//      
//      model.setMsgid("11");
//      model.setCreDtTm("22");
//      model.setSendBank("333");
//      model.setRecvBank("444");
//      model.setSysCd("555");
//      model.setOperationType("666");
//      model.setPmcCode("888");

//      sign15(model, SignatureUtil.UNION_APPRAW_SIGN);
//      UnionCertAppAPI UNION_CERTAPP_API = new UnionCertAppAPI("conf"+File.separator+"sys"+File.separator+"srj1401Hsm.conf");
//      
//      UNION_CERTAPP_API = new UnionCertAppAPI("21.129.12.3",22308, 0);
//      System.out.println("加签结果"+UNION_CERTAPP_API.UnionAppRawSign("11|22|333|444|555|666|".getBytes(),2,"PMS.323241000016.2"));
//
////        
//      
//      relieveSign16(model,UNION_APPRAW_VERIFY);
//      
//      SignatureUtil.relieveSign(model,SignatureUtil.UNION_APPRAW_VERIFY);
//      
//      System.out.println("裸签验签通过");
//      
//      
//      Ibps311Model model2 = new   Ibps311Model();
//      
//      model2.setMsgid("111111");
//      
//      model2.setCreDtTm("22222");
//      
//      model2.setInstgPty("3333");
//      
//      model2.setInstdPty("4444");
//      
//      model2.setPtcId("55555");
//      
//      System.out.println("证书签加签前 :"+model2.toString());
//      
//      // 证书 解签未过
//      SignatureUtil.sign15(model2,SignatureUtil.UNION_APPRAW_SIGN);
//      System.out.println("证书签加签后 :"+model2.toString());
//      
//      SignatureUtil.relieveSign(model2,SignatureUtil.UNION_APPDETACHED_VERIFY);
//      
//      System.out.println("证书签验签通过");
//      try {
//          UnionCertAppAPI unionCertAppAPI =  new UnionCertAppAPI("conf"+File.separator+"sys"+File.separator+"srj1401Hsm.conf");
//           String str = "11";
//           System.out.println(str);
//           unionCertAppAPI.initCertAppContext();
//
//           String str2 = unionCertAppAPI.UnionAppRawSign(str.getBytes(),2 ,"PMS.323241000016.2");
//           
//           System.out.println(str2);
//           System.out.println("测试结果 :"+str2);
//      } catch (Exception e) {
//          //  handle exception
//          e.printStackTrace();
//      }
         
    //  String appName = SignatureUtil.options.get("unionAppRawVerify.appId")+"3232100006"+SignatureUtil.options.get("unionAppRawVerify.appVer");
         
    //  UnionCertInfo unionCertInfo=UNION_CERTAPP_API.UnionAppDetachedVerify("111".getBytes(),"111");
    //  System.out.println(UNION_CERTAPP_API.getErrorCode());
    //  System.out.println(UNION_CERTAPP_API.getErrorMessage());
    //  System.out.println(appName);
        
    }
}


/**   
 * @ClassName:  UnionAppRawSign   
 * @Description: 普通裸签类
 * @author: qiran
 * @date:   2018年7月13日 下午9:01:09   
 *   
 */
class UnionAppRawSign implements Function<byte[],String>{
    private static final Logger log = LoggerFactory.getLogger(UnionAppRawSign.class);
    /**
     *    UnionAppRawSign(byte[] msg,int iAlgorithm,String appName);
     *    参数1: msg 待签名 数据原文
     *   参数2: iAlgorithm 摘要算法1 表示SHA1, 2 表示SM3, 256表示SHA256,512表示SHA512
     *   参数3: appName:证书应用名称,命名需遵循规则appID.bankID.ver, appID为    应用标识,bankID为机构标识, ver为版本号
     *   返回值: 加签结果
     */
    @Override
    public String apply(byte[] t) {
        String result = SignatureUtil.UNION_CERTAPP_API.UnionAppRawSign(t,SignatureUtil.options.get("unionAppRawSign.iAlgorithm"),SignatureUtil.options.get("unionAppRawSign.appName"));
        log.info("加签ErrorCode:{}",SignatureUtil.UNION_CERTAPP_API.getErrorCode());
        log.info("加签ErrorMessage:{}",SignatureUtil.UNION_CERTAPP_API.getErrorMessage());
        return result;
        
    }
    
}

/**   
 * @ClassName:  UnionAppRawVerify   
 * @Description: 普通验签类
 * @author: qiran
 * @date:   2018年7月13日 下午9:01:09   
 * @return 返回值: 0:验证结果正确  其他:验证结果失败
 */
class UnionAppRawVerify implements Function<Map<String,Object>,Integer>{
    private static final Logger log = LoggerFactory.getLogger(UnionAppRawVerify.class);
    /**
     * UnionAppRawVerify(byte[] msg,String signedData,String appName,int iAlgorithm);
     * 参数1: msg 待验签  数据原文
     * 参数2: signedData base64签名信息
     * 参数3:appName:证书应用名称,命名需遵循规则appID.bankID.ver, appID 为应用标识,bankID为机构标识, ver为版本号
     * 参数4: iAlgorithm:摘要算法1 表示SHA1, 2 表示SM3, 256表示SHA256,512表示SHA512
                 RSA证书只能选择SHA1/ SHA256/SHA512;SM2证书只能选择SM3算法
     * 返回值: 0:验证结果正确  其他:验证结果失败
     */
    @Override
    public Integer apply(Map<String,Object> map) {
        byte[] one = null;
        try {
            one = map.get("msg").toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("系统异常",e);
        }
        String signedData = map.get("signedData").toString();
        String appName = SignatureUtil.options.get("unionAppRawVerify.appId")+map.get("bankId").toString()+SignatureUtil.options.get("unionAppRawVerify.appVer");
        int iAlgorithm  = SignatureUtil.options.get("unionAppRawVerify.iAlgorithm");
        Integer a = SignatureUtil.UNION_CERTAPP_API.UnionAppRawVerify(one,signedData,appName,iAlgorithm);
        log.info("验签ErrorCode:{}",SignatureUtil.UNION_CERTAPP_API.getErrorCode());
        log.info("验签ErrorMessage:{}",SignatureUtil.UNION_CERTAPP_API.getErrorMessage());
        //SignatureUtil.UNION_CERTAPP_API.UnionAppRawVerify(map.get("msg").toString().getBytes(),map.get("signedData").toString(),SignatureUtil.options.get("unionAppRawVerify.appId")+map.get("bankId").toString()+SignatureUtil.options.get("unionAppRawVerify.appVer"),SignatureUtil.options.get("unionAppRawVerify.iAlgorithm"));       
        return a;
    }
    
}

/**   
 * @ClassName:  UnionAppDetachedSign   
 * @Description: PKCS7签名
 * @author: qiran
 * @date:   2018年7月13日 下午9:01:09   
 *   
 */
class UnionAppDetachedSign  implements Function<byte[],String>{
    
    /**
     * UnionAppDetachedSign(byte[] msg,String appName,int iAlgorithm);
     * 参数1:   msUnionAppRawVerifyg:待签名数据
     * 参数2: appName:证书应用名称,命名需遵循规则appID.bankID.ver, appID
     *      为应用标识,bankID为机构标识, ver为版本号
     * 参数3:  iAlgorithm:摘要算法1 表示SHA1, 2 表示SM3, 256表示SHA256,512表示SHA512
                         RSA证书只能选择SHA1/SHA256/SHA512;SM2证书只能选择SM3算法
     * 返回值:base64格式P7签名数据包      
     */
    @Override
    public String apply(byte[] t) {

        return SignatureUtil.UNION_CERTAPP_API.UnionAppDetachedSign(t,SignatureUtil.options.get("unionAppDetachedSign.appName"),SignatureUtil.options.get("unionAppDetachedSign.iAlgorithm"));
        
    }
}

/**   
 * @ClassName:  UnionAppDetachedVerify   
 * @Description: PKCS7验签
 * @author: qiran
 * @date:   2018年7月13日 下午9:01:09   
 * @return 返回值: 0:验证结果正确  其他:验证结果失败
 */
class UnionAppDetachedVerify implements Function<Map<String,Object>,Integer>{

    /**
     *  UnionCertInfo UnionAppDetachedVerify(byte[] msg,String signedMsg);
     * 参数1: msg:待签名数据原文
     * 参数2: signedMsg:base64格式PKCS7数据
     * 返回值 :UnionCertInfo
     *             String subject;      证书主题
     *             String ser_number;   证书序号
     *             String issuer_subject;   证书颁发者
     *             String start_time;   证书生效日期yyyyMMdd
     *             String end_time; 证书失效日期yyyyMMd
     *             String alg_id;     证书算法标识 "RSA"或"SM2" 
     *             String pk;         证书公钥(RSA公钥格式为DER Hex格式,SM2公钥 为”04||xHex||yHex”)
     *             String base64Cert;  证书数据(base64)
     */
    @Override
    public Integer apply(Map<String,Object> map) {
        
        UnionCertInfo unionCertInfo = SignatureUtil.UNION_CERTAPP_API.UnionAppDetachedVerify(map.get("msg").toString().getBytes(),map.get("signedData").toString());
        
        System.out.println(unionCertInfo.getPk());
        //由于 调用方法 以 0为成功 方法 所以 此处修改为返回0
        if(unionCertInfo!=null&&unionCertInfo.getPk()!=null&&"".equals(unionCertInfo.getPk())){
            return 0;
        }
        return 1;
    }
    
}

相关文章

网友评论

      本文标题:java人行超网加签验签代码

      本文链接:https://www.haomeiwen.com/subject/fdrudktx.html