华为云AXB隐私保护通话 java代码实现

518 阅读1分钟
package org.jeecg.modules.zl.zlUser.controller;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.zl.util.Method;
import org.jeecg.modules.zl.zlUser.mapper.IndexMapper;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 隐私保护通话
 *
 * @author zagwk
 * @version 1.0
 * @date 2021/3/22 0022 15:22
 */
@RestController
@RequestMapping("/privatePhone")
public class PrivatePhone {


    @Resource
    private RestTemplate restTemplate;
    @Resource
    private Method method;
    @Resource
    private IndexMapper indexMapper;

    /**
     * 绑定虚拟号码
     * @return
     */
    @RequestMapping("/bindPrivatePhone")
    public Result bindPrivatePhone(@RequestBody Map map){
        Map<String, Object> rMap = new HashMap<>(3);
        JSONObject json = new JSONObject();
        //主叫手机号码
        String caller = (String) map.get("caller");
        //被叫手机号码
        String called = (String) map.get("called");
        if (caller.equals(called)) {
            return Result.ok("无法联系自己");
        }
        // X号码(关系号码,华为云控制台购买)
        json.put("relationNum", "+86***********");
        // A方真实号码(手机或固话)
        json.put("callerNum", "+86" + caller);
        // B方真实号码(手机或固话)
        json.put("calleeNum", "+86" + called);
        //绑定关系持续时间 单位s
        json.put("duration", "60");
        //访问uri
        String path = "/rest/caas/relationnumber/partners/v1.0";

        //调用华为云隐私号绑定接口完成绑定
        Map responseEntity = bindPhone(json, path, "bind");
        //对返回的结果进行解析
        String resultCode = (String) responseEntity.get("resultcode");
        if ("0".equals(resultCode)) {
            //绑定成功
            String subscriptionId = (String) responseEntity.get("subscriptionId");
            //插入绑定记录
            map.put("subscriptionId", subscriptionId);
            //插入绑定记录
            if (1 == indexMapper.insertBingRecord(map)) {
                rMap.put("relationNum", "***********");
                return Result.OK("绑定成功",rMap);
            }
            return Result.ok("绑定成功");
        }
        return Result.ok("绑定失败,请稍后重试");

    }

    /**
     * 华为云接口 绑定虚拟号
     * @param json
     * @param path
     * @param type
     * @return
     */
    public Map bindPhone(JSONObject json, String path, String type) {
        String url = "***********************" + path;
        String app_key = "**************************";
        String app_secret = "**************************";
        //请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization",
                "WSSE realm="SDP", profile="UsernameToken", type="Appkey"");
        headers.add("Content-Type", "application/json;charset=UTF-8");
        headers.add("Accept", "application/json");
        headers.add("X-WSSE", buildWsseHeader(app_key, app_secret));

        //封装成一个请求对象
        HttpEntity entity = new HttpEntity(json, headers);
        String responseEntity;
        Map<String, Object> resultMap;

        try {
            if ("bind".equals(type)) {
                //绑定
                responseEntity = restTemplate.postForObject(url, entity, String.class);
            } else {
                //解绑
                ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.DELETE, entity, String.class);
                String body = result.getBody();
                Gson gson = new Gson();
                resultMap = gson.fromJson(body, new HashMap<>(3).getClass());
                return resultMap;
            }
        } catch (RestClientException e) {
            Map<String, String> map = new HashMap<>(3);
            map.put("resultcode", "1001");
            map.put("resultMsg", "华为云绑定异常,请稍后重试");
            return map;
        }
        //对返回的结果进行解析
        Gson gson = new Gson();
        Map responseMap = gson.fromJson(responseEntity, HashMap.class);
        return responseMap;

    }

    /**
     * 生成X-WSSE参数值
     *
     * @param appKey    appKey
     * @param appSecret appSecret
     * @return WSSE参数值
     */
    static String buildWsseHeader(String appKey, String appSecret) {
        String time = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").format(LocalDateTime.now());
        String nonce = UUID.randomUUID().toString().replace("-", "");
        MessageDigest md;
        byte[] passwordDigest = null;
        try {
            md = MessageDigest.getInstance("SHA-256");
            md.update((nonce + time + appSecret).getBytes());
            passwordDigest = md.digest();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        String passwordDigestBase64Str = Base64.getEncoder().encodeToString(passwordDigest);
        String WSSE_HEADER_FORMAT = "UsernameToken Username="%s",PasswordDigest="%s",Nonce="%s",Created="%s"";
        return String.format(WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time);
    }

    /**
     * 回调
     *
     * @param map map
     * @return 测试手机号
     */
    @RequestMapping(value = "callback", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String fCallback(@RequestBody Map<String, Object> map) {
        String eventType = (String) map.get("eventType");
        Map<String, String> statusInfo = (Map<String, String>) map.get("statusInfo");
        if (StringUtils.isBlank(eventType) || null == statusInfo) {
            map.put("resultCode", "10003");
            map.put("resultMsg", "入参不可为空");
            return new JSONObject(map).toString();
        }
        return callback(map);
    }

    /**
     * 回调方法
     *
     * @param map map
     * @return 回调方法
     */
    public String callback(Map<String, Object> map) {
        //华为云回调类型
        String eventType = (String) map.get("eventType");
        //呼叫状态事件的信息
        Map<String, Object> statusInfo = (Map<String, Object>) map.get("statusInfo");
        //唯一指定一条通话链路的标识ID
        String sessionId = (String) statusInfo.get("sessionId");
        //绑定ID
        String subscriptionId = (String) statusInfo.get("subscriptionId");
        //该呼叫事件发生时隐私保护通话平台的UNIX时间戳
        map.put("timestamp", statusInfo.get("timestamp"));
        map.put("sessionId", sessionId);
        //主叫号码
        map.put("caller", statusInfo.get("caller"));
        //被叫号码
        map.put("called", statusInfo.get("called"));
        map.put("subscriptionId", subscriptionId);
        //判断回调类型  disconnect:挂机事件
        if ("disconnect".equals(eventType)) {
            //执行华为云解绑接口
            unBindPrivatePhone(subscriptionId);
            //修改解绑时间
            indexMapper.updateUnBindTime(map);
            //获取隐私保护信息
            Map<Object, Object> privateInfo = indexMapper.selectPrivatePhoneInfo(subscriptionId);
            if (null != privateInfo) {
                long jobId = (long) privateInfo.get("jobId");
                String workerUserId = (String) privateInfo.get("workerUserId");
                //根据用户id和工作id获取沟通次数
                Integer comNum = indexMapper.getComNum(jobId, workerUserId);
                if (null==comNum || comNum==0){
                    //添加沟通信息
                    indexMapper.insertCommunicate(jobId, workerUserId);
                }else {
                    //修改沟通次数信息
                    indexMapper.editComNum(jobId, workerUserId,comNum+1);
                }
            }
        }
        return "HTTP/1.1 200 OK ";
    }

    /**
     * 解绑隐私号
     *
     * @param subscriptionId subscriptionId
     * @return 解绑隐私号
     */
    public Map unBindPrivatePhone(String subscriptionId) {
        //调用华为云隐私号绑定接口完成绑定
        String path = "/rest/caas/relationnumber/partners/v1.0?subscriptionId=" + subscriptionId;
        Map responseEntity = bindPhone(null, path, "unbind");
        return responseEntity;
    }

}