|  | @@ -1,11 +1,14 @@
 | 
	
		
			
				|  |  |  package com.fs.live.service.impl;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import com.alibaba.fastjson.JSON;
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.JSONObject;
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 | 
	
		
			
				|  |  |  import com.fs.common.core.domain.R;
 | 
	
		
			
				|  |  |  import com.fs.common.exception.base.BaseException;
 | 
	
		
			
				|  |  |  import com.fs.common.utils.DateUtils;
 | 
	
		
			
				|  |  |  import com.fs.common.utils.StringUtils;
 | 
	
		
			
				|  |  | +import com.fs.course.domain.FsUserTalent;
 | 
	
		
			
				|  |  | +import com.fs.course.service.IFsUserTalentService;
 | 
	
		
			
				|  |  |  import com.fs.live.domain.Live;
 | 
	
		
			
				|  |  |  import com.fs.live.domain.LiveData;
 | 
	
		
			
				|  |  |  import com.fs.live.domain.LiveVideo;
 | 
	
	
		
			
				|  | @@ -15,15 +18,19 @@ import com.fs.live.service.ILiveService;
 | 
	
		
			
				|  |  |  import com.fs.live.service.ILiveVideoService;
 | 
	
		
			
				|  |  |  import com.fs.system.domain.SysConfig;
 | 
	
		
			
				|  |  |  import com.fs.system.service.ISysConfigService;
 | 
	
		
			
				|  |  | -import com.qcloud.cos.utils.Md5Utils;
 | 
	
		
			
				|  |  |  import lombok.AllArgsConstructor;
 | 
	
		
			
				|  |  | +import okhttp3.FormBody;
 | 
	
		
			
				|  |  | +import okhttp3.OkHttpClient;
 | 
	
		
			
				|  |  | +import okhttp3.Request;
 | 
	
		
			
				|  |  | +import okhttp3.Response;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  |  import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  | +import com.fs.aicall.utils.Md5Utils;
 | 
	
		
			
				|  |  | +import org.springframework.util.Base64Utils;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -import java.util.Collections;
 | 
	
		
			
				|  |  | -import java.util.HashMap;
 | 
	
		
			
				|  |  | -import java.util.List;
 | 
	
		
			
				|  |  | -import java.util.Map;
 | 
	
		
			
				|  |  | +import java.io.IOException;
 | 
	
		
			
				|  |  | +import java.time.LocalDateTime;
 | 
	
		
			
				|  |  | +import java.util.*;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * 直播Service业务层处理
 | 
	
	
		
			
				|  | @@ -42,6 +49,9 @@ public class LiveServiceImpl extends ServiceImpl<LiveMapper, Live> implements IL
 | 
	
		
			
				|  |  |      @Autowired
 | 
	
		
			
				|  |  |      private ISysConfigService sysConfigService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private IFsUserTalentService fsUserTalentService;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  |       * 查询直播
 | 
	
		
			
				|  |  |       *
 | 
	
	
		
			
				|  | @@ -112,10 +122,17 @@ public class LiveServiceImpl extends ServiceImpl<LiveMapper, Live> implements IL
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public int insertLive(Live live){
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Live exist = liveMapper.selectLiveByTalentId(String.valueOf(live.getTalentId()));
 | 
	
		
			
				|  |  | +        if (exist != null) {
 | 
	
		
			
				|  |  | +            return 0;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          if(live.getLiveType() == 2 && StringUtils.isEmpty(live.getVideoUrl())) {
 | 
	
		
			
				|  |  |              throw new BaseException("录播必须上传视屏");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          live.setCreateTime(DateUtils.getNowDate());
 | 
	
		
			
				|  |  | +        live.setStatus(1);
 | 
	
		
			
				|  |  |          boolean save = save(live);
 | 
	
		
			
				|  |  |          LiveVideo liveVideo = new LiveVideo();
 | 
	
		
			
				|  |  |          liveVideo.setLiveId(live.getLiveId());
 | 
	
	
		
			
				|  | @@ -179,50 +196,149 @@ public class LiveServiceImpl extends ServiceImpl<LiveMapper, Live> implements IL
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  | -    public Map<String, Object> createLiveRoom(Long liveId) {
 | 
	
		
			
				|  |  | -        Map<String, Object> resultMap = new HashMap<>();
 | 
	
		
			
				|  |  | +    public R createLiveRoom(Long liveId) {
 | 
	
		
			
				|  |  |          Live live = this.selectLiveByLiveId(liveId);
 | 
	
		
			
				|  |  | -        if (live == null || live.getStatus() != 1 || live.getIsShow() != 1 || live.getIsAudit() != 1) {
 | 
	
		
			
				|  |  | -            resultMap.put("code", "500");
 | 
	
		
			
				|  |  | -            resultMap.put("msg", "您未拥有直播权限");
 | 
	
		
			
				|  |  | -            return resultMap;
 | 
	
		
			
				|  |  | +        if (live == null) {
 | 
	
		
			
				|  |  | +            return R.error("直播不存在");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if(live.getStatus() == 2){
 | 
	
		
			
				|  |  | +            return R.ok().put("rtmpUrl", live.getRtmpUrl());
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (live.getStatus() != 1 || live.getIsShow() != 1 || live.getIsAudit() != 1) {
 | 
	
		
			
				|  |  | +            return R.error("您未拥有直播权限");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("living.config");
 | 
	
		
			
				|  |  |          Map<String, String> livingConfigMap = JSON.parseObject(sysConfig.getConfigValue(), Map.class);
 | 
	
		
			
				|  |  |          if (livingConfigMap == null || livingConfigMap.isEmpty()) {
 | 
	
		
			
				|  |  | -            resultMap.put("code", "500");
 | 
	
		
			
				|  |  | -            resultMap.put("msg", "缺失直播配置");
 | 
	
		
			
				|  |  | -            return Collections.emptyMap();
 | 
	
		
			
				|  |  | +            return R.error("缺失直播配置");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          String rtmpPushUrl = generateRtmpPushUrl(livingConfigMap.get("domain"), livingConfigMap.get("app"), liveId.toString());
 | 
	
		
			
				|  |  |          String flvPlayUrl = generateFlvPlayUrl(livingConfigMap.get("http"), livingConfigMap.get("app"), liveId.toString());
 | 
	
		
			
				|  |  |          live.setRtmpUrl(rtmpPushUrl);
 | 
	
		
			
				|  |  |          live.setFlvHlsUrl(flvPlayUrl);
 | 
	
		
			
				|  |  | +        live.setStartTime(LocalDateTime.now());
 | 
	
		
			
				|  |  | +        live.setStatus(2);
 | 
	
		
			
				|  |  | +        live.setLiveType(1);
 | 
	
		
			
				|  |  |          this.updateLive(live);
 | 
	
		
			
				|  |  | -        resultMap.put("code", "200");
 | 
	
		
			
				|  |  | -        return resultMap;
 | 
	
		
			
				|  |  | +        return R.ok().put("rtmpUrl", rtmpPushUrl);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  | -    public Map<String, Object> getLiveRoom(String liveId) {
 | 
	
		
			
				|  |  | -        Map<String, Object> resultMap = new HashMap<>();
 | 
	
		
			
				|  |  | +    public R getLiveRoom(String liveId) {
 | 
	
		
			
				|  |  |          Live live = this.selectLiveByLiveId(Long.valueOf(liveId));
 | 
	
		
			
				|  |  |          if (live == null) {
 | 
	
		
			
				|  |  | -            resultMap.put("code", "500");
 | 
	
		
			
				|  |  | -            resultMap.put("msg", "未查询到直播间");
 | 
	
		
			
				|  |  | -            return resultMap;
 | 
	
		
			
				|  |  | +            return R.error("未查询到直播间");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return R.ok().put("livingUrl", live.getFlvHlsUrl()).put("liveStatus", live.getStatus());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public R checkLiving(Map<String, String> payload) {
 | 
	
		
			
				|  |  | +        if (payload == null || payload.isEmpty() || !payload.containsKey("userId") || !payload.containsKey("companyId")) {
 | 
	
		
			
				|  |  | +            return R.error("系统错误,请联系管理员");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // todo 后面修改
 | 
	
		
			
				|  |  | +        FsUserTalent fsUserTalent = fsUserTalentService.selectTalentByUserId(payload.get("userId"));
 | 
	
		
			
				|  |  | +//        if (fsUserTalent == null) {
 | 
	
		
			
				|  |  | +//            return R.error("您还未成为达人,无法开启直播!");
 | 
	
		
			
				|  |  | +//        }
 | 
	
		
			
				|  |  | +//        Live live = liveMapper.selectLiveByUserIdAndCompanyId(String.valueOf(fsUserTalent.getTalentId()), payload.get("companyId"));
 | 
	
		
			
				|  |  | +        Live live = liveMapper.selectLiveByTalentId("42");
 | 
	
		
			
				|  |  | +        if (live == null) {
 | 
	
		
			
				|  |  | +            return R.error("您未拥有直播权限!");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (live.getIsAudit() == 0) {
 | 
	
		
			
				|  |  | +            return R.error("直播间审核中!");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return R.ok().put("data", live);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public R closeLiving(Map<String, String> payload) {
 | 
	
		
			
				|  |  | +        if (!payload.containsKey("liveId")) {
 | 
	
		
			
				|  |  | +            return R.error("直播间id缺失");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (!payload.containsKey("userId")) {
 | 
	
		
			
				|  |  | +            return R.error("关闭直播异常,请联系管理员!");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        FsUserTalent fsUserTalent = fsUserTalentService.selectTalentByUserId(payload.get("userId"));
 | 
	
		
			
				|  |  | +        // todo  后面修改先写死
 | 
	
		
			
				|  |  | +        Live live = liveMapper.selectLiveByTalentId("42");
 | 
	
		
			
				|  |  | +        live.setStatus(1);
 | 
	
		
			
				|  |  | +        live.setFinishTime(LocalDateTime.now());
 | 
	
		
			
				|  |  | +        live.setLiveType(2);
 | 
	
		
			
				|  |  | +        liveMapper.updateLive(live);
 | 
	
		
			
				|  |  | +        return R.ok();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 身份证信息验证 阿里商品购买接口
 | 
	
		
			
				|  |  | +     * @param payload
 | 
	
		
			
				|  |  | +     * @return
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public R verifyIdInfo(Map<String, String> payload) {
 | 
	
		
			
				|  |  | +        if (!payload.containsKey("idCardUrl")) {
 | 
	
		
			
				|  |  | +            return R.error("身份证信息缺失");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        Live live = liveMapper.selectLiveByLiveId(Long.valueOf(payload.get("liveId")));
 | 
	
		
			
				|  |  | +        if (live == null) {
 | 
	
		
			
				|  |  | +            return R.error("直播间不存在");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        resultMap.put("code", "200");
 | 
	
		
			
				|  |  | -        resultMap.put("livingUrl", live.getFlvHlsUrl());
 | 
	
		
			
				|  |  | -        return resultMap;
 | 
	
		
			
				|  |  | +        String url = "https://puhui.shumaidata.com/idcard-ocr/photo/puhui";
 | 
	
		
			
				|  |  | +        // todo 买的产品 appcode 个人  需要更换为公司的
 | 
	
		
			
				|  |  | +        String appCode = "ed8f0f22564b48c5abdb18a02c1d701c";
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            Map<String, String> params = new HashMap<>();
 | 
	
		
			
				|  |  | +            //image 和 url 二选一 ,选择其中一个时,请注释另外一个参数,默认使用image
 | 
	
		
			
				|  |  | +            params.put("url", payload.get("idCardUrl"));
 | 
	
		
			
				|  |  | +//            params.put("image", "data:image/jpeg;base64," + base64String);
 | 
	
		
			
				|  |  | +            String result = postForm(appCode, url, params);
 | 
	
		
			
				|  |  | +            JSONObject jsonObject = JSONObject.parseObject(result);
 | 
	
		
			
				|  |  | +            if (200 == jsonObject.getIntValue("code") && jsonObject.getBooleanValue("success")) {
 | 
	
		
			
				|  |  | +                // todo  后面修改先写死
 | 
	
		
			
				|  |  | +                live.setIdCardUrl(payload.get("idCardUrl"));
 | 
	
		
			
				|  |  | +                liveMapper.updateLive(live);
 | 
	
		
			
				|  |  | +                return R.ok();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            e.printStackTrace();
 | 
	
		
			
				|  |  | +            return R.error("身份证信息校验异常");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return R.error("身份证信息校验失败");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /** 上面方法的数据解析
 | 
	
		
			
				|  |  | +     * 用到的HTTP工具包:okhttp 3.13.1
 | 
	
		
			
				|  |  | +     * <dependency>
 | 
	
		
			
				|  |  | +     * <groupId>com.squareup.okhttp3</groupId>
 | 
	
		
			
				|  |  | +     * <artifactId>okhttp</artifactId>
 | 
	
		
			
				|  |  | +     * <version>3.13.1</version>
 | 
	
		
			
				|  |  | +     * </dependency>
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static String postForm(String appCode, String url, Map<String, String> params) throws IOException {
 | 
	
		
			
				|  |  | +        OkHttpClient client = new OkHttpClient.Builder().build();
 | 
	
		
			
				|  |  | +        FormBody.Builder formbuilder = new FormBody.Builder();
 | 
	
		
			
				|  |  | +        Iterator<String> it = params.keySet().iterator();
 | 
	
		
			
				|  |  | +        while (it.hasNext()) {
 | 
	
		
			
				|  |  | +            String key = it.next();
 | 
	
		
			
				|  |  | +            formbuilder.add(key, params.get(key));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        FormBody body = formbuilder.build();
 | 
	
		
			
				|  |  | +        Request request = new Request.Builder().url(url).addHeader("Authorization", "APPCODE " + appCode).post(body).build();
 | 
	
		
			
				|  |  | +        Response response = client.newCall(request).execute();
 | 
	
		
			
				|  |  | +        return response.body().string();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public static String generateRtmpPushUrl(String domain, String app, String liveId) {
 | 
	
		
			
				|  |  |          long timestamp = System.currentTimeMillis() / 1000; // 秒级时间戳
 | 
	
		
			
				|  |  |          String SECRET_KEY = liveId + timestamp;
 | 
	
		
			
				|  |  | -        String sign = Md5Utils.md5Hex(liveId + SECRET_KEY + timestamp);
 | 
	
		
			
				|  |  | +        String sign = Base64Utils.encodeToString(Md5Utils.md5(liveId + SECRET_KEY + timestamp)).replace("/","") ;
 | 
	
		
			
				|  |  |          return String.format("rtmp://%s/%s/%s?timestamp=%d&sign=%s", domain, app, liveId,timestamp,sign);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -232,7 +348,7 @@ public class LiveServiceImpl extends ServiceImpl<LiveMapper, Live> implements IL
 | 
	
		
			
				|  |  |      public static String generateFlvPlayUrl(String domain, String app, String liveId) {
 | 
	
		
			
				|  |  |          long timestamp = System.currentTimeMillis() / 1000;
 | 
	
		
			
				|  |  |          String SECRET_KEY = liveId + timestamp;
 | 
	
		
			
				|  |  | -        String sign = Md5Utils.md5Hex(liveId + SECRET_KEY + timestamp);
 | 
	
		
			
				|  |  | -        return String.format("http://%s/%s/%s.flv?timestamp=%d&sign=%s", domain, app, liveId, timestamp, sign);
 | 
	
		
			
				|  |  | +        String sign = Base64Utils.encodeToString(Md5Utils.md5(liveId + SECRET_KEY + timestamp)).replace("/","");
 | 
	
		
			
				|  |  | +        return String.format("http://%s/%s/%s.m3u8?timestamp=%d&sign=%s", domain, app, liveId, timestamp, sign);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |