课程支付需求描述
1、课程支付说明
(1)课程分为免费课程和付费课程,如果是免费课程可以直接观看,如果是付费观看的课程,用户需下单支付后才可以观看
(2)如果是免费课程,在用户选择课程,进入到课程详情页面时候,直接显示 “立即观看”,用户点击立即观看,可以切换到播放列表进行视频播放
2、付费课程流程
(1)如果是付费课程,在用户选择课程,进入到课程详情页面时候,会显示 “立即购买”
(2)点击“立即购买”,会生成课程的订单,跳转到订单页面
(3)点击“去支付”,会跳转到支付页面,生成微信扫描的二维码
(4)使用微信扫描支付后,会跳转回到课程详情页面,同时显示“立即观看”
支付模块和开发订单接口
一、创建支付模块和环境准备
1、在service模块下创建子模块service_order
2、在service_order模块中引入依赖
<dependencies>
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
3、创建支付相关的表
- 两张表:t_order、t_pay_log
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='订单';
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='支付日志表';
注意:如果用的是邮箱,需要修改一下数据库字段mobile的长度
4、使用代码生成器生成相关代码
public class CodeGenerator {
@Test
public void run() {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
//C:\Users\86185\Desktop\guli_parent
gc.setOutputDir("C:\\Users\\86185\\Desktop\\guli_parent\\service\\service_ucenter" + "/src/main/java"); //输出目录
gc.setAuthor("czy"); //作者名
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
//生成包:com.czy.educenter
pc.setModuleName("educenter"); //模块名
pc.setParent("com.czy");
//生成包:com.czy.controller
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("ucenter_member");//根据数据库哪张表生成,有多张表就加逗号继续填写
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
5、application.properties配置文件
# 服务端口
server.port=8006
# 服务名
spring.application.name=service-ucenter
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
# redis
spring.redis.host=192.168.174.131
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.password=root123
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
#最小空闲
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/czy/educenter/mapper/xml/*.xml
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
二、【生成订单】接口
1、生成订单的接口
2、远程调用、订单公共返回类Vo
用于远程接口调用后返回给订单接口的统一返回类
com.czy.commonutils.ordervo.CourseWebVoOrder
@Data
public class CourseWebVoOrder {
private String id;
@ApiModelProperty(value = "课程标题")
private String title;
@ApiModelProperty(value = "课程销售价格,设置为0则可免费观看")
private BigDecimal price;
@ApiModelProperty(value = "总课时")
private Integer lessonNum;
@ApiModelProperty(value = "课程封面图片路径")
private String cover;
@ApiModelProperty(value = "销售数量")
private Long buyCount;
@ApiModelProperty(value = "浏览数量")
private Long viewCount;
@ApiModelProperty(value = "课程简介")
private String description;
@ApiModelProperty(value = "讲师ID")
private String teacherId;
@ApiModelProperty(value = "讲师姓名")
private String teacherName;
@ApiModelProperty(value = "讲师资历,一句话说明讲师")
private String intro;
@ApiModelProperty(value = "讲师头像")
private String avatar;
@ApiModelProperty(value = "课程一级类别ID")
private String subjectLevelOneId;
@ApiModelProperty(value = "类别一级名称")
private String subjectLevelOne;
@ApiModelProperty(value = "课程二级类别ID")
private String subjectLevelTwoId;
@ApiModelProperty(value = "类别二级名称")
private String subjectLevelTwo;
}
com.czy.commonutils.ordervo.UcenterMemberOrder
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="UcenterMember对象", description="会员表")
public class UcenterMemberOrder implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "会员id")
@TableId(value = "id", type = IdType.ID_WORKER_STR)
private String id;
@ApiModelProperty(value = "微信openid")
private String openid;
@ApiModelProperty(value = "手机号")
private String mobile;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "昵称")
private String nickname;
@ApiModelProperty(value = "性别 1 女,2 男")
private Integer sex;
@ApiModelProperty(value = "年龄")
private Integer age;
@ApiModelProperty(value = "用户头像")
private String avatar;
@ApiModelProperty(value = "用户签名")
private String sign;
@ApiModelProperty(value = "是否禁用 1(true)已禁用, 0(false)未禁用")
private Boolean isDisabled;
@ApiModelProperty(value = "逻辑删除 1(true)已删除, 0(false)未删除")
private Boolean isDeleted;
@ApiModelProperty(value = "创建时间")
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
@ApiModelProperty(value = "更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
}
3、获取课程信息
-
CourseFrontController
com.czy.eduservice.controller.front.CourseFrontController
@RestController
@RequestMapping("/eduservice/coursefront")
@CrossOrigin
public class CourseFrontController {
@Autowired
private EduCourseService courseService;
@Autowired
private EduChapterService chapterService;
//2.课程详情的方法
@GetMapping("getFrontCourseInfo/{courseId}")
public R getFrontCourseInfo(@PathVariable String courseId){
//根据课程id,编写sql语句查询课程信息
CourseWebVo courseWebVo = courseService.getBaseCourseInfo(courseId);
//根据课程id查询章节和小节
List<ChapterVo> chapterVideoList = chapterService.getChapterVideoByCourseId(courseId);
//创建一个实体类返回数据
return R.ok().data("courseWebVo",courseWebVo).data("chapterVideoList",chapterVideoList);
}
//根据课程id查询课程信息
@PostMapping("getCourseInfoOrder/{id}")
public CourseWebVoOrder getCourseInfoOrder(@PathVariable String id){
CourseWebVo courseInfo = courseService.getBaseCourseInfo(id);
CourseWebVoOrder courseWebVoOrder = new CourseWebVoOrder();
BeanUtils.copyProperties(courseInfo,courseWebVoOrder);
return courseWebVoOrder;
}
}
4、获取用户信息
@RestController
@RequestMapping("/educenter/member")
@CrossOrigin
public class UcenterMemberController {
@Autowired
private UcenterMemberService memberService;
//根据用户id获取用户信息
@PostMapping("getUserInfoOrder/{id}")
public UcenterMemberOrder getUserInfoOrder(@PathVariable String id){
UcenterMember member = memberService.getById(id);
//把member对象里面值复制给UcenterMemberOrder对象
UcenterMemberOrder ucenterMemberOrder = new UcenterMemberOrder();
BeanUtils.copyProperties(member,ucenterMemberOrder);
return ucenterMemberOrder;
}
}
5、远程调用Client接口
com.czy.eduorder.client
- EduClient接口
用于调用EduService模块的OpenFeign接口
@Component
@FeignClient(name="service-edu")
public interface EduClient {
//根据课程id查询课程信息
@PostMapping("/eduservice/coursefront/getCourseInfoOrder/{id}")
public CourseWebVoOrder getCourseInfoOrder(@PathVariable("id")String id);
}
-
UcenterClient接口 com.czy.eduorder.client
用于调用EduUcenter模块的OpenFeign接口
@Component
@FeignClient(name="service-ucenter")
public interface UcenterClient {
//根据用户id获取用户信息
@PostMapping("/educenter/member/getUserInfoOrder/{id}")
public UcenterMemberOrder getUserInfoOrder(@PathVariable("id") String id);
}
6、订单模块实现
- OrderController
com.czy.eduorder.controller
@RestController
@RequestMapping("/eduorder/order")
@CrossOrigin
public class OrderController {
@Autowired
private OrderService orderService;
//1 生成订单的方法
@PostMapping("createOrder/{courseId}")
public R saveOrder(@PathVariable String courseId, HttpServletRequest request) {
//从请求头获取用户id
String memberId = JwtUtils.getMemberIdByJwtToken(request);
//判断是否登录
if (StringUtils.isEmpty(memberId)){
throw new GuliException(20001,"请登录");
}
//创建订单,返回订单号
String orderNo = orderService.createOrders(courseId,memberId);
return R.ok().data("orderId",orderNo);
}
//2 根据订单id查询订单信息
@GetMapping("getOrderInfo/{orderId}")
public R getOrderInfo(@PathVariable String orderId) {
QueryWrapper<Order> wrapper = new QueryWrapper<>();
wrapper.eq("order_no",orderId);
Order order = orderService.getOne(wrapper);
return R.ok().data("item",order);
}
}
- service
com.czy.eduorder.service
接口
public interface OrderService extends IService<Order> {
//1.生成订单的方法
String createOrders(String courseId, String memberIdByJwtToken);
}
Impl
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
@Autowired
private EduClient eduClient;
@Autowired
private UcenterClient ucenterClient;
//1.生成订单的方法
@Override
public String createOrders(String courseId, String memberId) {
//通过远程调用根据用户id获取用户信息
UcenterMemberOrder userInfoOrder = ucenterClient.getUserInfoOrder(memberId);
//通过远程调用根据课程id获取课程信息
CourseWebVoOrder courseInfoOrder = eduClient.getCourseInfoOrder(courseId);
//创建Order对象,向order对象里面设置需要数据
Order order = new Order();
order.setOrderNo(OrderNoUtil.getOrderNo());//订单号
order.setCourseId(courseId); //课程id
order.setCourseTitle(courseInfoOrder.getTitle());
order.setCourseCover(courseInfoOrder.getCover());
order.setTeacherName(courseInfoOrder.getTeacherName());
order.setTotalFee(courseInfoOrder.getPrice());
order.setMemberId(memberId);
order.setMobile(userInfoOrder.getMobile());
order.setNickname(userInfoOrder.getNickname());
order.setStatus(0); //订单状态(0:未支付 1:已支付)
order.setPayType(1); //支付类型 ,微信1
order.setGmtCreate(new Date());
order.setGmtModified(new Date());
baseMapper.insert(order);
//返回订单号
return order.getOrderNo();
}
}
7、主启动类
需要
@EnableDiscoveryClient开启服务发现
@EnableFeignClients开启OpenFeign远程调用调用方需要配置
- ServiceOrderMain8007
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@ComponentScan(basePackages = {"com.czy"})
@MapperScan("com.czy.eduorder.mapper")
public class OrdersApplication {
public static void main(String[] args) {
SpringApplication.run(OrdersApplication.class,args);
}
}
- Service_edu_Main8001
@SpringBootApplication
@EnableDiscoveryClient //nacos注册
@EnableFeignClients //服务调用
@ComponentScan(basePackages = {"com.czy"})
public class EduApplication {
public static void main(String[] args) {
SpringApplication.run(EduApplication.class,args);
}
}
- serviceUcenterMain8006
@EnableDiscoveryClient //nacos注册
@ComponentScan({"com.czy"})
@SpringBootApplication
@MapperScan("com.czy.educenter.mapper")
public class UcenterApplication {
public static void main(String[] args) {
SpringApplication.run(UcenterApplication.class,args);
}
}
微信支付接口
一、生成微信支付二维码
1、编写controller
PayLogController
com.czy.eduorder.controller
@RestController
@RequestMapping("/eduorder/paylog")
@CrossOrigin
public class PayLogController {
@Autowired
private PayLogService payLogService;
//1.生成微信支付二维码接口
//参数是订单号
@GetMapping("createNative/{orderNo}")
public R createNative(@PathVariable String orderNo){
//返回信息,包含二维码地址,还有其他重要的信息
Map map = payLogService.createNatvie(orderNo);
System.out.println("+++++++++++返回二维码集合的map集合:"+map);
return R.ok().data(map);
}
}
2、编写service
- 接口
payLogService
@Service
public class PayLogServiceImpl extends ServiceImpl<PayLogMapper, PayLog> implements PayLogService {
@Autowired
private OrderService orderService;
//生成微信支付二维码接口
@Override
public Map createNatvie(String orderNo) {
try {
//1.根据订单号查询订单信息
QueryWrapper<Order> wrapper = new QueryWrapper<>();
wrapper.eq("order_no",orderNo);
Order order = orderService.getOne(wrapper);
//2、使用map设置生成二维码需要参数
HashMap<String, String> map = new HashMap<>();
map.put("appid","wx74862e0dfcf69954");//支付id
map.put("mch_id", "1558950191");//商户号
map.put("nonce_str", WXPayUtil.generateNonceStr());//生成随机的字符串,让每次生成的二维码不一样
map.put("body", order.getCourseTitle());//生成二维码的名字
map.put("out_trade_no", orderNo);//二维码唯一的标识
map.put("total_fee", order.getTotalFee().multiply(new BigDecimal("100")).longValue()+"");//支付金额
map.put("spbill_create_ip", "127.0.0.1");//现在进行支付的ip地址,实际项目使用项目的域名
map.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify");//支付后回调地址
map.put("trade_type", "NATIVE");//支付类型,NATIVE:根据价格生成二维码
//3.发送httpclient请求,传递参数xml格式,微信支付提供固定的地址
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
//参数1:要转换为xml格式的map
//参数2:商户的key,用于加密二维码中的信息
client.setXmlParam(WXPayUtil.generateSignedXml(map,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
client.setHttps(true);//上面发送请求的是https。默认支持,需要设置为true支持
//执行post请求发送
client.post();
//4.得到发送请求返回结果
//返回的结果是xml格式的
String content = client.getContent();
//把xml格式转换为map集合,他里面的数据不全
Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
//最终返回数据封装
HashMap hashMap = new HashMap<>();
hashMap.put("out_trade_no",orderNo);
hashMap.put("course_id",order.getCourseId());
hashMap.put("total_fee",order.getTotalFee());
hashMap.put("result_code",resultMap.get("result_code")); //二维码操作状态码
hashMap.put("code_url",resultMap.get("code_url")); //二维码地址
//微信支付二维码2小时过期,可采取2小时未支付取消订单
//0redisTemplate.opsForValue().set(orderNo, hashMap, 120, TimeUnit.MINUTES);
return hashMap;
}catch (Exception e){
e.printStackTrace();
throw new GuliException(20001,"生成二维码失败");
}
}
}
二、获取支付状态接口
1、编写controller
PayLogController
com.czy.eduorder.controller
@RestController
@RequestMapping("/eduorder/paylog")
@CrossOrigin
public class PayLogController {
@Autowired
private PayLogService payLogService;
//1.生成微信支付二维码接口
//参数是订单号
@GetMapping("createNative/{orderNo}")
public R createNative(@PathVariable String orderNo){
//返回信息,包含二维码地址,还有其他重要的信息
Map map = payLogService.createNatvie(orderNo);
System.out.println("+++++++++++返回二维码集合的map集合:"+map);
return R.ok().data(map);
}
//查询订单支付状态
//参数:订单号,根据订单号查询 支付状态
@GetMapping("queryPayStatus/{orderNo}")
public R queryPayStatus(@PathVariable String orderNo) {
Map<String,String> map = payLogService.queryPayStatus(orderNo);
System.out.println("*****查询订单状态map集合:"+map);
if(map == null) {
return R.error().message("支付出错了");
}
//如果返回map里面不为空,通过map获取订单状态
if(map.get("trade_state").equals("SUCCESS")) {//支付成功
//添加记录到支付表,更新订单表订单状态
payLogService.updateOrderStatus(map);
return R.ok().message("支付成功");
}
return R.ok().code(25000).message("支付中");
}
}
2、编写service
PayLogService接口
@Service
public class PayLogServiceImpl extends ServiceImpl<PayLogMapper, PayLog> implements PayLogService {
@Autowired
private OrderService orderService;
//2.根据订单号,查询订单支付状态
@Override
public Map<String, String> queryPayStatus(String orderNo) {
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、返回第三方的数据
String xml = client.getContent();
//4、转成Map
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
//5、返回
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<Order> wrapper = new QueryWrapper<>();
wrapper.eq("order_no",orderNo);
Order order = orderService.getOne(wrapper);
//判断订单状态是否为1,为1就是支付过了
if (order.getStatus().intValue()==1){return;}
//更新订单表中的叮当状态
order.setStatus(1);//1代表已支付
orderService.updateById(order);
//向支付表里添加支付记录
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));
payLog.setGmtCreate(new Date());
payLog.setGmtModified(new Date());
baseMapper.insert(payLog);
}
}
整合生成订单页面
一、页面样式修改
1、复制css样式文件到assets
2、修改default.vue页面
import '~/assets/css/reset.css'
import '~/assets/css/theme.css'
import '~/assets/css/global.css'
import '~/assets/css/web.css'
import '~/assets/css/base.css'
import '~/assets/css/activity_tab.css'
import '~/assets/css/bottom_rec.css'
import '~/assets/css/nice_select.css'
import '~/assets/css/order.css'
import '~/assets/css/swiper-3.3.1.min.css'
import "~/assets/css/pages-weixinpay.css"
import loginApi from '@/api/login'
import cookie from '~/node_modules/js-cookie'
二、课程支付前端
1、在api文件夹下创建order.js文件
import request from '@/utils/request'
export default {
//生成订单
createOrders(courseId) {
return request({
url: '/eduorder/order/createOrder/' + courseId,
method: 'post'
})
},
//根据订单id查询订单消息
getOrdersInfo(id) {
return request({
url: '/eduorder/order/getOrderInfo/' + id,
method: 'get'
})
},
//生成二维码的方法
createNative(orderNo) {
return request({
url: '/eduorder/paylog/createNative/' + orderNo,
method: 'get'
})
},
//查询订单状态的方法
//生成二维码的方法
queryPayStatus(orderNo) {
return request({
url: '/eduorder/paylog/queryPayStatus/' + orderNo,
method: 'get'
})
},
}
2、在课程详情页面中添加创建订单方法
在“立即购买”位置添加事件
//生成订单的方法
createOrders(){
orderApi.createOrder(this.course.courseId).then(resp=>{
//获取返回订单号
resp.data.data.orderNo
//跳转订单显示页面
this.$router.push({path:'/orders/'+resp.data.data.orderNo})
})
},
3、创建订单页面,显示订单信息
在pages下面创建order文件夹,创建_oid.vue页面
在_oid.vue页面调用方法,获取订单信息
(1)页面部分
<template>
<div class="Page Confirm">
<div class="Title">
<h1 class="fl f18">订单确认</h1>
<img src="~/assets/img/cart_setp2.png" class="fr">
<div class="clear"></div>
</div>
<form name="flowForm" id="flowForm" method="post" action="">
<table class="GoodList">
<tbody>
<tr>
<th class="name">商品</th>
<th class="price">原价</th>
<th class="priceNew">价格</th>
</tr>
</tbody>
<tbody>
<!-- <tr>
<td colspan="3" class="Title red f18 fb"><p>限时折扣</p></td>
</tr> -->
<tr>
<td colspan="3" class="teacher">讲师:{
{order.teacherName}}</td>
</tr>
<tr class="good">
<td class="name First">
<a target="_blank" :href="'https://localhost:3000/course/'+order.courseId">
<img :src="order.courseCover"></a>
<div class="goodInfo">
<input type="hidden" class="ids ids_14502" value="14502">
<a target="_blank" :href="'https://localhost:3000/course/'+ order.courseId">{
{order.courseTitle}}</a>
</div>
</td>
<td class="price">
<p>¥<strong>{
{order.totalFee}}</strong></p>
<!-- <span class="discName red">限时8折</span> -->
</td>
<td class="red priceNew Last">¥<strong>{
{order.totalFee}}</strong></td>
</tr>
<tr>
<td class="Billing tr" colspan="3">
<div class="tr">
<p>共 <strong class="red">1</strong> 件商品,合计<span
class="red f20">¥<strong>{
{order.totalFee}}</strong></span></p>
</div>
</td>
</tr>
</tbody>
</table>
<div class="Finish">
<div class="fr" id="AgreeDiv">
<label for="Agree"><p class="on"><input type="checkbox" checked="checked">我已阅读并同意<a href="javascript:" target="_blank">《谷粒学院购买协议》</a></p></label>
</div>
<div class="clear"></div>
<div class="Main fl">
<div class="fl">
<a :href="'/course/'+order.courseId">返回课程详情页</a>
</div>
<div class="fr">
<p>共 <strong class="red">1</strong> 件商品,合计<span class="red f20">¥<strong
id="AllPrice">{
{order.totalFee}}</strong></span></p>
</div>
</div>
<input name="score" value="0" type="hidden" id="usedScore">
<button class="fr redb" type="button" id="submitPay" @click="toPay()">去支付</button>
<div class="clear"></div>
</div>
</form>
</div>
</template>
(2)js脚本部分
<script>
import ordersApi from '@/api/order'
export default {
asyncData({ params, error }) {
return ordersApi.getOrdersInfo(params.oid)
.then(response => {
return {
order: response.data.data.item
}
})
},
methods:{
//去支付
toPay() {
this.$router.push({path:'/pay/'+this.order.orderNo})
}
}
}
</script>
3)拦截器
- guli-front\utils\request.js
拦截响应,看在是否有25000代码,如果有就不做任何动作
import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import cookie from 'js-cookie'
// 创建axios实例
const service = axios.create({
baseURL: 'http://localhost:9001', // api的base_url
timeout: 20000 // 请求超时时间
})
//第三步 创建拦截器 http request 拦截器
service.interceptors.request.use(
config => {
//debugger
//判断cookie里面是否有名称是guli_token数据
if (cookie.get('guli_token')) {
//把获取cookie值放到header里面
config.headers['token'] = cookie.get('guli_token');
}
return config
},
err => {
return Promise.reject(err);
})
// http response 拦截器
service.interceptors.response.use(
response => {
//debugger
if (response.data.code == 28004) {
console.log("response.data.resultCode是28004")
// 返回 错误代码-1 清除ticket信息并跳转到登录页面
//debugger
window.location.href = "/login"
return
} else {
if (response.data.code !== 20000) {
//25000:订单支付中,不做任何提示
if (response.data.code != 25000) {
Message({
message: response.data.message || 'error',
type: 'error',
duration: 5 * 1000
})
}
} else {
return response;
}
}
},
error => {
return Promise.reject(error.response) // 返回接口返回的错误信息
});
export default service
测试