0


项目中如何整合微信支付

📒博客首页:崇尚学技术的科班人
小肖来了🏇
**🍣今天给大家带来的文章是

《项目中如何整合微信支付》

🍣**
🍣希望各位小伙伴们能够耐心的读完这篇文章🍣
🙏博主也在学习阶段,如若发现问题,请告知,非常感谢🙏
💗同时也非常感谢各位小伙伴们的支持💗

文章目录

1、前言

  • 在上一篇的 **《如何获取微信用户的openId》**,在前面的文章中我也说过,微信用户的openId是微信开发的前提。因为往往要涉及到微信的一系列的服务,我们都需要进行微信的网页授权。那么openId就是一个关键了。而在这一篇文章中,我将跟大家介绍如何在自己的项目中整合微信支付。微信支付的话,涉及到money的话,那么就会需要大量的微信官方的限制 (比如:如果需要测试的话,那么就需要微信商户号;如果需要进行退款的话,那么就需要商户号的证书)
  • 当然了,整合微信支付的方式有很多种。在这一篇文章中,我就介绍我最近学习到的一种。

2、整合过程

2.1、整合过程用到的依赖

<!--    整合微信支付    --><dependency><groupId>cn.springboot</groupId><artifactId>best-pay-sdk</artifactId><version>1.1.0</version></dependency><!--整合freemarker--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>

2.2、微信账号配置信息

  • 配置类
importlombok.Data;importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.stereotype.Component;/**
 * @author :小肖
 * @date :Created in 2022/2/2 10:31
 */@Component@Data@ConfigurationProperties(prefix ="wechat")publicclassWechatAccountConfig{/**
     * 公众号id
     */privateString mpAppId;/**
     * 公众号密钥
     */privateString mpAppSecret;/**
     * 商户号
     */privateString mchId;/**
     * 商户密钥
     */privateString mchKey;/**
     * 商户证书路径
     */privateString keyPath;/**
     * 异步通知url
     */privateString notifyUrl;}
  • 配置信息
wechat:# 测试号的appidmpAppId: 你自己的测试号的appid
  mpAppSecret: 你自己的测试号的appSecret
  # 商户号的idmchId:1483469312# 商户号的密钥mchKey: c976503d34ca432c601361f969fd8d85
  # 商户号的证书所在路径  一般微信退款需要使用到证书keyPath: /var/weixin_cert/h5.p12
  # 异步通知的url 一般用于处理订单的支付状态notifyUrl: http://xiao-sell.natapp1.cc/sell/pay/notify
  • 其实微信支付大多的都是权限问题,所以账号的配置尤其重要。由上述代码也可以知道,项目运行时,配置类从配置文件中读取相关信息。

2.3、微信支付的WechatPayConfig配置类

importcom.lly835.bestpay.config.WxPayH5Config;importcom.lly835.bestpay.service.impl.BestPayServiceImpl;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;importorg.springframework.stereotype.Component;/**
 * @author :小肖
 * @date :Created in 2022/2/2 20:12
 */@ComponentpublicclassWechatPayConfig{@AutowiredprivateWechatAccountConfig wechatAccountConfig;@AutowiredprivateWxPayH5Config wxPayH5Config;@BeanpublicBestPayServiceImplbestPayService(){BestPayServiceImpl bestPayService =newBestPayServiceImpl();
        bestPayService.setWxPayH5Config(wxPayH5Config);return bestPayService;}@BeanpublicWxPayH5ConfigwxPayH5Config(){WxPayH5Config wxPayH5Config =newWxPayH5Config();
        wxPayH5Config.setAppId(wechatAccountConfig.getMpAppId());
        wxPayH5Config.setAppSecret(wechatAccountConfig.getMpAppSecret());
        wxPayH5Config.setMchId(wechatAccountConfig.getMchId());
        wxPayH5Config.setMchKey(wechatAccountConfig.getMchKey());
        wxPayH5Config.setKeyPath(wechatAccountConfig.getKeyPath());
        wxPayH5Config.setNotifyUrl(wechatAccountConfig.getNotifyUrl());return wxPayH5Config;}}

2.4、微信支付创建预付订单

  • PayService接口
PayResponsecreate(OrderDTO orderDTO);
  • PayService接口实现类
publicstaticfinalString ORDER_NAME ="微信点餐";/**
     * 1. 创建预付订单
     * @param orderDTO
     */@OverridepublicPayResponsecreate(OrderDTO orderDTO){PayRequest request =newPayRequest();

        request.setOpenid(orderDTO.getBuyerOpenid());
        request.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
        request.setOrderId(orderDTO.getOrderId());
        request.setOrderName(ORDER_NAME);
        request.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);
        log.info("【微信支付】 request={}",JsonUtil.toJson(request));// TODO  这里的微信支付由于没有微信商户号,所以测试不通过PayResponse response = bestPayService.pay(request);
        log.info("【微信支付】 response={}",JsonUtil.toJson(response));return response;}

2.5、跳转逻辑

@AutowiredprivateOrderService orderService;@AutowiredprivatePayService payService;// 前端的绿色的支付按钮 配置了该url进行绑定@GetMapping("/create")publicModelAndViewcreate(@RequestParam("orderId")String orderId,@RequestParam("returnUrl")String returnUrl,Map<String,Object> map){// 1. 查询订单OrderDTO orderDTO = orderService.findOne(orderId);if(orderDTO ==null){thrownewSellException(ResultEnum.ORDER_NOT_EXIST);}// 2. 发起支付/**
         * 1. 调用生成预付订单的业务
         * 但是由于微信支付服务号的缘故,所以会报出签名错误的错误
         */PayResponse payResponse = payService.create(orderDTO);/**
         * 2. 注入支付页面的相关参数以及实现跳转
         */
        map.put("payResponse",payResponse);
        map.put("returnUrl",returnUrl);returnnewModelAndView("pay/create",map);}
  • 前面我们已经生成了对应的预付订单,那么我们需要跳转至对应的支付页面。而这个方法就是实现的跳转逻辑,携带了一定的参数。

2.6、支付页面

<script>// 微信支付开发的第二步,我们平时跳转微信支付的页面,由于没有微信支付的确切的账号,所以无法完成测试functiononBridgeReady(){
        WeixinJSBridge.invoke('getBrandWCPayRequest',{// 如果这里的package写错了就会显示 缺少total_fee参数"appId":"${payResponse.appId}",//公众号名称,由商户传入"timeStamp":"${payResponse.timeStamp}",//时间戳,自1970年以来的秒数"nonceStr":"${payResponse.nonceStr}",//随机串"package":"${payResponse.packAge}","signType":"MD5",//微信签名方式:"paySign":"${payResponse.paySign}"//微信签名},function(res){//      if(res.err_msg == "get_brand_wcpay_request:ok" ) {}     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。// 3. 支付之后设置跳转的Url
                location.href ="${returnUrl}";});}if(typeof WeixinJSBridge =="undefined"){if( document.addEventListener ){
            document.addEventListener('WeixinJSBridgeReady', onBridgeReady,false);}elseif(document.attachEvent){
            document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
            document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);}}else{onBridgeReady();}</script>
  • 在支付页面中,设置了如果支付完成的话,那么就会实现相关的跳转。会跳转至相关的详情页面。
  • 还有就是需要对http://xiao-sell.natapp1.cc/sell/pay/url进行注册。

2.7、异步通知

  • 虽然我们都实现了支付的大部分内容,但是还有就是我们需要进行支付的异步通知,该异步通知是作用于商家的。在这个异步通知中,我们可以修改订单的支付状态等。
  • PayService接口
PayResponsenotify(String notifyData);
  • PayService接口实现类
@OverridepublicPayResponsenotify(String notifyData){// 1. 验证签名// 2. 支付的状态// 3. 支付金额// 4. 支付人(下单人 == 支付人)PayResponse payResponse = bestPayService.asyncNotify(notifyData);
        log.info("【微信支付】 异步通知 payResponse = {}",JsonUtil.toJson(payResponse));// 判断订单是否存在OrderDTO orderDTO = orderService.findOne(payResponse.getOrderId());if(orderDTO ==null){
            log.error("【微信支付】 异步通知 订单不存在 orderId={}",payResponse.getOrderId());thrownewSellException(ResultEnum.ORDER_NOT_EXIST);}// 判断订单金额是否一致// 这里判断金额的时候存在精度问题,所以我们需要进行改进if(!MathUtil.equals(orderDTO.getOrderAmount().doubleValue(),payResponse.getOrderAmount())){
            log.error("【微信支付】 异步通知 订单金额不一致 orderId = {}, 微信金额={}, 系统金额 = {}",
                    payResponse.getOrderId(),
                    orderDTO.getOrderAmount(),
                    payResponse.getOrderAmount());thrownewSellException(ResultEnum.WXPAY_NOTIFY_MONEY_VERIFY_ERROR);}// 修改订单状态
        orderService.paid(orderDTO);return payResponse;}

2.8、退款逻辑实现

微信退款需要使用到相关的证书,我们需要将证书放置在我们项目能够扫描到的且在

yaml

文件中配置了的路径上。

  • 取消订单业务逻辑
@Override@TransactionalpublicOrderDTOcancel(OrderDTO orderDTO){OrderMaster orderMaster =newOrderMaster();// 判断订单状态if(!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){
            log.error("【取消订单】: orderId = {}, orderStatus = {}",orderDTO.getOrderId(),orderDTO.getOrderStatus());thrownewSellException(ResultEnum.ORDER_STATUS_ERROR);}// 修改订单状态
        orderDTO.setOrderStatus(OrderStatusEnum.CANCEL.getCode());BeanUtils.copyProperties(orderDTO,orderMaster);OrderMaster updateResult = orderMasterDao.save(orderMaster);if(updateResult ==null){
            log.error("【取消订单】: 更新失败 orderMaster = {}",orderMaster);thrownewSellException(ResultEnum.ORDER_UPDATE_FAIL);}// 加库存if(CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){
            log.error("【取消订单】: 订单详情为空 orderDTO = {}",orderDTO);thrownewSellException(ResultEnum.ORDER_DETAIL_EMPTY);}List<CartDTO> cartDTOList = orderDTO.getOrderDetailList().stream().map(e ->newCartDTO(e.getProductId(),e.getProductQuantity())).collect(Collectors.toList());
        productService.increaseStock(cartDTOList);// 如果已支付,需要进行退款if(orderDTO.getPayStatus().equals(PayStatusEnum.FINISHED.getCode())){
            payService.refund(orderDTO);}return orderDTO;}
  • PayService接口
RefundResponserefund(OrderDTO orderDTO);
  • PayService接口实现类
// 该退款接口用于了 取消订单的业务中@OverridepublicRefundResponserefund(OrderDTO orderDTO){// 退款接口需要读取微信商户的证书RefundRequest refundRequest =newRefundRequest();
        refundRequest.setOrderId(orderDTO.getOrderId());
        refundRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
        refundRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);

        log.info("【微信退款】 refundRequest={}",JsonUtil.toJson(refundRequest));RefundResponse refundResponse = bestPayService.refund(refundRequest);
        log.info("【微信退款】 refundResponse={}",JsonUtil.toJson(refundResponse));return refundResponse;}

本文转载自: https://blog.csdn.net/weixin_56727438/article/details/122786920
版权归原作者 崇尚学技术的科班人 所有, 如有侵权,请联系我们删除。

“项目中如何整合微信支付”的评论:

还没有评论