支付模块-微信支付

目录

接口实现 

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

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

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

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

前端实现

​编辑

1.点击支付

2.订单详情页


接口实现 

 

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

  

依赖:

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

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

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

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

@Component
@FeignClient("service-edu")
public interface EduClient {

    /**
     * 1.远程调用ucenter中根据id获取用户信息的方法
     */
    @GetMapping("/eduservice/indexfront/getCourseInfoOrder/{id}")
    public CourseWebVoOrder getCourseInfoOrder(@PathVariable String id);

}
@Component
@FeignClient("service-ucenter")
public interface UcenterClient {

    /**
     * 1.根据课程id查询课程信息
     */
    @GetMapping("/educenter/member/getUserInfoOrder/{id}")
    public UcenterMemberOrder getUserInfoOrder(@PathVariable("id") String id);
}

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

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

@RestController
@RequestMapping("/eduorder/order")
@CrossOrigin
public class OrderController {

    @Autowired
    private OrderService orderService;

    /**
     * 1.生成订单的方法
     */
    @GetMapping("createOrder/{courseId}")
    public R saveOrder(@PathVariable String courseId, HttpServletRequest request){
        //1.生成订单号
       String orderNo=orderService.createOrders(courseId,JwtUtils.getMemberIdByJwtToken(request));
       return R.ok().data("orderId",orderNo);
    }
/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author testjava
 * @since 2022-07-25
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private EduClient eduClient;
    @Autowired
    private UcenterClient ucenterClient;

    /**
     * 1.生成订单的方法,通过远程调用两个feign方法(课程信息和人物信息)结合到Order中为订单
     * @param courseId
     * @param memberId
     * @return
     */
    @Override
    public String createOrders(String courseId, String memberId) {
       //1.通过远程调用根据用户id获取用户信息
        UcenterMemberOrder userInfoOrder = ucenterClient.getUserInfoOrder(memberId);

        //2.通过远程调用根据课程id获取课程信息
        CourseWebVoOrder courseInfoOrder = eduClient.getCourseInfoOrder(courseId);

        //3.创建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
        baseMapper.insert(order);//插入

        return order.getOrderNo();
    }
}

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

 

 

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

 /**
     * 2.根据订单id查询订单信息
     */
    @GetMapping("getOrderInfo/{orderId}")
    public R getOrderInfo(@PathVariable String orderId){//订单id查询
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no",orderId);

        Order order = orderService.getOne(wrapper);
        return R.ok().data("item",order);
    }

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

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

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

/**
 * <p>
 * 支付日志表 前端控制器
 * </p>
 *
 * @author testjava
 * @since 2022-07-25
 */
@RestController
@RequestMapping("/eduorder/paylog")
@CrossOrigin
public class PayLogController {

    @Autowired
    private PayLogService payLogService;

    /**
     * 1.生成微信支付的二维码接口
     */
    @GetMapping("createNative/{orderNo}")
    public R createNative(@PathVariable String orderNo) {
        //1.返回信息含有二维码的地址还有其他信息
        Map map = payLogService.createNative(orderNo);
        System.out.println("*****返回二维码map集合****:"+map);
        return R.ok().data(map);
    }

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

@Service
public class PayLogServiceImpl extends ServiceImpl<PayLogMapper, PayLog> implements PayLogService {

    @Autowired
    private OrderService orderService;

    /**
     * 1.返回二维码地址
     * @param orderNo
     * @return
     */
    @Override
    public Map createNative(String orderNo) {
        try {
            //1.根据订单id获取订单信息
            QueryWrapper<Order> wrapper = new QueryWrapper<>();
            wrapper.eq("order_no", orderNo);
            Order order = orderService.getOne(wrapper);

            //2.使用map设置二维码需要的参数
            HashMap map = new HashMap();
            map.put("appid","wx74862e0dfcf69954");
            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");
            map.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify\n");
            map.put("trade_type", "NATIVE");

            //3.发送httpclient请求,传递参数按照xml格式,微信支付提供固定地址
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");

            //设置参数,我们的商户key会对这些map参数进行加密->将map根据key进行加密并且传送到请求中去
            client.setXmlParam(WXPayUtil.generateSignedXml(map,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            client.setHttps(true);

            //执行请求发送
            client.post();

            //4.得到发送请求返回的结果,返回的内容是xml格式返回的(之前传参数也是xml格式)
            String content = client.getContent();
            //5.再把xml转为map
            Map<String,String>resultMap=WXPayUtil.xmlToMap(content);

            //6.前面的map只是为了给到http生成二维码,需要转为xml格式,现在我们这个结果resultMap就是二维码了
            //还需要一些关于订单的提示信息
            Map res = new HashMap<>();
            res.put("out_trade_no", orderNo);
            res.put("course_id", order.getCourseId());
            res.put("total_fee", order.getTotalFee());
            res.put("result_code", resultMap.get("result_code"));//状态码
            res.put("code_url", resultMap.get("code_url"));//二维码地址

            return res;

        } catch (Exception e) {
           throw new GuliException(20001,"生成二维码失败");
        }
    }

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

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

 /**
     * 2.查询订单状态
     * @param orderNo
     * @return
     */
    @GetMapping("queryPayStatus/{orderNo}")
    public R queryPayStatus(@PathVariable String orderNo){
       Map<String,String>map= payLogService.queryPayStatus(orderNo);
        System.out.println("返回二维码状态:"+map);
       //1.根据查询出来的订单状态进行判断
        if(map==null){
            return R.error().message("支付出错了...");
        }

        //2.如果返回的map不为空,从这里面获取订单状态
        if(map.get("trade_state").equals("SUCCESS")){//支付成功
            //3.添加记录到支付表中,并且更新订单表的状态
            payLogService.updateOrdersStatus(map);
            return R.ok();
        }
        return R.ok().code(25000).message("支付中");
    }

}

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

 /**
     * 1.查询订单支付状态
     * @param orderNo
     * @return
     */
    @Override
    public Map<String, String> queryPayStatus(String orderNo) {
      //1.封装参数
        try {
            HashMap map = new HashMap();
            map.put("appid", "wx74862e0dfcf69954");
            map.put("mch_id", "1558950191");
            map.put("out_trade_no", orderNo);
            map.put("nonce_str", WXPayUtil.generateNonceStr());

            //2.设置请求,利用xml进行请求
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setXmlParam(WXPayUtil.generateSignedXml(map,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            client.setHttps(true);
            client.post();

            //3.返回第三方的数据
            String xml = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);//将xml转为map数据

            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

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

 /**
     * 2.添加支付记录和更新订单状态
     * @param map
     */
    @Override
    public void updateOrdersStatus(Map<String, String> map) {
        //1.从map中获取订单号
        String orderNo = map.get("out_trade_no");
        //2.根据订单号查询订单信息
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no",orderNo);
        Order order = orderService.getOne(wrapper);

        //3.更新订单表的订单状态
        if(order.getStatus().intValue()==1){
            return;//说明支付过了
        }
        order.setStatus(1);
        orderService.updateById(order);

        //4.向支付表中添加支付记录
        PayLog payLog = new PayLog();
        payLog.setOrderNo(orderNo);
        payLog.setPayTime(new Date());
        payLog.setPayType(1);//支付类型 1wx
        payLog.setTotalFee(order.getTotalFee());//总金额(分)
        payLog.setTradeState(map.get("trade_state"));//支付状态
        payLog.setTransactionId(map.get("transaction_id"));//账单流水号
        payLog.setAttr(JSONObject.toJSONString(map));

        baseMapper.insert(payLog);//插入到支付日志表
    }

前端实现

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

1.点击支付

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

2.订单详情页

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

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

import ordersApi from "@/api/order";

export default {
  //1.return除了要return方法还要return成功数据
  asyncData({ params, error }) {
    // 2.名字是pid,那么动态路由的参数就是pid
    return ordersApi.createNative(params.pid).then((response) => {
      return {
        payObj: response.data.data,
      };
    });
  },

  data() {
    return {
      tiemer1: "",
    };
  },

  //2.定义mouted,意思是页面渲染之后执行,防止没有数据
  mounted() {
    //1.每隔3s调一次查询订单状态方法
    this.tiemer1 = setInterval(() => {
      this.queryOrderStatus(this.payObj.out_trade_no);
    }, 3000);
  },

  methods: {
    //3.查询支付状态
    queryOrderStatus(orderNo) {
      ordersApi.queryPayStatus(orderNo).then((response) => {
        console.log("正在查询订单信息.....");
        console.log(response.data);

    if(response.data.success){
        console.log("支付成功,清除定时器")
        //1.支付成功清除定时器
        clearInterval(this.tiemer1);
        //2.支付成功提示
        this.$message({
          type: "success",
          message: "支付成功!",
        });
        //3.跳转到课程详情页面观看视频
        this.$router.push({ path: "/course/" + this.payObj.course_id });
      }
     });
    },
  },
};
</script>

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fairy要carry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值