@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;
}
1.3 导入依赖
在订单模块service_order
导入微信支付需要的依赖:
com.github.wxpay
wxpay-sdk
0.0.3
com.alibaba
fastjson
1.4 配置文件
在配置文件application.properties
配置相关的信息:
服务端口
server.port=8007
服务名
spring.application.name=service-order
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
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
#配置mapper xml文件的路径
mybatis-plus.mapper-locations=classpath:com/atguigu/eduorder/mapper/xml/*.xml
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
#开启熔断机制
#feign.hystrix.enabled=true
设置hystrix超时时间,默认1000ms
#hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000
#关联的公众号appid
wx.pay.app_id=wx74862e0dfc69954
#商户号
wx.pay.partner=155895011
#商户key
wx.pay.partnerkey=T6m9iK73b0kn9g5v426MKHQH7X8rKwb
#回调地址
wx.pay.notifyurl=http://guli.shop/api/order/weixinPay/weixinNotify
#微信提供的固定地址
wx.pay.wxurl=https://api.mch.weixin.qq.com/pay/unifiedorder
#微信查询状态地址
wx.pay.queryUrl=https://api.mch.weixin.qq.com/pay/orderquery
1.5 创建读取微信支付相关信息的工具类
创建一个读取微信支付需要的信息的工具类ConstantWxPayUtils
:
@Controller
public class ConstantWxPayUtils implements InitializingBean {
@Value(“${wx.pay.app_id}”)
private String appID;
@Value(“${wx.pay.partner}”)
private String partner;
@Value(“${wx.pay.partnerkey}”)
private String partnerKey;
@Value(“${wx.pay.notifyurl}”)
private String notifyUrl;
@Value(“${wx.pay.wxurl}”)
private String wxUrl;
@Value(“${wx.pay.queryUrl}”)
private String queryUrl;
//定义公共静态常量
public static String WX_PAY_APP_ID;
public static String WX_PAY_PARTNER;
public static String WX_PAY_PARTNER_KEY;
public static String WX_PAY_NOTIFY_URL;
public static String WX_PAY_WX_URL;
public static String WX_PAY_QUERY_URL;
@Override
public void afterPropertiesSet() throws Exception {
WX_PAY_APP_ID = appID;
WX_PAY_PARTNER = partner;
WX_PAY_PARTNER_KEY = partnerKey;
WX_PAY_NOTIFY_URL = notifyUrl;
WX_PAY_WX_URL = wxUrl;
WX_PAY_QUERY_URL=queryUrl;
}
}
1.6 其他工具类
用于随机生成订单号的工具类OrderNoUtil
:
public class OrderNoUtil {
/**
-
获取订单号
-
@return
*/
public static String getOrderNo() {
SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmss”);
String newDate = sdf.format(new Date());
String result = “”;
Random random = new Random();
for (int i = 0; i < 3; i++) {
result += random.nextInt(10);
}
return newDate + result;
}
}
HttpClient
工具类:
/**
-
http请求客户端
-
@author xppll
*/
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 nvps = new LinkedList();
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;
}
}
这里一共涉及service_order
订单模块、service_ucenter
用户模块、service-edu
课程模块。
service_order
使用Fegin
远程调用其他模块的方法。
详细的Fegin的使用可以参考:SpringCloud-Feign远程调用
2.1 远程调用用户模块和课程模块
在service_order
订单模块创建:
@Component
@FeignClient(“service-ucenter”) //调用的服务名称
public interface UcenterClient {
//根据用户id获取用户信息,用于生成订单使用
@PostMapping(“/educenter/member/getUserInfoOrder/{id}”)
public UcenterMemberOrder getUserInfoOrder(@PathVariable(“id”) String id);
}
@Component
@FeignClient(“service-edu”) //调用的服务名称
public interface CourseClient {
//根据课程id查询课程信息
@PostMapping(“/eduservice/coursefront/getCourseInfoOrder/{id}”)
public CourseWebOrder getCourseInfoOrder(@PathVariable(“id”) String id);
}
2.2 远程调用方法的实现
在
service-edu
课程模块实现根据课程id查询课程信息的getCourseInfoOrder
方法
controller
层:
/**
-
根据课程id查询课程信息
-
@param id 客场id
-
@return CourseWebOrder
*/
@PostMapping(“getCourseInfoOrder/{id}”)
public CourseWebOrder getCourseInfoOrder(@PathVariable(“id”) String id) {
CourseWebVo courseInfo = courseService.getBaseCourseInfo(id);
CourseWebOrder courseWebOrder = new CourseWebOrder();
BeanUtils.copyProperties(courseInfo, courseWebOrder);
return courseWebOrder;
}
service
层:
/**
-
根据课程id,编写sql语句查询课程信息
-
@param courseId 课程id
-
@return CourseWebVo
*/
@Override
public CourseWebVo getBaseCourseInfo(String courseId) {
return baseMapper.getBaseCourseInfo(courseId);
}
mapper
层:
SELECT ec.id,
ec.title
,
ec.price
,
ec.lesson_num as lessonNum,
ec.cover,
ec.buy_count as buyCount,
ec.view_count as viewCount,
ecd.description,
et.id teacherId,
et.name
AS teacherName,
et.intro,
et.avatar,
es1.id as subjectLevelOneId,
es1.title
AS subjectLevelOne,
es2.id as subjectLevelTwoId,
es2.title
AS subjectLevelTwo
FROM edu_course ec
LEFT JOIN edu_course_description ecd ON ec.id = ecd.id
LEFT JOIN edu_teacher et ON ec.teacher_id
= et.id
LEFT JOIN edu_subject es1 ON ec.subject_parent_id
= es1.id
LEFT JOIN edu_subject es2 ON ec.subject_id
= es2.id
WHERE ec.id = #{courseId}
在
service_ucenter
用户模块实现根据用户id获取用户信息的getUserInfoOrder
方法
controller
层:
/**
-
根据用户id获取用户信息,用于生成订单使用
-
@param id 用户id
-
@return UcenterMemberOrder
*/
@PostMapping(“getUserInfoOrder/{id}”)
public UcenterMemberOrder getUserInfoOrder(@PathVariable(“id”) String id) {
UcenterMember member = memberService.getById(id);
UcenterMemberOrder memberOrder = new UcenterMemberOrder();
BeanUtils.copyProperties(member, memberOrder);
return memberOrder;
}
2.3 根据课程id和用户id生成订单
controller
层:
@CrossOrigin
@RestController
@RequestMapping(“/eduorder/order”)
public class OrderController {
@Autowired
private OrderService orderService;
/**
-
生成订单的方法
-
@param courseId 课程id
-
@param request 用于获取用户id
-
@return 返回订单号
*/
@PostMapping(“createOrder/{courseId}”)
public R saveOrder(@PathVariable(“courseId”) String courseId, HttpServletRequest request) {
//通过JWT工具类获取用户id
//创建订单,返回订单号
String orderNo = orderService.createOrderById(courseId, JwtUtils.getMemberIdByJwtToken(request));
return R.ok().data(“orderId”, orderNo);
}
}
service
层:
/**
-
根据courseId和userId生成订单
-
@param courseId 课程id
-
@param userId 用户id
-
@return 返回订单号
*/
@Override
public String createOrderById(String courseId, String userId) {
//通过远程调佣根据用户id获取用户信息
UcenterMemberOrder userInfoOrder = ucenterClient.getUserInfoOrder(userId);
//通过远程调佣根据课程id获取课程信息
CourseWebOrder courseInfoOrder = courseClient.getCourseInfoOrder(courseId);
Order order = new Order();
//订单号
order.setOrderNo(OrderNoUtil.getOrderNo());
order.setCourseId(courseId);
order.setCourseTitle(courseInfoOrder.getTitle());
order.setCourseCover(courseInfoOrder.getCover());
order.setTeacherName(courseInfoOrder.getTeacherName());
order.setTotalFee(courseInfoOrder.getPrice());
order.setMemberId(userId);
order.setMobile(userInfoOrder.getMobile());
order.setNickname(userInfoOrder.getNickname());
//支付状态 未支付:0 已支付:1
order.setStatus(0);
//支付类型 微信:1 支付宝:2
order.setPayType(1);
//保存到数据库
baseMapper.insert(order);
//返回订单号
return order.getOrderNo();
}
3.1 controller层
在OrderController
里创建getOrderInfo
用于生成订单:
/**
-
根据订单id查询订单信息
-
@param orderId 订单id
-
@return 返回订单信息
*/
@GetMapping(“getOrderInfo/{orderId}”)
public R getOrderInfo(@PathVariable(“orderId”) String orderId) {
Order order=orderService.getOrderByOrderId(orderId);
return R.ok().data(“item”, order);
}
3.2 service层
/**
-
根据订单id查询订单信息
-
@param orderId 订单id
-
@return 返回订单信息
*/
@Override
public Order getOrderByOrderId(String orderId) {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Order::getOrderNo, orderId);
return baseMapper.selectOne(queryWrapper);
}
4.1 controller层
在PayLogController
里创建createNative
用于生成支付二维码:
@CrossOrigin
@RestController
@RequestMapping(“/eduorder/paylog”)
public class PayLogController {
@Autowired
private PayLogService payLogService;
/**
-
根据订单号生成微信支付二维码
-
@param orderNo 订单号
-
@return R
*/
@GetMapping(“createNative/{orderNo}”)
public R createNative(@PathVariable(“orderNo”) String orderNo){
//返回信息,包含二维码地址,还有其他信息
Map map=payLogService.createNative(orderNo);
return R.ok().data(map);
}
}
4.2 service层
生成微信支付二维码大概分为这几步:
-
根据订单号查询订单信息
-
使用map设置生成二维码需要的参数
-
发送httpclient请求,传递xml格式的参数,传入微信支付提供的固定地址
-
得到发送请求返回的结果
-
最终返回封装数据
/**
-
根据订单号生成微信支付二维码
-
@param orderNo 订单号
-
@return map
*/
@Override
public Map createNative(String orderNo) {
try {
//1.根据订单号查询订单信息
Order order = orderService.getOrderByOrderId(orderNo);
//2.使用map设置生成二维码需要的参数
Map m = new HashMap();
//关联的公众号appid
m.put(“appid”, ConstantWxPayUtils.WX_PAY_APP_ID);
//商户号
m.put(“mch_id”, ConstantWxPayUtils.WX_PAY_PARTNER);
//随机字符串
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() + “”);
//支付的ip地址
m.put(“spbill_create_ip”, “127.0.0.1”);
m.put(“notify_url”, ConstantWxPayUtils.WX_PAY_NOTIFY_URL);
m.put(“trade_type”, “NATIVE”);
//3.发送httpclient请求,传递参数xml格式,传入微信支付提供的固定地址
HttpClient client = new HttpClient(ConstantWxPayUtils.WX_PAY_WX_URL);
//设置xml格式的参数,需要传入二维码参数m和商户key
client.setXmlParam(WXPayUtil.generateSignedXml(m, ConstantWxPayUtils.WX_PAY_PARTNER_KEY));
//默认不支持https,设置为true支持
client.setHttps(true);
//执行请求发送
client.post();
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
trade_no", orderNo);
//价格
m.put(“total_fee”, order.getTotalFee().multiply(new BigDecimal(“100”)).longValue() + “”);
//支付的ip地址
m.put(“spbill_create_ip”, “127.0.0.1”);
m.put(“notify_url”, ConstantWxPayUtils.WX_PAY_NOTIFY_URL);
m.put(“trade_type”, “NATIVE”);
//3.发送httpclient请求,传递参数xml格式,传入微信支付提供的固定地址
HttpClient client = new HttpClient(ConstantWxPayUtils.WX_PAY_WX_URL);
//设置xml格式的参数,需要传入二维码参数m和商户key
client.setXmlParam(WXPayUtil.generateSignedXml(m, ConstantWxPayUtils.WX_PAY_PARTNER_KEY));
//默认不支持https,设置为true支持
client.setHttps(true);
//执行请求发送
client.post();
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-1Rko38k2-1715075945478)]
[外链图片转存中…(img-BybIsr5Y-1715075945478)]
[外链图片转存中…(img-IPaiAwsy-1715075945479)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!