Day5谷粒学院 生成支付二维码、完善课程信息总结
1.生成支付二维码
需求:点击支付之后能够生成支付二维码,并且显示订单信息。扫码之后可以查询支付状态修改订单信息。
解决方案和思路
①点击去支付之后调用后端接口获取二维码地址以及订单信息
②在前端写好组件并且显示这个二维码,而且需要每过一段时间查询订单状态。如果订单已支付,那么就跳转回课程详情页面,并且修改订单表的status和增加支付记录。
③也就是两个后端接口,获取二维码,还有就是查询订单状态(向微信查询支付状态,而不是查询数据库的,相当于发送链接请求查询数据)并修改订单状态(这个是修改我们数据库的)和增加支付记录。。
遇到问题:
①如何隔一段时间去进行访问后端接口?
可以使用setInterval方法进行隔段时间调用。
②一开始支付了也没有跳转到详情页面?
可以在查询订单状态查询一下返回信息,并且注意一下订单号是不是没有传输成功之类的。
PayLogController
@GetMapping("createNative/{orderNo}")
public R createNative(@PathVariable("orderNo")String orderNo){
Map<String,Object> map=payLogService.createNative(orderNo);
System.out.println("二维码信息:"+map);
return R.ok().data(map);
}
@GetMapping("queryPayStatus/{orderNo}")
public R queryPayStatus(@PathVariable("orderNo")String orderNo){
log.info("orderNo:"+orderNo);
Map<String,String> map=payLogService.queryPayStatus(orderNo);
log.info("我执行了");
if(map==null){
log.info("失败");
return R.error().message("支付失败");
}
if (map.get("trade_state").equals("SUCCESS")){ //支付成功
System.out.println("成功");
payLogService.updatePayStatus(map);
return R.ok().message("支付成功");
}
log.info("正在支付");
return R.ok().code(25000).message("支付中");
}
PayLogService
@Override
public Map<String, String> queryPayStatus(String orderNo) {
//1.封装参数
//1、封装参数
try {
//1、封装参数
Map m = new HashMap<>();
m.put("appid", "wx74862e0dfcf69954");
m.put("mch_id", "1558950191");
m.put("out_trade_no", orderNo);
m.put("nonce_str", WXPayUtil.generateNonceStr());
//2、发送httpClient请求
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
client.setHttps(true);
client.setXmlParam(WXPayUtil.generateSignedXml(m,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));//通过商户key加密
client.post();
//3、返回第三方的数据x
String xml = client.getContent();
//4、转成Map
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
System.out.println("resultMap:"+resultMap);
//5、返回
return resultMap;
} catch (Exception e) {
e.printStackTrace();
throw new MyException(20001,"查询失败");
}
}
@Override
public void updatePayStatus(Map<String, String> map) {
//1.查询订单
String orderNo = map.get("out_trade_no");
QueryWrapper<Order> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("order_no",orderNo);
Order order = orderService.getOne(queryWrapper);
//2.判断订单state是否已经支付
if(order.getStatus().intValue()==1){
return ;
}
//3.如果不是1就更新状态
order.setStatus(1);
orderService.updateById(order);
//4.添加支付信息
PayLog payLog=new PayLog();
payLog.setOrderNo(orderNo);//支付订单号
payLog.setPayTime(new Date());//支付时间
payLog.setPayType(1);//支付类型
payLog.setTotalFee(order.getTotalFee());//总金额(分)
payLog.setTradeState(map.get("trade_state"));//支付状态
payLog.setTransactionId(map.get("transaction_id"));//订单流水号
payLog.setAttr(JSONObject.toJSONString(map));
baseMapper.insert(payLog);
}
支付页面
<template>
<div class="cart py-container">
<!--主内容-->
<div class="checkout py-container pay">
<div class="checkout-tit">
<h4 class="fl tit-txt">
<span class="success-icon"></span
><span class="success-info"
>订单提交成功,请您及时付款!订单 号:{{
payObj.out_trade_no
}}</span
>
</h4>
<span class="fr"
><em class="sui-lead">应付金额:</em
><em class="orange money">¥{{ payObj.total_fee }}</em></span
>
<div class="clearfix"></div>
</div>
<div class="checkout-steps">
<div class="fl weixin">微信支付</div>
<div class="fl sao">
<p class="red">请使用微信扫一扫。</p>
<div class="fl code">
<!-- <img id="qrious" src="~/assets/img/erweima.png" alt=""> -->
<!-- <qriously value="weixin://wxpay/bizpayurl?pr=R7tnDpZ":size="338"/> -->
<!--code_url为二维码地址,这里需要通过一个vue的组件【qriously】显示-->
<!--执行npm install vue-qriously下载组件-->
<qriously :value="payObj.code_url" :size="338" />
<div class="saosao">
<p>请使用微信扫一扫</p>
<p>扫描二维码支付</p>
</div>
</div>
</div>
<div class="clearfix"></div>
<!-- <p><a href="pay.html" target="_blank">> 其他支付方式</a></p> -->
</div>
</div>
</div>
</template>
<script>
import orderApi from "@/api/order"
export default {
asyncData({params,error}){
return orderApi.createOrderNative(params.pid)
.then(response=>{
return {
payObj:response.data.data
}
})
},
data(){
return {
time1:''
}
},
mounted(){
this.time1=setInterval(()=>{
this.queryPayStatus(this.payObj.out_trade_no);
// alert(this.payObj.out_trade_no)
},3000)
}
,
methods:{
queryPayStatus(orderNo){
orderApi.queryPayStatus(orderNo)
.then(response=>{
if(response.data.success){
//1.清除time1
clearInterval(this.time1)
//2.提示
this.$message({
type:"success",
message:"支付成功"
})
//3.跳回课程详细页面
this.$router.push({path:'/course/'+this.payObj.course_id})
}
})
}
}
}
</script>
2.完善课程信息总结
需求:如果是免费的那么就是课程详情页面显示立即观看,如果要收费那么就是立即购买,如果已经支付那么就是立即观看。
解决方案和思路
①前端直接判断price来决定是不是免费就能够替换立即购买和立即观看。
②要知道是不是已经支付,那么就要查询订单状态(数据库),如果支付,那么就调整为立即观看。
遇到问题:
①在什么地方获取这个订单状态数据?
在生成课程详细的时候就要获取,也就是要在之前获取课程详细消息的时候获取基本信息和章节信息还要获取订单状态(远程调用)。这样才能够判断并且生成组件。
CourseFrontController
@ApiOperation("根据课程id查询对应的课程基本信息和章节信息")
@GetMapping("getCourseFrontInfo/{courseId}")
public R getCourseFrontInfo(@PathVariable("courseId")String courseId, HttpServletRequest request){
//1.获取基本的课程信息
CourseWebVo courseWebVo=eduCourseService.getBaseCourseInfo(courseId);
//2.获取所有章节和小节信息
List<ChapterVo> chapterVideoList = chapterService.getAllChapterVideoByCourseId(courseId);
//3.远程调用获取用户是否已经缴费
String memberId = JwtUtils.getMemberIdByJwtToken(request);
boolean isBuy = orderClient.isBuyCourse(courseId, memberId);
// log.info(String.valueOf(isBuy));
return R.ok().data("chapterVideoList",chapterVideoList).data("courseWebVo",courseWebVo).data("isBuy",isBuy);
}
OrderController
@GetMapping("isBuyCourse/{courseId}/{memberId}")
public boolean isBuyCourse(
@PathVariable("courseId")String courseId,
@PathVariable("memberId")String memberId
){
//1.写好条件
QueryWrapper<Order> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("course_id",courseId);
queryWrapper.eq("member_id",memberId);
queryWrapper.eq("status",1);
int count = orderService.count(queryWrapper);
if(count>0){
return true;
}else{
return false;
}
}
详情页面部分
<section class="c-attr-mt">
<a
v-if="isBuy||Number(course.price)===0"
@click="createOrders()"
href="#"
title="立即观看"
class="comm-btn c-btn-3"
>立即观看</a
>
<a
v-else
@click="createOrders()"
href="#"
title="立即购买"
class="comm-btn c-btn-3"
>立即购买</a
>
</section>
data() {
return {
// courseId: "",
isBuy:''
。。。
}