文章目录
- 一、环境搭建
-
- 1、引入依赖
- 2、数据库
- 3、代码生成器生成代码
- 4、application.yml
- 5、启动类
- 二、后端
-
- 1、生成订单
-
- 1、编写根据课程id获取课程详细信息的接口
- 2、复制对应实体类
- 3、编写feign接口
- 4、编写生成订单和根据订单id查询订单的接口
- 5、测试
- 2、生成微信支付二维码
-
- 1、前戏
- 2、controller
- 3、工具类
- 4、service
- 3、查询支付状态,订单是否支付成功
-
- 4、课程详情功能完善
-
- 1、编写根据用户id和课程id查询订单信息接口
- 2、service-edu中远程调用接口
- 3、编写查询是否被购买接口
- 4、测试
- 三、前端
-
- 1、订单页面整合
-
- 1、修改课程详情页面代码,实现点击购买,跳转页面
- 2、编写订单动态路由页面
- 2、二维码页面整合(qriously组件)
-
- 1、修改订单页面,点击去支付,跳转到支付页面
- 2、编写api接口
- 3、编写程序
- 4、测试
- 3、修改课程页面,让其判断,购买状态,如果已购,不显示立即购买,显示立即观看
-
一、环境搭建
1、引入依赖
<!--微信支付-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.70</version>
</dependency>
2、数据库
CREATE TABLE `t_order` (
`id` char(19) NOT NULL DEFAULT '',
`order_no` varchar(20) NOT NULL DEFAULT '' COMMENT '订单号',
`course_id` varchar(19) NOT NULL DEFAULT '' COMMENT '课程id',
`course_title` varchar(100) DEFAULT NULL COMMENT '课程名称',
`course_cover` varchar(255) DEFAULT NULL COMMENT '课程封面',
`teacher_name` varchar(20) DEFAULT NULL COMMENT '讲师名称',
`member_id` varchar(19) NOT NULL DEFAULT '' COMMENT '会员id',
`nickname` varchar(50) DEFAULT NULL COMMENT '会员昵称',
`mobile` varchar(11) DEFAULT NULL COMMENT '会员手机',
`total_fee` decimal(10,2) DEFAULT '0.01' COMMENT '订单金额(分)',
`pay_type` tinyint(3) DEFAULT NULL COMMENT '支付类型(1:微信 2:支付宝)',
`status` tinyint(3) DEFAULT NULL COMMENT '订单状态(0:未支付 1:已支付)',
`is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `ux_order_no` (`order_no`),
KEY `idx_course_id` (`course_id`),
KEY `idx_member_id` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单';
INSERT INTO `t_order` VALUES ('1195693605513891841','1195693605555834880','18','Java精品课程','http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/06/866e9aca-b530-4f71-a690-72d4a4bfd1e7.jpg','晴天','1','小三1231','13700000001',1,NULL,0,0,'2019-11-16 21:22:25','2019-11-16 21:22:25'),('1195694200178118657','1195694200186507264','18','Java精品课程','http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/06/866e9aca-b530-4f71-a690-72d4a4bfd1e7.jpg','晴天','1','小三1231','13700000001',1,NULL,0,0,'2019-11-16 21:24:47','2019-11-16 21:24:47'),('1196264007411744769','1196264005255872512','1192252213659774977','java基础课程:test','https://guli-file-190513.oss-cn-beijing.aliyuncs.com/cover/default.gif','晴天','1','小三1231','13700000001',1,NULL,1,0,'2019-11-18 11:09:00','2019-11-18 11:10:14'),('1196265495278174209','1196265495273979904','18','Java精品课程','http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/06/866e9aca-b530-4f71-a690-72d4a4bfd1e7.jpg','晴天','1','小三1231','13700000001',1,NULL,0,0,'2019-11-18 11:14:54','2019-11-18 11:14:54');
CREATE TABLE `t_pay_log` (
`id` char(19) NOT NULL DEFAULT '',
`order_no` varchar(20) NOT NULL DEFAULT '' COMMENT '订单号',
`pay_time` datetime DEFAULT NULL COMMENT '支付完成时间',
`total_fee` decimal(10,2) DEFAULT '0.01' COMMENT '支付金额(分)',
`transaction_id` varchar(30) DEFAULT NULL COMMENT '交易流水号',
`trade_state` char(20) DEFAULT NULL COMMENT '交易状态',
`pay_type` tinyint(3) NOT NULL DEFAULT '0' COMMENT '支付类型(1:微信 2:支付宝)',
`attr` text COMMENT '其他属性',
`is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付日志表';
INSERT INTO `t_pay_log` VALUES ('1194498446013001730','1194498300579704832','2019-11-13 14:13:17',1,'4200000469201911130676624386','SUCCESS',1,'{\"transaction_id\":\"4200000469201911130676624386\",\"nonce_str\":\"2Lc23ILl231It53M\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CFT\",\"openid\":\"oNpSGwR-QGG5DaZtDkh2UZlsFDQE\",\"sign\":\"5404850AA3ED0E844DE104651477F07A\",\"return_msg\":\"OK\",\"fee_type\":\"CNY\",\"mch_id\":\"1473426802\",\"cash_fee\":\"1\",\"out_trade_no\":\"1194498300579704832\",\"cash_fee_type\":\"CNY\",\"appid\":\"wx8397f8696b538317\",\"total_fee\":\"1\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"NATIVE\",\"result_code\":\"SUCCESS\",\"attach\":\"\",\"time_end\":\"20191113141314\",\"is_subscribe\":\"N\",\"return_code\":\"SUCCESS\"}',0,'2019-11-13 14:13:17','2019-11-13 14:13:17'),('1195253787449430017','1195253049260314624','2019-11-15 16:14:44',1,'4200000454201911150981874895','SUCCESS',1,'{\"transaction_id\":\"4200000454201911150981874895\",\"nonce_str\":\"MAM5UM4Xhv1lItvO\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CFT\",\"openid\":\"oNpSGwR-QGG5DaZtDkh2UZlsFDQE\",\"sign\":\"7DBDCAF4A078B30BB3EF073E6A238C20\",\"return_msg\":\"OK\",\"fee_type\":\"CNY\",\"mch_id\":\"1473426802\",\"cash_fee\":\"1\",\"out_trade_no\":\"1195253049260314624\",\"cash_fee_type\":\"CNY\",\"appid\":\"wx8397f8696b538317\",\"total_fee\":\"1\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"NATIVE\",\"result_code\":\"SUCCESS\",\"attach\":\"\",\"time_end\":\"20191115161440\",\"is_subscribe\":\"N\",\"return_code\":\"SUCCESS\"}',0,'2019-11-15 16:14:44','2019-11-15 16:14:44'),('1196264321397342210','1196264005255872512','2019-11-18 11:10:14',1,'4200000453201911184025781554','SUCCESS',1,'{\"transaction_id\":\"4200000453201911184025781554\",\"nonce_str\":\"D1dHexCLIFIxAAg2\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CFT\",\"openid\":\"oNpSGwR-QGG5DaZtDkh2UZlsFDQE\",\"sign\":\"C9F5CA1EE49EA7891736D73BEB423962\",\"return_msg\":\"OK\",\"fee_type\":\"CNY\",\"mch_id\":\"1473426802\",\"cash_fee\":\"1\",\"out_trade_no\":\"1196264005255872512\",\"cash_fee_type\":\"CNY\",\"appid\":\"wx8397f8696b538317\",\"total_fee\":\"1\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"NATIVE\",\"result_code\":\"SUCCESS\",\"attach\":\"\",\"time_end\":\"20191118111011\",\"is_subscribe\":\"N\",\"return_code\":\"SUCCESS\"}',0,'2019-11-18 11:10:14','2019-11-18 11:10:14');
3、代码生成器生成代码
4、application.yml
server:
port: 8006
spring:
application:
name: service-order
profiles:
active: dev
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/gulischool?serverTimeZone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
jackson:
date-format: yyyy-MM-DD HH:mm:ss
time-zone: GMT+8
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
feign:
client:
config:
default:
connect-timeout: 10000
read-timeout: 10000
hystrix:
enabled: true
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
mybatis-plus:
mapper-locations: classpath:com/yzpnb/order_service/mapper/xml/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
5、启动类
package com.yzpnb.order_service;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages={"com.yzpnb"})
@EnableDiscoveryClient
@MapperScan("com.yzpnb.order_service.mapper")
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
二、后端
所需接口 |
生成订单(用户点击购买按钮) |
根据订单id查询订单信息 |
生成微信支付二维码 |
查询订单支付状态接口 |
1、生成订单
分析 |
我们需要根据课程id获取课程信息 |
根据用户id获取用户信息 |
需要使用Feign |
1、编写根据课程id获取课程详细信息的接口
@ApiOperation("根据课程id获取课程信息")
@GetMapping("selectCourseAllInfoVoApiById")
public CourseAllInfoVo selectCourseAllInfoVoApiById(@ApiParam(name = "id",value = "课程id")
@RequestParam(value = "id") String id){
CourseAllInfoVo courseAllInfoVo = eduCourseService.selectCourseAllInfoVo(id);
return courseAllInfoVo;
}
2、复制对应实体类
3、编写feign接口
4、编写生成订单和根据订单id查询订单的接口
package com.yzpnb.order_service.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yzpnb.common_utils.JwtUtils;
import com.yzpnb.common_utils.Result;
import com.yzpnb.order_service.entity.TOrder;
import com.yzpnb.order_service.entity.educourse.CourseAllInfoVo;
import com.yzpnb.order_service.entity.ucenter.UcenterMember;
import com.yzpnb.order_service.feign.FeignToEduServiceClient;
import com.yzpnb.order_service.feign.FeignToUcenterClient;
import com.yzpnb.order_service.service.TOrderService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
@RestController
@RequestMapping("/order_service/t-order")
@CrossOrigin
public class TOrderController {
@Autowired
private TOrderService tOrderService;
@Autowired
private FeignToEduServiceClient feignToEduServiceClient;
@Autowired
private FeignToUcenterClient feignToUcenterClient;
@ApiOperation("根据课程id和用户id创建订单,返回订单id")
@PostMapping("createOrder/{courseId}")
public Result createOrder(@ApiParam(name = "courseId",value = "课程id")
@PathVariable(value = "courseId") String courseId,
HttpServletRequest request){
String memberId = JwtUtils.getMemberIdByJwtToken(request);
CourseAllInfoVo courseAllInfoVo = feignToEduServiceClient.selectCourseAllInfoVoApiById(courseId);
UcenterMember ucenterMember = feignToUcenterClient.selectById(memberId);
SimpleDateFormat sd=new SimpleDateFormat("yyyyMMddHHmmss");
Random random=new Random();
String orderNo="";
for(int i=0;i<=3;i++){
orderNo += random.nextInt(10);
}
orderNo=sd.format(new Date())+orderNo;
TOrder order=new TOrder();
order.setOrderNo(orderNo);
order.setCourseId(courseId);
order.setCourseTitle(courseAllInfoVo.getTitle());
order.setCourseCover(courseAllInfoVo.getCover());
order.setTeacherName(courseAllInfoVo.getTeacherName());
order.setTotalFee(courseAllInfoVo.getPrice());
order.setMemberId(memberId);
order.setMobile(ucenterMember.getMobile());
order.setNickname(ucenterMember.getNickname());
order.setStatus(0);
order.setPayType(1);
tOrderService.save(order);
return Result.ok().data("orderId",orderNo);
}
@ApiOperation("根据订单id获取订单信息")
@GetMapping("selectOrderById/{orderId}")
public Result selectOrderById(@PathVariable String orderId) {
QueryWrapper<TOrder> wrapper = new QueryWrapper<>();
wrapper.eq("order_no",orderId);
TOrder order = tOrderService.getOne(wrapper);
return Result.ok().data("item", order);
}
}
5、测试
涉及到HttpClient,就不要想着用swagger测试了,请直接跳到前端的1、订单页面整合中测试 |
2、生成微信支付二维码
1、前戏
和上次的微信二维码登陆一样,这功能也需要企业认证,我们还是蹭尚硅谷的进行学习 |
weixin:
pay:
# 关联的公众号appid
appid: wx74862e0dfcf69954
# 商户号
partner: 1558950191
# 商户key
partnerkey: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
# 回调地址
notifyurl: http://guli.shop/api/order/weixinPay/weixinNotify
2、controller
package com.yzpnb.order_service.controller;
import com.yzpnb.common_utils.Result;
import com.yzpnb.order_service.service.TPayLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/order_service/t-pay-log")
@CrossOrigin
public class TPayLogController {
@Autowired
private TPayLogService tPayLogServicee;
@ApiOperation("根据订单号生成支付二维码")
@GetMapping("createNative/{orderNo}")
public Result createNative( @ApiParam(name = "orderNo",value = "订单号")
@PathVariable String orderNo) {
Map map = tPayLogServicee.createNative(orderNo);
return Result.ok().data(map);
}
}
3、工具类
<!--apache HttpClient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
package com.yzpnb.order_service.utils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class HttpClient {
private String url;
private Map<String, String> param;
private int statusCode;
private String content;
private String xmlParam;
private boolean isHttps;
public boolean isHttps() {
return isHttps;
}
public void setHttps(boolean isHttps) {
this.isHttps = isHttps;
}
public String getXmlParam() {
return xmlParam;
}
public void setXmlParam(String xmlParam) {
this.xmlParam = xmlParam;
}
public HttpClient(String url, Map<String, String> param) {
this.url = url;
this.param = param;
}
public HttpClient(String url) {
this.url = url;
}
public void setParameter(Map<String, String> map) {
param = map;
}
public void addParameter(String key, String value) {
if (param == null)
param = new HashMap<String, String>();
param.put(key, value);
}
public void post() throws ClientProtocolException, IOException {
HttpPost http = new HttpPost(url);
setEntity(http);
execute(http);
}
public void put() throws ClientProtocolException, IOException {
HttpPut http = new HttpPut(url);
setEntity(http);
execute(http);
}
public void get() throws ClientProtocolException, IOException {
if (param != null) {
StringBuilder url = new StringBuilder(this.url);
boolean isFirst = true;
for (String key : param.keySet()) {
if (isFirst)
url.append("?");
else
url.append("&");
url.append(key).append("=").append(param.get(key));
}
this.url = url.toString();
}
HttpGet http = new HttpGet(url);
execute(http);
}
private void setEntity(HttpEntityEnclosingRequestBase http) {
if (param != null) {
List<NameValuePair> nvps = new LinkedList<NameValuePair>();
for (String key : param.keySet())
nvps.add(new BasicNameValuePair(key, param.get(key)));
http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
}
if (xmlParam != null) {
http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
}
}
private void execute(HttpUriRequest http) throws ClientProtocolException,
IOException {
CloseableHttpClient httpClient = null;
try {
if (isHttps) {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.build();
} else {
httpClient = HttpClients.createDefault();
}
CloseableHttpResponse response = httpClient.execute(http);
try {
if (response != null) {
if (response.getStatusLine() != null)
statusCode = response.getStatusLine().getStatusCode();
HttpEntity entity = response.getEntity();
content = EntityUtils.toString(entity, Consts.UTF_8);
}
} finally {
response.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpClient.close();
}
}
public int getStatusCode() {
return statusCode;
}
public String getContent() throws ParseException, IOException {
return content;
}
}
4、service
package com.yzpnb.order_service.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.wxpay.sdk.WXPayUtil;
import com.yzpnb.order_service.entity.TOrder;
import com.yzpnb.order_service.entity.TPayLog;
import com.yzpnb.order_service.mapper.TPayLogMapper;
import com.yzpnb.order_service.service.TOrderService;
import com.yzpnb.order_service.service.TPayLogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yzpnb.order_service.utils.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
@Service
public class TPayLogServiceImpl extends ServiceImpl<TPayLogMapper, TPayLog> implements TPayLogService {
@Autowired
private TOrderService tOrderService;
@Override
public Map createNative(String orderNo) {
try {
QueryWrapper<TOrder> wrapper = new QueryWrapper<>();
wrapper.eq("order_no",orderNo);
TOrder order = tOrderService.getOne(wrapper);
Map m = new HashMap();
m.put("appid", "wx74862e0dfcf69954");
m.put("mch_id", "1558950191");
m.put("nonce_str", WXPayUtil.generateNonceStr());
m.put("body", order.getCourseTitle());
m.put("out_trade_no", orderNo);
m.put("total_fee", order.getTotalFee().multiply(new BigDecimal("100")).longValue()+"");
m.put("spbill_create_ip", "127.0.0.1");
m.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify\n");
m.put("trade_type", "NATIVE");
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
client.setHttps(true);
client.post();
String xml = client.getContent();
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
Map map = new HashMap<>();
map.put("out_trade_no", orderNo);
map.put("course_id", order.getCourseId());
map.put("total_fee", order.getTotalFee());
map.put("result_code", resultMap.get("result_code"));
map.put("code_url", resultMap.get("code_url"));
return map;
} catch (Exception e) {
e.printStackTrace();
return new HashMap<>();
}
}
}
3、查询支付状态,订单是否支付成功
如果支付成功,将订单表中支付状态改为1,日志表中增加记录(用于申诉等使用) |
1、controller
@ApiOperation("根据订单号查询支付状态,支付成功,添加订单日志")
@GetMapping("/queryPayStatus/{orderNo}")
public Result queryPayStatus(@PathVariable String orderNo) {
Map<String, String> map = tPayLogServicee.queryPayStatus(orderNo);
if (map == null) {
return Result.error().message("支付出错");
}
if (map.get("trade_state").equals("SUCCESS")) {
tPayLogServicee.updateOrderStatus(map);
return Result.ok().message("支付成功");
}
return Result.ok().code(25000).message("支付中");
}
### 2、service
@Override
public Map<String, String> queryPayStatus(String orderNo) {
try {
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());
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
client.setHttps(true);
client.post();
String xml = client.getContent();
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
return resultMap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void updateOrderStatus(Map<String, String> map) {
String orderNo = map.get("out_trade_no");
QueryWrapper<TOrder> wrapper = new QueryWrapper<>();
wrapper.eq("order_no",orderNo);
TOrder order = tOrderService.getOne(wrapper);
if(order.getStatus().intValue() == 1) return;
order.setStatus(1);
tOrderService.updateById(order);
TPayLog payLog=new TPayLog();
payLog.setOrderNo(order.getOrderNo());
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);
}
4、课程详情功能完善
1、编写根据用户id和课程id查询订单信息接口
@ApiOperation("根据用户id和课程id查询订单信息,已经支付返回true,没有返回false")
@GetMapping("isBuyCourse")
public boolean isBuyCourse(@RequestParam(value = "memberid") String memberid,
@RequestParam(value = "courseid") String courseid) {
int count = tOrderService.count(new QueryWrapper<TOrder>().eq("member_id", memberid).eq("course_id", courseid).eq("status", 1));
if(count>0) {
return true;
} else {
return false;
}
}
2、service-edu中远程调用接口
3、编写查询是否被购买接口
@Autowired
private FeignToOrderClient feignToOrderClient;
@ApiOperation("根据id查询课程详情,并判断课程十分被购买")
@GetMapping("getCourseInfo/{id}")
public Result getCourseInfo(@PathVariable(value = "id") String id, HttpServletRequest request) {
CourseApiInfoVo courseApiInfoVo = eduCourseService.selectCourserApiInfoVoById(id);
List<ChapterVo> chapterVideoList = eduChapterService.selectChapterVideoByCourseId(id);
boolean buyCourse = feignToOrderClient.isBuyCourse(JwtUtils.getMemberIdByJwtToken(request), id);
Map<String , Object> map=new HashMap<>();
map.put("courseFrontInfo",courseApiInfoVo);
map.put("chapterVideoList",chapterVideoList);
map.put("isbuy",buyCourse);
return Result.ok().data(map);
}
4、测试
三、前端
1、订单页面整合
1、修改课程详情页面代码,实现点击购买,跳转页面
2、编写订单动态路由页面
2、二维码页面整合(qriously组件)
需要使用qriously组件,它会根据地址实时下载图片显示 |
1、修改订单页面,点击去支付,跳转到支付页面
2、编写api接口
3、编写程序
4、测试
3、修改课程页面,让其判断,购买状态,如果已购,不显示立即购买,显示立即观看
1、api接口
2、代码
3、测试