Using SpringBoot RestTemplate to implement third-party interface docking

Posted by mc2007 on Sun, 27 Oct 2019 11:58:32 +0100

To implement the docking of third-party interfaces, you can use httpclient (older) or SpringBoot RestTemplate (new generation). You can choose an appropriate way for docking according to your preferences. I recommend using SpringBoot RestTemplate.

The specific use is as follows:

Custom configuration class:
  • Configuration in application.yml file:
    Note: corresponding to the attributes in the XXXConfig entity class, the configuration in application.yml must be at the same level. As shown in the following figure: baseAPIURL, id, uCode
  • XXXConfig entity class example:
    Note: the @ ConfigurationProperties(prefix = "xxx.xxx") annotation is added above the custom entity class.
    The function of this annotation is to read the information configured in the yml file or properties file and automatically encapsulate it into entity classes (as follows: XXXConfig).
    When we need these configuration information, @ Autowired is convenient and fast.
@Data
@Component
@ConfigurationProperties(prefix = "xxx.api")
public class XXXConfig {
  /**
   * API Address (generally domain name)
   */
  private String baseAPIURL;
  /**
   * ID(According to the interface document definition)
   */
  private String id;
  /**
   * Access code
   */
  private String uCode;
}
Custom interface request class and response class:
  • Request class: (the common attribute can extract a Base class, and the custom request class inherits the Base class)
@Data
public class XXXReq extends XXXBase {

	// Request path
  public static final String REQ_URL = "xxxxxxxxx";

  /**
   * Request parameters
   */
  private String XXXX;
}
  • Response class:
@Data
public class XXXResp implements Serializable {

    /**
     * code
     */
    private Integer code;
    /**
     * Prompt information
     */
    private String msg;
    /**
     * Specific data
     */
    private Map<String,Object> data;
}
Generate signature:

Parameter params: the parameter you need to generate sign.

Most of the signature rules are: concatenate the strings, sort them according to the post request parameter keyASCII, generate a string, then encrypt the string with MD5 or BCrypt, and then convert the encrypted string to uppercase, and the resulting string is taken as a sign.

Attachment: MD5 encryption tools:

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @author wangyan@163.com
 * @version 1.0
 * @date 2019-10-24 19:20
 */
public class Md5Encrypt {
    /**
     * Used building output
     */
    private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
            'b', 'c', 'd', 'e', 'f'};

    /**
     * MD5 encryption of strings
     *
     * @param text Plaintext
     * @return ciphertext
     */
    public static String md5(String text) {
        MessageDigest msgDigest = null;
        try {
            msgDigest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("System doesn't support MD5 algorithm.");
        }
        try {
            msgDigest.update(text.getBytes("UTF-8")); // Note that the interface is signed according to the specified encoding form.
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("System doesn't support your  EncodingException.");
        }
        byte[] bytes = msgDigest.digest();
        String md5Str = new String(encodeHex(bytes));
        return md5Str;
    }
    private static char[] encodeHex(byte[] data) {
        int l = data.length;
        char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
            out[j++] = DIGITS[0x0F & data[i]];
        }
        return out;
    }

    public static void main(String[] args) {
        System.out.println(Md5Encrypt.md5(Md5Encrypt.md5("123456" + "shanshi")));
    }
}
Interface:
  XXXResp xxxApiCall(xxxxReq xxReq);
Implementation class:
 @Override
    public XXXResp xxxApiCall(xxxxReq xxReq) {
    	//The common request map field for generating the signature extracts a method mapUtil(), which is attached below.
    	// The map is to generate sign
        Map map = signUtil.mapUtil();
        // Non public properties can be assigned here
        map.put("xxxx", xxReq.getXXXX());
        //param is the interface request parameter
        MultiValueMap<String, Object> param = signUtil.multiValueMap(map);
        // Request parameters other than common request parameters can be added here
        param.add("xxxx", xxReq.getXXXX());
        // Request full path
        String requestUrl = xxxConfig.getBaseAPIURL() + xxReq.REQ_URL;
        // apiUtil.sendPost is the send request method
        // paramList represents the parameters of your request interface
		// url indicates the interface path of the request (full path: domain name + interface path)
		// It will be introduced below.
        Map result = apiUtil.sendPost(param, requestUrl);
        // signUtil.responseUtil is a custom return data analysis method, which will be attached below.
        return signUtil.responseUtil(result);
    }
Control layer:
 @PostMapping(value = "/XXXX")
    @PreAuthorize("hasAnyRole('ADMIN','PRICE_ALL','PRICE_SELECT')")
    @ResponseBody
    public ResponseEntity getStockPrice(@RequestBody XXXReq xxxReq) {
        xxxService.xxxApiCall(xxxReq);
        return new ResponseEntity(xxxService.xxxApiCall(xxxReq), HttpStatus.OK);
    }
Defining a bean config (instance RestTemplate object)

Request class

paramList represents the parameters of your request interface
url indicates the interface path of the request (full path: domain name + interface path)
result.getBody() is the data returned in response. You can process the data according to your own business requirements.

Appendix:

 /**
     * Generate signature public request map field
     *
     * @return
     */
    public Map mapUtil() {
        Map<String, Object> map = new HashMap<>();
        map.put("id", xxxConfig.getId());
        map.put("timeStamp", xxxx.DateUtil.getTimeStamp());
        map.put("uCode", xxxConfig.getUCode());
        return map;
    }

    /**
     * Third party interface request parameter common fields
     *
     * @param map
     * @return
     */
    public MultiValueMap<String, Object> multiValueMap(Map map) {
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("id", map.get("id"));
        param.add("uCode", map.get("uCode"));
        param.add("timeStamp", map.get("timeStamp"));
        param.add("sign", SignUtil.createSign(map));
        return param;
    }

    /**
     * Return data analysis
     *
     * @param resultMap
     * @return
     */
    public XXXResp responseUtil(Map resultMap) {
        XXXResp xxxResp = new XXXResp();
        xxxResp.setCode((Integer) resultMap.get("code"));
        xxxResp.setMsg((String) resultMap.get("msg"));
        xxxResp.setData((Map) resultMap.get("data"));
        return xxxResp;
    }

Topics: Java SpringBoot Attribute encoding