package com.dobbinsoft.fw.support.component.open; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.asymmetric.KeyType; import com.alibaba.fastjson.JSONObject; import com.dobbinsoft.fw.support.component.open.exception.OpenPlatformException; import com.dobbinsoft.fw.support.component.open.model.*; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; /** * ClassName: AbstractOpenPlatform * Description: 一个抽象的开放平台,定义了抽象的功能,持久层方案,由业务层决定 * * @author: e-weichaozheng * @date: 2021-04-23 */ @Slf4j public class OpenPlatform { @Autowired protected OpenPlatformStorageStrategy openPlatformStorageStrategy; private OkHttpClient okHttpClient = new OkHttpClient(); private ThreadLocal clientCodeThreadLocal = new ThreadLocal<>(); public void setClientCode(String clientCode) { clientCodeThreadLocal.set(clientCode); } public String getClientCode() { return clientCodeThreadLocal.get(); } public void removeClientCode() { clientCodeThreadLocal.remove(); } /** * 初始化客户端 * * @param client * @return */ public OPClient init(OPClient client) throws OpenPlatformException { // 1. 校验Code是否重复 if (StrUtil.isEmpty(client.getCode())) { throw new OpenPlatformException("客户代号不能为空"); } if (openPlatformStorageStrategy.checkClientExists(client.getCode())) { throw new OpenPlatformException("客户代号重复,请换一个"); } // 2. 持久化 OPClient opClient = openPlatformStorageStrategy.initClient(client.getCode(), client.getNotifyUrl(), client.getPublicKey2()); opClient.setPrivateKey1(null); return opClient; } public Boolean setPublicKey(String clientCode, String publicKey) { if (StrUtil.isEmpty(clientCode)) { throw new OpenPlatformException("客户代号不能为空"); } if (StrUtil.isEmpty(publicKey)) { throw new OpenPlatformException("公钥不能为空"); } return openPlatformStorageStrategy.setClientPublicKey(clientCode, publicKey); } public Boolean setNotifyUrl(String clientCode, String notifyUrl) { if (StrUtil.isEmpty(clientCode)) { throw new OpenPlatformException("客户代号不能为空"); } if (StrUtil.isEmpty(notifyUrl)) { throw new OpenPlatformException("回调地址不能为空"); } return openPlatformStorageStrategy.setClientNotifyUrl(clientCode, notifyUrl); } public OPClient getClient(String clientCode) { OPClient client = openPlatformStorageStrategy.getClient(clientCode); if (client == null) { throw new OpenPlatformException("客户代号并不存在"); } return client; } /** * 获取客户权限列表 * * @param clientCode * @return */ public Boolean setPermissionList(String clientCode, List permissions) { if (StrUtil.isEmpty(clientCode)) { throw new OpenPlatformException("客户代号不能为空"); } return openPlatformStorageStrategy.setClientPermissionList(clientCode, permissions); } public Boolean checkApiPermission(String clientCode, String group, String method) { if (StrUtil.isEmpty(clientCode)) { throw new OpenPlatformException("客户代号不能为空"); } return openPlatformStorageStrategy.checkApiPermission(clientCode, group, method); } public Map decrypt(String clientCode, String ciphertext) { String publicKey2 = openPlatformStorageStrategy.getClient(clientCode).getPublicKey2(); String parameterMapStr = new String(SecureUtil.rsa(null, publicKey2).decrypt(ciphertext, KeyType.PublicKey), StandardCharsets.UTF_8); String[] pairs = parameterMapStr.split("&"); Map map = new HashMap<>(); for (String v : pairs) { if (!StringUtils.isEmpty(v)) { String[] pair = v.split("="); if (pair.length > 1 && !StringUtils.isEmpty(pair[0])) { map.put(pair[0], new String[] {pair[1]}); } } } return map; } /** * 向客户回调地址发送请求 * * @param clientCode * @param params 请求参数 */ public void sendNotify(String clientCode, Map params) { params.put("opversion", UUID.randomUUID().toString()); List paramsRawList = params.keySet().stream().map(item -> (item + "=" + params.get(item))).collect(Collectors.toList()); OPNotify opNotify = new OPNotify(); opNotify.setParams(paramsRawList); opNotify.setClientCode(clientCode); opNotify.setTimes(1); int status = this.sendNotify(opNotify); opNotify.setStatus(status); if (status == 0) { opNotify.setNextNotify(new Date(System.currentTimeMillis() + 3000l)); } else { opNotify.setNextNotify(new Date()); } openPlatformStorageStrategy.storeNotify(opNotify); } public int sendNotify(OPNotify opNotify) { try { opNotify.getParams().add("timestamp=" + System.currentTimeMillis()); opNotify.getParams().sort(String::compareTo); // 发送一次Http请求 String rawBody = opNotify.getParams().stream().collect(Collectors.joining("&")); OPData opData = new OPData(); opData.setClientCode(opNotify.getClientCode()); OPClient clientWithPK = openPlatformStorageStrategy.getClientWithPK(opNotify.getClientCode()); opData.setCiphertext(SecureUtil.rsa(clientWithPK.getPrivateKey1(), clientWithPK.getPublicKey1()).encryptBase64(rawBody, KeyType.PrivateKey)); MediaType mediaType = MediaType.parse("application/json"); RequestBody body = RequestBody.create(mediaType, JSONObject.toJSONString(opData)); Response responseBody = okHttpClient.newCall(new Request .Builder() .url(clientWithPK.getNotifyUrl()) .post(body).build()) .execute(); if (responseBody.code() == 200) { return OPNotifyStatusType.OK.getCode(); } else { return OPNotifyStatusType.FAIL.getCode(); } } catch (IOException e) { return OPNotifyStatusType.FAIL.getCode(); } catch (Exception e) { log.error("[发送通知] 异常", e); return OPNotifyStatusType.FAIL.getCode(); } } }