当前位置: 首页 > news >正文

dedecms 图片网站模板网站开发文档源码

dedecms 图片网站模板,网站开发文档源码,网站模板 安全吗,做外贸网站那家专业苍穹外卖-day08 本项目学自黑马程序员的《苍穹外卖》项目#xff0c;是瑞吉外卖的Plus版本 功能更多#xff0c;更加丰富。 结合资料#xff0c;和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频#xff1a;https://www.bilibili.com/video/BV1TP411v7v6/?sp…苍穹外卖-day08 本项目学自黑马程序员的《苍穹外卖》项目是瑞吉外卖的Plus版本 功能更多更加丰富。 结合资料和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频https://www.bilibili.com/video/BV1TP411v7v6/?spm_id_from333.337.search-card.all.click 资料关注黑马程序员公众号----回复苍穹外卖 一起学习一起加油 【可以使用ApiFox代替YApi来导入的接口文档】 1、学习内网穿透 2、学习微信小程序怎么进行微信支付的知识 在课程的知识中我发现在地址修改部分的地址修改代码不完整已经在下面的修改地址的代码部分加上了sql代码 if testprovinceCode ! nullprovince_code #{provinceCode},/ifif testprovinceName ! nullprovince_name #{provinceName},/ifif testcityCode ! nullcity_code #{cityCode},/ifif testcityName ! nullcity_name #{cityName},/ifif testdistrictCode ! nulldistrict_code #{districtCode},/ifif testdistrictName ! nulldistrict_name #{districtName},/if文章目录 苍穹外卖-day081. 导入地址簿功能代码1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计1.1.3 表设计 1.2 代码导入1.2.1 Mapper层1.2.2 Service层1.2.3 Controller层 1.3 功能测试1.4 代码提交 2. 用户下单2.1 需求分析和设计2.1.1 产品原型2.1.2 接口设计2.1.3 表设计 2.2 代码开发2.2.1 DTO设计2.2.2 VO设计2.2.3 Controller层2.2.4 Service层接口2.2.5 Service层实现类2.2.6 Mapper层 2.3 功能测试2.4 代码提交 3. 订单支付3.1 微信支付介绍3.2 微信支付准备工作3.2.1 如何保证数据安全3.2.2 如何调用到商户系统 3.3 代码导入3.3.1 微信支付相关配置3.3.2 Mapper层3.3.3 Service层3.3.4 Controller层 3.4 功能测试3.5 代码提交 1. 导入地址簿功能代码 1.1 需求分析和设计 1.1.1 产品原型 地址簿指的是消费者用户的地址信息用户登录成功后可以维护自己的地址信息。同一个用户可以有多个地址信息但是只能有一个默认地址。 效果图 对于地址簿管理我们需要实现以下几个功能 查询地址列表新增地址修改地址删除地址设置默认地址查询默认地址 1.1.2 接口设计 根据上述原型图先粗粒度设计接口共包含7个接口。 接口设计 新增地址查询登录用户所有地址查询默认地址根据id修改地址根据id删除地址根据id查询地址设置默认地址 接下来细粒度分析每个接口明确每个接口的请求方式、请求路径、传入参数和返回值。 1). 新增地址 2). 查询登录用户所有地址 3). 查询默认地址 4). 修改地址 5). 根据id删除地址 6). 根据id查询地址 7). 设置默认地址 1.1.3 表设计 用户的地址信息会存储在address_book表即地址簿表中。具体表结构如下 字段名数据类型说明备注idbigint主键自增user_idbigint用户id逻辑外键consigneevarchar(50)收货人sexvarchar(2)性别phonevarchar(11)手机号province_codevarchar(12)省份编码province_namevarchar(32)省份名称city_codevarchar(12)城市编码city_namevarchar(32)城市名称district_codevarchar(12)区县编码district_namevarchar(32)区县名称detailvarchar(200)详细地址信息具体到门牌号labelvarchar(100)标签公司、家、学校is_defaulttinyint(1)是否默认地址1是 0否 这里面有一个字段is_default实际上我们在设置默认地址时只需要更新这个字段就可以了。 1.2 代码导入 对于这一类的单表的增删改查我们已经写过很多了基本的开发思路都是一样的那么本小节的用户地址簿管理的增删改查功能我们就不再一一实现了基本的代码我们都已经提供了直接导入进来做一个测试即可。 导入课程资料中的地址簿模块功能代码 进入到sky-server模块中 1.2.1 Mapper层 创建AddressBookMapper.java package com.sky.mapper;import com.sky.entity.AddressBook; import org.apache.ibatis.annotations.*; import java.util.List;Mapper public interface AddressBookMapper {/*** 条件查询* param addressBook* return*/ListAddressBook list(AddressBook addressBook);/*** 新增* param addressBook*/Insert(insert into address_book (user_id, consignee, phone, sex, province_code, province_name, city_code, city_name, district_code, district_name, detail, label, is_default) values (#{userId}, #{consignee}, #{phone}, #{sex}, #{provinceCode}, #{provinceName}, #{cityCode}, #{cityName}, #{districtCode}, #{districtName}, #{detail}, #{label}, #{isDefault}))void insert(AddressBook addressBook);/*** 根据id查询* param id* return*/Select(select * from address_book where id #{id})AddressBook getById(Long id);/*** 根据id修改* param addressBook*/void update(AddressBook addressBook);/*** 根据 用户id修改 是否默认地址* param addressBook*/Update(update address_book set is_default #{isDefault} where user_id #{userId})void updateIsDefaultByUserId(AddressBook addressBook);/*** 根据id删除地址* param id*/Delete(delete from address_book where id #{id})void deleteById(Long id);}创建AddressBookMapper.xml ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.sky.mapper.AddressBookMapperselect idlist parameterTypeAddressBook resultTypeAddressBookselect * from address_bookwhereif testuserId ! nulland user_id #{userId}/ifif testphone ! nulland phone #{phone}/ifif testisDefault ! nulland is_default #{isDefault}/if/where/selectupdate idupdate parameterTypeaddressBookupdate address_booksetif testconsignee ! nullconsignee #{consignee},/ifif testsex ! nullsex #{sex},/ifif testprovinceCode ! nullprovince_code #{provinceCode},/ifif testprovinceName ! nullprovince_name #{provinceName},/ifif testcityCode ! nullcity_code #{cityCode},/ifif testcityName ! nullcity_name #{cityName},/ifif testdistrictCode ! nulldistrict_code #{districtCode},/ifif testdistrictName ! nulldistrict_name #{districtName},/ifif testphone ! nullphone #{phone},/ifif testdetail ! nulldetail #{detail},/ifif testlabel ! nulllabel #{label},/ifif testisDefault ! nullis_default #{isDefault},/if/setwhere id #{id}/update/mapper1.2.2 Service层 创建AddressBookService.java package com.sky.service;import com.sky.entity.AddressBook; import java.util.List;public interface AddressBookService {ListAddressBook list(AddressBook addressBook);void save(AddressBook addressBook);AddressBook getById(Long id);void update(AddressBook addressBook);void setDefault(AddressBook addressBook);void deleteById(Long id);}创建AddressBookServiceImpl.java package com.sky.service.impl;import com.sky.context.BaseContext; import com.sky.entity.AddressBook; import com.sky.mapper.AddressBookMapper; import com.sky.service.AddressBookService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List;Service Slf4j public class AddressBookServiceImpl implements AddressBookService {Autowiredprivate AddressBookMapper addressBookMapper;/*** 条件查询** param addressBook* return*/public ListAddressBook list(AddressBook addressBook) {return addressBookMapper.list(addressBook);}/*** 新增地址** param addressBook*/public void save(AddressBook addressBook) {addressBook.setUserId(BaseContext.getCurrentId());addressBook.setIsDefault(0);addressBookMapper.insert(addressBook);}/*** 根据id查询** param id* return*/public AddressBook getById(Long id) {AddressBook addressBook addressBookMapper.getById(id);return addressBook;}/*** 根据id修改地址** param addressBook*/public void update(AddressBook addressBook) {addressBookMapper.update(addressBook);}/*** 设置默认地址** param addressBook*/Transactionalpublic void setDefault(AddressBook addressBook) {//1、将当前用户的所有地址修改为非默认地址 update address_book set is_default ? where user_id ?addressBook.setIsDefault(0);addressBook.setUserId(BaseContext.getCurrentId());addressBookMapper.updateIsDefaultByUserId(addressBook);//2、将当前地址改为默认地址 update address_book set is_default ? where id ?addressBook.setIsDefault(1);addressBookMapper.update(addressBook);}/*** 根据id删除地址** param id*/public void deleteById(Long id) {addressBookMapper.deleteById(id);}}1.2.3 Controller层 package com.sky.controller.user;import com.sky.context.BaseContext; import com.sky.entity.AddressBook; import com.sky.result.Result; import com.sky.service.AddressBookService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List;RestController RequestMapping(/user/addressBook) Api(tags C端地址簿接口) public class AddressBookController {Autowiredprivate AddressBookService addressBookService;/*** 查询当前登录用户的所有地址信息** return*/GetMapping(/list)ApiOperation(查询当前登录用户的所有地址信息)public ResultListAddressBook list() {AddressBook addressBook new AddressBook();addressBook.setUserId(BaseContext.getCurrentId());ListAddressBook list addressBookService.list(addressBook);return Result.success(list);}/*** 新增地址** param addressBook* return*/PostMappingApiOperation(新增地址)public Result save(RequestBody AddressBook addressBook) {addressBookService.save(addressBook);return Result.success();}GetMapping(/{id})ApiOperation(根据id查询地址)public ResultAddressBook getById(PathVariable Long id) {AddressBook addressBook addressBookService.getById(id);return Result.success(addressBook);}/*** 根据id修改地址** param addressBook* return*/PutMappingApiOperation(根据id修改地址)public Result update(RequestBody AddressBook addressBook) {addressBookService.update(addressBook);return Result.success();}/*** 设置默认地址** param addressBook* return*/PutMapping(/default)ApiOperation(设置默认地址)public Result setDefault(RequestBody AddressBook addressBook) {addressBookService.setDefault(addressBook);return Result.success();}/*** 根据id删除地址** param id* return*/DeleteMappingApiOperation(根据id删除地址)public Result deleteById(Long id) {addressBookService.deleteById(id);return Result.success();}/*** 查询默认地址*/GetMapping(default)ApiOperation(查询默认地址)public ResultAddressBook getDefault() {//SQL:select * from address_book where user_id ? and is_default 1AddressBook addressBook new AddressBook();addressBook.setIsDefault(1);addressBook.setUserId(BaseContext.getCurrentId());ListAddressBook list addressBookService.list(addressBook);if (list ! null list.size() 1) {return Result.success(list.get(0));}return Result.error(没有查询到默认地址);}}1.3 功能测试 可以通过如下方式进行测试 查看控制台sql和数据库中的数据变化Swagger接口文档测试前后端联调 我们直接使用前后端联调测试 启动后台服务编译小程序 登录进入首页–进入个人中心–进入地址管理 1). 新增收货地址 添加两条收货地址 查看收货地址 查看数据库 2). 设置默认收货地址 设置默认地址 查看数据库 3). 删除收货地址 进行编辑 删除地址 查看数据库 1.4 代码提交 2. 用户下单 2.1 需求分析和设计 2.1.1 产品原型 用户下单业务说明 在电商系统中用户是通过下单的方式通知商家用户已经购买了商品需要商家进行备货和发货。 用户下单后会产生订单相关数据订单数据需要能够体现如下信息 用户将菜品或者套餐加入购物车后可以点击购物车中的 “去结算” 按钮页面跳转到订单确认页面点击 “去支付” 按钮则完成下单操作。 用户点餐业务流程(效果图) 2.1.2 接口设计 接口分析 接口设计 2.1.3 表设计 用户下单业务对应的数据表为orders表和order_detail表(一对多关系,一个订单关联多个订单明细) 表名含义说明orders订单表主要存储订单的基本信息(如: 订单号、状态、金额、支付方式、下单用户、收件地址等)order_detail订单明细表主要存储订单详情信息(如: 该订单关联的套餐及菜品的信息) 具体的表结构如下: 1). orders订单表 字段名数据类型说明备注idbigint主键自增numbervarchar(50)订单号statusint订单状态1待付款 2待接单 3已接单 4派送中 5已完成 6已取消user_idbigint用户id逻辑外键address_book_idbigint地址id逻辑外键order_timedatetime下单时间checkout_timedatetime付款时间pay_methodint支付方式1微信支付 2支付宝支付pay_statustinyint支付状态0未支付 1已支付 2退款amountdecimal(10,2)订单金额remarkvarchar(100)备注信息phonevarchar(11)手机号冗余字段addressvarchar(255)详细地址信息冗余字段consigneevarchar(32)收货人冗余字段cancel_reasonvarchar(255)订单取消原因rejection_reasonvarchar(255)拒单原因cancel_timedatetime订单取消时间estimated_delivery_timedatetime预计送达时间delivery_statustinyint配送状态1立即送出 0选择具体时间delivery_timedatetime送达时间pack_amountint打包费tableware_numberint餐具数量tableware_statustinyint餐具数量状态1按餐量提供 0选择具体数量 2). order_detail订单明细表 字段名数据类型说明备注idbigint主键自增namevarchar(32)商品名称冗余字段imagevarchar(255)商品图片路径冗余字段order_idbigint订单id逻辑外键dish_idbigint菜品id逻辑外键setmeal_idbigint套餐id逻辑外键dish_flavorvarchar(50)菜品口味numberint商品数量amountdecimal(10,2)商品单价 **说明**用户提交订单时需要往订单表orders中插入一条记录并且需要往order_detail中插入一条或多条记录。 2.2 代码开发 2.2.1 DTO设计 根据用户下单接口的参数设计DTO 在sky-pojo模块OrdersSubmitDTO.java已定义 package com.sky.dto;import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime;Data public class OrdersSubmitDTO implements Serializable {//地址簿idprivate Long addressBookId;//付款方式private int payMethod;//备注private String remark;//预计送达时间JsonFormat(shape JsonFormat.Shape.STRING, pattern yyyy-MM-dd HH:mm:ss)private LocalDateTime estimatedDeliveryTime;//配送状态 1立即送出 0选择具体时间private Integer deliveryStatus;//餐具数量private Integer tablewareNumber;//餐具数量状态 1按餐量提供 0选择具体数量private Integer tablewareStatus;//打包费private Integer packAmount;//总金额private BigDecimal amount; }2.2.2 VO设计 根据用户下单接口的返回结果设计VO 在sky-pojo模块OrderSubmitVO.java已定义 package com.sky.vo;import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime;Data Builder NoArgsConstructor AllArgsConstructor public class OrderSubmitVO implements Serializable {//订单idprivate Long id;//订单号private String orderNumber;//订单金额private BigDecimal orderAmount;//下单时间private LocalDateTime orderTime; }2.2.3 Controller层 创建OrderController并提供用户下单方法 package com.sky.controller.user;import com.sky.dto.OrdersPaymentDTO; import com.sky.dto.OrdersSubmitDTO; import com.sky.result.PageResult; import com.sky.result.Result; import com.sky.service.OrderService; import com.sky.vo.OrderPaymentVO; import com.sky.vo.OrderSubmitVO; import com.sky.vo.OrderVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;/*** 订单*/ RestController(userOrderController) RequestMapping(/user/order) Slf4j Api(tags C端-订单接口) public class OrderController {Autowiredprivate OrderService orderService;/*** 用户下单** param ordersSubmitDTO* return*/PostMapping(/submit)ApiOperation(用户下单)public ResultOrderSubmitVO submit(RequestBody OrdersSubmitDTO ordersSubmitDTO) {log.info(用户下单{}, ordersSubmitDTO);OrderSubmitVO orderSubmitVO orderService.submitOrder(ordersSubmitDTO);return Result.success(orderSubmitVO);} }2.2.4 Service层接口 创建OrderService接口并声明用户下单方法 package com.sky.service;import com.sky.dto.*; import com.sky.vo.OrderSubmitVO;public interface OrderService {/*** 用户下单* param ordersSubmitDTO* return*/OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO); }2.2.5 Service层实现类 创建OrderServiceImpl实现OrderService接口 package com.sky.service.impl;/*** 订单*/ Service Slf4j public class OrderServiceImpl implements OrderService {Autowiredprivate OrderMapper orderMapper;Autowiredprivate OrderDetailMapper orderDetailMapper;Autowiredprivate ShoppingCartMapper shoppingCartMapper;Autowiredprivate AddressBookMapper addressBookMapper;/*** 用户下单** param ordersSubmitDTO* return*/Transactionalpublic OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {//异常情况的处理收货地址为空、超出配送范围、购物车为空AddressBook addressBook addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());if (addressBook null) {throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);}Long userId BaseContext.getCurrentId();ShoppingCart shoppingCart new ShoppingCart();shoppingCart.setUserId(userId);//查询当前用户的购物车数据ListShoppingCart shoppingCartList shoppingCartMapper.list(shoppingCart);if (shoppingCartList null || shoppingCartList.size() 0) {throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);}//构造订单数据Orders order new Orders();BeanUtils.copyProperties(ordersSubmitDTO,order);order.setPhone(addressBook.getPhone());order.setAddress(addressBook.getDetail());order.setConsignee(addressBook.getConsignee());order.setNumber(String.valueOf(System.currentTimeMillis()));order.setUserId(userId);order.setStatus(Orders.PENDING_PAYMENT);order.setPayStatus(Orders.UN_PAID);order.setOrderTime(LocalDateTime.now());//向订单表插入1条数据orderMapper.insert(order);//订单明细数据ListOrderDetail orderDetailList new ArrayList();for (ShoppingCart cart : shoppingCartList) {OrderDetail orderDetail new OrderDetail();BeanUtils.copyProperties(cart, orderDetail);orderDetail.setOrderId(order.getId());orderDetailList.add(orderDetail);}//向明细表插入n条数据orderDetailMapper.insertBatch(orderDetailList);//清理购物车中的数据shoppingCartMapper.deleteByUserId(userId);//封装返回结果OrderSubmitVO orderSubmitVO OrderSubmitVO.builder().id(order.getId()).orderNumber(order.getNumber()).orderAmount(order.getAmount()).orderTime(order.getOrderTime()).build();return orderSubmitVO;}}2.2.6 Mapper层 创建OrderMapper接口和对应的xml映射文件 OrderMapper.java package com.sky.mapper;Mapper public interface OrderMapper {/*** 插入订单数据* param order*/void insert(Orders order); } OrderMapper.xml ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.sky.mapper.OrderMapperinsert idinsert parameterTypeOrders useGeneratedKeystrue keyPropertyidinsert into orders(number, status, user_id, address_book_id, order_time, checkout_time, pay_method, pay_status, amount, remark,phone, address, consignee, estimated_delivery_time, delivery_status, pack_amount, tableware_number,tableware_status)values (#{number}, #{status}, #{userId}, #{addressBookId}, #{orderTime}, #{checkoutTime}, #{payMethod},#{payStatus}, #{amount}, #{remark}, #{phone}, #{address}, #{consignee},#{estimatedDeliveryTime}, #{deliveryStatus}, #{packAmount}, #{tablewareNumber}, #{tablewareStatus})/insert /mapper 创建OrderDetailMapper接口和对应的xml映射文件 OrderDetailMapper.java package com.sky.mapper;import com.sky.entity.OrderDetail; import java.util.List;Mapper public interface OrderDetailMapper {/*** 批量插入订单明细数据* param orderDetails*/void insertBatch(ListOrderDetail orderDetails);}OrderDetailMapper.xml ?xml version1.0 encodingUTF-8 ? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.sky.mapper.OrderDetailMapperinsert idinsertBatch parameterTypelistinsert into order_detail(name, order_id, dish_id, setmeal_id, dish_flavor, number, amount, image)valuesforeach collectionorderDetails itemod separator,(#{od.name},#{od.orderId},#{od.dishId},#{od.setmealId},#{od.dishFlavor},#{od.number},#{od.amount},#{od.image})/foreach/insert/mapper2.3 功能测试 登录小程序完成下单操作 下单操作时同时会删除购物车中的数据 查看shopping_cart表 去结算–去支付 查看orders表 查看order_detail表 同时购物车表中数据删除 2.4 代码提交 3. 订单支付 3.1 微信支付介绍 前面的课程已经实现了用户下单那接下来就是订单支付就是完成付款功能。支付大家应该都不陌生了在现实生活中经常购买商品并且使用支付功能来付款在付款的时候可能使用比较多的就是微信支付和支付宝支付了。在苍穹外卖项目中选择的就是微信支付这种支付方式。 要实现微信支付就需要注册微信支付的一个商户号这个商户号是必须要有一家企业并且有正规的营业执照。只有具备了这些资质之后才可以去注册商户号才能开通支付权限。 个人不具备这种资质所以我们在学习微信支付时最重要的是了解微信支付的流程并且能够阅读微信官方提供的接口文档能够和第三方支付平台对接起来就可以了。 微信支付产品 本项目选择小程序支付 参考https://pay.weixin.qq.com/static/product/product_index.shtml 微信支付接入流程 微信小程序支付时序图 微信支付相关接口 **JSAPI下单**商户系统调用该接口在微信支付服务后台生成预支付交易单(对应时序图的第5步) **微信小程序调起支付**通过JSAPI下单接口获取到发起支付的必要参数prepay_id然后使用微信支付提供的小程序方法调起小程序支付(对应时序图的第10步) 3.2 微信支付准备工作 3.2.1 如何保证数据安全 完成微信支付有两个关键的步骤 第一个就是需要在商户系统当中调用微信后台的一个下单接口就是生成预支付交易单。 第二个就是支付成功之后微信后台会给推送消息。 这两个接口数据的安全性要求其实是非常高的。 **解决**微信提供的方式就是对数据进行加密、解密、签名多种方式。要完成数据加密解密需要提前准备相应的一些文件其实就是一些证书。 获取微信支付平台证书、商户私钥文件 有条件的可以获得 在后绪程序开发过程中就会使用到这两个文件需要提前把这两个文件准备好。 3.2.2 如何调用到商户系统 微信后台会调用到商户系统给推送支付的结果在这里我们就会遇到一个问题就是微信后台怎么就能调用到我们这个商户系统呢因为这个调用过程其实本质上也是一个HTTP请求。 目前商户系统它的ip地址就是当前自己电脑的ip地址只是一个局域网内的ip地址微信后台无法调用到。 解决内网穿透。通过cpolar软件可以获得一个临时域名而这个临时域名是一个公网ip这样微信后台就可以请求到商户系统了。 cpolar软件的使用 1). 下载与安装 下载地址https://dashboard.cpolar.com/get-started 在资料中已提供可无需下载。 安装过程中一直下一步即可不再演示。 2). cpolar指定authtoken 复制authtoken 执行命令 cpolar authtoken 复制的authtoken3). 获取临时域名 执行命令 cpolar.exe http 8080获取域名 4). 验证临时域名有效性 访问接口文档 使用localhost:8080访问 使用临时域名访问 证明临时域名生效。 3.3 代码导入 导入资料中的微信支付功能代码即可 3.3.1 微信支付相关配置 application-dev.yml sky:wechat:appid: wxcd2e39f677fd30basecret: 84fbfdf5ea288f0c432d829599083637mchid : 1561414331mchSerialNo: 4B3B3DC35414AD50B1B755BAF8DE9CC7CF407606privateKeyFilePath: D:\apiclient_key.pemapiV3Key: CZBK51236435wxpay435434323FFDuv3weChatPayCertFilePath: D:\wechatpay_166D96F876F45C7D07CE98952A96EC980368ACFC.pemnotifyUrl: https://www.weixin.qq.com/wxpay/pay.phprefundNotifyUrl: https://www.weixin.qq.com/wxpay/pay.phpapplication.yml sky:wechat:appid: ${sky.wechat.appid}secret: ${sky.wechat.secret}mchid : ${sky.wechat.mchid}mchSerialNo: ${sky.wechat.mchSerialNo}privateKeyFilePath: ${sky.wechat.privateKeyFilePath}apiV3Key: ${sky.wechat.apiV3Key}weChatPayCertFilePath: ${sky.wechat.weChatPayCertFilePath}notifyUrl: ${sky.wechat.notifyUrl}refundNotifyUrl: ${sky.wechat.refundNotifyUrl} WeChatProperties.java读取配置(已定义) package com.sky.properties;import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;Component ConfigurationProperties(prefix sky.wechat) Data public class WeChatProperties {private String appid; //小程序的appidprivate String secret; //小程序的秘钥private String mchid; //商户号private String mchSerialNo; //商户API证书的证书序列号private String privateKeyFilePath; //商户私钥文件private String apiV3Key; //证书解密的密钥private String weChatPayCertFilePath; //平台证书private String notifyUrl; //支付成功的回调地址private String refundNotifyUrl; //退款成功的回调地址 }3.3.2 Mapper层 在OrderMapper.java中添加getByNumberAndUserId和update两个方法 /*** 根据订单号和用户id查询订单* param orderNumber* param userId*/Select(select * from orders where number #{orderNumber} and user_id #{userId})Orders getByNumberAndUserId(String orderNumber, Long userId);/*** 修改订单信息* param orders*/void update(Orders orders);在OrderMapper.xml中添加 update idupdate parameterTypecom.sky.entity.Ordersupdate orderssetif testcancelReason ! null and cancelReason! cancel_reason#{cancelReason},/ifif testrejectionReason ! null and rejectionReason! rejection_reason#{rejectionReason},/ifif testcancelTime ! nullcancel_time#{cancelTime},/ifif testpayStatus ! nullpay_status#{payStatus},/ifif testpayMethod ! nullpay_method#{payMethod},/ifif testcheckoutTime ! nullcheckout_time#{checkoutTime},/ifif teststatus ! nullstatus #{status},/ifif testdeliveryTime ! nulldelivery_time #{deliveryTime}/if/setwhere id #{id} /update3.3.3 Service层 在OrderService.java中添加payment和paySuccess两个方法定义 /*** 订单支付* param ordersPaymentDTO* return*/OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception;/*** 支付成功修改订单状态* param outTradeNo*/void paySuccess(String outTradeNo);在OrderServiceImpl.java中实现payment和paySuccess两个方法 Autowiredprivate UserMapper userMapper;Autowiredprivate WeChatPayUtil weChatPayUtil;/*** 订单支付** param ordersPaymentDTO* return*/public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {// 当前登录用户idLong userId BaseContext.getCurrentId();User user userMapper.getById(userId);//调用微信支付接口生成预支付交易单JSONObject jsonObject weChatPayUtil.pay(ordersPaymentDTO.getOrderNumber(), //商户订单号new BigDecimal(0.01), //支付金额单位 元苍穹外卖订单, //商品描述user.getOpenid() //微信用户的openid);if (jsonObject.getString(code) ! null jsonObject.getString(code).equals(ORDERPAID)) {throw new OrderBusinessException(该订单已支付);}OrderPaymentVO vo jsonObject.toJavaObject(OrderPaymentVO.class);vo.setPackageStr(jsonObject.getString(package));return vo;}/*** 支付成功修改订单状态** param outTradeNo*/public void paySuccess(String outTradeNo) {// 当前登录用户idLong userId BaseContext.getCurrentId();// 根据订单号查询当前用户的订单Orders ordersDB orderMapper.getByNumberAndUserId(outTradeNo, userId);// 根据订单id更新订单的状态、支付方式、支付状态、结账时间Orders orders Orders.builder().id(ordersDB.getId()).status(Orders.TO_BE_CONFIRMED).payStatus(Orders.PAID).checkoutTime(LocalDateTime.now()).build();orderMapper.update(orders);}3.3.4 Controller层 在OrderController.java中添加payment方法 /*** 订单支付** param ordersPaymentDTO* return*/PutMapping(/payment)ApiOperation(订单支付)public ResultOrderPaymentVO payment(RequestBody OrdersPaymentDTO ordersPaymentDTO) throws Exception {log.info(订单支付{}, ordersPaymentDTO);OrderPaymentVO orderPaymentVO orderService.payment(ordersPaymentDTO);log.info(生成预支付交易单{}, orderPaymentVO);return Result.success(orderPaymentVO);}PayNotifyController.java package com.sky.controller.notify;import com.alibaba.druid.support.json.JSONUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.sky.annotation.IgnoreToken; import com.sky.properties.WeChatProperties; import com.sky.service.OrderService; import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; import lombok.extern.slf4j.Slf4j; import org.apache.http.entity.ContentType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.nio.charset.StandardCharsets; import java.util.HashMap;/*** 支付回调相关接口*/ RestController RequestMapping(/notify) Slf4j public class PayNotifyController {Autowiredprivate OrderService orderService;Autowiredprivate WeChatProperties weChatProperties;/*** 支付成功回调** param request*/RequestMapping(/paySuccess)public void paySuccessNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {//读取数据String body readData(request);log.info(支付成功回调{}, body);//数据解密String plainText decryptData(body);log.info(解密后的文本{}, plainText);JSONObject jsonObject JSON.parseObject(plainText);String outTradeNo jsonObject.getString(out_trade_no);//商户平台订单号String transactionId jsonObject.getString(transaction_id);//微信支付交易号log.info(商户平台订单号{}, outTradeNo);log.info(微信支付交易号{}, transactionId);//业务处理修改订单状态、来单提醒orderService.paySuccess(outTradeNo);//给微信响应responseToWeixin(response);}/*** 读取数据** param request* return* throws Exception*/private String readData(HttpServletRequest request) throws Exception {BufferedReader reader request.getReader();StringBuilder result new StringBuilder();String line null;while ((line reader.readLine()) ! null) {if (result.length() 0) {result.append(\n);}result.append(line);}return result.toString();}/*** 数据解密** param body* return* throws Exception*/private String decryptData(String body) throws Exception {JSONObject resultObject JSON.parseObject(body);JSONObject resource resultObject.getJSONObject(resource);String ciphertext resource.getString(ciphertext);String nonce resource.getString(nonce);String associatedData resource.getString(associated_data);AesUtil aesUtil new AesUtil(weChatProperties.getApiV3Key().getBytes(StandardCharsets.UTF_8));//密文解密String plainText aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),nonce.getBytes(StandardCharsets.UTF_8),ciphertext);return plainText;}/*** 给微信响应* param response*/private void responseToWeixin(HttpServletResponse response) throws Exception{response.setStatus(200);HashMapObject, Object map new HashMap();map.put(code, SUCCESS);map.put(message, SUCCESS);response.setHeader(Content-type, ContentType.APPLICATION_JSON.toString());response.getOutputStream().write(JSONUtils.toJSONString(map).getBytes(StandardCharsets.UTF_8));response.flushBuffer();} }3.4 功能测试 测试过程中可通过断点方式查看后台每一步执行情况。 下单 去支付 确认支付 进行扫码支付即可。 3.5 代码提交
http://www.w-s-a.com/news/675518/

相关文章:

  • 如何用微信做网站免费设计logo网站有哪些
  • 服务平台型网站余姚网站定制
  • 网站搭建联系方式太平阳电脑网网站模板
  • 请简述网站制作流程html5网络公司网站模板
  • 海尔集团企业网站建设分析重庆市建设银行网站
  • 介绍公司的网站有哪些广西壮族自治区
  • 网站做rss wordpress9 1短视频安装软件
  • 网站建设价格西安室内设计网站排行榜前十名知乎
  • 用nas建设服务器网站用vs做音乐网站
  • 天津市武清区住房建设网站网站自适应框架
  • 制作移动网站公司网站开发职业规划
  • 网站头部怎样做有气势wordpress 页面 锚
  • 秦皇岛网站建设系统推荐个人网站免费制作
  • 我做夫人那些年网站登录wordpress 扫码付费
  • 网站关键词代码怎么做公司 网站建设
  • 哈尔滨多语言网站建设wordpress分类链接
  • 购物网站项目介绍软件开发流程的五大步骤
  • 做的网站怎么放在网上2008 iis搭建网站
  • 网站维护服务公司上海兼职网站制作
  • 企业做网站需要多少钱湘潭九华网站
  • 嘉兴建站服务微营销官网
  • 比较好的网页模板网站浦项建设(中国)有限公司网站
  • 有趣的个人网站网页设计与制作的岗位职责
  • 有建设网站的软件吗长沙做网站的公司对比
  • 网站的外链接数中铝长城建设有限公司网站
  • 北京建设网站公司网站建设费用 无形资产
  • 适合seo的建站系统如何建立网页
  • 我想自己建立一个网站给大家分享个永久免费的云服务器
  • 怎样做网站和网站的友情链接官网优化 报价
  • 购买网站空间大小聊城网站空间公司