| | |
| | | private String paperPic; |
| | | @ApiModelProperty("拉起确认收款页面参数") |
| | | private String packageInfo; |
| | | |
| | | @ApiModelProperty("绑定关系id") |
| | | @TableField("subscription_id") |
| | | private String subscriptionId; |
| | | @ApiModelProperty("虚拟号码") |
| | | @TableField("virtual_number") |
| | | private String virtualNumber; |
| | | @ApiModelProperty("电话录音") |
| | | @TableField("phone_recording") |
| | | private String phoneRecording; |
| | | @ApiModelProperty("录音文件存储的服务器域名") |
| | | @TableField("record_domain") |
| | | private String recordDomain; |
| | | @ApiModelProperty("录音文件名") |
| | | @TableField("record_object_name") |
| | | private String recordObjectName; |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public R<Boolean> orderSubmit(OrderSubmitRequest orderSubmitRequest) { |
| | | public R<String> orderSubmit(OrderSubmitRequest orderSubmitRequest) { |
| | | return R.fail(cause.getMessage()); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public R<String> updateSubscriptionId(String orderId, String subscriptionId, String virtualNumber) { |
| | | return R.fail(cause.getMessage()); |
| | | } |
| | | |
| | | @Override |
| | | public R<String> updatePhoneRecording(String orderId, String audioUrl) { |
| | | return R.fail(cause.getMessage()); |
| | | } |
| | | |
| | | @Override |
| | | public R<Boolean> changeOrderState(String orderId, Integer state) { |
| | | return R.fail(cause.getMessage()); |
| | | } |
| | |
| | | /** |
| | | * 根据类型获取交易额 |
| | | * |
| | | * @param cityList 城市列表 |
| | | * @param type 查询类型 |
| | | * @return 交易额 |
| | | */ |
| | | @GetMapping(value = "/order/tradeMoney") |
| | |
| | | * @return 提交结果 |
| | | */ |
| | | @PostMapping(value = "/order/orderSubmit") |
| | | R<Boolean> orderSubmit(@RequestBody OrderSubmitRequest orderSubmitRequest); |
| | | R<String> orderSubmit(@RequestBody OrderSubmitRequest orderSubmitRequest); |
| | | |
| | | /** |
| | | * 师傅端-定时调度记录师傅所走路线经纬度 |
| | |
| | | */ |
| | | @GetMapping(value = "/order/getTodayOrderData") |
| | | R<List<Order>> getTodayOrderData(); |
| | | |
| | | /** |
| | | * 设置订单的绑定id |
| | | * @param orderId |
| | | * @param subscriptionId |
| | | * @return |
| | | */ |
| | | @GetMapping(value = "/order/updateSubscriptionId") |
| | | R<String> updateSubscriptionId(@RequestParam("orderId")String orderId, |
| | | @RequestParam("subscriptionId")String subscriptionId, |
| | | @RequestParam("virtualNumber")String virtualNumber); |
| | | /** |
| | | * 设置订单的通话录音 |
| | | * @param orderId 订单id |
| | | * @param audioUrl 音频地址 |
| | | * @return |
| | | */ |
| | | @GetMapping(value = "/order/updatePhoneRecording") |
| | | R<String> updatePhoneRecording(@RequestParam("orderId")String orderId, |
| | | @RequestParam("audioUrl")String audioUrl); |
| | | |
| | | } |
| | |
| | | <version>0.2.12</version> |
| | | <scope>compile</scope> |
| | | </dependency> |
| | | <!-- 转MultipartFile才需要导这个maven包 --> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-test</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | <build> |
| | |
| | | import com.ruoyi.admin.service.*; |
| | | import com.ruoyi.admin.utils.DescribeInstances; |
| | | import com.ruoyi.admin.utils.HttpUtil; |
| | | import com.ruoyi.admin.utils.PrivateNumberUtil; |
| | | import com.ruoyi.admin.vo.OrderByServeRecordVO; |
| | | import com.ruoyi.admin.vo.OrderDetailVO; |
| | | import com.ruoyi.admin.vo.OrderReasinDto; |
| | | import com.ruoyi.admin.vo.ReassinDto; |
| | | import com.ruoyi.admin.voice.util.AXBUtil; |
| | | import com.ruoyi.common.core.constant.Constants; |
| | | import com.ruoyi.common.core.domain.BaseEntity; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.exception.GlobalException; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.utils.DateUtils; |
| | | import com.ruoyi.common.core.utils.GaoDeMapUtil; |
| | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.util.StringUtils; |
| | |
| | | private ExchangeDispatchClient dispatchClient; |
| | | @Resource |
| | | private TokenService tokenService; |
| | | @Resource |
| | | private RecoveryClassifyService recoveryClassifyService; |
| | | |
| | | @Resource |
| | | private FranchiseeService franchiseeService; |
| | | @Resource |
| | | private PrivateNumberUtil privateNumberUtil; |
| | | @Autowired |
| | | private IamConfigService iamConfigService; |
| | | /** |
| | | * 雪花算法类 |
| | | */ |
| | |
| | | } |
| | | return R.ok(orderDetailVO); |
| | | } |
| | | @Resource |
| | | private RecoveryClassifyService recoveryClassifyService; |
| | | |
| | | @Resource |
| | | private FranchiseeService franchiseeService; |
| | | /** |
| | | * 订单列表 |
| | | * |
| | |
| | | @RequiresPermissions("order_reassignment") |
| | | @ApiOperation(value = "订单列表-订单派单/改派", tags = {"后台-订单管理"}) |
| | | @PostMapping(value = "/reassignment") |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R<String> reassignment(@RequestBody OrderReasinDto orderReasinDto) { |
| | | // String[] split = orderIds.split(","); |
| | | for (ReassinDto orderId : orderReasinDto.getReassinDtos()) { |
| | | |
| | | MasterWorker masterWorker = masterWorkerService.lambdaQuery() |
| | | .eq(MasterWorker::getId, orderReasinDto.getWorkerId()) |
| | | .eq(MasterWorker::getIsDelete, 0).one(); |
| | | Order item = orderClient.detail(orderId.getOrderId()).getData(); |
| | | Order order = orderClient.exchangeOrder(orderId.getType(), orderId.getOrderId(), orderReasinDto.getWorkerId(), |
| | | masterWorker.getRealName(), masterWorker.getPhone()).getData(); |
| | | // 订单派单 |
| | | boolean result = true; |
| | | if (Constants.TWO.equals(orderId.getType())) { |
| | | orderClient.updateArrivalTime(order.getId(),orderReasinDto.getArriveTime()); |
| | | |
| | | if (order.getState().equals(Constants.SIX) || order.getState().equals(Constants.THREE)) { |
| | | orderClient.updateState(order.getId(), 7); |
| | | |
| | | //如果是待改派,将上门时间设置为最新的,并且更新再投原因 |
| | | if (order.getState().equals(Constants.SIX)){ |
| | | dispatchClient.changeReason(order.getId(), ""); |
| | | MasterWorker masterWorker = masterWorkerService.lambdaQuery() |
| | | .eq(MasterWorker::getId, orderReasinDto.getWorkerId()) |
| | | .eq(MasterWorker::getIsDelete, 0).one(); |
| | | Order order = orderClient.exchangeOrder(orderId.getType(), orderId.getOrderId(), orderReasinDto.getWorkerId(), |
| | | masterWorker.getRealName(), masterWorker.getPhone()).getData(); |
| | | try{ |
| | | // 虚拟号码 师傅号码备案 |
| | | String fileName = privateNumberUtil.uploadNumberFile(masterWorker.getProfilePicture()).getData(); |
| | | R r = privateNumberUtil.addANumber(masterWorker.getPhone(), masterWorker.getRealName(), masterWorker.getIdNumber(), fileName); |
| | | }catch (Exception e){ |
| | | throw new GlobalException("虚拟号码绑定异常!"); |
| | | } |
| | | // 虚拟号码配置 |
| | | IamConfig iamConfig = iamConfigService.getById(1); |
| | | // 订单派单 |
| | | if (Constants.TWO.equals(orderId.getType())) { |
| | | orderClient.updateArrivalTime(order.getId(),orderReasinDto.getArriveTime()); |
| | | if (order.getState().equals(Constants.SIX) || order.getState().equals(Constants.THREE)) { |
| | | orderClient.updateState(order.getId(), 7); |
| | | //如果是待改派,将上门时间设置为最新的,并且更新再投原因 |
| | | if (order.getState().equals(Constants.SIX)){ |
| | | dispatchClient.changeReason(order.getId(), ""); |
| | | } |
| | | } |
| | | // 订单状态为 待完工时,需要更改状态 待上门且清空师傅到达预约点时间 |
| | | if (order.getState().equals(Constants.TWO)) { |
| | | orderClient.updateStateAndArrivalTime(orderId.getOrderId(), Constants.ONE); |
| | | } |
| | | if(StringUtils.hasLength(order.getSubscriptionId())){ |
| | | // 虚拟号码更换 |
| | | AXBUtil.axbModifyNumber(iamConfig.getAppKey(),iamConfig.getAppSecret(),order.getSubscriptionId(), order.getReservationPhone(), masterWorker.getPhone()); |
| | | }else { |
| | | // 虚拟号码绑定 |
| | | String result = AXBUtil.axbBindNumber(iamConfig.getAppKey(), iamConfig.getAppSecret(), order.getOrderNumber(), order.getReservationPhone(), masterWorker.getPhone()); |
| | | // 存储绑定后的唯一标识 |
| | | JSONObject jsonObject = JSONObject.parseObject(result); |
| | | String subscriptionId = jsonObject.getString("subscriptionId"); |
| | | orderClient.updateSubscriptionId(order.getId(), subscriptionId,iamConfig.getVirtualNumber()); |
| | | } |
| | | |
| | | }else { |
| | | orderClient.updateArrivalTime(order.getId(),orderReasinDto.getArriveTime()); |
| | | orderClient.updateState(order.getId(), 7); |
| | | // 虚拟号码绑定 |
| | | String result = AXBUtil.axbBindNumber(iamConfig.getAppKey(), iamConfig.getAppSecret(), order.getOrderNumber(), order.getReservationPhone(), masterWorker.getPhone()); |
| | | // 存储绑定后的唯一标识 |
| | | JSONObject jsonObject = JSONObject.parseObject(result); |
| | | String subscriptionId = jsonObject.getString("subscriptionId"); |
| | | orderClient.updateSubscriptionId(order.getId(), subscriptionId,iamConfig.getVirtualNumber()); |
| | | |
| | | } |
| | | // 订单状态为 待完工时,需要更改状态 待上门且清空师傅到达预约点时间 |
| | | if (order.getState().equals(Constants.TWO)) { |
| | | orderClient.updateStateAndArrivalTime(orderId.getOrderId(), Constants.ONE); |
| | | ChannelHandlerContext context = NettyChannelMap.getData(String.valueOf(orderReasinDto.getWorkerId())); |
| | | if (null != context) { |
| | | NettyWebSocketController.sendMsgToClient(context, "您有一条新的订单,请注意查收!"); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | // 生成改派信息 |
| | | // ChangeDispatch changeDispatch = new ChangeDispatch(); |
| | | // changeDispatch.setWorkerId(item.getServerId()); |
| | | // changeDispatch.setWorkerName(item.getServerName()); |
| | | // changeDispatch.setApplyReason(orderReasinDto.getApplyReason()); |
| | | // changeDispatch.setApplyTime(new Date()); |
| | | // changeDispatch.setState(Constants.ONE); |
| | | // changeDispatch.setOrderId(orderId.getOrderId()); |
| | | // changeDispatch.setOrderNumber(item.getOrderNumber()); |
| | | // if (null != item.getUserId()) { |
| | | // changeDispatch.setUserId(item.getUserId()); |
| | | // } |
| | | // changeDispatch.setUserName(item.getReservationName()); |
| | | // changeDispatch.setIsDelete(Constants.ZERO); |
| | | // result = dispatchClient.saveRecord(changeDispatch).getData(); |
| | | }else { |
| | | orderClient.updateArrivalTime(order.getId(),orderReasinDto.getArriveTime()); |
| | | orderClient.updateState(order.getId(), 7); |
| | | } |
| | | ChannelHandlerContext context = NettyChannelMap.getData(String.valueOf(orderReasinDto.getWorkerId())); |
| | | if (null != context) { |
| | | NettyWebSocketController.sendMsgToClient(context, "您有一条新的订单,请注意查收!"); |
| | | } |
| | | // try { |
| | | // WebSocketServer.sendInfo("您有一条新的订单,请注意查收!", String.valueOf(workerId)); |
| | | // } catch (IOException e) { |
| | | // return R.fail("订单推送失败!"); |
| | | // } |
| | | } |
| | | |
| | | return R.ok() ; |
| | | } |
| | | |
| | |
| | | /** |
| | | * 订单列表-excel导出 |
| | | * |
| | | * @param name 师傅姓名 |
| | | * @param phone 师傅电话 |
| | | */ |
| | | @RequiresPermissions("order_count") |
| | | @ApiOperation(value = "订单统计", tags = {"后台-订单管理"}) |
| New file |
| | |
| | | package com.ruoyi.admin.controller; |
| | | |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.ruoyi.admin.entity.Order; |
| | | import com.ruoyi.admin.service.OrderService; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * <p> |
| | | * 协议政策、司机操作指导 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-05-29 |
| | | */ |
| | | @Slf4j |
| | | @RestController |
| | | @RequestMapping("/privateNumber") |
| | | public class PrivateNumberCallBackController { |
| | | |
| | | |
| | | @Resource |
| | | private OrderService orderService; |
| | | |
| | | /** |
| | | * 隐私号码回调 |
| | | */ |
| | | @PostMapping(value = "/callBack") |
| | | public R<String> callBack(@RequestBody JSONObject jsonObject) { |
| | | JSONArray feeLst = jsonObject.getJSONArray("feeLst"); |
| | | for (int i = 0; i < feeLst.size(); i++) { |
| | | JSONObject feeLstJson = feeLst.getJSONObject(i); |
| | | String subscriptionId = feeLstJson.getString("subscriptionId"); |
| | | String recordDomain = feeLstJson.getString("recordDomain"); |
| | | String recordObjectName = feeLstJson.getString("recordObjectName"); |
| | | String recordBucketName = feeLstJson.getString("recordBucketName"); |
| | | log.info("隐私号码回调:{},录音文件名:{},录音服务器名:{}", subscriptionId, recordObjectName, recordDomain); |
| | | Order order = orderService.getOne(Wrappers.lambdaQuery(Order.class) |
| | | .eq(Order::getSubscriptionId, subscriptionId) |
| | | .last("LIMIT 1")); |
| | | if(Objects.nonNull(order)){ |
| | | order.setRecordDomain(recordDomain); |
| | | order.setRecordObjectName(recordObjectName); |
| | | orderService.updateById(order); |
| | | } |
| | | } |
| | | return R.ok("OK"); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * 虚拟号码配置 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @TableName("t_iam_config") |
| | | @ApiModel(value = "t_iam_config对象", description = "虚拟号码配置") |
| | | public class IamConfig implements Serializable { |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Integer id; |
| | | @ApiModelProperty("用户") |
| | | @TableField("userName") |
| | | private String userName; |
| | | @ApiModelProperty("子账号") |
| | | @TableField("account") |
| | | private String account; |
| | | @ApiModelProperty("子账号密码") |
| | | @TableField("password") |
| | | private String password; |
| | | @ApiModelProperty("虚拟号码APP_Key") |
| | | @TableField("appKey") |
| | | private String appKey; |
| | | @ApiModelProperty("虚拟号码APP_Secret") |
| | | @TableField("appSecret") |
| | | private String appSecret; |
| | | @ApiModelProperty("虚拟号码") |
| | | @TableField("virtualNumber") |
| | | private String virtualNumber; |
| | | } |
| | |
| | | @TableField(exist = false) |
| | | private String applyReason; |
| | | |
| | | @ApiModelProperty("绑定关系id") |
| | | @TableField("subscription_id") |
| | | private String subscriptionId; |
| | | @ApiModelProperty("虚拟号码") |
| | | @TableField("virtual_number") |
| | | private String virtualNumber; |
| | | @ApiModelProperty("电话录音") |
| | | @TableField("phone_recording") |
| | | private String phoneRecording; |
| | | @ApiModelProperty("录音文件存储的服务器域名") |
| | | @TableField("record_domain") |
| | | private String recordDomain; |
| | | @ApiModelProperty("录音文件名") |
| | | @TableField("record_object_name") |
| | | private String recordObjectName; |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.admin.entity.IamConfig; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * <p> |
| | | * 虚拟号码管理 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | @Mapper |
| | | public interface IamConfigMapper extends BaseMapper<IamConfig> { |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.admin.entity.IamConfig; |
| | | |
| | | /** |
| | | * <p> |
| | | * 改派管理 服务类 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | public interface IamConfigService extends IService<IamConfig> { |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.admin.entity.IamConfig; |
| | | import com.ruoyi.admin.mapper.IamConfigMapper; |
| | | import com.ruoyi.admin.service.IamConfigService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 改派管理 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | @Service |
| | | public class IamConfigServiceImpl extends ServiceImpl<IamConfigMapper, IamConfig> implements IamConfigService { |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.utils; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.ruoyi.admin.entity.IamConfig; |
| | | import com.ruoyi.admin.service.IamConfigService; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.redis.service.RedisService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import okhttp3.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.StringUtils; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Date; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | @Slf4j |
| | | @Component |
| | | public class PrivateNumberUtil { |
| | | |
| | | @Autowired |
| | | private RedisService redisService; |
| | | @Autowired |
| | | private IamConfigService iamConfigService; |
| | | |
| | | private final String TOKEN_URL = "https://iam.cn-south-1.myhuaweicloud.com/v3/auth/tokens"; |
| | | private final String UPLOAD_NUMBER_FILE_URL = "https://rtc.cn-north-1.myhuaweicloud.com/v1/privatenumber/a-number/files?agree_authorization_statement=true"; |
| | | private final String ADD_A_NUMBER_URL = "https://rtc.cn-north-1.myhuaweicloud.com/v1.0/privatenumber/a-number?agree_authorization_statement=true"; |
| | | |
| | | /** |
| | | * 获取token |
| | | * @return |
| | | */ |
| | | public String getToken() { |
| | | String token = redisService.getCacheObject("PRIVATE_NUMBER:"); |
| | | if(StringUtils.hasLength(token)){ |
| | | return token; |
| | | } |
| | | IamConfig iamConfig = iamConfigService.getById(1); |
| | | String userName = iamConfig.getUserName(); |
| | | String account = iamConfig.getAccount(); |
| | | String password = iamConfig.getPassword(); |
| | | OkHttpClient client = new OkHttpClient().newBuilder() |
| | | .build(); |
| | | MediaType mediaType = MediaType.parse("text/plain"); |
| | | RequestBody body = RequestBody.create(mediaType, "{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"name\":\""+userName+"\"},\"name\":\""+account+"\",\"password\":\""+password+"\"}}},\"scope\":{\"domain\":{},\"project\":{\"name\":\"cn-north-1\"}}}}"); |
| | | Request request = new Request.Builder() |
| | | .url(TOKEN_URL) |
| | | .method("POST", body) |
| | | .build(); |
| | | Response response = null; |
| | | try { |
| | | response = client.newCall(request).execute(); |
| | | } catch (IOException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | // 获取响应头 X-Subject-Token |
| | | token = response.header("X-Subject-Token"); |
| | | if(StringUtils.hasLength(token)){ |
| | | ResponseBody responseBody = response.body(); |
| | | if(responseBody != null) { |
| | | try { |
| | | String string = responseBody.string(); |
| | | log.info("获取token:{}",string); |
| | | JSONObject jsonObject = JSONObject.parseObject(string); |
| | | JSONObject tokenJson = jsonObject.getJSONObject("token"); |
| | | Date expiresAt = tokenJson.getDate("expires_at"); |
| | | redisService.setCacheObject("PRIVATE_NUMBER:",token,expiresAt.getTime()-System.currentTimeMillis(), TimeUnit.MILLISECONDS); |
| | | } catch (IOException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | | return token; |
| | | }else { |
| | | return null; |
| | | } |
| | | } |
| | | /** |
| | | * 获取token |
| | | * @return |
| | | */ |
| | | public static String getTokenTest() { |
| | | String account = "hsg13437173440"; |
| | | String userName = "denglu"; |
| | | String password = "6!JR8Fn0"; |
| | | OkHttpClient client = new OkHttpClient().newBuilder() |
| | | .build(); |
| | | MediaType mediaType = MediaType.parse("text/plain"); |
| | | RequestBody body = RequestBody.create(mediaType, "{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"name\":\""+account+"\"},\"name\":\""+userName+"\",\"password\":\""+password+"\"}}},\"scope\":{\"domain\":{},\"project\":{\"name\":\"cn-north-1\"}}}}"); |
| | | Request request = new Request.Builder() |
| | | .url("https://iam.cn-south-1.myhuaweicloud.com/v3/auth/tokens") |
| | | .method("POST", body) |
| | | .build(); |
| | | Response response = null; |
| | | try { |
| | | response = client.newCall(request).execute(); |
| | | } catch (IOException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | // 获取响应头 X-Subject-Token |
| | | String token = response.header("X-Subject-Token"); |
| | | if(StringUtils.hasLength(token)){ |
| | | return token; |
| | | }else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 上传号码文件 |
| | | * @param filePath |
| | | */ |
| | | public R<String> uploadNumberFile(String filePath) { |
| | | MultipartFile file = UrlToMultipartFileUtil.urlTransferMultipartFile(filePath); |
| | | MultipartFile[] files = new MultipartFile[]{file}; |
| | | OkHttpClient client = new OkHttpClient().newBuilder() |
| | | .build(); |
| | | // 构建multipart/form-data请求体 |
| | | MultipartBody.Builder builder = new MultipartBody.Builder(); |
| | | builder.setType(MultipartBody.FORM); |
| | | // 添加文件到请求体 |
| | | try { |
| | | for (MultipartFile multipartFile : files) { |
| | | if (multipartFile != null && !multipartFile.isEmpty()) { |
| | | RequestBody fileBody = RequestBody.create( |
| | | MediaType.parse(multipartFile.getContentType()), |
| | | multipartFile.getBytes() |
| | | ); |
| | | builder.addFormDataPart("files", multipartFile.getOriginalFilename(), fileBody); |
| | | } |
| | | } |
| | | } catch (IOException e) { |
| | | System.err.println("Error reading multipart file: " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | return R.fail("文件读取失败: " + e.getMessage()); |
| | | } |
| | | RequestBody body = builder.build(); |
| | | Request request = new Request.Builder() |
| | | .url(UPLOAD_NUMBER_FILE_URL) |
| | | .method("POST", body) |
| | | .addHeader("X-Auth-Token", getToken()) |
| | | .build(); |
| | | Response response = null; |
| | | try { |
| | | response = client.newCall(request).execute(); |
| | | ResponseBody responseBody = response.body(); |
| | | if(responseBody != null) { |
| | | try { |
| | | String string = responseBody.string(); |
| | | log.info("上传号码文件:{}",string); |
| | | JSONObject jsonObject = JSONObject.parseObject(string); |
| | | String result = jsonObject.getString("result"); |
| | | if("Upload Successful.".equals(result)){ |
| | | return R.ok(file.getOriginalFilename(),""); |
| | | }else { |
| | | String failReason = jsonObject.getString("failReason"); |
| | | return R.fail(failReason); |
| | | } |
| | | } catch (IOException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | return R.fail(); |
| | | } |
| | | public static R uploadNumberFileTest(String filePath,String accessToken) { |
| | | MultipartFile file = UrlToMultipartFileUtil.urlTransferMultipartFile(filePath); |
| | | MultipartFile[] files = new MultipartFile[]{file}; |
| | | OkHttpClient client = new OkHttpClient().newBuilder() |
| | | .build(); |
| | | // 构建multipart/form-data请求体 |
| | | MultipartBody.Builder builder = new MultipartBody.Builder(); |
| | | builder.setType(MultipartBody.FORM); |
| | | // 添加文件到请求体 |
| | | try { |
| | | for (MultipartFile multipartFile : files) { |
| | | if (multipartFile != null && !multipartFile.isEmpty()) { |
| | | RequestBody fileBody = RequestBody.create( |
| | | MediaType.parse(multipartFile.getContentType()), |
| | | multipartFile.getBytes() |
| | | ); |
| | | builder.addFormDataPart("files", multipartFile.getOriginalFilename(), fileBody); |
| | | } |
| | | } |
| | | } catch (IOException e) { |
| | | System.err.println("Error reading multipart file: " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | return R.fail("文件读取失败: " + e.getMessage()); |
| | | } |
| | | RequestBody body = builder.build(); |
| | | Request request = new Request.Builder() |
| | | .url("https://rtc.cn-north-1.myhuaweicloud.com/v1/privatenumber/a-number/files?agree_authorization_statement=true") |
| | | .method("POST", body) |
| | | .addHeader("X-Auth-Token", getTokenTest()) |
| | | .build(); |
| | | Response response = null; |
| | | try { |
| | | response = client.newCall(request).execute(); |
| | | ResponseBody responseBody = response.body(); |
| | | if(responseBody != null) { |
| | | try { |
| | | String string = responseBody.string(); |
| | | System.err.println("body:::::::::::::::::"+string); |
| | | JSONObject jsonObject = JSONObject.parseObject(string); |
| | | String result = jsonObject.getString("result"); |
| | | if("Upload Successful.".equals(result)){ |
| | | return R.ok(); |
| | | }else { |
| | | String failReason = jsonObject.getString("failReason"); |
| | | return R.fail(failReason); |
| | | } |
| | | } catch (IOException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | return R.fail(); |
| | | } |
| | | |
| | | /** |
| | | * 新增租户级 A 号码报备接口 |
| | | * @param fileName |
| | | */ |
| | | public R addANumber(String number, String realName, String idNumber, String fileName) { |
| | | JSONObject requestBody = new JSONObject(); |
| | | JSONArray numbers = new JSONArray(); |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("number", "+86"+number); // 手机号码 |
| | | jsonObject.put("numberType", 1); // 号码类型 1=手机号 2=固话 |
| | | jsonObject.put("name", realName); // 真实姓名 |
| | | jsonObject.put("identityCard",idNumber); // 身份证号 |
| | | jsonObject.put("liveFaceImage", fileName); // 号码所属人现场照片文件名 |
| | | numbers.add(jsonObject); |
| | | requestBody.put("numbers", numbers); |
| | | OkHttpClient client = new OkHttpClient().newBuilder() |
| | | .build(); |
| | | // 构建json请求体 |
| | | MediaType mediaType = MediaType.parse("application/json"); |
| | | String requestBodyJson = requestBody.toJSONString(); |
| | | RequestBody body = RequestBody.create(mediaType, requestBodyJson); |
| | | Request request = new Request.Builder() |
| | | .url(ADD_A_NUMBER_URL) |
| | | .method("POST", body) |
| | | .addHeader("X-Auth-Token", getToken()) |
| | | .addHeader("Content-Type", "application/json") |
| | | .addHeader("Accept", "application/json") |
| | | .build(); |
| | | Response response = null; |
| | | try { |
| | | response = client.newCall(request).execute(); |
| | | ResponseBody responseBody = response.body(); |
| | | if(responseBody != null) { |
| | | String string = responseBody.string(); |
| | | log.info("新增租户级 A 号码报备接口:{}",string); |
| | | // 解析响应JSON |
| | | JSONObject responseJson = JSONObject.parseObject(string); |
| | | String result = responseJson.getString("result"); |
| | | if("Add Successful.".equals(result)){ |
| | | return R.ok(); |
| | | }else { |
| | | String errorMsg = responseJson.getString("error_msg"); |
| | | return R.fail(errorMsg); |
| | | } |
| | | } |
| | | } catch (IOException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | return R.fail(); |
| | | } |
| | | public static R addANumberTest(String number, String realName, String idNumber, String fileName) { |
| | | JSONObject requestBody = new JSONObject(); |
| | | JSONArray numbers = new JSONArray(); |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("number", "+86"+number); // 手机号码 |
| | | jsonObject.put("numberType", 1); // 号码类型 1=手机号 2=固话 |
| | | jsonObject.put("name", realName); // 真实姓名 |
| | | jsonObject.put("identityCard",idNumber); // 身份证号 |
| | | jsonObject.put("liveFaceImage", fileName); // 号码所属人现场照片文件名 |
| | | numbers.add(jsonObject); |
| | | requestBody.put("numbers", numbers); |
| | | OkHttpClient client = new OkHttpClient().newBuilder() |
| | | .build(); |
| | | // 构建json请求体 |
| | | MediaType mediaType = MediaType.parse("application/json"); |
| | | String requestBodyJson = requestBody.toJSONString(); |
| | | RequestBody body = RequestBody.create(mediaType, requestBodyJson); |
| | | Request request = new Request.Builder() |
| | | .url("https://rtc.cn-north-1.myhuaweicloud.com/v1.0/privatenumber/a-number?agree_authorization_statement=true") |
| | | .method("POST", body) |
| | | .addHeader("X-Auth-Token", getTokenTest()) |
| | | .addHeader("Content-Type", "application/json") |
| | | .addHeader("Accept", "application/json") |
| | | .build(); |
| | | Response response = null; |
| | | try { |
| | | response = client.newCall(request).execute(); |
| | | ResponseBody responseBody = response.body(); |
| | | if(responseBody != null) { |
| | | String string = responseBody.string(); |
| | | log.info("新增租户级 A 号码报备接口:{}",string); |
| | | System.err.println("body:::::::::::::::::+++++++++++"+string); |
| | | // 解析响应JSON |
| | | JSONObject responseJson = JSONObject.parseObject(string); |
| | | String result = responseJson.getString("result"); |
| | | if("Add Successful.".equals(result)){ |
| | | return R.ok(); |
| | | }else { |
| | | String errorMsg = responseJson.getString("error_msg"); |
| | | return R.fail(errorMsg); |
| | | } |
| | | } |
| | | } catch (IOException e) { |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | return R.fail(); |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | // String token = "MIINawYJKoZIhvcNAQcCoIINXDCCDVgCAQExDTALBglghkgBZQMEAgEwggt9BgkqhkiG9w0BBwGgggtuBIILansidG9rZW4iOnsiZXhwaXJlc19hdCI6IjIwMjUtMTAtMjFUMDI6Mzc6NTAuODE0MDAwWiIsIm1ldGhvZHMiOlsicGFzc3dvcmQiXSwiY2F0YWxvZyI6W10sInJvbGVzIjpbeyJuYW1lIjoib3BfZ2F0ZWRfY3Nic19yZXBfYWNjZWxlcmF0aW9uIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfZWNzX2Rpc2tBY2MiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9kc3NfbW9udGgiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9vYnNfZGVlcF9hcmNoaXZlIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfYV9jbi1zb3V0aC00YyIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2RlY19tb250aF91c2VyIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfY2JyX3NlbGxvdXQiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9lY3Nfb2xkX3Jlb3VyY2UiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9ldnNfUm95YWx0eSIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX3dlbGlua2JyaWRnZV9lbmRwb2ludF9idXkiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9jYnJfZmlsZSIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2Rtcy1yb2NrZXRtcTUtYmFzaWMiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9ldnNfRVNpbmdsZV9jb3B5U1NEIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfZG1zLWthZmthMyIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX29ic19kZWNfbW9udGgiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9jc2JzX3Jlc3RvcmUiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9jYnJfdm13YXJlIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfaWRtZV9tYm1fZm91bmRhdGlvbiIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX211bHRpX2JpbmQiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9zbW5fY2FsbG5vdGlmeSIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2FfYXAtc291dGhlYXN0LTNkIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfY3Nic19wcm9ncmVzc2JhciIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2Nlc19yZXNvdXJjZWdyb3VwX3RhZyIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2Vjc19vZmZsaW5lX2FjNyIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2V2c19yZXR5cGUiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9rb29tYXAiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9ldnNfZXNzZDIiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9kbXMtYW1xcC1iYXNpYyIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2V2c19wb29sX2NhIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfYV9jbi1zb3V0aHdlc3QtMmIiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9od2NwaCIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2Vjc19vZmZsaW5lX2Rpc2tfNCIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX3Ntbl93ZWxpbmtyZWQiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9odl92ZW5kb3IiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9hX2NuLW5vcnRoLTRlIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfYV9jbi1ub3J0aC00ZCIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2Vjc19oZWNzX3giLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9jYnJfZmlsZXNfYmFja3VwIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfZWNzX2FjNyIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2VwcyIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2NzYnNfcmVzdG9yZV9hbGwiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9hX2NuLW5vcnRoLTRmIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfb3BfZ2F0ZWRfcm91bmR0YWJsZSIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2V2c19leHQiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9wZnNfZGVlcF9hcmNoaXZlIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfYV9hcC1zb3V0aGVhc3QtMWUiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9hX3J1LW1vc2Nvdy0xYiIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2FfYXAtc291dGhlYXN0LTFkIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfYXBwc3RhZ2UiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9hX2FwLXNvdXRoZWFzdC0xZiIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX3Ntbl9hcHBsaWNhdGlvbiIsImlkIjoiMCJ9LHsibmFtZSI6Im9wX2dhdGVkX2V2c19jb2xkIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfZWNzX2dwdV9nNXIiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9vcF9nYXRlZF9tZXNzYWdlb3ZlcjVnIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfZWNzX3JpIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfYV9ydS1ub3J0aHdlc3QtMmMiLCJpZCI6IjAifSx7Im5hbWUiOiJvcF9nYXRlZF9pZWZfcGxhdGludW0iLCJpZCI6IjAifV0sInByb2plY3QiOnsiZG9tYWluIjp7Im5hbWUiOiJoc2cxMzQzNzE3MzQ0MCIsImlkIjoiNDY5ZWU1MzAzMjdlNGYzOTkxMTgyNjg0MmRiY2E3ZTcifSwibmFtZSI6ImNuLW5vcnRoLTEiLCJpZCI6IjY3MDc2YWVjOTAyODQ4Zjc4NGI3YWMxMzk0NzY1NmYzIn0sImlzc3VlZF9hdCI6IjIwMjUtMTAtMjBUMDI6Mzc6NTAuODE0MDAwWiIsInVzZXIiOnsiZG9tYWluIjp7Im5hbWUiOiJoc2cxMzQzNzE3MzQ0MCIsImlkIjoiNDY5ZWU1MzAzMjdlNGYzOTkxMTgyNjg0MmRiY2E3ZTcifSwibmFtZSI6ImRlbmdsdSIsInBhc3N3b3JkX2V4cGlyZXNfYXQiOiIiLCJpZCI6IjMyN2YwNjQ0N2Y1OTRkYzc5M2JjOTg4NTkwOGUwZWRiIn19fTGCAcEwggG9AgEBMIGXMIGJMQswCQYDVQQGEwJDTjESMBAGA1UECAwJR3VhbmdEb25nMREwDwYDVQQHDAhTaGVuWmhlbjEuMCwGA1UECgwlSHVhd2VpIFNvZnR3YXJlIFRlY2hub2xvZ2llcyBDby4sIEx0ZDEOMAwGA1UECwwFQ2xvdWQxEzARBgNVBAMMCmNhLmlhbS5wa2kCCQDcsytdEGFqEDALBglghkgBZQMEAgEwDQYJKoZIhvcNAQEBBQAEggEAbtVzZi6mqzlm1pyXLoQK2jNhfm5hqnjO8LrWK5FK1rtWpQU8ouEFJBfUDor6kcJpetMnf8fnpJF9Lmd+rT8N5-39Cpdr831ooUJufWIzBSt8Y+N+IoFUpQd-Ut5PRl0YpGWf90015EHcY-hhJk6rW-URTPXwC57f8CGkd3gOF7PPlv9TzIYtyjpCCjJah2kGjqfogYIQ9l1EBsZQplYd5OaYaH-dvxFBA8tlNteaEWGRAfhqsu6bbMVXlFG0VwlnQdUFvR6N7dUytmgKxaaHjyH2KUuGwgh6ELevfnYyqoYk-UAarnr3MbrnpmfcL7z3D-4aBOSTmXIOIHFkFRiUCQ=="; |
| | | R r = uploadNumberFileTest("https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/38878509-00b7-4fb2-9c3a-b53d8161d84a.jpg",""); |
| | | // System.err.println(r.getMsg()); |
| | | // String tokenTest = getTokenTest(); |
| | | // System.err.println(tokenTest); |
| | | // R r = addANumberTest("17828262728", "刘杰", "511028200002150816", "avatar6278474701910805124b53d8161d84a.jpg"); |
| | | // System.err.println(r.getMsg()); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.utils; |
| | | |
| | | import org.apache.http.entity.ContentType; |
| | | import org.springframework.mock.web.MockMultipartFile; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.*; |
| | | import java.net.URL; |
| | | |
| | | public class UrlToMultipartFileUtil { |
| | | |
| | | // url: 链接,可访问的图片,视频,或其他文件 |
| | | public static MultipartFile urlTransferMultipartFile(String url){ |
| | | //对本地文件命名,可以从链接截取,可以自己手写,看需求 https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/98c0800f-3178-4db5-bf21-d53de2ed7849.jpg |
| | | // 截取出文件名,不包含尾缀 |
| | | String fileName = url.substring(url.lastIndexOf("-") + 1); |
| | | File file = null; |
| | | URL urlfile; |
| | | InputStream inStream = null; |
| | | OutputStream os = null; |
| | | MultipartFile multipartFile = null; |
| | | try { |
| | | file = File.createTempFile("avatar", fileName); |
| | | //下载 |
| | | urlfile = new URL(url); |
| | | inStream = urlfile.openStream(); |
| | | os = new FileOutputStream(file); |
| | | |
| | | int bytesRead = 0; |
| | | byte[] buffer = new byte[8192]; |
| | | while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) { |
| | | os.write(buffer, 0, bytesRead); |
| | | } |
| | | // file转multipartFile,如果只需要转File就不用加下面这两行代码,直接返回File即可 |
| | | FileInputStream inputStream = new FileInputStream(file); |
| | | multipartFile = new MockMultipartFile(file.getName(), file.getName(), |
| | | ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | if (null != os) { |
| | | os.close(); |
| | | } |
| | | if (null != inStream) { |
| | | inStream.close(); |
| | | } |
| | | // 用完删除 |
| | | if (null != file){ |
| | | file.delete(); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | // 按需返回file还是multipartFile |
| | | return multipartFile; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.voice.service; |
| | | |
| | | /** |
| | | * AXB模式接口 |
| | | */ |
| | | public interface IAXBInterfaceDemo { |
| | | /** |
| | | * Set X number to be the privacy number between number a and number b | |
| | | * 隐私号码AXB绑定 |
| | | * |
| | | * @param relationNum 关系号码 |
| | | * @param callerNum 主叫号码 |
| | | * @param calleeNum 被叫号码 |
| | | */ |
| | | String axbBindNumber(String relationNum, String callerNum, String calleeNum); |
| | | |
| | | /** |
| | | * Modify number a/b of the privacy relationship assigned by subscriptionId | |
| | | * 隐私号码AXB绑定信息修改 |
| | | * |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param callerNum 主叫号码 |
| | | * @param calleeNum 被叫号码 |
| | | */ |
| | | void axbModifyNumber(String subscriptionId, String callerNum, String calleeNum); |
| | | |
| | | /** |
| | | * Unbind the privacy relationship between number a and number b | 隐私号码AXB解绑 |
| | | * |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param relationNum 关系号码 都传时以subscriptionId优先 |
| | | */ |
| | | void axbUnbindNumber(String subscriptionId, String relationNum); |
| | | |
| | | /** |
| | | * Query the privacy binding relationship on the X number | 查询AXB绑定信息 |
| | | * |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param relationNum 关系号码 都传时以subscriptionId优先 |
| | | */ |
| | | void axbQueryBindRelation(String subscriptionId, String relationNum); |
| | | |
| | | /** |
| | | * Get download link of the record file created in call | 获取录音文件下载地址 |
| | | * |
| | | * @param recordDomain 录音文件存储的服务器域名 |
| | | * @param fileName 录音文件名 |
| | | */ |
| | | String axbGetRecordDownloadLink(String recordDomain, String fileName); |
| | | |
| | | /** |
| | | * Stop the call on the X number assigned by sessionid | 终止呼叫 |
| | | * |
| | | * @param sessionid 呼叫会话ID 通过"呼叫事件通知接口"获取 |
| | | */ |
| | | void axbStopCall(String sessionid); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.voice.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.ruoyi.admin.voice.service.IAXBInterfaceDemo; |
| | | import com.ruoyi.admin.voice.util.HttpUtilClient; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * AXB模式接口测试 |
| | | */ |
| | | @Slf4j |
| | | public class AXBInterfaceDemoImpl implements IAXBInterfaceDemo { |
| | | |
| | | private String appKey; // APP_Key |
| | | private String appSecret; // APP_Secret |
| | | private String ompDomainName; // APP接入地址 |
| | | |
| | | public AXBInterfaceDemoImpl(String appKey, String appSecret, String ompDomainName) { |
| | | this.appKey = appKey; |
| | | this.appSecret = appSecret; |
| | | this.ompDomainName = ompDomainName; |
| | | } |
| | | |
| | | /** |
| | | * Build the real url of https request | 构建隐私保护通话平台请求路径 |
| | | * |
| | | * @param path 接口访问URI |
| | | * @return |
| | | */ |
| | | private String buildOmpUrl(String path) { |
| | | return ompDomainName + path; |
| | | } |
| | | |
| | | @Override |
| | | public String axbBindNumber(String relationNum, String callerNum, String calleeNum) { |
| | | if (StringUtils.isBlank(relationNum) || StringUtils.isBlank(callerNum) || StringUtils.isBlank(calleeNum)) { |
| | | log.info("axbBindNumber set params error"); |
| | | throw new ServiceException("axbBindNumber set params error"); |
| | | } |
| | | |
| | | // 必填,AXB模式绑定接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 封装JOSN请求 |
| | | JSONObject json = new JSONObject(); |
| | | json.put("relationNum", relationNum); // X号码(关系号码) |
| | | json.put("callerNum", callerNum); // A方真实号码(手机或固话) |
| | | json.put("calleeNum", calleeNum); // B方真实号码(手机或固话) |
| | | |
| | | /** |
| | | * 选填,各参数要求请参考"AXB模式绑定接口" |
| | | */ |
| | | // json.put("areaCode", "0755"); //城市码 |
| | | // json.put("areaMatchMode", "1"); //号码筛选方式 |
| | | // json.put("callDirection", 0); //允许呼叫的方向 |
| | | // json.put("duration", 86400); //绑定关系保持时间 |
| | | // json.put("recordFlag", false); //是否通话录音 |
| | | // json.put("recordHintTone", "recordHintTone.wav"); //录音提示音 |
| | | // json.put("maxDuration", 60); //单次通话最长时间 |
| | | // json.put("lastMinVoice", "lastMinVoice.wav"); //通话最后一分钟提示音 |
| | | // json.put("privateSms", true); //是否支持短信功能 |
| | | // JSONObject preVoice = new JSONObject(); |
| | | // preVoice.put("callerHintTone", "callerHintTone.wav"); //设置A拨打X号码时的通话前等待音 |
| | | // preVoice.put("calleeHintTone", "calleeHintTone.wav"); //设置B拨打X号码时的通话前等待音 |
| | | // json.put("preVoice", preVoice); //个性化通话前等待音 |
| | | |
| | | String result = HttpUtilClient.sendPost(appKey, appSecret, realUrl, json.toString()); |
| | | log.info("Response is :" + result); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public void axbModifyNumber(String subscriptionId, String callerNum, String calleeNum) { |
| | | if (StringUtils.isBlank(subscriptionId)) { |
| | | log.info("axbModifyNumber set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式绑定信息修改接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 封装JOSN请求 |
| | | JSONObject json = new JSONObject(); |
| | | json.put("subscriptionId", subscriptionId); // 绑定关系ID |
| | | if (StringUtils.isNotBlank(callerNum)) { |
| | | json.put("callerNum", callerNum); // 将A方修改为新的号码(手机或固话) |
| | | } |
| | | if (StringUtils.isNotBlank(calleeNum)) { |
| | | json.put("calleeNum", calleeNum); // 将B方修改为新的号码(手机或固话) |
| | | } |
| | | |
| | | /** |
| | | * 选填,各参数要求请参考"AXB模式绑定信息修改接口" |
| | | */ |
| | | // json.put("callDirection", 0); //允许呼叫的方向 |
| | | // json.put("duration", 86400); //绑定关系保持时间 |
| | | // json.put("maxDuration", 90); //单次通话最长时间 |
| | | // json.put("lastMinVoice", "lastMinVoice.wav"); //通话最后一分钟提示音 |
| | | // json.put("privateSms", true); //是否支持短信功能 |
| | | // json.put("recordFlag", false); //是否通话录音 |
| | | // JSONObject preVoice = new JSONObject(); |
| | | // preVoice.put("callerHintTone", "callerHintTone.wav"); //设置A拨打X号码时的通话前等待音 |
| | | // preVoice.put("calleeHintTone", "calleeHintTone.wav"); //设置B拨打X号码时的通话前等待音 |
| | | // json.put("preVoice", preVoice); //个性化通话前等待音 |
| | | |
| | | String result = HttpUtilClient.sendPut(appKey, appSecret, realUrl, json.toString()); |
| | | log.info("Response is :" + result); |
| | | } |
| | | |
| | | @Override |
| | | public void axbUnbindNumber(String subscriptionId, String relationNum) { |
| | | if (StringUtils.isBlank(subscriptionId) && StringUtils.isBlank(relationNum)) { |
| | | log.info("axbUnbindNumber set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式解绑接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 申明对象 |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | if (StringUtils.isNotBlank(subscriptionId)) { |
| | | map.put("subscriptionId", subscriptionId); // 绑定关系ID |
| | | } else { |
| | | map.put("relationNum", relationNum); // X号码(关系号码) |
| | | } |
| | | |
| | | String result = HttpUtilClient.sendDelete(appKey, appSecret, realUrl, HttpUtilClient.map2UrlEncodeString(map)); |
| | | log.info("Response is :" + result); |
| | | } |
| | | |
| | | @Override |
| | | public void axbQueryBindRelation(String subscriptionId, String relationNum) { |
| | | if (StringUtils.isBlank(subscriptionId) && StringUtils.isBlank(relationNum)) { |
| | | log.info("axbQueryBindRelation set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式绑定信息查询接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 申明对象 |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | if (StringUtils.isNotBlank(subscriptionId)) { |
| | | map.put("subscriptionId", subscriptionId); // 绑定关系ID |
| | | } else { |
| | | map.put("relationNum", relationNum); // X号码(关系号码) |
| | | |
| | | /** |
| | | * 选填,各参数要求请参考"AXB模式绑定信息查询接口" |
| | | */ |
| | | // map.put("pageIndex", 1); //查询的分页索引,从1开始编号 |
| | | // map.put("pageSize", 20); //查询的分页大小,即每次查询返回多少条数据 |
| | | } |
| | | |
| | | String result = HttpUtilClient.sendGet(appKey, appSecret, realUrl, HttpUtilClient.map2UrlEncodeString(map)); |
| | | log.info("Response is :" + result); |
| | | } |
| | | |
| | | @Override |
| | | public String axbGetRecordDownloadLink(String recordDomain, String fileName) { |
| | | if (StringUtils.isBlank(recordDomain) || StringUtils.isBlank(fileName)) { |
| | | log.info("axbGetRecordDownloadLink set params error"); |
| | | throw new ServiceException("axbGetRecordDownloadLink set params error"); |
| | | } |
| | | // 必填,AXB模式获取录音文件下载地址接口访问URI |
| | | String url = "/rest/provision/voice/record/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 申明对象 |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | map.put("recordDomain", recordDomain); // 录音文件存储的服务器域名 |
| | | map.put("fileName", fileName); // 录音文件名 |
| | | |
| | | String result = HttpUtilClient.sendGet(appKey, appSecret, realUrl, HttpUtilClient.map2UrlEncodeString(map)); |
| | | log.info("Response is :" + result); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public void axbStopCall(String sessionid) { |
| | | if (StringUtils.isBlank(sessionid)) { |
| | | log.info("axbStopCall set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式终止呼叫接口访问URI |
| | | String url = "/rest/httpsessions/callStop/v2.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 封装JOSN请求 |
| | | JSONObject json = new JSONObject(); |
| | | json.put("sessionid", sessionid); // 呼叫会话ID |
| | | json.put("signal", "call_stop"); // 取值固定为"call_stop" |
| | | |
| | | String result = HttpUtilClient.sendPost(appKey, appSecret, realUrl, json.toString()); |
| | | log.info("Response is :" + result); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.voice.util; |
| | | |
| | | |
| | | import com.ruoyi.admin.voice.service.IAXBInterfaceDemo; |
| | | import com.ruoyi.admin.voice.service.impl.AXBInterfaceDemoImpl; |
| | | |
| | | public class AXBUtil { |
| | | |
| | | /** |
| | | * 必填,请登录管理控制台,从"应用管理"页获取 |
| | | */ |
| | | private final static String OMPDOMAINNAME = "https://rtcpns.cn-north-1.myhuaweicloud.com"; // APP接入地址 |
| | | |
| | | /** |
| | | * AXB模式 绑定号码 |
| | | * @param relationNum X 隐私号码 13154610294 |
| | | * @param callerNum A |
| | | * @param calleeNum B |
| | | */ |
| | | public static String axbBindNumber(String appKey,String appSecret,String relationNum, String callerNum, String calleeNum) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第一步: 号码绑定,即调用AXB模式绑定接口 93f4474b-3e0b-490d-bd1d-b6fd31b63c0b |
| | | return axb.axbBindNumber("+86"+relationNum, "+86"+callerNum, "+86"+calleeNum); |
| | | } |
| | | |
| | | /** |
| | | * Get download link of the record file created in call | 获取录音文件下载地址 |
| | | * @param recordDomain 录音文件存储的服务器域名 |
| | | * @param fileName 录音文件名 |
| | | */ |
| | | public static String axbGetRecordDownloadLink(String appKey,String appSecret,String recordDomain, String fileName) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第三步: 用户通话结束,若设置录音,则商户可以获取录音文件下载地址,即调用获取录音文件下载地址接口 |
| | | return axb.axbGetRecordDownloadLink(recordDomain, fileName); |
| | | } |
| | | /** |
| | | * Modify number a/b of the privacy relationship assigned by subscriptionId | |
| | | * 隐私号码AXB绑定信息修改 |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param callerNum 主叫号码 |
| | | * @param calleeNum 被叫号码 |
| | | */ |
| | | public static void axbModifyNumber(String appKey,String appSecret,String subscriptionId, String callerNum, String calleeNum) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第四步: 根据业务需求,可更改绑定关系,即调用AXB模式绑定信息修改接口 |
| | | axb.axbModifyNumber(subscriptionId, callerNum, calleeNum); |
| | | } |
| | | |
| | | /** |
| | | * AXB模式 解绑号码 |
| | | * @param subscriptionId 绑定号码后的唯一标识 |
| | | * @param relationNum X 隐私号码 13154610294 |
| | | */ |
| | | public static void axbUnbindNumber(String appKey,String appSecret,String subscriptionId, String relationNum) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第五步: 隐私号码循环使用,商户可将绑定关系解绑,即调用AXB模式解绑接口 |
| | | axb.axbUnbindNumber(subscriptionId, "+86"+relationNum); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.admin.voice.util; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.IOUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | |
| | | import javax.net.ssl.*; |
| | | import java.io.*; |
| | | import java.net.URL; |
| | | import java.net.URLEncoder; |
| | | import java.security.cert.CertificateException; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * HTTP协议传输工具类 |
| | | */ |
| | | @Slf4j |
| | | public class HttpUtilClient { |
| | | |
| | | private static final int HTTP_STATUS_OK = 200; |
| | | |
| | | /** |
| | | * 向指定 URL发送POST方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param jsonBody |
| | | * @return |
| | | */ |
| | | public static String sendPost(String appKey, String appSecret, String url, String jsonBody) { |
| | | DataOutputStream out = null; |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | URL realUrl = new URL(url); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoOutput(true); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("POST"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | |
| | | log.info("RequestBody is : " + jsonBody); |
| | | |
| | | connection.connect(); |
| | | out = new DataOutputStream(connection.getOutputStream()); |
| | | out.writeBytes(jsonBody); |
| | | out.flush(); |
| | | out.close(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (HTTP_STATUS_OK == status) { |
| | | is = connection.getInputStream(); |
| | | } else { |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is, "UTF-8")); |
| | | String line = ""; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send Post request catch exception: " + e.toString()); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(out); |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL发送PUT方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param jsonBody |
| | | * @return |
| | | */ |
| | | public static String sendPut(String appKey, String appSecret, String url, String jsonBody) { |
| | | DataOutputStream out = null; |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | URL realUrl = new URL(url); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoOutput(true); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("PUT"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | |
| | | log.info("RequestBody is : " + jsonBody); |
| | | |
| | | connection.connect(); |
| | | out = new DataOutputStream(connection.getOutputStream()); |
| | | out.writeBytes(jsonBody); |
| | | out.flush(); |
| | | out.close(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (HTTP_STATUS_OK == status) { |
| | | is = connection.getInputStream(); |
| | | } else { |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send Put request catch exception: " + e.toString()); |
| | | e.printStackTrace(); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(out); |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL发送DELETE方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param params |
| | | * @return |
| | | */ |
| | | public static String sendDelete(String appKey, String appSecret, String url, String params) { |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | String realPath = url + (StringUtils.isEmpty(params) ? "" : "?" + params); |
| | | URL realUrl = new URL(realPath); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("DELETE"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | |
| | | log.info("RequestBody is : " + params); |
| | | |
| | | connection.connect(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (HTTP_STATUS_OK == status) { |
| | | is = connection.getInputStream(); |
| | | } else { |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send DELETE request catch exception: " + e.toString()); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL发送GET方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param params |
| | | * @return |
| | | */ |
| | | public static String sendGet(String appKey, String appSecret, String url, String params) { |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | String realPath = url + (StringUtils.isEmpty(params) ? "" : "?" + params); |
| | | URL realUrl = new URL(realPath); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("GET"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | connection.setInstanceFollowRedirects(false); //设置本次连接不自动处理重定向 |
| | | |
| | | log.info("RequestBody is : " + params); |
| | | |
| | | connection.connect(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (301 == status) { //获取录音文件下载地址 |
| | | return connection.getHeaderField("Location"); |
| | | }else if (HTTP_STATUS_OK == status) { //查询绑定信息 |
| | | is = connection.getInputStream(); |
| | | } else { //获取错误码 |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send GET request catch exception: " + e.toString()); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 键值对转查询url |
| | | * |
| | | * @param map |
| | | * @return |
| | | */ |
| | | public static String map2UrlEncodeString(Map<String, Object> map) { |
| | | if(null == map || map.isEmpty()) { |
| | | return ""; |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | String temp = ""; |
| | | |
| | | for (String s : map.keySet()) { |
| | | try { |
| | | temp = URLEncoder.encode(String.valueOf(map.get(s)), "UTF-8"); |
| | | } catch (UnsupportedEncodingException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | sb.append(s).append("=").append(temp).append("&"); |
| | | } |
| | | return sb.deleteCharAt(sb.length() - 1).toString(); |
| | | } |
| | | |
| | | /** |
| | | * 忽略SSL证书校验 |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | static void trustAllHttpsCertificates() throws Exception { |
| | | TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { |
| | | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { |
| | | return; |
| | | } |
| | | |
| | | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { |
| | | return; |
| | | } |
| | | |
| | | public X509Certificate[] getAcceptedIssuers() { |
| | | return null; |
| | | } |
| | | } }; |
| | | SSLContext sc = SSLContext.getInstance("SSL"); |
| | | sc.init(null, trustAllCerts, null); |
| | | HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright Notice: |
| | | * Copyright 1998-2008, Huawei Technologies Co., Ltd. ALL Rights Reserved. |
| | | * |
| | | * Warning: This computer software sourcecode is protected by copyright law |
| | | * and international treaties. Unauthorized reproduction or distribution |
| | | * of this sourcecode, or any portion of it, may result in severe civil and |
| | | * criminal penalties, and will be prosecuted to the maximum extent |
| | | * possible under the law. |
| | | */ |
| | | package com.ruoyi.admin.voice.util; |
| | | |
| | | //import java.nio.charset.Charset; |
| | | |
| | | import javax.crypto.Mac; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | public class StringUtil { |
| | | public static final String AKSK_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\""; |
| | | |
| | | public static boolean strIsNullOrEmpty(String s) { |
| | | return (null == s || s.trim().length() < 1); |
| | | } |
| | | |
| | | public static String buildAKSKHeader(String appKey, String appSecret) throws Exception { |
| | | if (StringUtil.strIsNullOrEmpty(appKey) || StringUtil.strIsNullOrEmpty(appSecret)) { |
| | | return null; |
| | | } |
| | | |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); |
| | | format.setTimeZone(TimeZone.getTimeZone("UTC")); |
| | | Calendar calendar = Calendar.getInstance(); |
| | | String time = format.format(calendar.getTime()); |
| | | String stNonce = UUID.randomUUID().toString().replace("-", "").toUpperCase(Locale.ROOT); |
| | | String str = stNonce + time; |
| | | Mac mac = Mac.getInstance("HmacSHA256"); |
| | | mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); |
| | | byte[] authBytes = mac.doFinal(str.getBytes(StandardCharsets.UTF_8)); |
| | | String passwordDigestBase64Str = encodeBase64(authBytes); |
| | | return String.format(AKSK_HEADER_FORMAT, appKey, passwordDigestBase64Str, stNonce, time); |
| | | } |
| | | |
| | | private static String encodeBase64(byte[] bytes) { |
| | | if (bytes.length == 0) { |
| | | return null; |
| | | } else { |
| | | return new String(Base64.getEncoder().encode(bytes), StandardCharsets.UTF_8); |
| | | } |
| | | } |
| | | } |
| | |
| | | .eq(Order::getId, orderId).set(Order::getState, state).update()); |
| | | } |
| | | |
| | | /** |
| | | * 更改订单虚拟童话绑定id |
| | | */ |
| | | @ApiOperation(value = "订单列表-设置虚拟号码绑定id", tags = {"后台-订单管理"}) |
| | | @GetMapping(value = "/updateSubscriptionId") |
| | | public R<Boolean> updateSubscriptionId(@RequestParam("orderId") String orderId, |
| | | @RequestParam("subscriptionId")String subscriptionId, |
| | | @RequestParam("virtualNumber")String virtualNumber) { |
| | | // 修改订单设置绑定id |
| | | orderService.lambdaUpdate().eq(Order::getId, orderId) |
| | | .set(Order::getSubscriptionId, subscriptionId) |
| | | .set(Order::getVirtualNumber, virtualNumber) |
| | | .update(); |
| | | return R.ok(); |
| | | } |
| | | /** |
| | | * 更改订单虚拟童话录音 |
| | | */ |
| | | @ApiOperation(value = "订单列表-设置虚拟号码绑定id", tags = {"后台-订单管理"}) |
| | | @GetMapping(value = "/updatePhoneRecording") |
| | | public R<Boolean> updatePhoneRecording(@RequestParam("orderId") String orderId, |
| | | @RequestParam("audioUrl")String audioUrl) { |
| | | // 修改订单设置绑定id |
| | | orderService.lambdaUpdate().eq(Order::getId, orderId) |
| | | .set(Order::getPhoneRecording, audioUrl) |
| | | .update(); |
| | | return R.ok(); |
| | | } |
| | | |
| | | |
| | | @ApiOperation(value = "订单列表-增加打印次数", tags = {"后台-订单管理"}) |
| | | @PostMapping(value = "/count") |
| | |
| | | @ApiOperation(value = "订单完工-提交订单", tags = {"师傅端-订单列表"}) |
| | | @PostMapping(value = "/orderSubmit") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public R<Boolean> orderSubmit(@RequestBody OrderSubmitRequest orderSubmitRequest) { |
| | | public R<String> orderSubmit(@RequestBody OrderSubmitRequest orderSubmitRequest) { |
| | | // 订单信息 |
| | | Order order = orderService.lambdaQuery().eq(Order::getId, orderSubmitRequest.getOrderId()) |
| | | .eq(Order::getIsDelete, 0).one(); |
| | |
| | | serveRecord.setCardPic(orderSubmitRequest.getCardPic()); |
| | | serveRecord.setMachinePic(orderSubmitRequest.getMachinePic()); |
| | | boolean save = serveRecordService.save(serveRecord); |
| | | return R.ok(update && save); |
| | | if(update && save){ |
| | | return R.ok(order.getSubscriptionId(), "订单提交成功!"); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | |
| | | @TableField("msg_count") |
| | | private Integer msgCount; |
| | | |
| | | @ApiModelProperty("绑定关系id") |
| | | @TableField("subscription_id") |
| | | private String subscriptionId; |
| | | @ApiModelProperty("虚拟号码") |
| | | @TableField("virtual_number") |
| | | private String virtualNumber; |
| | | @ApiModelProperty("电话录音") |
| | | @TableField("phone_recording") |
| | | private String phoneRecording; |
| | | @ApiModelProperty("录音文件存储的服务器域名") |
| | | @TableField("record_domain") |
| | | private String recordDomain; |
| | | @ApiModelProperty("录音文件名") |
| | | @TableField("record_object_name") |
| | | private String recordObjectName; |
| | | } |
| | |
| | | import cn.afterturn.easypoi.cache.manager.IFileLoader; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.admin.api.feignClient.AdminClient; |
| | | import com.ruoyi.common.core.constant.Constants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.domain.Result; |
| | |
| | | import com.ruoyi.order.api.feignClient.ExchangeDispatchClient; |
| | | import com.ruoyi.order.api.feignClient.OrderClient; |
| | | import com.ruoyi.system.api.model.LoginUserInfo; |
| | | import com.ruoyi.worker.entity.IamConfig; |
| | | import com.ruoyi.worker.entity.MasterWorker; |
| | | import com.ruoyi.worker.entity.RecoveryServe; |
| | | import com.ruoyi.worker.service.IamConfigService; |
| | | import com.ruoyi.worker.service.MasterWorkerService; |
| | | import com.ruoyi.worker.service.RecoveryServeService; |
| | | import com.ruoyi.worker.vo.ServeCoordinate; |
| | | import com.ruoyi.worker.voice.util.AXBUtil; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | |
| | | import java.time.Duration; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Optional; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.stream.Collectors; |
| | | import javax.annotation.Resource; |
| | | |
| | | import lombok.Synchronized; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.StringUtils; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | |
| | | |
| | | @Resource |
| | | private RedisService redisService; |
| | | @Resource |
| | | private IamConfigService iamConfigService; |
| | | |
| | | /** |
| | | * linux服务器保存订单轨迹文件夹 |
| | |
| | | if (null == loginWorker) { |
| | | return R.loginExpire("登录失效!"); |
| | | } |
| | | return orderClient.orderSubmit(orderSubmitRequest); |
| | | R<String> result = orderClient.orderSubmit(orderSubmitRequest); |
| | | String subscriptionId = result.getData(); |
| | | boolean flag = false; |
| | | if (StringUtils.hasLength(subscriptionId)) { |
| | | IamConfig iamConfig = iamConfigService.getById(1); |
| | | // 查询音频链接 |
| | | OrderDetailVO data = orderClient.orderDetail(orderSubmitRequest.getOrderId()).getData(); |
| | | if(Objects.nonNull(data)){ |
| | | Order orderInfo = data.getOrderInfo(); |
| | | if (Objects.nonNull(orderInfo)){ |
| | | String recordDomain = orderInfo.getRecordDomain(); |
| | | String recordObjectName = orderInfo.getRecordObjectName(); |
| | | String audioUrl = AXBUtil.axbGetRecordDownloadLink(iamConfig.getAppKey(), iamConfig.getAppSecret(),recordDomain, recordObjectName); |
| | | orderInfo.setPhoneRecording(audioUrl); |
| | | // 设置音频 |
| | | orderClient.updatePhoneRecording(orderInfo.getId(), audioUrl); |
| | | } |
| | | } |
| | | // 虚拟号码解绑 |
| | | AXBUtil.axbUnbindNumber(iamConfig.getAppKey(), iamConfig.getAppSecret(),subscriptionId, iamConfig.getVirtualNumber()); |
| | | flag = true; |
| | | } |
| | | return R.ok(flag); |
| | | } |
| | | private static final double EARTH_RADIUS_METERS = 6371000.0; |
| | | /** |
| New file |
| | |
| | | package com.ruoyi.worker.entity; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Getter; |
| | | import lombok.Setter; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * 虚拟号码配置 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | @Getter |
| | | @Setter |
| | | @TableName("t_iam_config") |
| | | @ApiModel(value = "t_iam_config对象", description = "虚拟号码配置") |
| | | public class IamConfig implements Serializable { |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Integer id; |
| | | @ApiModelProperty("用户") |
| | | @TableField("userName") |
| | | private String userName; |
| | | @ApiModelProperty("子账号") |
| | | @TableField("account") |
| | | private String account; |
| | | @ApiModelProperty("子账号密码") |
| | | @TableField("password") |
| | | private String password; |
| | | @ApiModelProperty("虚拟号码APP_Key") |
| | | @TableField("appKey") |
| | | private String appKey; |
| | | @ApiModelProperty("虚拟号码APP_Secret") |
| | | @TableField("appSecret") |
| | | private String appSecret; |
| | | @ApiModelProperty("虚拟号码") |
| | | @TableField("virtualNumber") |
| | | private String virtualNumber; |
| | | } |
| New file |
| | |
| | | package com.ruoyi.worker.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.worker.entity.IamConfig; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * <p> |
| | | * 虚拟号码管理 Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | @Mapper |
| | | public interface IamConfigMapper extends BaseMapper<IamConfig> { |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.worker.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.worker.entity.IamConfig; |
| | | |
| | | /** |
| | | * <p> |
| | | * 改派管理 服务类 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | public interface IamConfigService extends IService<IamConfig> { |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.worker.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.worker.entity.IamConfig; |
| | | import com.ruoyi.worker.mapper.IamConfigMapper; |
| | | import com.ruoyi.worker.service.IamConfigService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 改派管理 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author hjl |
| | | * @since 2024-07-08 |
| | | */ |
| | | @Service |
| | | public class IamConfigServiceImpl extends ServiceImpl<IamConfigMapper, IamConfig> implements IamConfigService { |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.worker.voice.service; |
| | | |
| | | /** |
| | | * AXB模式接口 |
| | | */ |
| | | public interface IAXBInterfaceDemo { |
| | | /** |
| | | * Set X number to be the privacy number between number a and number b | |
| | | * 隐私号码AXB绑定 |
| | | * |
| | | * @param relationNum 关系号码 |
| | | * @param callerNum 主叫号码 |
| | | * @param calleeNum 被叫号码 |
| | | */ |
| | | String axbBindNumber(String relationNum, String callerNum, String calleeNum); |
| | | |
| | | /** |
| | | * Modify number a/b of the privacy relationship assigned by subscriptionId | |
| | | * 隐私号码AXB绑定信息修改 |
| | | * |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param callerNum 主叫号码 |
| | | * @param calleeNum 被叫号码 |
| | | */ |
| | | void axbModifyNumber(String subscriptionId, String callerNum, String calleeNum); |
| | | |
| | | /** |
| | | * Unbind the privacy relationship between number a and number b | 隐私号码AXB解绑 |
| | | * |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param relationNum 关系号码 都传时以subscriptionId优先 |
| | | */ |
| | | void axbUnbindNumber(String subscriptionId, String relationNum); |
| | | |
| | | /** |
| | | * Query the privacy binding relationship on the X number | 查询AXB绑定信息 |
| | | * |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param relationNum 关系号码 都传时以subscriptionId优先 |
| | | */ |
| | | void axbQueryBindRelation(String subscriptionId, String relationNum); |
| | | |
| | | /** |
| | | * Get download link of the record file created in call | 获取录音文件下载地址 |
| | | * |
| | | * @param recordDomain 录音文件存储的服务器域名 |
| | | * @param fileName 录音文件名 |
| | | */ |
| | | String axbGetRecordDownloadLink(String recordDomain, String fileName); |
| | | |
| | | /** |
| | | * Stop the call on the X number assigned by sessionid | 终止呼叫 |
| | | * |
| | | * @param sessionid 呼叫会话ID 通过"呼叫事件通知接口"获取 |
| | | */ |
| | | void axbStopCall(String sessionid); |
| | | } |
| New file |
| | |
| | | package com.ruoyi.worker.voice.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.worker.voice.service.IAXBInterfaceDemo; |
| | | import com.ruoyi.worker.voice.util.HttpUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * AXB模式接口测试 |
| | | */ |
| | | @Slf4j |
| | | public class AXBInterfaceDemoImpl implements IAXBInterfaceDemo { |
| | | |
| | | private String appKey; // APP_Key |
| | | private String appSecret; // APP_Secret |
| | | private String ompDomainName; // APP接入地址 |
| | | |
| | | public AXBInterfaceDemoImpl(String appKey, String appSecret, String ompDomainName) { |
| | | this.appKey = appKey; |
| | | this.appSecret = appSecret; |
| | | this.ompDomainName = ompDomainName; |
| | | } |
| | | |
| | | /** |
| | | * Build the real url of https request | 构建隐私保护通话平台请求路径 |
| | | * |
| | | * @param path 接口访问URI |
| | | * @return |
| | | */ |
| | | private String buildOmpUrl(String path) { |
| | | return ompDomainName + path; |
| | | } |
| | | |
| | | @Override |
| | | public String axbBindNumber(String relationNum, String callerNum, String calleeNum) { |
| | | if (StringUtils.isBlank(relationNum) || StringUtils.isBlank(callerNum) || StringUtils.isBlank(calleeNum)) { |
| | | log.info("axbBindNumber set params error"); |
| | | throw new ServiceException("axbBindNumber set params error"); |
| | | } |
| | | |
| | | // 必填,AXB模式绑定接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 封装JOSN请求 |
| | | JSONObject json = new JSONObject(); |
| | | json.put("relationNum", relationNum); // X号码(关系号码) |
| | | json.put("callerNum", callerNum); // A方真实号码(手机或固话) |
| | | json.put("calleeNum", calleeNum); // B方真实号码(手机或固话) |
| | | |
| | | /** |
| | | * 选填,各参数要求请参考"AXB模式绑定接口" |
| | | */ |
| | | // json.put("areaCode", "0755"); //城市码 |
| | | // json.put("areaMatchMode", "1"); //号码筛选方式 |
| | | // json.put("callDirection", 0); //允许呼叫的方向 |
| | | // json.put("duration", 86400); //绑定关系保持时间 |
| | | // json.put("recordFlag", false); //是否通话录音 |
| | | // json.put("recordHintTone", "recordHintTone.wav"); //录音提示音 |
| | | // json.put("maxDuration", 60); //单次通话最长时间 |
| | | // json.put("lastMinVoice", "lastMinVoice.wav"); //通话最后一分钟提示音 |
| | | // json.put("privateSms", true); //是否支持短信功能 |
| | | // JSONObject preVoice = new JSONObject(); |
| | | // preVoice.put("callerHintTone", "callerHintTone.wav"); //设置A拨打X号码时的通话前等待音 |
| | | // preVoice.put("calleeHintTone", "calleeHintTone.wav"); //设置B拨打X号码时的通话前等待音 |
| | | // json.put("preVoice", preVoice); //个性化通话前等待音 |
| | | |
| | | String result = HttpUtil.sendPost(appKey, appSecret, realUrl, json.toString()); |
| | | log.info("Response is :" + result); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public void axbModifyNumber(String subscriptionId, String callerNum, String calleeNum) { |
| | | if (StringUtils.isBlank(subscriptionId)) { |
| | | log.info("axbModifyNumber set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式绑定信息修改接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 封装JOSN请求 |
| | | JSONObject json = new JSONObject(); |
| | | json.put("subscriptionId", subscriptionId); // 绑定关系ID |
| | | if (StringUtils.isNotBlank(callerNum)) { |
| | | json.put("callerNum", callerNum); // 将A方修改为新的号码(手机或固话) |
| | | } |
| | | if (StringUtils.isNotBlank(calleeNum)) { |
| | | json.put("calleeNum", calleeNum); // 将B方修改为新的号码(手机或固话) |
| | | } |
| | | |
| | | /** |
| | | * 选填,各参数要求请参考"AXB模式绑定信息修改接口" |
| | | */ |
| | | // json.put("callDirection", 0); //允许呼叫的方向 |
| | | // json.put("duration", 86400); //绑定关系保持时间 |
| | | // json.put("maxDuration", 90); //单次通话最长时间 |
| | | // json.put("lastMinVoice", "lastMinVoice.wav"); //通话最后一分钟提示音 |
| | | // json.put("privateSms", true); //是否支持短信功能 |
| | | // json.put("recordFlag", false); //是否通话录音 |
| | | // JSONObject preVoice = new JSONObject(); |
| | | // preVoice.put("callerHintTone", "callerHintTone.wav"); //设置A拨打X号码时的通话前等待音 |
| | | // preVoice.put("calleeHintTone", "calleeHintTone.wav"); //设置B拨打X号码时的通话前等待音 |
| | | // json.put("preVoice", preVoice); //个性化通话前等待音 |
| | | |
| | | String result = HttpUtil.sendPut(appKey, appSecret, realUrl, json.toString()); |
| | | log.info("Response is :" + result); |
| | | } |
| | | |
| | | @Override |
| | | public void axbUnbindNumber(String subscriptionId, String relationNum) { |
| | | if (StringUtils.isBlank(subscriptionId) && StringUtils.isBlank(relationNum)) { |
| | | log.info("axbUnbindNumber set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式解绑接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 申明对象 |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | if (StringUtils.isNotBlank(subscriptionId)) { |
| | | map.put("subscriptionId", subscriptionId); // 绑定关系ID |
| | | } else { |
| | | map.put("relationNum", relationNum); // X号码(关系号码) |
| | | } |
| | | |
| | | String result = HttpUtil.sendDelete(appKey, appSecret, realUrl, HttpUtil.map2UrlEncodeString(map)); |
| | | log.info("Response is :" + result); |
| | | } |
| | | |
| | | @Override |
| | | public void axbQueryBindRelation(String subscriptionId, String relationNum) { |
| | | if (StringUtils.isBlank(subscriptionId) && StringUtils.isBlank(relationNum)) { |
| | | log.info("axbQueryBindRelation set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式绑定信息查询接口访问URI |
| | | String url = "/rest/caas/relationnumber/partners/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 申明对象 |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | if (StringUtils.isNotBlank(subscriptionId)) { |
| | | map.put("subscriptionId", subscriptionId); // 绑定关系ID |
| | | } else { |
| | | map.put("relationNum", relationNum); // X号码(关系号码) |
| | | |
| | | /** |
| | | * 选填,各参数要求请参考"AXB模式绑定信息查询接口" |
| | | */ |
| | | // map.put("pageIndex", 1); //查询的分页索引,从1开始编号 |
| | | // map.put("pageSize", 20); //查询的分页大小,即每次查询返回多少条数据 |
| | | } |
| | | |
| | | String result = HttpUtil.sendGet(appKey, appSecret, realUrl, HttpUtil.map2UrlEncodeString(map)); |
| | | log.info("Response is :" + result); |
| | | } |
| | | |
| | | @Override |
| | | public String axbGetRecordDownloadLink(String recordDomain, String fileName) { |
| | | if (StringUtils.isBlank(recordDomain) || StringUtils.isBlank(fileName)) { |
| | | log.info("axbGetRecordDownloadLink set params error"); |
| | | throw new ServiceException("axbGetRecordDownloadLink set params error"); |
| | | } |
| | | // 必填,AXB模式获取录音文件下载地址接口访问URI |
| | | String url = "/rest/provision/voice/record/v1.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 申明对象 |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | map.put("recordDomain", recordDomain); // 录音文件存储的服务器域名 |
| | | map.put("fileName", fileName); // 录音文件名 |
| | | |
| | | String result = HttpUtil.sendGet(appKey, appSecret, realUrl, HttpUtil.map2UrlEncodeString(map)); |
| | | log.info("Response is :" + result); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public void axbStopCall(String sessionid) { |
| | | if (StringUtils.isBlank(sessionid)) { |
| | | log.info("axbStopCall set params error"); |
| | | return; |
| | | } |
| | | |
| | | // 必填,AXB模式终止呼叫接口访问URI |
| | | String url = "/rest/httpsessions/callStop/v2.0"; |
| | | String realUrl = buildOmpUrl(url); |
| | | |
| | | // 封装JOSN请求 |
| | | JSONObject json = new JSONObject(); |
| | | json.put("sessionid", sessionid); // 呼叫会话ID |
| | | json.put("signal", "call_stop"); // 取值固定为"call_stop" |
| | | |
| | | String result = HttpUtil.sendPost(appKey, appSecret, realUrl, json.toString()); |
| | | log.info("Response is :" + result); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ruoyi.worker.voice.util; |
| | | |
| | | |
| | | import com.ruoyi.worker.voice.service.IAXBInterfaceDemo; |
| | | import com.ruoyi.worker.voice.service.impl.AXBInterfaceDemoImpl; |
| | | |
| | | public class AXBUtil { |
| | | |
| | | /** |
| | | * 必填,请登录管理控制台,从"应用管理"页获取 |
| | | */ |
| | | private final static String OMPDOMAINNAME = "https://rtcpns.cn-north-1.myhuaweicloud.com"; // APP接入地址 |
| | | |
| | | /** |
| | | * AXB模式 绑定号码 |
| | | * @param relationNum X 隐私号码 13154610294 |
| | | * @param callerNum A |
| | | * @param calleeNum B |
| | | */ |
| | | public static String axbBindNumber(String appKey,String appSecret,String relationNum, String callerNum, String calleeNum) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第一步: 号码绑定,即调用AXB模式绑定接口 93f4474b-3e0b-490d-bd1d-b6fd31b63c0b |
| | | return axb.axbBindNumber("+86"+relationNum, "+86"+callerNum, "+86"+calleeNum); |
| | | } |
| | | |
| | | /** |
| | | * Get download link of the record file created in call | 获取录音文件下载地址 |
| | | * @param recordDomain 录音文件存储的服务器域名 |
| | | * @param fileName 录音文件名 |
| | | */ |
| | | public static String axbGetRecordDownloadLink(String appKey,String appSecret,String recordDomain, String fileName) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第三步: 用户通话结束,若设置录音,则商户可以获取录音文件下载地址,即调用获取录音文件下载地址接口 |
| | | return axb.axbGetRecordDownloadLink(recordDomain, fileName); |
| | | } |
| | | |
| | | /** |
| | | * Modify number a/b of the privacy relationship assigned by subscriptionId | |
| | | * 隐私号码AXB绑定信息修改 |
| | | * @param subscriptionId 绑定关系ID |
| | | * @param callerNum 主叫号码 |
| | | * @param calleeNum 被叫号码 |
| | | */ |
| | | public static void axbModifyNumber(String appKey,String appSecret,String subscriptionId, String callerNum, String calleeNum) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第四步: 根据业务需求,可更改绑定关系,即调用AXB模式绑定信息修改接口 |
| | | axb.axbModifyNumber(subscriptionId, callerNum, calleeNum); |
| | | } |
| | | |
| | | /** |
| | | * AXB模式 解绑号码 |
| | | * @param subscriptionId 绑定号码后的唯一标识 |
| | | * @param relationNum X 隐私号码 13154610294 |
| | | */ |
| | | public static void axbUnbindNumber(String appKey,String appSecret,String subscriptionId, String relationNum) { |
| | | IAXBInterfaceDemo axb = new AXBInterfaceDemoImpl(appKey, appSecret, OMPDOMAINNAME); |
| | | // 第五步: 隐私号码循环使用,商户可将绑定关系解绑,即调用AXB模式解绑接口 |
| | | axb.axbUnbindNumber(subscriptionId, "+86"+relationNum); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.ruoyi.worker.voice.util; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.IOUtils; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | |
| | | import javax.net.ssl.*; |
| | | import java.io.*; |
| | | import java.net.URL; |
| | | import java.net.URLEncoder; |
| | | import java.security.cert.CertificateException; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * HTTP协议传输工具类 |
| | | */ |
| | | @Slf4j |
| | | public class HttpUtil { |
| | | |
| | | private static final int HTTP_STATUS_OK = 200; |
| | | |
| | | /** |
| | | * 向指定 URL发送POST方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param jsonBody |
| | | * @return |
| | | */ |
| | | public static String sendPost(String appKey, String appSecret, String url, String jsonBody) { |
| | | DataOutputStream out = null; |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | URL realUrl = new URL(url); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoOutput(true); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("POST"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | |
| | | log.info("RequestBody is : " + jsonBody); |
| | | |
| | | connection.connect(); |
| | | out = new DataOutputStream(connection.getOutputStream()); |
| | | out.writeBytes(jsonBody); |
| | | out.flush(); |
| | | out.close(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (HTTP_STATUS_OK == status) { |
| | | is = connection.getInputStream(); |
| | | } else { |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is, "UTF-8")); |
| | | String line = ""; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send Post request catch exception: " + e.toString()); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(out); |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL发送PUT方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param jsonBody |
| | | * @return |
| | | */ |
| | | public static String sendPut(String appKey, String appSecret, String url, String jsonBody) { |
| | | DataOutputStream out = null; |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | URL realUrl = new URL(url); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoOutput(true); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("PUT"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | |
| | | log.info("RequestBody is : " + jsonBody); |
| | | |
| | | connection.connect(); |
| | | out = new DataOutputStream(connection.getOutputStream()); |
| | | out.writeBytes(jsonBody); |
| | | out.flush(); |
| | | out.close(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (HTTP_STATUS_OK == status) { |
| | | is = connection.getInputStream(); |
| | | } else { |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send Put request catch exception: " + e.toString()); |
| | | e.printStackTrace(); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(out); |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL发送DELETE方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param params |
| | | * @return |
| | | */ |
| | | public static String sendDelete(String appKey, String appSecret, String url, String params) { |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | String realPath = url + (StringUtils.isEmpty(params) ? "" : "?" + params); |
| | | URL realUrl = new URL(realPath); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("DELETE"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | |
| | | log.info("RequestBody is : " + params); |
| | | |
| | | connection.connect(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (HTTP_STATUS_OK == status) { |
| | | is = connection.getInputStream(); |
| | | } else { |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send DELETE request catch exception: " + e.toString()); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL发送GET方法的请求 |
| | | * |
| | | * @param appKey |
| | | * @param appSecret |
| | | * @param url |
| | | * @param params |
| | | * @return |
| | | */ |
| | | public static String sendGet(String appKey, String appSecret, String url, String params) { |
| | | BufferedReader in = null; |
| | | StringBuffer result = new StringBuffer(); |
| | | HttpsURLConnection connection = null; |
| | | InputStream is = null; |
| | | |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) { |
| | | return true; |
| | | } |
| | | }; |
| | | try { |
| | | trustAllHttpsCertificates(); |
| | | } catch (Exception e1) { |
| | | e1.printStackTrace(); |
| | | } |
| | | try { |
| | | String realPath = url + (StringUtils.isEmpty(params) ? "" : "?" + params); |
| | | URL realUrl = new URL(realPath); |
| | | connection = (HttpsURLConnection) realUrl.openConnection(); |
| | | |
| | | connection.setHostnameVerifier(hv); |
| | | connection.setDoInput(true); |
| | | connection.setRequestMethod("GET"); |
| | | connection.setRequestProperty("Accept", "application/json"); |
| | | connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); |
| | | connection.setRequestProperty("Authorization", |
| | | "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""); |
| | | connection.setRequestProperty("X-AKSK", StringUtil.buildAKSKHeader(appKey, appSecret)); |
| | | connection.setInstanceFollowRedirects(false); //设置本次连接不自动处理重定向 |
| | | |
| | | log.info("RequestBody is : " + params); |
| | | |
| | | connection.connect(); |
| | | |
| | | int status = connection.getResponseCode(); |
| | | if (301 == status) { //获取录音文件下载地址 |
| | | return connection.getHeaderField("Location"); |
| | | }else if (HTTP_STATUS_OK == status) { //查询绑定信息 |
| | | is = connection.getInputStream(); |
| | | } else { //获取错误码 |
| | | is = connection.getErrorStream(); |
| | | } |
| | | in = new BufferedReader(new InputStreamReader(is)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) { |
| | | result.append(line); |
| | | } |
| | | } catch (Exception e) { |
| | | log.info("Send GET request catch exception: " + e.toString()); |
| | | } |
| | | finally { |
| | | IOUtils.closeQuietly(is); |
| | | IOUtils.closeQuietly(in); |
| | | if (null != connection) { |
| | | IOUtils.close(connection); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 键值对转查询url |
| | | * |
| | | * @param map |
| | | * @return |
| | | */ |
| | | public static String map2UrlEncodeString(Map<String, Object> map) { |
| | | if(null == map || map.isEmpty()) { |
| | | return ""; |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | String temp = ""; |
| | | |
| | | for (String s : map.keySet()) { |
| | | try { |
| | | temp = URLEncoder.encode(String.valueOf(map.get(s)), "UTF-8"); |
| | | } catch (UnsupportedEncodingException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | sb.append(s).append("=").append(temp).append("&"); |
| | | } |
| | | return sb.deleteCharAt(sb.length() - 1).toString(); |
| | | } |
| | | |
| | | /** |
| | | * 忽略SSL证书校验 |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | static void trustAllHttpsCertificates() throws Exception { |
| | | TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { |
| | | public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { |
| | | return; |
| | | } |
| | | |
| | | public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { |
| | | return; |
| | | } |
| | | |
| | | public X509Certificate[] getAcceptedIssuers() { |
| | | return null; |
| | | } |
| | | } }; |
| | | SSLContext sc = SSLContext.getInstance("SSL"); |
| | | sc.init(null, trustAllCerts, null); |
| | | HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * Copyright Notice: |
| | | * Copyright 1998-2008, Huawei Technologies Co., Ltd. ALL Rights Reserved. |
| | | * |
| | | * Warning: This computer software sourcecode is protected by copyright law |
| | | * and international treaties. Unauthorized reproduction or distribution |
| | | * of this sourcecode, or any portion of it, may result in severe civil and |
| | | * criminal penalties, and will be prosecuted to the maximum extent |
| | | * possible under the law. |
| | | */ |
| | | package com.ruoyi.worker.voice.util; |
| | | |
| | | //import java.nio.charset.Charset; |
| | | |
| | | import javax.crypto.Mac; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | public class StringUtil { |
| | | public static final String AKSK_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\""; |
| | | |
| | | public static boolean strIsNullOrEmpty(String s) { |
| | | return (null == s || s.trim().length() < 1); |
| | | } |
| | | |
| | | public static String buildAKSKHeader(String appKey, String appSecret) throws Exception { |
| | | if (StringUtil.strIsNullOrEmpty(appKey) || StringUtil.strIsNullOrEmpty(appSecret)) { |
| | | return null; |
| | | } |
| | | |
| | | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); |
| | | format.setTimeZone(TimeZone.getTimeZone("UTC")); |
| | | Calendar calendar = Calendar.getInstance(); |
| | | String time = format.format(calendar.getTime()); |
| | | String stNonce = UUID.randomUUID().toString().replace("-", "").toUpperCase(Locale.ROOT); |
| | | String str = stNonce + time; |
| | | Mac mac = Mac.getInstance("HmacSHA256"); |
| | | mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); |
| | | byte[] authBytes = mac.doFinal(str.getBytes(StandardCharsets.UTF_8)); |
| | | String passwordDigestBase64Str = encodeBase64(authBytes); |
| | | return String.format(AKSK_HEADER_FORMAT, appKey, passwordDigestBase64Str, stNonce, time); |
| | | } |
| | | |
| | | private static String encodeBase64(byte[] bytes) { |
| | | if (bytes.length == 0) { |
| | | return null; |
| | | } else { |
| | | return new String(Base64.getEncoder().encode(bytes), StandardCharsets.UTF_8); |
| | | } |
| | | } |
| | | } |