微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,

文章目录

  • 一、环境搭建
    • 1、引入依赖
    • 2、数据库
    • 3、代码生成器生成代码
    • 4、application.yml
    • 5、启动类
  • 二、后端
    • 1、生成订单
      • 1、编写根据课程id获取课程详细信息的接口
      • 2、复制对应实体类
      • 3、编写feign接口
      • 4、编写生成订单和根据订单id查询订单的接口
      • 5、测试
    • 2、生成微信支付二维码
      • 1、前戏
      • 2、controller
      • 3、工具类
      • 4、service
    • 3、查询支付状态,订单是否支付成功
      • 1、controller
    • 4、课程详情功能完善
      • 1、编写根据用户id和课程id查询订单信息接口
      • 2、service-edu中远程调用接口
      • 3、编写查询是否被购买接口
      • 4、测试
  • 三、前端
    • 1、订单页面整合
      • 1、修改课程详情页面代码,实现点击购买,跳转页面
      • 2、编写订单动态路由页面
    • 2、二维码页面整合(qriously组件)
      • 1、修改订单页面,点击去支付,跳转到支付页面
      • 2、编写api接口
      • 3、编写程序
      • 4、测试
    • 3、修改课程页面,让其判断,购买状态,如果已购,不显示立即购买,显示立即观看
      • 1、api接口
      • 2、代码
      • 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>

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第1张图片

2、数据库

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第2张图片

# Host: localhost  (Version 5.7.19)
# Date: 2019-11-18 15:49:50
# Generator: MySQL-Front 6.1  (Build 1.26)


#
# Structure for table "t_order"
#

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='订单';

#
# Data for table "t_order"
#

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');

#
# Structure for table "t_pay_log"
#

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='支付日志表';

#
# Data for table "t_pay_log"
#

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张图片

3、代码生成器生成代码

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第4张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第5张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第6张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第7张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第8张图片

4、application.yml

server:
  port: 8006 #微服务端口号为8001
spring:
  application:
    name: service-order #服务名
  profiles:
    active: dev #环境设置 dev表示构建阶段,test表示测试阶段,prod表示发布阶段
  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: #我们的时区是东八区,应该加8个小时,时区显示格式也需要改成我们想要的
    date-format: yyyy-MM-DD HH:mm:ss
    time-zone: GMT+8
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #nacos
feign:
  client:
    config:
      default:
        connect-timeout: 10000 #设置超时限制,必须超过10000ms才报错
        read-timeout: 10000 #设置Feign服务熔断机制的最大超时限制
  hystrix:
    enabled: true #开启熔断机制
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000 #设置hystri超时时间 默认1000ms(10s)


mybatis-plus:
  mapper-locations: classpath:com/yzpnb/order_service/mapper/xml/*.xml #配置mapper xml文件的路径
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis日志

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"})//这样它会将所有com.yzpnb包下内容扫描,而不只是扫描子文件或同级文件
@EnableDiscoveryClient //nacos注册
@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

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第9张图片

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;
    }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第10张图片

2、复制对应实体类

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第11张图片

3、编写feign接口

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第12张图片

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;

/**
 * 

* 订单 前端控制器 *

* * @author testjava * @since 2020-06-06 */
@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){ //1、获取用户id String memberId = JwtUtils.getMemberIdByJwtToken(request); //2、根据课程id获取课程信息 CourseAllInfoVo courseAllInfoVo = feignToEduServiceClient.selectCourseAllInfoVoApiById(courseId); //3、根据用户id获取用户信息 UcenterMember ucenterMember = feignToUcenterClient.selectById(memberId); //4、随机生成订单号 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; //4、创建订单 TOrder order=new TOrder(); order.setOrderNo(orderNo);//订单号 order.setCourseId(courseId);//课程id order.setCourseTitle(courseAllInfoVo.getTitle());//课程标题 order.setCourseCover(courseAllInfoVo.getCover());//课程封面 order.setTeacherName(courseAllInfoVo.getTeacherName());//讲师姓名 order.setTotalFee(courseAllInfoVo.getPrice());//课程价格 order.setMemberId(memberId);//用户id order.setMobile(ucenterMember.getMobile());//用户电话 order.setNickname(ucenterMember.getNickname());//用户昵称 order.setStatus(0);//订单状态,默认未支付 order.setPayType(1);//支付类型默认为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); } }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第13张图片

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;

/**
 * 

* 支付日志表 前端控制器 *

* * @author testjava * @since 2020-06-06 */
@RestController @RequestMapping("/order_service/t-pay-log") @CrossOrigin public class TPayLogController { @Autowired private TPayLogService tPayLogServicee; /** * 生成二维码 * * @return */ @ApiOperation("根据订单号生成支付二维码") @GetMapping("createNative/{orderNo}") public Result createNative( @ApiParam(name = "orderNo",value = "订单号") @PathVariable String orderNo) { Map map = tPayLogServicee.createNative(orderNo); return Result.ok().data(map); } }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第14张图片

3、工具类

引入依赖
<!--apache HttpClient-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.12</version>
        </dependency>

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第15张图片

工具类,用来将字符串转换为Xml文件
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;

/**
 * http请求客户端
 * 
 * @author qy
 * 
 */
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);
	}

	/**
	 * set http post,put param
	 */
	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;
	}

}

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第16张图片

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;

/**
 * 

* 支付日志表 服务实现类 *

* * @author testjava * @since 2020-06-06 */
@Service public class TPayLogServiceImpl extends ServiceImpl<TPayLogMapper, TPayLog> implements TPayLogService { @Autowired private TOrderService tOrderService; //引入订单接口 /** * 根据订单号获取支付二维码 * @param orderNo * @return */ @Override public Map createNative(String orderNo) { try { //根据订单id获取订单信息 QueryWrapper<TOrder> wrapper = new QueryWrapper<>(); wrapper.eq("order_no",orderNo); TOrder order = tOrderService.getOne(wrapper); Map m = new HashMap(); //1、设置支付参数 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()+"");//订单价格,改成圆角分的Long类型,并转为字符串 m.put("spbill_create_ip", "127.0.0.1"); //支付ip地址,一般写你的项目域名yzpnb.XXXX,这里做本地测试,所以写127.0.0.1 m.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify\n");//回调地址 m.put("trade_type", "NATIVE");//生成支付类型,NATIAE表示根据价格生成二维码 //2、HTTPClient来根据URL访问第三方接口并且传递参数,发送httpclient请求,传递参数xml格式,传入微信支付提供的固定地址 HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder"); //client设置参数 client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));//使用了微信工具类,通过商户key对参数进行加密 client.setHttps(true);//我们访问https请求,默认不支持,将其设置为支持 client.post();//使用post发送http请求 //3、返回第三方的数据 String xml = client.getContent();//返回信息为xml格式信息 Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);//通过微信工具类,将xml格式解析为map集合 //4、封装返回结果集 Map map = new HashMap<>(); map.put("out_trade_no", orderNo); //订单编号 map.put("course_id", order.getCourseId()); //课程id map.put("total_fee", order.getTotalFee()); //总价格 map.put("result_code", resultMap.get("result_code")); //发送请求后状态码(微信返回的) map.put("code_url", resultMap.get("code_url")); //二维码地址(微信返回的) //微信支付二维码2小时过期,可采取2小时未支付取消订单 //redisTemplate.opsForValue().set(orderNo, map, 120, TimeUnit.MINUTES); return map; } catch (Exception e) { e.printStackTrace(); return new HashMap<>();//请求二维码失败,返回空的map集合 } } }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第17张图片

3、查询支付状态,订单是否支付成功

如果支付成功,将订单表中支付状态改为1,日志表中增加记录(用于申诉等使用)

1、controller

@ApiOperation("根据订单号查询支付状态,支付成功,添加订单日志")
    @GetMapping("/queryPayStatus/{orderNo}")
    public Result queryPayStatus(@PathVariable String orderNo) {

        //调用查询接口,查询订单状态(不是我们的数据库状态,而是微信中支付状态,为了方便,还是返回map)
        Map<String, String> map = tPayLogServicee.queryPayStatus(orderNo);

        if (map == null) {//没有值,表示没有支付,出错
            return Result.error().message("支付出错");
        }
        if (map.get("trade_state").equals("SUCCESS")) {//获取微信返回数据中支付状态,如果成功
            //更改订单状态,改订单状态为1,并添加日志
            tPayLogServicee.updateOrderStatus(map);
            return Result.ok().message("支付成功");
        }

        return Result.ok().code(25000).message("支付中");
    }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第18张图片### 2、service

   /**
     * 根据订单号查询订单支付状态(微信)
     * @param orderNo
     * @return
     */
    @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来根据URL访问第三方接口并且传递参数,发送httpclient请求,传递参数xml格式,传入微信支付提供的固定地址
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));//使用了微信工具类,通过商户key对参数进行加密
            client.setHttps(true);//我们访问https请求,默认不支持,将其设置为支持
            client.post();//使用post发送http请求
            //3、返回第三方的数据
            String xml = client.getContent();//返回信息为xml格式信息
            //4、转成Map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);//通过微信工具类,将xml格式解析为map集合
            //5、返回
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 更改订单状态,改订单状态为1,并添加日志
     * @param map
     */
    @Override
    public void updateOrderStatus(Map<String, String> map) {
        //获取订单id
        String orderNo = map.get("out_trade_no");

        //根据订单id查询订单信息
        QueryWrapper<TOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no",orderNo);
        TOrder order = tOrderService.getOne(wrapper);

        if(order.getStatus().intValue() == 1) return;//为1表示已经支付,不执行下面的操作
        order.setStatus(1);//否则就设置为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);//插入到支付日志表
    }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第19张图片

4、课程详情功能完善

查看课程详情的时候,判断用户是否已经购买课程

1、编写根据用户id和课程id查询订单信息接口

@ApiOperation("根据用户id和课程id查询订单信息,已经支付返回true,没有返回false")
    @GetMapping("isBuyCourse")
    public boolean isBuyCourse(@RequestParam(value = "memberid") String memberid,
                               @RequestParam(value = "courseid") String courseid) {
        //订单状态是1表示支付成功
        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;
        }
    }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第20张图片

2、service-edu中远程调用接口

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第21张图片

3、编写查询是否被购买接口

 //根据id查询课程详情信息
    @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);
    }

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第22张图片

4、测试

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第23张图片

三、前端

1、订单页面整合

1、修改课程详情页面代码,实现点击购买,跳转页面

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第24张图片

2、编写订单动态路由页面

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第25张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第26张图片

2、二维码页面整合(qriously组件)

需要使用qriously组件,它会根据地址实时下载图片显示

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第27张图片微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第28张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第29张图片

1、修改订单页面,点击去支付,跳转到支付页面

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第30张图片

2、编写api接口

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第31张图片

3、编写程序

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第32张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第33张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第34张图片

4、测试

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第35张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第36张图片

3、修改课程页面,让其判断,购买状态,如果已购,不显示立即购买,显示立即观看

1、api接口

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第37张图片

2、代码

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第38张图片
微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第39张图片

3、测试

微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”十、微信扫码支付功能,_第40张图片

你可能感兴趣的:(扫码支付,java,数据库,spring,cloud,feign)