更新时间:2023-10-11 GMT+08:00

实现示例

调用时请按照实际的cc-gateway地址修改样例:

  • https://ip:port/agentgateway

    其中,ip为CC-Gateway服务器地址,port为CC-Gateway服务器的HTTPS端口号。

  • WORKNO为座席工号,PASSWORD为座席密码,PHONENUMBER为座席软电话号码。
  • IF_TRUST_ALL为是否信任所有证书,取值范围为false/true,默认为false,需要加载CC-Gateway客户端证书truststore.jks,并配置客户端证书密码TRUSTSTORE_PASSWORD。配置为true有安全风险,请谨慎使用。
  • truststore.jks证书需要跟编译后的MainTest.class放在同一层目录。
package com.huawei.example;

import com.alibaba.fastjson.JSON;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.prng.SP800SecureRandomBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.security.provider.Sun;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CRL;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertStore;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXParameters;
import java.security.cert.PKIXRevocationChecker;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.CertPathTrustManagerParameters;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class MainTest {
    private static final String AGENTGATEWAY_URL = "https://ip:port/agentgateway";

    private static final String WORKNO = "100";

    private static final String PASSWORD = "xxxxxxxx";

    private static final String PHONENUMBER = "88880001";

    private static final boolean IF_TRUST_ALL = false;

    private static final String TRUSTSTORE_PASSWORD = "******";

    private static final long MAX_IDLE_TIME = 2L;

    private static final String HTTP = "http";

    private static final String HTTPS = "https";

    private static SSLConnectionSocketFactory sslsf = null;

    private static PoolingHttpClientConnectionManager cm = null;

    private static CloseableHttpClient httpClient = null;

    private static final int HTTPCLIENT_CM_MAXCONNECTION = 200;

    private static final int HTTPCLIENT_CM_MAXPERROUTECONNECTION = 20;

    private static final int CONNECT_TIMEOUT = 10000;

    private static final int CONNECTION_REQUEST_TIMEOUT = 10000;

    private static final int SOCKET_TIMEOUT = 20000;

    private static final int AES_KEY_BIT_LENGTH = 256;

    private static final int ENTROPY_SOURCE_BIT_LENGTH = 384;

    private static final boolean FORCE_RESEED = false;

    private static final boolean PREDICTION_RESISTANT = false;

    private static final FastSecureRandomUtil FAST_SECURE_RANDOM = new FastSecureRandomUtil();

    /**
     * @param args
     */
    public static void main(String[] args) {
        MainTest test = new MainTest();
        Map<String, String> resultMap = test.login(WORKNO, PASSWORD, PHONENUMBER);
        if (resultMap == null) {
            System.out.println("Send http request to agentgateway failed");
            return;
        }
        String guid = resultMap.get("guid");
        String agwResultString = resultMap.get("result");
        HashMap<String, Object> agwResult = JSON.parseObject(agwResultString, HashMap.class);
        if (agwResult == null) {
            System.out.println("Parse json to map failed");
            return;
        }


        if ("0".equals(agwResult.get("retcode"))) {
            //log in successfully
            System.out.println("----login ok");
        } else if ("100-002".equals(agwResult.get("retcode"))) {
            //Agent has logged in, but Agent can forcibly log in
            System.out.println("----has login");
            resultMap = test.forceLogin(WORKNO, PASSWORD, PHONENUMBER);
            if (resultMap == null) {
                System.out.println("Send http request to agentgateway failed");
                return;
            }

            guid = resultMap.get("guid");
            agwResultString = resultMap.get("result");
            agwResult = JSON.parseObject(agwResultString, HashMap.class);
            if (agwResult == null) {
                System.out.println("Parse json to map failed");
                return;
            }

            if ("0".equals(agwResult.get("retcode"))) {
                //forcibly log in successfully
                System.out.println("----forceLogin ok");
            } else {
                System.out.println("----forceLogin failed");
                return;
            }
        } else {
            System.out.println("----login failed");
            return;
        }

        //Need to add guid to http request for Authentication after log in
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("guid", guid);

        //After log in,when agent reset skills,  agent can receive call from customer request
        resultMap = test.resetSkill(WORKNO, true, "", headers);
        if (resultMap == null) {
            System.out.println("Send http request to agentgateway failed");
            return;
        }
        agwResultString = resultMap.get("result");
        agwResult = JSON.parseObject(agwResultString, HashMap.class);
        if (agwResult == null) {
            System.out.println("Parse json to map failed");
            return;
        }

        if ("0".equals(agwResult.get("retcode"))) {
            //Reset skills successfully
            System.out.println("----resetSkill ok");
        } else {
            System.out.println("----resetSkill failed");
            return;
        }

        /**
         *After log in and reset skill successfully. We need to start a thread to get the agent's event by interval.
         */
        Map<String, String> event = null;
        while (true) {
            event = null;
            resultMap = test.getAgentEvent(WORKNO, headers);
            if (resultMap == null) {
                System.out.println("Send http request to agentgateway failed");
                return;
            }

            //if agentgateway uses dynamic authentication mode, the guid will be updated by interval.
            //You can get the guid from the reponse of get the agent's event request
            guid = resultMap.get("guid");
            if (guid != null && guid != "") {
                headers = new HashMap<String, String>();
                headers.put("guid", guid);
            }

            agwResultString = resultMap.get("result");
            agwResult = JSON.parseObject(agwResultString, HashMap.class);
            if (agwResult == null) {
                System.out.println("Parse json to map failed");
                return;
            }

            if ("0".equals(agwResult.get("retcode"))) {
                //Get the agent's event successfully
                event = (Map<String, String>) agwResult.get("event");
                if (event != null) {
                    System.out.println("----getAgentEvent ok:" + agwResultString);
                } else {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        System.out.println("getAgentEvent InterruptedException ");
                    }
                }
            } else if ("000-003".equals(agwResult.get("retcode")) || "100-006".equals(agwResult.get("retcode"))) {
                //No right to visit the interface
                break;
            } else {
                System.out.println("----getAgentEvent failed");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    System.out.println("getAgentEvent InterruptedException ");
                }
            }
        }
    }

    private static TrustManager[] trustManagers = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }
    };

    static {
        InputStream inStream = null;
        InputStream crlInputStream = null;
        SSLContext context = null;
        try {
            context = SSLContext.getInstance("TLSv1.2");

            if (IF_TRUST_ALL) {
                context.init(null, trustManagers, getSecurityRandomInstance());
            } else {

                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                inStream = MainTest.class.getResourceAsStream("truststore.jks");

                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(inStream, TRUSTSTORE_PASSWORD.toCharArray());

                String crlFile = "";
                if (!crlFile.isEmpty()) {
                    crlInputStream = new FileInputStream(crlFile);
                }
                loadTrustCertificate(context, certificateFactory, keyStore, crlInputStream);
            }

            sslsf = new SSLConnectionSocketFactory(context, new String[]{"TLSv1.2"}, null,
                    NoopHostnameVerifier.INSTANCE);
            httpClient = createHttpClient();
        } catch (Exception e) {
            System.out.println("init occur Exception: " + e.getMessage());
        } finally {
            IOUtils.closeQuietly(inStream, null);
            IOUtils.closeQuietly(crlInputStream, null);
        }
    }

    public static SecureRandom getSecurityRandomInstance() {
        try {
            SecureRandom secureRandom = FAST_SECURE_RANDOM.getSecureRandom();
            secureRandom.setSeed(secureRandom.generateSeed(64));
            return secureRandom;
        } catch (Exception e) {
            System.out.println("get SecureRandom instance failed" + e);
            throw e;
        }
    }

    private static void loadTrustCertificate(SSLContext context, CertificateFactory certificateFactory,
                                             KeyStore keyStore, InputStream crlInputStream) {
        try {
            Collection<CRL> crls = null;
            if (null != crlInputStream) {
                crls = new HashSet();
                crls.add(certificateFactory.generateCRL(crlInputStream));
            }
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
            PKIXParameters pkixParams = new PKIXBuilderParameters(keyStore, new X509CertSelector());
            if (null != crls) {
                List<CertStore> certStores = new ArrayList();
                certStores.add(CertStore.getInstance("Collection", new CollectionCertStoreParameters(crls)));
                CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX", new Sun());
                PKIXRevocationChecker revocateChecker = (PKIXRevocationChecker) certPathBuilder.getRevocationChecker();
                revocateChecker.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
                        PKIXRevocationChecker.Option.NO_FALLBACK));
                pkixParams.setRevocationEnabled(true);
                pkixParams.setCertStores(certStores);
                pkixParams.addCertPathChecker(revocateChecker);
            } else {
                pkixParams.setRevocationEnabled(false);
            }

            tmf.init(new CertPathTrustManagerParameters(pkixParams));
            context.init(null, tmf.getTrustManagers(), getSecurityRandomInstance());
        } catch (Exception e) {
            System.out.println("loadTrustCertificate occur exception: " + e.getMessage());
        }
    }

    /**
     * createHttpClient
     *
     * @return CloseableHttpClient
     * @throws Exception Exception
     */
    private static CloseableHttpClient createHttpClient() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register(
                HTTP, new PlainConnectionSocketFactory()).register(HTTPS, sslsf).build();

        cm = new PoolingHttpClientConnectionManager(registry);

        int maxConnect;
        int maxPerRouteConnect;
        String maxConnectNum = "10";
        String maxPreConnectNum = "100";
        try {
            maxConnect = Integer.parseInt(maxConnectNum);
        } catch (NumberFormatException e) {
            maxConnect = HTTPCLIENT_CM_MAXCONNECTION;
        }

        try {
            maxPerRouteConnect = Integer.parseInt(maxPreConnectNum);
        } catch (NumberFormatException e) {
            maxPerRouteConnect = HTTPCLIENT_CM_MAXPERROUTECONNECTION;
        }

        cm.setMaxTotal(maxConnect);
        cm.setDefaultMaxPerRoute(maxPerRouteConnect);

        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build();

        httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .evictExpiredConnections()
                .evictIdleConnections(MAX_IDLE_TIME, TimeUnit.SECONDS)
                .disableAutomaticRetries()
                .setConnectionManager(cm)
                .build();
        return httpClient;
    }

    /**
     * log in
     *
     * @param workNo      the work no of the agent
     * @param password    the password of the agent
     * @param phoneNumber the phone number of the agent
     * @return
     */
    public Map<String, String> login(String workNo, String password, String phoneNumber) {
        String loginUrl = AGENTGATEWAY_URL + "/resource/onlineagent/" + workNo;
        Map<String, Object> loginParam = new HashMap<String, Object>();
        loginParam.put("password", password);
        loginParam.put("phonenum", phoneNumber);
        return put(loginUrl, loginParam, null);
    }

    /**
     * When agent has logged in, call the interface to forcibly log in
     *
     * @param workNo      the work no of the agent
     * @param password    the password of the agent
     * @param phoneNumber the phone number of the agent
     * @return
     */
    public Map<String, String> forceLogin(String workNo, String password, String phoneNumber) {
        String loginUrl = AGENTGATEWAY_URL + "/resource/onlineagent/" + workNo + "/forcelogin";
        Map<String, Object> loginParam = new HashMap<String, Object>();
        loginParam.put("password", password);
        loginParam.put("phonenum", phoneNumber);
        return put(loginUrl, loginParam, null);
    }

    /**
     * After log in, reset the skills
     *
     * @param workNo   the work no of the agent
     * @param autoFlag Is automatically signed into the skill queue
     * @param skillId  the id of the skill. if has more than one skill that need to be sign, it is split by ;
     * @param headers  the field is used to set the header of http request
     * @return
     */
    public Map<String, String> resetSkill(String workNo, boolean autoFlag,
                                          String skillId, Map<String, String> headers) {
        String url = AGENTGATEWAY_URL + "/resource/onlineagent/" + workNo + "/resetskill/" + autoFlag;
        if (skillId != null && skillId != "") {
            url = url + "?skillid=" + skillId;
        }
        return post(url, null, headers);
    }

    /**
     * Get the agent's event
     *
     * @param workNo  workNo the work no of the agent
     * @param headers the field is used to set the header of http request
     * @return
     */
    public Map<String, String> getAgentEvent(String workNo, Map<String, String> headers) {
        String url = AGENTGATEWAY_URL + "/resource/agentevent/" + workNo;
        return get(url, headers);
    }

    /**
     * Send http's PUT request
     *
     * @param url          the address of the request
     * @param entityParams the paramters of entity
     * @param headers      the field is used to set the header of http request
     * @return
     */
    public Map<String, String> put(String url, Map<String, Object> entityParams, Map<String, String> headers) {
        CloseableHttpClient httpClient = null;
        Map<String, String> resultMap = null;
        try {
            httpClient = createHttpClient();

            HttpPut httpPut = new HttpPut(url);
            if (entityParams != null) {
                String jsonString = JSON.toJSONString(entityParams);
                HttpEntity entity = new StringEntity(jsonString);
                httpPut.setEntity(entity);

            }

            if (headers != null) {
                Set<Entry<String, String>> headersSet = headers.entrySet();
                for (Entry<String, String> entry : headersSet) {
                    httpPut.setHeader(entry.getKey(), entry.getValue());
                }
            }
            httpPut.setHeader("Content-Type", "application/json");
            HttpResponse response = httpClient.execute(httpPut);
            int returnCode = response.getStatusLine().getStatusCode();
            if (returnCode == HttpStatus.SC_OK) {
                InputStream is = response.getEntity().getContent();
                BufferedReader in = new BufferedReader(new InputStreamReader(is));
                StringBuffer buffer = new StringBuffer();
                String line = "";
                while ((line = in.readLine()) != null) {
                    buffer.append(line);
                }

                Header[] allHeaders = response.getAllHeaders();
                String guid = "";
                if (allHeaders != null && allHeaders.length > 0) {
                    for (Header header : allHeaders) {
                        if (header.getName().equals("Set-GUID")) {
                            String setGuid = header.getValue();
                            if (setGuid != null) {
                                guid = setGuid.replace("JSESSIONID=", "");
                            }
                            break;
                        }
                    }
                }
                resultMap = new HashMap<String, String>();
                resultMap.put("guid", guid);
                resultMap.put("result", buffer.toString());
            } else {
                System.out.println(returnCode);
            }
            return resultMap;
        } catch (ClientProtocolException e) {
            System.out.println("HttpPut ClientProtocolException ");
        } catch (IOException e) {
            System.out.println("HttpPut IOException ");
        } catch (Exception e) {
            System.out.println("HttpPut Exception ");
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
        return resultMap;
    }


    /**
     * Send http's POST request
     *
     * @param url          the address of the request
     * @param entityParams the paramters of entity
     * @param headers      the field is used to set the header of http request
     * @return
     */
    public Map<String, String> post(String url, Map<String, Object> entityParams, Map<String, String> headers) {
        CloseableHttpClient httpClient = null;
        Map<String, String> resultMap = null;
        try {
            httpClient = createHttpClient();

            HttpPost httpPost = new HttpPost(url);
            if (entityParams != null) {
                String jsonString = JSON.toJSONString(entityParams);
                HttpEntity entity = new StringEntity(jsonString);
                httpPost.setEntity(entity);

            }

            if (headers != null) {
                Set<Entry<String, String>> headersSet = headers.entrySet();
                for (Entry<String, String> entry : headersSet) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }
            httpPost.setHeader("Content-Type", "application/json");
            HttpResponse response = httpClient.execute(httpPost);
            int returnCode = response.getStatusLine().getStatusCode();
            if (returnCode == HttpStatus.SC_OK) {
                InputStream is = response.getEntity().getContent();
                BufferedReader in = new BufferedReader(new InputStreamReader(is));
                StringBuffer buffer = new StringBuffer();
                String line = "";
                while ((line = in.readLine()) != null) {
                    buffer.append(line);
                }
                resultMap = new HashMap<String, String>();
                resultMap.put("result", buffer.toString());
            } else {
                System.out.println(returnCode);
            }
            return resultMap;
        } catch (ClientProtocolException e) {
            System.out.println("HttpPost ClientProtocolException");
        } catch (IOException e) {
            System.out.println("HttpPost IOException");
        } catch (Exception e) {
            System.out.println("HttpPost Exception");
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
        return resultMap;
    }


    /**
     * Send http's GET request
     *
     * @param url     the address of the request
     * @param headers the field is used to set the header of http request
     * @return
     */
    public Map<String, String> get(String url, Map<String, String> headers) {
        CloseableHttpClient httpClient = null;
        Map<String, String> resultMap = null;
        try {
            httpClient = createHttpClient();

            HttpGet httpGet = new HttpGet(url);
            if (headers != null) {
                Set<Entry<String, String>> headersSet = headers.entrySet();
                for (Entry<String, String> entry : headersSet) {
                    httpGet.setHeader(entry.getKey(), entry.getValue());
                }
            }
            httpGet.setHeader("Content-Type", "application/json");
            HttpResponse response = httpClient.execute(httpGet);
            int returnCode = response.getStatusLine().getStatusCode();
            if (returnCode == HttpStatus.SC_OK) {
                InputStream is = response.getEntity().getContent();
                BufferedReader in = new BufferedReader(new InputStreamReader(is));
                StringBuffer buffer = new StringBuffer();
                String line = "";
                while ((line = in.readLine()) != null) {
                    buffer.append(line);
                }

                Header[] allHeaders = response.getAllHeaders();
                String guid = "";
                if (allHeaders != null && allHeaders.length > 0) {
                    for (Header header : allHeaders) {
                        if (header.getName().equals("Set-GUID")) {
                            String setGuid = header.getValue();
                            if (setGuid != null) {
                                guid = setGuid.replace("JSESSIONID=", "");
                            }
                            break;
                        }
                    }
                }
                resultMap = new HashMap<String, String>();
                resultMap.put("guid", guid);
                resultMap.put("result", buffer.toString());
            } else {
                System.out.println(returnCode);
            }
            return resultMap;
        } catch (ClientProtocolException e) {
            System.out.println("HttpGet ClientProtocolException");
        } catch (IOException e) {
            System.out.println("HttpGet IOException");
        } catch (Exception e) {
            System.out.println("HttpGet Exception");
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
        return resultMap;
    }
}

package com.huawei.example;

import lombok.extern.log4j.Log4j2;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.prng.SP800SecureRandomBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;

@Log4j2
public class FastSecureRandomUtil {
    private static final int AES_KEY_BIT_LENGTH = 256;

    private static final int ENTROPY_SOURCE_BIT_LENGTH = 384;

    private static final boolean FORCE_RESEED = false;

    private static final boolean PREDICTION_RESISTANT = false;

    static {
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    private final SecureRandom fastRandom;

    public FastSecureRandomUtil() throws Exception {
        SecureRandom source = null;
        try {
            source = SecureRandom.getInstanceStrong();
        } catch (NoSuchAlgorithmException e) {
            log.error("FastSecureRandom NoSuchAlgorithmException: {}.", e.getMessage());
            throw new Exception("FastSecureRandom NoSuchAlgorithmException.", e);
        }

        BlockCipher cipher = new AESEngine();

        byte[] nonce = new byte[ENTROPY_SOURCE_BIT_LENGTH / Byte.SIZE];
        source.nextBytes(nonce);

        fastRandom = new SP800SecureRandomBuilder(source, PREDICTION_RESISTANT).setEntropyBitsRequired(
                ENTROPY_SOURCE_BIT_LENGTH).buildCTR(cipher, AES_KEY_BIT_LENGTH, nonce, FORCE_RESEED);
    }

    public byte[] getRandomBytes(int byteSize) {
        byte[] randomBytes = new byte[byteSize];
        fastRandom.nextBytes(randomBytes);
        return randomBytes;
    }


    public SecureRandom getSecureRandom() {
        return fastRandom;
    }
}