• 支付模块-微信支付


    目录

    接口实现 

    第一步:当点击立即购买生成订单

    第二步:根据订单id查询订单信息

    第三步:生成微信支付的二维码

    第四步:查询订单支付状态

    前端实现

    ​编辑

    1.点击支付

    2.订单详情页


    接口实现 

     

    像这种微服务B2C模式的,订单业务需要远程调用我们的课程信息+用户信息

      

    依赖:

    1. <dependency>
    2. <groupId>com.github.wxpaygroupId>
    3. <artifactId>wxpay-sdkartifactId>
    4. <version>0.0.3version>
    5. dependency>
    6. <dependency>
    7. <groupId>com.alibabagroupId>
    8. <artifactId>fastjsonartifactId>
    9. dependency>

    第一步:当点击立即购买生成订单

    通过远程调用,order业务调用course+user

    1.查询Course课程信息暴露出来的接口+用户信息接口

    1. @Component
    2. @FeignClient("service-edu")
    3. public interface EduClient {
    4. /**
    5. * 1.远程调用ucenter中根据id获取用户信息的方法
    6. */
    7. @GetMapping("/eduservice/indexfront/getCourseInfoOrder/{id}")
    8. public CourseWebVoOrder getCourseInfoOrder(@PathVariable String id);
    9. }
    1. @Component
    2. @FeignClient("service-ucenter")
    3. public interface UcenterClient {
    4. /**
    5. * 1.根据课程id查询课程信息
    6. */
    7. @GetMapping("/educenter/member/getUserInfoOrder/{id}")
    8. public UcenterMemberOrder getUserInfoOrder(@PathVariable("id") String id);
    9. }

    2.生成订单的接口+实现类

    通过请求头得到token然后给到JWT进行解析得到用户id

    1. @RestController
    2. @RequestMapping("/eduorder/order")
    3. @CrossOrigin
    4. public class OrderController {
    5. @Autowired
    6. private OrderService orderService;
    7. /**
    8. * 1.生成订单的方法
    9. */
    10. @GetMapping("createOrder/{courseId}")
    11. public R saveOrder(@PathVariable String courseId, HttpServletRequest request){
    12. //1.生成订单号
    13. String orderNo=orderService.createOrders(courseId,JwtUtils.getMemberIdByJwtToken(request));
    14. return R.ok().data("orderId",orderNo);
    15. }
    1. /**
    2. *

    3. * 订单 服务实现类
    4. *

    5. *
    6. * @author testjava
    7. * @since 2022-07-25
    8. */
    9. @Service
    10. public class OrderServiceImpl extends ServiceImpl implements OrderService {
    11. @Autowired
    12. private EduClient eduClient;
    13. @Autowired
    14. private UcenterClient ucenterClient;
    15. /**
    16. * 1.生成订单的方法,通过远程调用两个feign方法(课程信息和人物信息)结合到Order中为订单
    17. * @param courseId
    18. * @param memberId
    19. * @return
    20. */
    21. @Override
    22. public String createOrders(String courseId, String memberId) {
    23. //1.通过远程调用根据用户id获取用户信息
    24. UcenterMemberOrder userInfoOrder = ucenterClient.getUserInfoOrder(memberId);
    25. //2.通过远程调用根据课程id获取课程信息
    26. CourseWebVoOrder courseInfoOrder = eduClient.getCourseInfoOrder(courseId);
    27. //3.创建order对象,向order对象里面设置需要的数据
    28. Order order = new Order();
    29. order.setOrderNo(OrderNoUtil.getOrderNo());
    30. order.setCourseId(courseId); //课程id
    31. order.setCourseTitle(courseInfoOrder.getTitle());
    32. order.setCourseCover(courseInfoOrder.getCover());
    33. order.setTeacherName(courseInfoOrder.getTeacherName());
    34. order.setTotalFee(courseInfoOrder.getPrice());
    35. order.setMemberId(memberId);
    36. order.setMobile(userInfoOrder.getMobile());
    37. order.setNickname(userInfoOrder.getNickname());
    38. order.setStatus(0);//订单状态(0:未支付 1:已支付)
    39. order.setPayType(1);//支付类型 微信1
    40. baseMapper.insert(order);//插入
    41. return order.getOrderNo();
    42. }
    43. }

     返回的CourseWebVoOrder等远程调用的类放在公共模块中

     

     

    第二步:根据订单id查询订单信息

    1. /**
    2. * 2.根据订单id查询订单信息
    3. */
    4. @GetMapping("getOrderInfo/{orderId}")
    5. public R getOrderInfo(@PathVariable String orderId){//订单id查询
    6. QueryWrapper wrapper = new QueryWrapper<>();
    7. wrapper.eq("order_no",orderId);
    8. Order order = orderService.getOne(wrapper);
    9. return R.ok().data("item",order);
    10. }

    第三步:生成微信支付的二维码

    准备工作(wxid,商户号,商户key)

    1.根据订单号获取订单信息

    1. /**
    2. *

    3. * 支付日志表 前端控制器
    4. *

    5. *
    6. * @author testjava
    7. * @since 2022-07-25
    8. */
    9. @RestController
    10. @RequestMapping("/eduorder/paylog")
    11. @CrossOrigin
    12. public class PayLogController {
    13. @Autowired
    14. private PayLogService payLogService;
    15. /**
    16. * 1.生成微信支付的二维码接口
    17. */
    18. @GetMapping("createNative/{orderNo}")
    19. public R createNative(@PathVariable String orderNo) {
    20. //1.返回信息含有二维码的地址还有其他信息
    21. Map map = payLogService.createNative(orderNo);
    22. System.out.println("*****返回二维码map集合****:"+map);
    23. return R.ok().data(map);
    24. }

    2.1根据订单号获取订单信息——>2.2业务实现类中设置支付参数 ——>2.3将参数请求到我们vx支付的接口地址,回调得到返回集(client.getContent(),利用WXPayUtil将xml转为map集合方便返回到前端)

    1. @Service
    2. public class PayLogServiceImpl extends ServiceImpl implements PayLogService {
    3. @Autowired
    4. private OrderService orderService;
    5. /**
    6. * 1.返回二维码地址
    7. * @param orderNo
    8. * @return
    9. */
    10. @Override
    11. public Map createNative(String orderNo) {
    12. try {
    13. //1.根据订单id获取订单信息
    14. QueryWrapper wrapper = new QueryWrapper<>();
    15. wrapper.eq("order_no", orderNo);
    16. Order order = orderService.getOne(wrapper);
    17. //2.使用map设置二维码需要的参数
    18. HashMap map = new HashMap();
    19. map.put("appid","wx74862e0dfcf69954");
    20. map.put("mch_id", "1558950191");
    21. map.put("nonce_str", WXPayUtil.generateNonceStr());//随机生成一个二维码
    22. map.put("body", order.getCourseTitle());
    23. map.put("out_trade_no", orderNo);//二维码标识订单号
    24. map.put("total_fee", order.getTotalFee().multiply(new BigDecimal("100")).longValue()+"");//价格
    25. map.put("spbill_create_ip", "127.0.0.1");
    26. map.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify\n");
    27. map.put("trade_type", "NATIVE");
    28. //3.发送httpclient请求,传递参数按照xml格式,微信支付提供固定地址
    29. HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
    30. //设置参数,我们的商户key会对这些map参数进行加密->将map根据key进行加密并且传送到请求中去
    31. client.setXmlParam(WXPayUtil.generateSignedXml(map,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
    32. client.setHttps(true);
    33. //执行请求发送
    34. client.post();
    35. //4.得到发送请求返回的结果,返回的内容是xml格式返回的(之前传参数也是xml格式)
    36. String content = client.getContent();
    37. //5.再把xml转为map
    38. MapresultMap=WXPayUtil.xmlToMap(content);
    39. //6.前面的map只是为了给到http生成二维码,需要转为xml格式,现在我们这个结果resultMap就是二维码了
    40. //还需要一些关于订单的提示信息
    41. Map res = new HashMap<>();
    42. res.put("out_trade_no", orderNo);
    43. res.put("course_id", order.getCourseId());
    44. res.put("total_fee", order.getTotalFee());
    45. res.put("result_code", resultMap.get("result_code"));//状态码
    46. res.put("code_url", resultMap.get("code_url"));//二维码地址
    47. return res;
    48. } catch (Exception e) {
    49. throw new GuliException(20001,"生成二维码失败");
    50. }
    51. }

    第四步:查询订单支付状态

     1.先查订单的支付状态,返回的支付state为成功——>2.然后在支付日志表中添加一条记录,并且更新订单表状态

    1. /**
    2. * 2.查询订单状态
    3. * @param orderNo
    4. * @return
    5. */
    6. @GetMapping("queryPayStatus/{orderNo}")
    7. public R queryPayStatus(@PathVariable String orderNo){
    8. Mapmap= payLogService.queryPayStatus(orderNo);
    9. System.out.println("返回二维码状态:"+map);
    10. //1.根据查询出来的订单状态进行判断
    11. if(map==null){
    12. return R.error().message("支付出错了...");
    13. }
    14. //2.如果返回的map不为空,从这里面获取订单状态
    15. if(map.get("trade_state").equals("SUCCESS")){//支付成功
    16. //3.添加记录到支付表中,并且更新订单表的状态
    17. payLogService.updateOrdersStatus(map);
    18. return R.ok();
    19. }
    20. return R.ok().code(25000).message("支付中");
    21. }
    22. }

      业务实现类-根据订单号查询订单状态

    1. /**
    2. * 1.查询订单支付状态
    3. * @param orderNo
    4. * @return
    5. */
    6. @Override
    7. public Map queryPayStatus(String orderNo) {
    8. //1.封装参数
    9. try {
    10. HashMap map = new HashMap();
    11. map.put("appid", "wx74862e0dfcf69954");
    12. map.put("mch_id", "1558950191");
    13. map.put("out_trade_no", orderNo);
    14. map.put("nonce_str", WXPayUtil.generateNonceStr());
    15. //2.设置请求,利用xml进行请求
    16. HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
    17. client.setXmlParam(WXPayUtil.generateSignedXml(map,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
    18. client.setHttps(true);
    19. client.post();
    20. //3.返回第三方的数据
    21. String xml = client.getContent();
    22. Map resultMap = WXPayUtil.xmlToMap(xml);//将xml转为map数据
    23. return resultMap;
    24. } catch (Exception e) {
    25. e.printStackTrace();
    26. }
    27. return null;
    28. }

    业务实现-添加支付记录+更新订单状态

    1. /**
    2. * 2.添加支付记录和更新订单状态
    3. * @param map
    4. */
    5. @Override
    6. public void updateOrdersStatus(Map map) {
    7. //1.从map中获取订单号
    8. String orderNo = map.get("out_trade_no");
    9. //2.根据订单号查询订单信息
    10. QueryWrapper wrapper = new QueryWrapper<>();
    11. wrapper.eq("order_no",orderNo);
    12. Order order = orderService.getOne(wrapper);
    13. //3.更新订单表的订单状态
    14. if(order.getStatus().intValue()==1){
    15. return;//说明支付过了
    16. }
    17. order.setStatus(1);
    18. orderService.updateById(order);
    19. //4.向支付表中添加支付记录
    20. PayLog payLog = new PayLog();
    21. payLog.setOrderNo(orderNo);
    22. payLog.setPayTime(new Date());
    23. payLog.setPayType(1);//支付类型 1wx
    24. payLog.setTotalFee(order.getTotalFee());//总金额(分)
    25. payLog.setTradeState(map.get("trade_state"));//支付状态
    26. payLog.setTransactionId(map.get("transaction_id"));//账单流水号
    27. payLog.setAttr(JSONObject.toJSONString(map));
    28. baseMapper.insert(payLog);//插入到支付日志表
    29. }

    前端实现

     当点击商品的去支付就会生成支付的二维码

    1.点击支付

    1. methods:{
    2. //去支付,通过动态路由的方式传递orderNo订单号
    3. toPay(){
    4. this.$router.push({path:'/pay/'+this.order.orderNo})
    5. }
    6. }

    2.订单详情页

    因为oid页面到pid页面点击toPay方法传入订单号,我们这里根据订单号调后台接口createNative生成二维码

    mouted()方法:里面定义一个定时器,每3s判断一次订单的状态,如果订单响应状态为success则清除定时器——>跳转到订单详情页去看视频

    1. import ordersApi from "@/api/order";
    2. export default {
    3. //1.return除了要return方法还要return成功数据
    4. asyncData({ params, error }) {
    5. // 2.名字是pid,那么动态路由的参数就是pid
    6. return ordersApi.createNative(params.pid).then((response) => {
    7. return {
    8. payObj: response.data.data,
    9. };
    10. });
    11. },
    12. data() {
    13. return {
    14. tiemer1: "",
    15. };
    16. },
    17. //2.定义mouted,意思是页面渲染之后执行,防止没有数据
    18. mounted() {
    19. //1.每隔3s调一次查询订单状态方法
    20. this.tiemer1 = setInterval(() => {
    21. this.queryOrderStatus(this.payObj.out_trade_no);
    22. }, 3000);
    23. },
    24. methods: {
    25. //3.查询支付状态
    26. queryOrderStatus(orderNo) {
    27. ordersApi.queryPayStatus(orderNo).then((response) => {
    28. console.log("正在查询订单信息.....");
    29. console.log(response.data);
    30. if(response.data.success){
    31. console.log("支付成功,清除定时器")
    32. //1.支付成功清除定时器
    33. clearInterval(this.tiemer1);
    34. //2.支付成功提示
    35. this.$message({
    36. type: "success",
    37. message: "支付成功!",
    38. });
    39. //3.跳转到课程详情页面观看视频
    40. this.$router.push({ path: "/course/" + this.payObj.course_id });
    41. }
    42. });
    43. },
    44. },
    45. };

  • 相关阅读:
    [Docker]六.Docker自动部署nodejs以及golang项目
    windows 定制 terminal 上手实践
    ArrayList和CopyOnWriteArrayList
    软件外包开发人员分类
    聊聊Tomcat
    0基础学习VR全景平台篇 第104篇:720全景后期软件安装
    论文阅读:scHybridBERT
    C++之多态<polymorphism>
    Elasticsearch7.7的安装与启动
    实在智能AI+RPA:引领数字化转型的超自动化智能体
  • 原文地址:https://blog.csdn.net/weixin_57128596/article/details/127301746