手把手教你调用招商银行接口

  • 一、下载示例代码
  • 二、申请测试环境、或者生产环境加入到示例代码
  • 三、调用招商银行接口参数拼装
  • 四、调用接口测试
  • 五、最后,贴上我自己改造过的工具类
    • 1、这是获取银行环境参数的工具类
    • 2、新增记账子单元 NTDMAADD-参数dto
    • 3、这是调用银行接口的工具类,一般就用“commonRequestMethod”方法

一、下载示例代码

首先到招商银行的文档中心下载示例代码:
https://openbiz.cmbchina.com/developer/UI/Business/CloudDirectConnect/Public/DocumentCenter/DocDetail.aspx?bizkey=DCCT20201215143758097&fabizkey=1&treeID=100034594



这个下载下来是一个压缩包,打开压缩包,里面有一个,java文件这个文件就是示例代码了。

二、申请测试环境、或者生产环境加入到示例代码


这里面的公钥、私钥等环境参数是不能直接用的(红框框住的那些就是),需要企业事先跟招商银行申请测试环境,申请成功后将申请环境中的参数与示例代码的参数一一替换。

三、调用招商银行接口参数拼装


这个data参数里面的就是招商银行的接口参数,这样看有点费劲,格式一下json

注意,reqid是有格式要求的

这个接口的funcode是“NTDMAADD”,在文档中找到对应的接口详情

会有接口的使用说明,请求和响应的参数介绍,往下拉还会有调用示例和响应示例

四、调用接口测试

在调用接口前记得找管理网银的同事添加一下本机ip的白名单,否则会出现白名单错误,出现这个错误说明接口传参没问题了,就差白名单了。

添加了白名单之后,如果响应体中参数“resultcode”的值为“SUC0000”,说明接口调用成功,保存下需要的返回信息即可。

当然也可以用postman测试

但是“DATA”参数还是需要用示例代码中的方法加密,个人觉得意义不大。

五、最后,贴上我自己改造过的工具类

这个不是调用接口必要的,只是觉得经过我改动后调用接口方便一点

1、这是获取银行环境参数的工具类

import lombok.Data;/*** 银行配置dto** @author:user* @date: 2022-03-25 10:51*/
@Data
public class BankConfigDto {//公钥private String pubkeyStr;//私钥private String prikeyStr;//AESKEYprivate String AESKEY;//用户idprivate String UID;//访问地址private String URL;//=============以下参数并不是所有的银行接口都需要,所以是非必填的//付方账号private String payacc;//模式编号private String busmod;//网银审批标志    可选;Y 直连经办,客户端审批private String grtflg;//分行号private String bbknbr;}

2、新增记账子单元 NTDMAADD-参数dto

这只是这个接口的dto,后面要调用其他接口再增加对应的参数dto。


import lombok.Data;/*** 新增记账子单元 NTDMAADD-参数dto** @author:user* @date: 2022-03-25 18:14*/
@Data
public class NTDMAADDParam {//账号private String accnbr;//记账子单元编号// 不超过 10 位private String dmanbr;//记账子单元名称private String dmanam;//=================以下字段为非必填//额度控制标志//空:默认 Y,Y:允许透支 N:不允许透支private String ovrctl;//退票处理方式//空:默认 N,Y: 退回原记账子单元 N:退回结算户private String bcktyp;//余额非零时是否可关闭//Y:可关闭, N:不可关闭 空:默认 Yprivate String clstyp;
}

3、这是调用银行接口的工具类,一般就用“commonRequestMethod”方法


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;import org.apache.commons.lang.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jeecg.common.util.ReflectHelper;
import org.jeecg.modules.cmb.dto.*;
import org.jeecg.modules.cmb.entity.CMBBase64;
import org.jeecg.modules.cmb.entity.CMBRequest;
import org.jeecg.modules.cmb.entity.CMBRestBuilder;
import org.jeecg.modules.cmb.enums.CMBTransAction;/*** 调用银行接口工具类** @author:user* @date: 2022-03-24 11:50*/
public class CMBUtils {static String pubkeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5Ec7viMyQC5SShRz1jP0IQRLLVGDQ4f1rgZwtxT4ZOgnWxUoAHquj2yIrgFjNpWVnt/1dJGtXWkpp2UN3jMI5ubjVQkL0OFD+8r0IFXYAARsCLAwVLF0LE487KvVRaQC7A7rPlFfBtE/v++KajzMuDauNlIASYobcFKYdZ89vIfE/xMg/44QJqQ2XBkoMnJ7ul0kMdh4YWOQnO0qqvXD2eK3KPaXMRtxieGsVBgsvtETprw98bTl9tPUBUrneyirrccS8/Z6raV6nioyx2RzrMld8YnjlnV2YTJpNAlG+y/wLoKY55Rkjcvg9wSe8qbI/VtYVQfQz8gfeUzFQTKKCwIDAQAB";static String prikeyStr = "MIIEowIBAAKCAQEAwN7xTseqQs1pNA/+gTgXRqcxCYfkxDTsckfqf3O2ndsvJS5T" + "8Fb0oHTyjy0HjrKLASWWUKfhQGXPHbo1FQd+0TyHxSza55+HtXquUq7QsAITHCu3"+ "U7aslvC7xe6/2E7nhu1TausF1nSyB1o4xVEjZyjrdQpTID0JvG8BtA5Yem9YDBCM" + "ZHBxvarQHVqdBsqo2G3M09qeUDbY3DuBgdiVAw0ApIM8mKGj4jsWmRSnypuxl40B"+ "jWAr6Xgk44MpSGHndhiFXGvfMRRYEd8Z30w32QlB+Gjk8rQwXnvxG8YCBPYqXVkq" + "wld81bHFFz5zHQ0qekPhD8RrFimPn+RaD9VNfwIDAQABAoIBAQCxUUZQw0hJOkgq"+ "UToO2t6rWjK/LGyp5m4rcuqoWl3eKxDhAgKxx4AHtPz7nM6B5qvdVg0oAfAZIICW" + "OAdtWgLBowC/yklHAWfm9O8nnQjHiGDBWX+mOx/ZdWFsy98cow5BAhfbCE/Jpme2"+ "UsA2yC3gPcKbS+64iOVWlEfgnf/CLte/dE0eAMfsp5wXpwv3ygA4wtyd2X2P+y6s" + "+WYBKSvNMS08W4dsxwU9Q3AG3hS0Uab09qIPNS8tEMZ2L1tl0/VvkrAYjayM1CcK"+ "CrSnwtH6eJVi4WQxL1K3QxyxDKucsOlqSHg++4VMpGZNpvstn3IsY3PyCgfsODvH" + "aoygvDBhAoGBAPxxdcI9stK9bIGSms0FqbVXYj8WmAjE/M9B7ECToWRQg65Gf8MY"+ "PyUSkY2mbDHwf+yPsUb5Oli+a2GW8BwmJWeXEIy0lQxa1TS2b7CN6XJtZVnjEgiZ" + "d7bXy/j69r/C4CMlfbrRWnUGftKr/U7ynaGs10/bISeW12E7WdLV5+kDAoGBAMOW"+ "nEzAFMPFzG9p/GtYpWU5jMNSiakzfm6n9Nwr7dFGnLhVGtO6act1bm/WB26NAgIE" + "ArhcitoKrI346nfkoZLXBpzzyJgFx4r31d1RN9Vsrt6AEywlwnLwHk2HXtCwmqre"+ "hZ4I741S2rHlaT8ifNwLyjW2sbw9QnpC3RL7R3rVAoGAOI/Dbs4cLxO6KB4NCTrn" + "l3YI0VHiprRcYKPIp39sfel8V6P8JF5eZ5QNgMt1GotkXkCj298jr5aawLbs/aGe"+ "Z+N1FdGwQ6BmfPUTeV+SmszgFI/IDp00MYeQcCzq9HRZfAZ+cUlPF0FpURKwIuxB" + "XWQ4qe/TMeeeQm7l5VOALrkCgYAljLa5LW9PHpxfD3P8j+pBAsl5flEbgN1XFTu3"+ "QV/I+8t+wCgEWheRjhwDsI2AteWayXZUOsAVmFMEdrNdDTHP5SRJ4auzM/jZPzd5" + "4+vaN6Fi6ifEJAOu2VaX/9M+MYmgIFR6wLBs62k9GhQYoOBjxoetxENfJkuq+UdE"+ "K6XPeQKBgFvf+SUrg7hFpRRyCq+DehdMQk1TJnEPTNLOalfrA/319KA8LGa0Q+ay" + "5c2mDc9F//yAJEAT1WTEqHnvKBQvjofFAGRntoCT8anAnskSytwwpltKqDcpoKx/"+ "hVK+eVL47wuFroCBLGj0Zm3I7S+saGGmVllEky4jceE7IMTN7i6W";private static PrivateKey privateKey;private static PublicKey publicKey;static String UID = "N002985759";static String URL = "http://99.12.250.6:9080/cdcserver/api/v2";static String AESKEY = "YSqdwE8vAQ1BcfYCpESUsnVzOOMA2ZSd";public static void main(String[] args) throws Exception {// TODO Auto-generated method stubtry {BankConfigDto bankConfigDto = new BankConfigDto();bankConfigDto.setPubkeyStr(pubkeyStr);bankConfigDto.setPrikeyStr(prikeyStr);bankConfigDto.setAESKEY(AESKEY);bankConfigDto.setUID(UID);bankConfigDto.setURL(URL);//            //============================新增记账子单元 接口测试================================NTDMAADDParam ntdmaaddParam = new NTDMAADDParam();ntdmaaddParam.setAccnbr("769900019310827");ntdmaaddParam.setDmanbr("10101");ntdmaaddParam.setDmanam("测试嘿嘿");List<NTDMAADDParam> ntdmaaddx = new ArrayList<>();ntdmaaddx.add(ntdmaaddParam);//拼接银行请求body里面的参数Map<String, Object> body = new HashMap<>();body.put("ntdmaaddx", ntdmaaddx);//接口funcode参数String funcode = "NTDMAADD";List<String> requestEmptyFiledList = Arrays.asList("ovrctl", "bcktyp", "clstyp");JSONObject jsonObject4 = commonRequestMethod(bankConfigDto, funcode, body, requestEmptyFiledList, "参数【body】");System.out.println("jsonObject4 " + jsonObject4);} catch (Exception e) {e.printStackTrace();}}/*** 银行接口公共请求方法* @param bankConfigDto  银行相关配置* @param funcode  银行接口的funcode* @param body  银行接口的body属性值,目前只有Object和Map<String, Object>两种类型* @param emptyFiledList  body属性中可以为空的属性值,没有传null* @param message  在为空的基础上,前面添加的提示信息,没有传null* @return* @throws Exception*/public static <T> JSONObject commonRequestMethod(BankConfigDto bankConfigDto, String funcode, T body, List<String> emptyFiledList, String message) throws Exception {//校验body参数checkBody(body, emptyFiledList, message);return DoProcessMyself(bankConfigDto, funcode, body);}//15位真实账号+10位记账子单元编号(长度可小于10位)=25位交易识别账号,可用于对外收款,并实现自动记账功能。(交易识别不支持外币)。public static void modifySubAcc( SubAccUpdateDto updateDto) throws Exception {init();JSONObject jsonObject = new JSONObject();CMBRequest<SubAccUpdateDto> request =  new CMBRestBuilder().of(updateDto).build(CMBTransAction.AccMgt_UPDATE, UID);jsonObject.put("request", request);DoProcess(JSONObject.parseObject(jsonObject.toJSONString()), privateKey);}/*** 获取主账号15位* @param accno25* @return*/public static String getMainAcc2Accnbr(String accno25){return accno25.substring(0,15);}public static String getYurrefNoByReceiptName(String receiptName){return receiptName.substring(receiptName.lastIndexOf("_")+1,receiptName.lastIndexOf("."));}//etytim 的格式是一个把是时分秒连起来的格式 但是数据库要求有时分秒,所以这里做一下转化public static String getDateStr(String dateStr){return dateStr.substring(0,4)+"-"+dateStr.substring(4,6)+"-"+dateStr.substring(6,8);}public  static String getEtytime(String etytim){return etytim.substring(0,2)+":"+etytim.substring(2,4)+":"+etytim.substring(4,6);}/*** 获取账号编号主账号后半部分数据10位后的数据* @param accno25* @return*/public static String getSubAccUtil2Manbr(String accno25){return accno25.substring(15);}/*** 判断银行调用结果是否成功* @param responseJson 银行响应结果json* @return*/public static Boolean isSuccess(JSONObject responseJson) {return "SUC0000".equals(getCmbResponseParam(responseJson, "head", "resultcode"));}/*** 获取调用银行接口的响应参数值,不能通过该方法获取signature参数下的值* @param responseJson 银行响应结果json* @param param1 要获取的结果参数名 (一级或者二级)* @param param2 要获取的结果参数名 (三级,没有可以为空,如果是body下的参数则一定要写正确)* @return*/public static String getCmbResponseParam(JSONObject responseJson, String param1, String param2) {JSONObject response = (JSONObject) responseJson.get("response");checkParam(response, "返回结果中【response】为空或传入param1有误!");JSONObject head = (JSONObject) response.get("head");checkParam(head, "返回结果中【head】为空或传入param1有误!");JSONObject body = (JSONObject) response.get("body");checkParam(body, "返回结果中【body】为空或传入param1有误!");//head下的参数List<String> param2List = Arrays.asList("bizcode", "funcode", "reqid", "resultcode", "resultmsg", "rspid", "userid");JSONObject result = null;if ("response".equals(param1)) {result = response;} else if ("head".equals(param1)) {result = StringUtils.isNotBlank(param2) && param2List.contains(param2) ? (JSONObject) head.get(param2) : head;} else if ("body".equals(param1)) {result = StringUtils.isNotBlank(param2) && param2List.contains(param2) ? (JSONObject) body.get(param2) : body;} else {throw new RuntimeException("传入param2时param1不能为空!");}return result.toString();}/*** 获取请求参数json* @param bankConfigDto  银行接口参数,这里用来校验是否为空,这个方法只使用到了UID* @param funcode 接口code* @param body  请求json中的参数body,泛型类型* @return*/public static <T> JSONObject getRequestJson(BankConfigDto bankConfigDto, String funcode, T body) {checkBankConfig(bankConfigDto);checkParam(funcode, "funcode不能为空!");String data = "{\"request\":{\"body\":" + JSON.toJSONString(body) + ",\"head\":{\"funcode\":\"" + funcode + "\",\"reqid\":\"" + getTimestamp() + "\",\"userid\":\"" + bankConfigDto.getUID() + "\"}}}";return JSONObject.parseObject(data);}/*** 校验银行body参数* @param body  body参数* @param emptyFiledList  可以为空的属性集合,为JavaBean的属性,没有可以为空的传null* @param message  在为空的基础上,前面添加的提示信息,没有传null*/public static <T> void checkBody(T body, List<String> emptyFiledList, String message) {if (body instanceof Map) {Map<String, Object> map = (Map<String, Object>) body;for (Map.Entry<String, Object> entry : map.entrySet()) {String key = entry.getKey();Object value = entry.getValue();List list = null;if (value instanceof List) {list = (List) value;} else {throw new RuntimeException("map集合中key为【" + key + "】的value值非法!应为List!");}checkList(list, emptyFiledList, message);}} else {checkBean(body, emptyFiledList, message);}}/*** 校验参数集合* @param list  参数集合* @param emptyFiledList  可以为空的属性集合,为JavaBean的属性,没有可以为空的传null* @param message  在为空的基础上,前面添加的提示信息,没有传null*/public static <T> void checkList(List<T> list, List<String> emptyFiledList, String message) {checkParam(list, (StringUtils.isBlank(message) ? "集合" : message) + "为空!");for (int i = 0; i < list.size(); i++) {T t = list.get(i);checkBean(t, emptyFiledList, (StringUtils.isBlank(message) ? "集合的" : message + "的") + "第【" + i + "】条记录");}}/*** 校验参数集合* @param list  参数集合*/public static <T> void checkList(List<T> list) {checkList(list, null, null);}/*** 校验参数集合* @param list  参数集合* @param emptyFiledList  可以为空的属性集合,没有传null*/public static <T> void checkList(List<T> list, List<String> emptyFiledList) {checkList(list, emptyFiledList, null);}/*** 校验参数集合* @param list  参数集合* @param message  在为空的基础上,前面添加的提示信息,没有传null*/public static <T> void checkList(List<T> list, String message) {checkList(list, null, message);}/*** 校验javabean,传其他类型的对象可能会报错* @param obj  校验的javabean* @param emptyFiledList 可以为空的属性集合,没有传null* @param message  在为空的基础上,前面添加的提示信息,没有传null*/public static void checkBean(Object obj, List<String> emptyFiledList, String message) {checkParam(obj, (StringUtils.isBlank(message) ? "对象" : message) + "为空!");//传入为空属性集合为null表示当前集合所有属性都不能为空,但为了做校验,emptyFiledList也不能为null//在这里做校验可以减少http请求emptyFiledList = null != emptyFiledList ? emptyFiledList : new ArrayList<>();List<Map> objectInfoList = ReflectHelper.getFiledsInfo(obj);for (Map objectInfo : objectInfoList) {String name = (String) objectInfo.get("name"); //对象属性名,属性名都是字符串//可以为空的属性不做校验if (!emptyFiledList.contains(name)) {//校验对象属性值是否为空checkParam(objectInfo.get("value"), (StringUtils.isBlank(message) ? "对象的" : message + "的") + "【" + name + "】属性为空!");}}}/*** 校验javabean,传其他类型的对象可能会报错* @param obj  校验的javabean*/public static void checkBean(Object obj) {checkBean(obj, null, null);}/*** 校验javabean,传其他类型的对象可能会报错* @param obj  校验的javabean* @param emptyFiledList  可以为空的属性集合*/public static void checkBean(Object obj, List<String> emptyFiledList) {checkBean(obj, emptyFiledList, null);}/*** 校验javabean,传其他类型的对象可能会报错* @param obj  校验的javabean* @param message  在为空的基础上,前面添加的提示信息*/public static void checkBean(Object obj, String message) {checkBean(obj, null, message);}/*** 校验参数是否为空* @param obj 参数* @param message 提示信息*/public static void checkParam(Object obj, String message) {if (obj instanceof String) {if (StringUtils.isBlank((String) obj)) throw new RuntimeException(message);}Optional.ofNullable(obj).orElseThrow(() -> new RuntimeException(message));}/*** 校验银行配置是否为空* @param bankConfigDto 银行配置*/public static void checkBankConfig(BankConfigDto bankConfigDto) {checkParam(bankConfigDto, "传入银行配置为空!");checkParam(bankConfigDto.getPubkeyStr(), "银行公钥为空!");checkParam(bankConfigDto.getPrikeyStr(), "银行私钥为空!");checkParam(bankConfigDto.getAESKEY(), "银行AESKEY为空!");checkParam(bankConfigDto.getAESKEY(), "银行UID为空!");checkParam(bankConfigDto.getURL(), "银行接口路径为空!");//        Optional.ofNullable(bankConfigDto.getPayacc()).orElseThrow(() -> new RuntimeException("银行付方账号为空!"));
//        Optional.ofNullable(bankConfigDto.getBusmod()).orElseThrow(() -> new RuntimeException("银行模式编号为空!"));
//        Optional.ofNullable(bankConfigDto.getGrtflg()).orElseThrow(() -> new RuntimeException("银行网银审批标志为空!"));
//        Optional.ofNullable(bankConfigDto.getBbknbr()).orElseThrow(() -> new RuntimeException("银行分行号为空!"));}//这是用来获取时间戳的方法,用来生成唯一的银行接口参数reqidpublic static String getTimestamp() {SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS");//设置日期格式String date = df.format(new Date());// new Date()为获取当前系统时间,也可使用当前时间戳Random random = new Random();int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// System.out.println(rannum);String rand = date + rannum;System.out.println(rand);//        SimpleDateFormat df2 = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
//        String date2 = df2.format(new Date());// new Date()为获取当前系统时间,也可使用当前时间戳
//        System.out.println(date2);return rand;}//============================这里开始是银行的相关类public static void init() throws Exception {Security.addProvider(new BouncyCastleProvider());publicKey = getPublicKeyFromBytes(pubkeyStr);privateKey = getPrivateKeyFromBytes(prikeyStr, "PKCS");}//这是经过自己加工的DoProcess方法public static <T> JSONObject DoProcessMyself(BankConfigDto bankConfigDto, String funcode, T body) throws Exception {//这个方法放在前面是为了校验参数JSONObject jObject = getRequestJson(bankConfigDto, funcode, body);//要先执行初始化的方法,不然调用银行接口会报错init();JSONObject object = new JSONObject();// 签名object.put("sigdat", "__signature_sigdat__");object.put("sigtim", GetTime());//object.put("sigtim", "20191023165900");jObject.put("signature", object);String source = serialJsonOrdered(jObject);System.out.println(source);String data = signRsa2048(source.getBytes(), getPrivateKeyFromBytes(bankConfigDto.getPrikeyStr(), "PKCS"));object.put("sigdat", data);jObject.put("signature", object);// AES加密//因为在前面校验过了,这里直接使用byte[] AESBytes = bankConfigDto.getAESKEY().getBytes();String AesPlainxt = serialJsonOrdered(jObject);System.out.println("加密前req:  " + AesPlainxt);String req = encryptAES256Str(AesPlainxt, AESBytes);System.out.println("加密后req:  " + req);//发送请求HashMap<String, String> map = new HashMap<>();map.put("UID", bankConfigDto.getUID());map.put("FUNCODE", funcode);  //银行最近新增的map.put("DATA", URLEncoder.encode(req, "utf-8"));String res = doPostForm(bankConfigDto.getURL(), map);System.out.println("请求结果 res:  " + res);//返回结果中包含这个两个字符,可能是没有白名单,也可能用户没有权限,或者其他错误if ((res.contains("CDCServer:") && res.contains("ErrMsg:"))) {throw new RuntimeException(res);}//解密请求String resplain = decryptAES256(res, AESBytes, true);System.out.println("res decrypt: " + resplain);JSONObject object2 =  JSONObject.parseObject(resplain);JSONObject object3 = object2.getJSONObject("signature");String resSign = object3.getString("sigdat");object3.put("sigdat", "__signature_sigdat__");object2.put("signature", object3);String resSignSource = serialJsonOrdered(object2);System.out.println("验签原文: " + resSignSource);System.out.println("验签签名值: " +resSign);Boolean verify = signRsa2048Verify(resSignSource.getBytes(), CMBBase64.decode(resSign), getPublicKeyFromBytes(bankConfigDto.getPubkeyStr()));System.out.println("验签结果: " + verify);return JSONObject.parseObject(resSignSource);}//这是原始的DoProcesspublic static String DoProcess(JSONObject jObject, PrivateKey prikey) throws Exception {JSONObject object = new JSONObject();// 签名object.put("sigdat", "__signature_sigdat__");object.put("sigtim", GetTime());//object.put("sigtim", "20191023165900");jObject.put("signature", object);String source = serialJsonOrdered(jObject);System.out.println(source);String data = signRsa2048(source.getBytes());object.put("sigdat", data);jObject.put("signature", object);// AES加密String AesPlainxt = serialJsonOrdered(jObject);System.out.println("加密前req:  " + AesPlainxt);String req = encryptAES256Str(AesPlainxt, AESKEY.getBytes());System.out.println("加密后req:  " + req);//发送请求HashMap<String, String> map = new HashMap<>();map.put("UID", UID);map.put("DATA", URLEncoder.encode(req, "utf-8"));String res = doPostForm(URL, map);System.out.println("发送请求 res:  " + res);//解密请求String resplain = decryptAES256(res, AESKEY.getBytes(), true);System.out.println("res decrypt: " + resplain);JSONObject object2 =  JSONObject.parseObject(resplain);JSONObject object3 = object2.getJSONObject("signature");String resSign = object3.getString("sigdat");object3.put("sigdat", "__signature_sigdat__");object2.put("signature", object3);String resSignSource = serialJsonOrdered(object2);System.out.println("验签原文: " + resSignSource);System.out.println("验签签名值: " +resSign);Boolean verify = signRsa2048Verify(resSignSource.getBytes(), CMBBase64.decode(resSign), publicKey);System.out.println("验签结果: " + verify);return resSignSource;}public static String GetTime() {Date date = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");return dateFormat.format(date);}public static String GetTime(String datePattern) {Date date = new Date();SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);return dateFormat.format(date);}public static String encryptAES256Str(String content, byte[] bytePassword) {return CMBBase64.encode(encryptAES256(content, bytePassword));}public static byte[] encryptAES256(String content, byte[] bytePassword) {try {Cipher cipherInstance = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");SecretKeySpec key = new SecretKeySpec(bytePassword, "AES");cipherInstance.init(Cipher.ENCRYPT_MODE, key);byte[] byteContent = content.getBytes();byte[] cryptograph = cipherInstance.doFinal(byteContent);return cryptograph;} catch (Exception e) {e.printStackTrace();System.out.println(e.getMessage());}return bytePassword;}public static String decryptAES256(String content, byte[] bytePassword, boolean logError) {if (content == null || content.length() == 0) {System.out.println("decryptAES256 param content is null or empty");}byte[] bContent = null;try {bContent = CMBBase64.decode(content);} catch (Exception e) {System.out.println("decryptAES256  appear error");e.printStackTrace();}try {Cipher cipherInstance = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");SecretKeySpec key = new SecretKeySpec(bytePassword, "AES");cipherInstance.init(Cipher.DECRYPT_MODE, key);byte[] crypted = cipherInstance.doFinal(bContent);return new String(crypted, "utf-8");} catch (Exception e) {System.out.println(e.getMessage());}return content;}public static String signRsa2048(byte[] baSource) throws Exception {try {Signature signature = Signature.getInstance("SHA256WithRSA");signature.initSign(privateKey);signature.update(baSource);return CMBBase64.encode(signature.sign());} catch (Exception e) {System.out.println("signRsa2048 appear error " + e.getMessage());throw new Exception("signRsa2048 appear error " + e.getMessage());}}public static String signRsa2048(byte[] baSource, PrivateKey prvKey) throws Exception {try {Signature signature = Signature.getInstance("SHA256WithRSA");signature.initSign(prvKey);signature.update(baSource);return CMBBase64.encode(signature.sign());} catch (Exception e) {System.out.println("signRsa2048 appear error" + e.getMessage());throw new Exception("signRsa2048 appear error " + e.getMessage());}}public static boolean signRsa2048Verify(byte[] baSource, byte[] baSignature, PublicKey pubKey) throws Exception {try {Signature signature = Signature.getInstance("SHA256WithRSA");signature.initVerify(pubKey);signature.update(baSource);return signature.verify(baSignature);} catch (Exception e) {System.out.println("验签失败 " + e.getMessage());throw new Exception("验签失败 " + e.getMessage());}}public static PrivateKey getPrivateKeyFromBytes(String crtBase64, String type) throws Exception {// type = PKCS,X509try {byte[] baKey = CMBBase64.decode(crtBase64);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey prvkey = keyFactory.generatePrivate(type.equals("PKCS") ? new PKCS8EncodedKeySpec(baKey) : new X509EncodedKeySpec(baKey));return prvkey;} catch (Exception e) {throw new Exception("getPrivateKeyFromBytes error" + e.getMessage());}}public static PublicKey getPublicKeyFromBytes(String crtBase64) throws Exception {try {X509EncodedKeySpec keySpec = new X509EncodedKeySpec(CMBBase64.decode(crtBase64));KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey key = keyFactory.generatePublic(keySpec);return key;} catch (Exception e) {throw new Exception("getPublicKeyFromBytes error" + e.getMessage());}}public static String doPostForm(String httpUrl, Map param) {HttpURLConnection connection = null;InputStream is = null;OutputStream os = null;BufferedReader br = null;String result = null;try {URL url = new URL(httpUrl);// trustAllHttpsCertificates();SSLContext sslcontext;sslcontext = SSLContext.getInstance("SSL", "SunJSSE");sslcontext.init(null, new TrustManager[] { new MyX509TrustManager() }, new java.security.SecureRandom());// URL url = new URL("https://xxxx");HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {public boolean verify(String s, SSLSession sslsession) {System.out.println("WARNING: Hostname is not matched for cert.");return true;}};HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("POST");connection.setConnectTimeout(15000);connection.setReadTimeout(60000);connection.setInstanceFollowRedirects(true);connection.setDoOutput(true);connection.setDoInput(true);connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");os = connection.getOutputStream();os.write(createLinkString(param).getBytes());if (connection.getResponseCode() != 200) {is = connection.getErrorStream();br = new BufferedReader(new InputStreamReader(is, "UTF-8"));StringBuffer sbf = new StringBuffer();String temp = null;while ((temp = br.readLine()) != null) {sbf.append(temp);sbf.append("\r\n");}result = sbf.toString();} else {is = connection.getInputStream();br = new BufferedReader(new InputStreamReader(is, "UTF-8"));StringBuffer sbf = new StringBuffer();String temp = null;while ((temp = br.readLine()) != null) {sbf.append(temp);sbf.append("\r\n");}result = sbf.toString();}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();} finally {if (null != br) {try {br.close();} catch (IOException e) {e.printStackTrace();}}if (null != os) {try {os.close();} catch (IOException e) {e.printStackTrace();}}if (null != is) {try {is.close();} catch (IOException e) {e.printStackTrace();}}connection.disconnect();}return result;}public static String createLinkString(Map<String, String> params) throws UnsupportedEncodingException {ArrayList<String> keys = new ArrayList<String>(params.keySet());Collections.sort(keys);StringBuilder prestr = new StringBuilder();for (int i = 0; i < keys.size(); i++) {String key = keys.get(i);String value = params.get(key);if (i == keys.size() - 1) {prestr.append(key).append("=").append(value);} else {prestr.append(key).append("=").append(value).append("&");}}return prestr.toString();}public static String serialJsonOrdered(JSONObject json) {StringBuilder appender = new StringBuilder();appender.append("{");Iterator<String> keys = new TreeSet<>(json.keySet()).iterator();boolean isFirstEle = true;while (keys.hasNext()) {if (!isFirstEle) {appender.append(",");}String key = keys.next();Object val = json.get(key);if (val instanceof JSONObject) {appender.append("\"").append(key).append("\":");appender.append(serialJsonOrdered((JSONObject) val));} else if (val instanceof JSONArray) {JSONArray jarray = (JSONArray) val;appender.append("\"").append(key).append("\":[");boolean isFirstArrEle = true;for (int i = 0; i < jarray.size(); i++) {if (!isFirstArrEle) {appender.append(",");}Object obj = jarray.get(i);if (obj instanceof JSONObject) {appender.append(serialJsonOrdered((JSONObject) obj));} else {appender.append(obj.toString().replaceAll("\"", "\\\\\""));}isFirstArrEle = false;}appender.append("]");} else {String value = "";if (val instanceof String) {value = "\"" + val.toString().replaceAll("\"", "\\\\\"") + "\"";} else {value = val.toString().replaceAll("\"", "\\\\\"");}appender.append("\"").append(key).append("\":").append(value);}isFirstEle = false;}appender.append("}");return appender.toString();}
}class MyX509TrustManager implements X509TrustManager {@Overridepublic void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {// TODO Auto-generated method stub}@Overridepublic void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {// TODO Auto-generated method stub}@Overridepublic X509Certificate[] getAcceptedIssuers() {// TODO Auto-generated method stubreturn null;}
}

调用招商银行接口(手把手教程,附调用接口工具类)相关推荐

  1. python连接微信接口开发教程_Python调用微信公众平台接口操作示例

    本文实例讲述了Python调用微信公众平台接口操作.分享给大家供大家参考,具体如下: 这里使用的是Django,其他类似 # coding=utf-8 from django.http import ...

  2. python链接微信接口开发教程_Python调用微信公众平台接口操作示例

    本文实例讲述了Python调用微信公众平台接口操作.分享给大家供大家参考,具体如下: 这里使用的是Django,其他类似 # coding=utf-8 from django.http import ...

  3. 如何利用MATLAB调用手机摄像头(手把手教程)

    一.下载并安装Droidcam 电脑端下载地址:http://www.dev47apps.com/ 手机端可直接通过App Store或应用商店下载. 下载完成后,安装. 1.1 Windows端 可 ...

  4. [Go实战]CGO 入门系列-手把手教程4 调用 libevent (c语言类库)为案例

    cgo-libevent-for-windows cgo-libevent-for-windows 参考文章: 1.环境(windows) 2.下载libevent源码 并制作dll动态库 利用min ...

  5. [Go实战]CGO 入门系列-手把手教程3 调用 mysql (c语言类库)为案例

    cgo-mysql-for-windows 1.安装环境 2.编译 && 运行 2.1 dll 编译 def 2.2 def && dll 编译 a 2.3 编译运行e ...

  6. 联想 android 5.1 root权限,联想A520手机ROOT权限图文教程(附联想A520root工具)

    联想A520 ROOT教程: 2.将手机USB调试打开; 步骤:设置----应用程序----开发-----USB调试 设置----应用程序----未知源,后面的勾打上就行; 3.打开了USB调试和未知 ...

  7. zemax设置 像方远心_[入门] [ZEMAX] [成像] 手把手教程:一个双高斯类镜头

    今天,我们来手把手做一个入门成像设计练习:一个双高斯物镜 设计指标如下图所示 好,我们开始吧 从指标中我们看到视场角为6.5°,所以我们可以从ZEMAX中的sample中选择比较接近的5°的双高斯镜头 ...

  8. ImageView可直接调用的,根据URL设置图片的工具类

    ImageView 是Android编程中最常用的组件之一. 但是根据图片的URL设置图片却很麻烦.因为获取网络图片的操作必须在异步线程中进行,根据URL设置ImageView图片就可能需要进行线程间 ...

  9. 调用阿里云发送短信验证码的工具类

    /*** @Description 阿里云短信发送工具类* @Author 曰业而安*/ public class SendSmsUtil { //phone 手机号 //param 验证码 注意这里 ...

  10. 最实用入门 EOS 手册,先收藏再看(附106个工具类链接)

    本文将 EOS 分为 EOS 诞生之路.账户与钱包.BFT-DPOS 共识机制.资源分配.社区治理.DApp 生态.经济模型.智能合约.侧链与代码分叉 9 大部分,各部分均附以网站索引,将帮助大家更加 ...

最新文章

  1. esp32 camera_利用Phyphox和ESP32蓝牙制作欧姆表测电阻
  2. R语言计算回归模型的SST、SSR以及SSE指标实战
  3. python opencv 透视变换
  4. Js中for循环的阻塞机制
  5. 骚操作!Intellij IDEA居然藏着这些实用小技巧 !
  6. netstat命令总结
  7. 亦云小组KTV点歌系统简介
  8. [Android]解决Fragment无法使用android:onClick属性
  9. 字符串经典题之参数解析
  10. Linux--Tail命令
  11. 鸿蒙WLAN模组联网+解决在Visual Studio Code不能更改Linux文件的问题
  12. mysql自左连接最大值_mysql左连接自连接例子
  13. Windows下使用emacs+cscope
  14. linux虚拟主机用织梦,织梦程序用什么虚拟主机很服务器好
  15. java 驼峰自动映射_总结springboot开启mybatis驼峰命名自动映射的三种方式
  16. 期刊分类abcde_ABCD期刊分类目录
  17. 计算机Word文档新建样式A1是啥意思,高会《职称计算机》Word 2007:创建新样式
  18. android PMU
  19. 项目管理高手常用的10种图表!
  20. 七月上(歌词背后的故事)

热门文章

  1. “NP问题是可计算的吗?” - 从“可计算性”的角度审视NP
  2. 基于MFC的Media Player播放器的制作(4---功能实现代码)
  3. 一个简易版的spice VDI 云桌面 客户端 系统
  4. [转载]使用 SVK 构建分布式版本控制环境
  5. python爬虫——爬取淘票票正在热映电影
  6. 怎么安装Python?改选什么版本呢?Python新手必看
  7. 华清远见嵌入式班结业总结
  8. SpringBoot配置Mybatis多数据源
  9. 地图采集车的那些事 | 时间同步
  10. win10的IE闪退及“启用或关闭windows功能”里没有IE选项