赞
踩
从这开始有点摆烂了,有点累了写不动了,很大一部分是抄了官方的笔记,兄弟们见谅
接口文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
(1)绑定域名
与微信分享一致
先登录微信公众平台进入“设置与开发”,“公众号设置”的“功能设置”里填写“JS接口安全域名”。
说明:因为测试号不支持支付功能,需要使用正式号才能进行测试。
这些都是配置内网穿透的域名
(2)商户平台配置支付目录
还是在订单接口
(1)创建WXPayController
@Api(tags = "微信支付接口") @RestController @RequestMapping("/api/order/wxPay") public class WXPayController { @Autowired private WXPayService wxPayService; @ApiOperation(value = "下单 小程序支付") @GetMapping("/createJsapi/{orderNo}") public Result createJsapi( @ApiParam(name = "orderNo", value = "订单No", required = true) @PathVariable("orderNo") String orderNo) { return Result.ok(wxPayService.createJsapi(orderNo)); } }
(2)创建WXPayService
public interface WXPayService {
Map createJsapi(String orderNo);
}
(3)service_order引入依赖
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
(4)创建WXPayServiceImpl
@Service @Slf4j public class WXPayServiceImpl implements WXPayService { @Autowired private OrderInfoService orderInfoService; @Resource private UserInfoFeignClient userInfoFeignClient; @Override public Map<String, String> createJsapi(String orderNo) { try { Map<String, String> paramMap = new HashMap(); //1、设置参数 paramMap.put("appid", "wxf913bfa3a2c7eeeb"); paramMap.put("mch_id", "1481962542"); paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); paramMap.put("body", "test"); paramMap.put("out_trade_no", orderNo); paramMap.put("total_fee", "1"); paramMap.put("spbill_create_ip", "127.0.0.1"); paramMap.put("notify_url", "http://内网穿透隧道/api/order/wxPay/notify"); paramMap.put("trade_type", "JSAPI"); // paramMap.put("openid", "o1R-t5trto9c5sdYt6l1ncGmY5Y"); //UserInfo userInfo = userInfoFeignClient.getById(paymentInfo.getUserId()); // paramMap.put("openid", "oepf36SawvvS8Rdqva-Cy4flFFg"); paramMap.put("openid", "oQTXC56lAy3xMOCkKCImHtHoLL"); //2、HTTPClient来根据URL访问第三方接口并且传递参数 HttpClientUtils client = new HttpClientUtils("https://api.mch.weixin.qq.com/pay/unifiedorder"); //client设置参数 client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, "MXb72b9RfshXZD4FRGV5KLqmv5bx9LT9")); client.setHttps(true); client.post(); //3、返回第三方的数据 String xml = client.getContent(); Map<String, String> resultMap = WXPayUtil.xmlToMap(xml); if(null != resultMap.get("result_code") && !"SUCCESS".equals(resultMap.get("result_code"))) { System.out.println("error1"); } //4、再次封装参数 Map<String, String> parameterMap = new HashMap<>(); String prepayId = String.valueOf(resultMap.get("prepay_id")); String packages = "prepay_id=" + prepayId; parameterMap.put("appId", "wxf913bfa3a2c7eeeb"); parameterMap.put("nonceStr", resultMap.get("nonce_str")); parameterMap.put("package", packages); parameterMap.put("signType", "MD5"); parameterMap.put("timeStamp", String.valueOf(new Date().getTime())); String sign = WXPayUtil.generateSignature(parameterMap, "MXb72b9RfshXZD4FRGV5KLqmv5bx9LT9"); //返回结果 Map<String, String> result = new HashMap(); result.put("appId", "wxf913bfa3a2c7eeeb"); result.put("timeStamp", parameterMap.get("timeStamp")); result.put("nonceStr", parameterMap.get("nonceStr")); result.put("signType", "MD5"); result.put("paySign", sign); result.put("package", packages); System.out.println(result); return result; } catch (Exception e) { e.printStackTrace(); return new HashMap<>(); } } }
(1)修改service-user模块配置文件
wechat.mpAppId: wxf913bfa3a2c7eeeb
## 硅谷课堂微信公众平台api秘钥
wechat.mpAppSecret: cd360d429e5c8db0c638d5ef9df74f6d
(2)service-user模块创建controller
@Controller @RequestMapping("/api/user/openid") public class GetOpenIdController { @Autowired private WxMpService wxMpService; @GetMapping("/authorize") public String authorize(@RequestParam("returnUrl") String returnUrl, HttpServletRequest request) { String userInfoUrl = "http://内网穿透隧道/api/user/openid/userInfo"; String redirectURL = wxMpService .oauth2buildAuthorizationUrl(userInfoUrl, WxConsts.OAUTH2_SCOPE_USER_INFO, URLEncoder.encode(returnUrl.replace("guiguketan", "#"))); return "redirect:" + redirectURL; } @GetMapping("/userInfo") @ResponseBody public String userInfo(@RequestParam("code") String code, @RequestParam("state") String returnUrl) throws Exception { WxMpOAuth2AccessToken wxMpOAuth2AccessToken = this.wxMpService.oauth2getAccessToken(code); String openId = wxMpOAuth2AccessToken.getOpenId(); System.out.println("【微信网页授权】openId={}"+openId); return openId; } }
(3)修改前端App.vue
......
if (token == '') {
let url = window.location.href.replace('#', 'guiguketan')
//修改认证controller路径
window.location = 'http://内网穿透隧道路径.com/api/user/openid/authorize?returnUrl=' + url
}
......
(4)复制返回的openid到支付接口中测试
(1)trade.vue订单页面
(2)pay.vue微信支付页面
支付完毕后会得到一个序列号
我们通过这个方法把这个序列号进行测试
(1)OrderInfoApiController添加方法
@ApiOperation(value = "获取")
@GetMapping("getInfo/{id}")
public Result getInfo(@PathVariable Long id) {
OrderInfoVo orderInfoVo = orderInfoService.getOrderInfoVoById(id);
return Result.ok(orderInfoVo);
}
(2)OrderInfoServiceImpl实现方法
@Override
public OrderInfoVo getOrderInfoVoById(Long id) {
OrderInfo orderInfo = this.getById(id);
OrderDetail orderDetail = orderDetailService.getById(id);
OrderInfoVo orderInfoVo = new OrderInfoVo();
BeanUtils.copyProperties(orderInfo, orderInfoVo);
orderInfoVo.setCourseId(orderDetail.getCourseId());
orderInfoVo.setCourseName(orderDetail.getCourseName());
return orderInfoVo;
}
(1)WXPayController添加方法
@ApiOperation(value = "查询支付状态") @GetMapping("/queryPayStatus/{orderNo}") public Result queryPayStatus( @ApiParam(name = "orderNo", value = "订单No", required = true) @PathVariable("orderNo") String orderNo) { System.out.println("orderNo:"+orderNo); //调用查询接口 Map<String, String> resultMap = wxPayService.queryPayStatus(orderNo); if (resultMap == null) {//出错 return Result.fail(null).message("支付出错"); } if ("SUCCESS".equals(resultMap.get("trade_state"))) {//如果成功 //更改订单状态,处理支付结果 String out_trade_no = resultMap.get("out_trade_no"); System.out.println("out_trade_no:"+out_trade_no); orderInfoService.updateOrderStatus(out_trade_no); return Result.ok(null).message("支付成功"); } return Result.ok(null).message("支付中"); }
(2)WXPayServiceImpl实现方法
@Override public Map queryPayStatus(String orderNo) { try { //1、封装参数 Map paramMap = new HashMap<>(); paramMap.put("appid", wxPayAccountConfig.getAppId()); paramMap.put("mch_id", wxPayAccountConfig.getMchId()); paramMap.put("out_trade_no", orderNo); paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); //2、设置请求 HttpClientUtils client = new HttpClientUtils("https://api.mch.weixin.qq.com/pay/orderquery"); client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, wxPayAccountConfig.getKey())); client.setHttps(true); client.post(); //3、返回第三方的数据 String xml = client.getContent(); Map<String, String> resultMap = WXPayUtil.xmlToMap(xml); //6、转成Map //7、返回 return resultMap; } catch (Exception e) { e.printStackTrace(); } return null; }
(3)OrderInfoServiceImpl实现方法
@Override
public void updateOrderStatus(String out_trade_no) {
//根据out_trade_no查询订单
LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OrderInfo::getOutTradeNo,out_trade_no);
OrderInfo orderInfo = baseMapper.selectOne(wrapper);
//更新订单状态 1 已经支付
orderInfo.setOrderStatus("1");
baseMapper.updateById(orderInfo);
}
硅谷课堂会定期推出直播课程,方便学员与名师之间的交流互动,在直播间老师可以推荐点播课程(类似直播带货),学员可以点赞交流,购买推荐的点播课程。
一个完整直播实现流程:
1.采集、2.滤镜处理、3.编码、4.推流、5.CDN分发、6.拉流、7.解码、8.播放、9.聊天互动。
通用直播模型
如何快速开发完整直播
利用第三方SDK开发
第三方SDK好处
欢拓云直播
根据上面的综合对比和调研,我们最终选择了“欢拓与直播平台”,它为我们提供了完整的可以直接使用的示例代码,方便我们开发对接。
欢拓是一家以直播技术为核心的网络平台,旨在帮助人们通过网络也能实现真实互动通讯。从2010年开始,欢拓就专注于音频、视频的采样、编码、后处理及智能传输研究,并于2013年底正式推出了针对企业/开发者的直播云服务系统,帮助开发者轻松实现真人互动。该系统适用场景包括在线教育、游戏语音、娱乐互动、远程会议(PC、移动均可)等等。针对应用场景,采用先进技术解决方案和产品形态,让客户和客户的用户满意!
官网:https://www.talk-fun.com/
接口文档地址:http://open.talk-fun.com/docs/getstartV2/document.html
开通账号
通过官网:https://www.talk-fun.com/,联系客户或400电话开通账号,开通**“生活直播”**权限。开通后注意使用有效期,一般一周左右,可以再次申请延期。
说明:官网免费试用,功能有限制,不建议使用
创建直播
1、在直播管理创建直播
2、创建直播,选择主播模式
3、配置直播,可以自行查看
开始直播
1、在直播列表,点击“直播入口”
主播端下载“云直播客户端”,“频道id与密码”为直播客户端的登录账号;
下面还有管理员,主播进行直播时,助教可以在聊天时与观众互动。
2、电脑端安装后如图:
3、使用“频道id与密码”登录
4、点击“开始直播”,打开摄像头即可开始直播。
用户观看
1、在直播列表,点击“直播入口”
2、在观众一栏点击进入,即可在网页端观看直播。
体验总结
上面的体验完全能够满足我们业务的需要,硅谷课堂的需求是定期推出直播课程,方便学员与名师之间的交流互动,在直播间老师可以推荐点播课程(类似直播带货),学员可以点赞交流,购买推荐的点播课程。
直播平台只是做了直播相关的业务,不能与我们的业务进行衔接,我们期望是在硅谷课堂的管理后台管理直播相关的业务,那么怎么做呢?对接直播业务接口,直播平台有对应的直播接口,我们直接对接即可。
tml#bdpc):基于专业的跨平台视频编解码技术和大规模视频内容分发网络,提供稳定流畅、低延时、高并发的实时音视频服务,可将视频直播无缝对接到自身App.
第三方SDK好处
根据上面的综合对比和调研,我们最终选择了“欢拓与直播平台”,它为我们提供了完整的可以直接使用的示例代码,方便我们开发对接。
欢拓是一家以直播技术为核心的网络平台,旨在帮助人们通过网络也能实现真实互动通讯。从2010年开始,欢拓就专注于音频、视频的采样、编码、后处理及智能传输研究,并于2013年底正式推出了针对企业/开发者的直播云服务系统,帮助开发者轻松实现真人互动。该系统适用场景包括在线教育、游戏语音、娱乐互动、远程会议(PC、移动均可)等等。针对应用场景,采用先进技术解决方案和产品形态,让客户和客户的用户满意!
官网:https://www.talk-fun.com/
接口文档地址:http://open.talk-fun.com/docs/getstartV2/document.html
[外链图片转存中…(img-YaTUa8hs-1658285395973)]
开通账号
通过官网:https://www.talk-fun.com/,联系客户或400电话开通账号,开通**“生活直播”**权限。开通后注意使用有效期,一般一周左右,可以再次申请延期。
说明:官网免费试用,功能有限制,不建议使用
创建直播
1、在直播管理创建直播
2、创建直播,选择主播模式
3、配置直播,可以自行查看
开始直播
1、在直播列表,点击“直播入口”
主播端下载“云直播客户端”,“频道id与密码”为直播客户端的登录账号;
下面还有管理员,主播进行直播时,助教可以在聊天时与观众互动。
2、电脑端安装后如图:
3、使用“频道id与密码”登录
4、点击“开始直播”,打开摄像头即可开始直播。
用户观看
1、在直播列表,点击“直播入口”
2、在观众一栏点击进入,即可在网页端观看直播。
体验总结
上面的体验完全能够满足我们业务的需要,硅谷课堂的需求是定期推出直播课程,方便学员与名师之间的交流互动,在直播间老师可以推荐点播课程(类似直播带货),学员可以点赞交流,购买推荐的点播课程。
直播平台只是做了直播相关的业务,不能与我们的业务进行衔接,我们期望是在硅谷课堂的管理后台管理直播相关的业务,那么怎么做呢?对接直播业务接口,直播平台有对应的直播接口,我们直接对接即可。
上面我们已经开通了“生活类直播”。
获取openId与openToken
登录进入开放后台,后台首页即可获取openId与openToken
对接说明
1、使用HTTP协议进行信息交互,字符编码统一采用UTF-8
2、除非特殊说明,接口地址统一为:https://api.talk-fun.com/portal.php
3、除非特殊说明,同时支持GET和POST两种参数传递方式
4、除非特殊说明,返回信息支持JSON格式
5、除了sign外,其余所有请求参数值都需要进行URL编码
6、参数表中,类型一栏声明的定义为:int 代表整数类型;string 代表字符串类型,如果后面有括号,括号中的数字代表该参数的最大长度;array/object表示数组类型
7、openID、openToken参数的获取见对接流程说明
了解接口文档
接口文档地址:https://open.talk-fun.com/docs/getstartV2/api/live_dir.html
了解接口文档
根据接口文档,了解我们需要对接哪些接口
添加直播
api名称:course.add
,SDK对应方法:courseAdd
添加直播是一定需要的
更新直播信息
api名称:course.update
,SDK对应方法courseUpdate
删除直播信息
api名称:course.delete
,SDK对应方法:courseDelete
修改生活直播相关配置
api名称:course.updateLifeConfig
,SDK对应方法:updateLifeConfig
设置功能很多,但是我们只需要几个即可,这个接口我们需要做如下设置:
1、界面模式:pageViewMode 界面模式 1全屏模式 0二分屏 2课件模式
2、观看人数开关:number 观看人数开关;number.enable 是否开启 观看人数 0否 1是;示例:{“enable”:“1”}
3、商城开关(直播推荐课程):goodsListEdit 商品列表编辑,状态goodsListEdit.status 0覆盖,1追加,不传默认为0;示例:{“status”:1};
直播设置最终效果:
按照课程ID获取访客列表
改接口在:"访客/管理员列表"下面
通过该接口统计课程观看人数信息
直播访客api名称:course.visitor.list
,SDK对应方法:courseVisitorList
下载SDK
直播平台为我们准备了SDK,我们直接使用
下载地址:https://open.talk-fun.com/docs/getstartV2/api/introduce/sdkdownload.html
已下载:当前目录/MTCloud-java-sdk-1.6.zip
创建service_live模块
Pom引入相关依赖
<!-- 直播 -->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
刚刚在上面下载的直播SDK
把SDK文件夹下的内容复制进工程
涉及的数据库
代码生成、配置文件、网关注册 之类的我就不多说了
分页查询
LiveCourseController类
@RestController @RequestMapping(value="/admin/live/liveCourse") public class LiveCourseController { @Autowired private LiveCourseService liveCourseService; @Autowired private LiveCourseAccountService liveCourseAccountService; @ApiOperation(value = "获取分页列表") @GetMapping("{page}/{limit}") public Result index( @ApiParam(name = "page", value = "当前页码", required = true) @PathVariable Long page, @ApiParam(name = "limit", value = "每页记录数", required = true) @PathVariable Long limit) { Page<LiveCourse> pageParam = new Page<>(page, limit); IPage<LiveCourse> pageModel = liveCourseService.selectPage(pageParam); return Result.ok(pageModel); } }
LiveCourseService接口
public interface LiveCourseService extends IService<LiveCourse> {
//直播课程分页查询
IPage<LiveCourse> selectPage(Page<LiveCourse> pageParam);
}
下一步就该写分页查询实现类了,但是因为有教师相关信息,所以又得远程接口调用了
专门查询直播课程教师的
@ApiOperation("根据id查询")
@GetMapping("inner/getTeacher/{id}")
public Teacher getTeacherLive(@PathVariable Long id) {
Teacher teacher = teacherService.getById(id);
return teacher;
}
远程接口定义
远程调用处理好了,就可以开始继续开发接口实现类了
先把远程调用模块的接口加上
<!--远程调用-->
<dependency>
<artifactId>service_client</artifactId>
<groupId>com</groupId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
测试
参数是JSON形式的对象
先添加工具类对象
LiveCourseController类
LiveCourseService接口
Boolean save(LiveCourseFormVo liveCourseVo);
LiveCourseServiceImpl实现,这个挺多的,建议看看
LiveCourseController类
@ApiOperation(value = "删除")
@DeleteMapping("remove/{id}")
public Result remove(@PathVariable Long id) {
liveCourseService.removeLive(id);
return Result.ok(null);
}
LiveCourseService接口
//删除直播课程
void removeLive(Long id);
LiveCourseServiceImpl实现
//删除直播课程 @Override public void removeLive(Long id) { //根据id查询直播课程信息 LiveCourse liveCourse = baseMapper.selectById(id); if(liveCourse != null) { //获取直播courseid Long courseId = liveCourse.getCourseId(); try { //调用方法删除平台直播课程 mtCloudClient.courseDelete(courseId.toString()); //删除表数据 baseMapper.deleteById(id); } catch (Exception e) { e.printStackTrace(); throw new GgktException(20001,"删除直播课程失败"); } } }
LiveCourseController类
@ApiOperation(value = "获取") @GetMapping("get/{id}") public Result<LiveCourse> get(@PathVariable Long id) { LiveCourse liveCourse = liveCourseService.getById(id); return Result.ok(liveCourse); } @ApiOperation(value = "获取") @GetMapping("getInfo/{id}") public Result<LiveCourseFormVo> getInfo(@PathVariable Long id) { return Result.ok(liveCourseService.getLiveCourseFormVo(id)); } @ApiOperation(value = "修改") @PutMapping("update") public Result updateById(@RequestBody LiveCourseFormVo liveCourseVo) { liveCourseService.updateById(liveCourseVo); return Result.ok(null); }
LiveCourseService接口
//修改
void updateById(LiveCourseFormVo liveCourseVo);
//获取
LiveCourseFormVo getLiveCourseFormVo(Long id);
LiveCourseServiceImpl实现
@Resource private LiveCourseAccountService liveCourseAccountService; @Resource private LiveCourseDescriptionService liveCourseDescriptionService; @Autowired private CourseFeignClient teacherFeignClient; @Resource private MTCloud mtCloudClient; //更新 @Override public void updateById(LiveCourseFormVo liveCourseFormVo) { //根据id获取直播课程基本信息 LiveCourse liveCourse = baseMapper.selectById(liveCourseFormVo.getId()); BeanUtils.copyProperties(liveCourseFormVo,liveCourse); //讲师 Teacher teacher = teacherFeignClient.getTeacherInfo(liveCourseFormVo.getTeacherId()); // * course_id 课程ID // * account 发起直播课程的主播账号 // * course_name 课程名称 // * start_time 课程开始时间,格式:2015-01-01 12:00:00 // * end_time 课程结束时间,格式:2015-01-01 13:00:00 // * nickname 主播的昵称 // * accountIntro 主播的简介 // * options 可选参数 HashMap<Object, Object> options = new HashMap<>(); try { String res = mtCloudClient.courseUpdate(liveCourse.getCourseId().toString(), teacher.getId().toString(), liveCourse.getCourseName(), new DateTime(liveCourse.getStartTime()).toString("yyyy-MM-dd HH:mm:ss"), new DateTime(liveCourse.getEndTime()).toString("yyyy-MM-dd HH:mm:ss"), teacher.getName(), teacher.getIntro(), options); //返回结果转换,判断是否成功 CommonResult<JSONObject> commonResult = JSON.parseObject(res, CommonResult.class); if(Integer.parseInt(commonResult.getCode()) == MTCloud.CODE_SUCCESS) { JSONObject object = commonResult.getData(); //更新直播课程基本信息 liveCourse.setCourseId(object.getLong("course_id")); baseMapper.updateById(liveCourse); //直播课程描述信息更新 LiveCourseDescription liveCourseDescription = liveCourseDescriptionService.getLiveCourseById(liveCourse.getId()); liveCourseDescription.setDescription(liveCourseFormVo.getDescription()); liveCourseDescriptionService.updateById(liveCourseDescription); } else { throw new GgktException(20001,"修改直播课程失败"); } } catch (Exception e) { e.printStackTrace(); } } @Override public LiveCourseFormVo getLiveCourseFormVo(Long id) { LiveCourse liveCourse = this.getById(id); LiveCourseDescription liveCourseDescription = liveCourseDescriptionService.getByLiveCourseId(id); LiveCourseFormVo liveCourseFormVo = new LiveCourseFormVo(); BeanUtils.copyProperties(liveCourse, liveCourseFormVo); liveCourseFormVo.setDescription(liveCourseDescription.getDescription()); return liveCourseFormVo; }
LiveCourseDescriptionService添加方法
public interface LiveCourseDescriptionService extends IService<LiveCourseDescription> {
LiveCourseDescription getByLiveCourseId(Long liveCourseId);
}
LiveCourseDescriptionServiceImpl实现方法
@Service
public class LiveCourseDescriptionServiceImpl extends ServiceImpl<LiveCourseDescriptionMapper, LiveCourseDescription> implements LiveCourseDescriptionService {
@Override
public LiveCourseDescription getByLiveCourseId(Long liveCourseId) {
return this.getOne(new LambdaQueryWrapper<LiveCourseDescription>().eq(LiveCourseDescription::getLiveCourseId, liveCourseId));
}
}
LiveCourseController类
@Autowired
private LiveCourseAccountService liveCourseAccountService;
@ApiOperation(value = "获取")
@GetMapping("getLiveCourseAccount/{id}")
public Result<LiveCourseAccount> getLiveCourseAccount(@PathVariable Long id) {
return Result.ok(liveCourseAccountService.getByLiveCourseId(id));
}
LiveCourseAccountService接口
public interface LiveCourseAccountService extends IService<LiveCourseAccount> {
LiveCourseAccount getByLiveCourseId(Long liveCourseId);
}
LiveCourseAccountServiceImpl实现
@Service
public class LiveCourseAccountServiceImpl extends ServiceImpl<LiveCourseAccountMapper, LiveCourseAccount> implements LiveCourseAccountService {
@Override
public LiveCourseAccount getByLiveCourseId(Long liveCourseId) {
return baseMapper.selectOne(new LambdaQueryWrapper<LiveCourseAccount>().eq(LiveCourseAccount::getLiveCourseId, liveCourseId));
}
}
查看配置信息
(1)LiveCourseController类
@ApiOperation(value = "获取")
@GetMapping("getCourseConfig/{id}")
public Result getCourseConfig(@PathVariable Long id) {
return Result.ok(liveCourseService.getCourseConfig(id));
}
(2)LiveCourseService添加方法
//获取配置
LiveCourseConfigVo getCourseConfig(Long id);
(3)LiveCourseServiceImpl实现
@Autowired private LiveCourseConfigService liveCourseConfigService; @Autowired private LiveCourseGoodsService liveCourseGoodsService; @Override public LiveCourseConfigVo getCourseConfig(Long id) { LiveCourseConfigVo liveCourseConfigVo = new LiveCourseConfigVo(); LiveCourseConfig liveCourseConfig = liveCourseConfigService.getByLiveCourseId(id); if(null != liveCourseConfig) { List<LiveCourseGoods> liveCourseGoodsList = liveCourseGoodsService.findByLiveCourseId(id); BeanUtils.copyProperties(liveCourseConfig, liveCourseConfigVo); liveCourseConfigVo.setLiveCourseGoodsList(liveCourseGoodsList); } return liveCourseConfigVo; }
(4)LiveCourseConfigService添加方法
public interface LiveCourseConfigService extends IService<LiveCourseConfig> {
//查看配置信息
LiveCourseConfig getByLiveCourseId(Long id);
}
(5)LiveCourseConfigServiceImpl实现方法
@Service
public class LiveCourseConfigServiceImpl extends ServiceImpl<LiveCourseConfigMapper, LiveCourseConfig> implements LiveCourseConfigService {
//查看配置信息
@Override
public LiveCourseConfig getByLiveCourseId(Long liveCourseId) {
return baseMapper.selectOne(new LambdaQueryWrapper<LiveCourseConfig>().eq(
LiveCourseConfig::getLiveCourseId,
liveCourseId));
}
}
(6)LiveCourseGoodsService添加方法
public interface LiveCourseGoodsService extends IService<LiveCourseGoods> {
//获取课程商品列表
List<LiveCourseGoods> findByLiveCourseId(Long id);
}
(7)LiveCourseGoodsServiceImpl实现方法
@Service
public class LiveCourseGoodsServiceImpl extends ServiceImpl<LiveCourseGoodsMapper, LiveCourseGoods> implements LiveCourseGoodsService {
//获取课程商品列表
@Override
public List<LiveCourseGoods> findByLiveCourseId(Long liveCourseId) {
return baseMapper.selectList(new LambdaQueryWrapper<LiveCourseGoods>()
.eq(LiveCourseGoods::getLiveCourseId, liveCourseId));
}
}
(1)LiveCourseController添加方法
@ApiOperation(value = "修改配置")
@PutMapping("updateConfig")
public Result updateConfig(@RequestBody LiveCourseConfigVo liveCourseConfigVo) {
liveCourseService.updateConfig(liveCourseConfigVo);
return Result.ok(null);
}
(2)LiveCourseService添加方法
//修改配置
void updateConfig(LiveCourseConfigVo liveCourseConfigVo);
(3)LiveCourseServiceImpl实现方法
@Override public void updateConfig(LiveCourseConfigVo liveCourseConfigVo) { LiveCourseConfig liveCourseConfigUpt = new LiveCourseConfig(); BeanUtils.copyProperties(liveCourseConfigVo, liveCourseConfigUpt); if(null == liveCourseConfigVo.getId()) { liveCourseConfigService.save(liveCourseConfigUpt); } else { liveCourseConfigService.updateById(liveCourseConfigUpt); } liveCourseGoodsService.remove(new LambdaQueryWrapper<LiveCourseGoods>().eq(LiveCourseGoods::getLiveCourseId, liveCourseConfigVo.getLiveCourseId())); if(!CollectionUtils.isEmpty(liveCourseConfigVo.getLiveCourseGoodsList())) { liveCourseGoodsService.saveBatch(liveCourseConfigVo.getLiveCourseGoodsList()); } this.updateLifeConfig(liveCourseConfigVo); } /** * 上传直播配置 * @param liveCourseConfigVo */ @SneakyThrows private void updateLifeConfig(LiveCourseConfigVo liveCourseConfigVo) { LiveCourse liveCourse = this.getById(liveCourseConfigVo.getLiveCourseId()); //参数设置 HashMap<Object,Object> options = new HashMap<Object, Object>(); //界面模式 options.put("pageViewMode", liveCourseConfigVo.getPageViewMode()); //观看人数开关 JSONObject number = new JSONObject(); number.put("enable", liveCourseConfigVo.getNumberEnable()); options.put("number", number.toJSONString()); //观看人数开关 JSONObject store = new JSONObject(); number.put("enable", liveCourseConfigVo.getStoreEnable()); number.put("type", liveCourseConfigVo.getStoreType()); options.put("store", number.toJSONString()); //商城列表 List<LiveCourseGoods> liveCourseGoodsList = liveCourseConfigVo.getLiveCourseGoodsList(); if(!CollectionUtils.isEmpty(liveCourseGoodsList)) { List<LiveCourseGoodsView> liveCourseGoodsViewList = new ArrayList<>(); for(LiveCourseGoods liveCourseGoods : liveCourseGoodsList) { LiveCourseGoodsView liveCourseGoodsView = new LiveCourseGoodsView(); BeanUtils.copyProperties(liveCourseGoods, liveCourseGoodsView); liveCourseGoodsViewList.add(liveCourseGoodsView); } JSONObject goodsListEdit = new JSONObject(); goodsListEdit.put("status", "0"); options.put("goodsListEdit ", goodsListEdit.toJSONString()); options.put("goodsList", JSON.toJSONString(liveCourseGoodsViewList)); } String res = mtCloudClient.courseUpdateLifeConfig(liveCourse.getCourseId().toString(), options); CommonResult<JSONObject> commonResult = JSON.parseObject(res, CommonResult.class); if(Integer.parseInt(commonResult.getCode()) != MTCloud.CODE_SUCCESS) { throw new GgktException(20001,"修改配置信息失败"); } }
(1)LiveCourseController添加方法
@ApiOperation(value = "获取最近的直播")
@GetMapping("findLatelyList")
public Result findLatelyList() {
return Result.ok(liveCourseService.findLatelyList());
}
(2)LiveCourseService添加方法
//获取最近的直播
List<LiveCourseVo> findLatelyList();
(3)LiveCourseServiceImpl实现方法
@Override public List<LiveCourseVo> findLatelyList() { List<LiveCourseVo> liveCourseVoList = baseMapper.findLatelyList(); for(LiveCourseVo liveCourseVo : liveCourseVoList) { liveCourseVo.setStartTimeString(new DateTime(liveCourseVo.getStartTime()).toString("yyyy年MM月dd HH:mm")); liveCourseVo.setEndTimeString(new DateTime(liveCourseVo.getEndTime()).toString("HH:mm")); Long teacherId = liveCourseVo.getTeacherId(); Teacher teacher = teacherFeignClient.getTeacherInfo(teacherId); liveCourseVo.setTeacher(teacher); liveCourseVo.setLiveStatus(this.getLiveStatus(liveCourseVo)); } return liveCourseVoList; } /** * 直播状态 0:未开始 1:直播中 2:直播结束 * @param liveCourse * @return */ private int getLiveStatus(LiveCourse liveCourse) { // 直播状态 0:未开始 1:直播中 2:直播结束 int liveStatus = 0; Date curTime = new Date(); if(DateUtil.dateCompare(curTime, liveCourse.getStartTime())) { liveStatus = 0; } else if(DateUtil.dateCompare(curTime, liveCourse.getEndTime())) { liveStatus = 1; } else { liveStatus = 2; } return liveStatus; }
(4)LiveCourseMapper添加方法
public interface LiveCourseMapper extends BaseMapper<LiveCourse> {
//获取最近直播
List<LiveCourseVo> findLatelyList();
}
(5)LiveCourseMapper.xml编写sql语句
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.atguigu.ggkt.live.mapper.LiveCourseMapper"> <resultMap id="liveCourseMap" type="com.atguigu.ggkt.vo.live.LiveCourseVo" autoMapping="true"> </resultMap> <!-- 用于select查询公用抽取的列 --> <sql id="columns"> id,course_id,course_name,start_time,end_time,teacher_id,cover,create_time,update_time,is_deleted </sql> <select id="findLatelyList" resultMap="liveCourseMap"> select <include refid="columns" /> from live_course where date(start_time) >= curdate() order by id asc limit 5 </select> </mapper>
(1)CourseController添加方法
@GetMapping("findAll")
public Result findAll() {
List<Course> list = courseService.findlist();
return Result.ok(list);
}
(2)CourseService实现方法
@Override
public List<Course> findlist() {
List<Course> list = baseMapper.selectList(null);
list.stream().forEach(item -> {
this.getTeacherAndSubjectName(item);
});
return list;
}
先改路由 router->index.js路由
定义调用接口
CV页面样式
用户观看端集成
接口文档:https://open.talk-fun.com/docs/js/index.html
用户要观看直播,必须获取对应的用户access_token,通过access_token 获取观看的直播课程;
接口参数:直播id,用户id
还是在Live模块下创建LiveCourseApiController
(1)创建LiveCourseApiController
(2)LiveCourseService添加方法
JSONObject getPlayAuth(Long id, Long userId);
(3)LiveCourseServiceImpl实现方法
下载地址:https://open.talk-fun.com/docs/js/download.html
使用快捷模板
下载模板,修改token获取方式
var url = window.location.search
var token = url.split("=")[1]
(1)创建直播播放页面 live.html
观众在直播详情页面点击观看,获取通过接口获取access_token,然后带上access_token参数跳转到直播观看页面即可,关键代码:
liveInfo.vue
play() {
api.getPlayAuth(this.liveCourseId).then(response => {
console.log(response.data);
window.location = './live.html?token='+response.data.access_token;
this.finished = true;
});
},
http://localhost:8080/live.html为直播观看访问方式
(1)LiveCourseApiController类
@ApiOperation("根据ID查询课程")
@GetMapping("getInfo/{courseId}")
public Result getInfo(
@ApiParam(value = "课程ID", required = true)
@PathVariable Long courseId){
Map<String, Object> map = liveCourseService.getInfoById(courseId);
return Result.ok(map);
}
(2)LiveCourseServiceImpl实现
@Override public Map<String, Object> getInfoById(Long id) { LiveCourse liveCourse = this.getById(id); liveCourse.getParam().put("startTimeString", new DateTime(liveCourse.getStartTime()).toString("yyyy年MM月dd HH:mm")); liveCourse.getParam().put("endTimeString", new DateTime(liveCourse.getEndTime()).toString("yyyy年MM月dd HH:mm")); Teacher teacher = teacherFeignClient.get(liveCourse.getTeacherId()); LiveCourseDescription liveCourseDescription = liveCourseDescriptionService.getByLiveCourseId(id); Map<String, Object> map = new HashMap<>(); map.put("liveCourse", liveCourse); map.put("liveStatus", this.getLiveStatus(liveCourse)); map.put("teacher", teacher); if(null != liveCourseDescription) { map.put("description", liveCourseDescription.getDescription()); } else { map.put("description", ""); } return map; }
这个我觉得挺重要的,单独拿一篇出来讲
地址:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。