文章目录博客首页:崇尚学技术的科班人
小肖来了
今天给大家带来的文章是《项目中如何整合微信支付》
希望各位小伙伴们能够耐心的读完这篇文章
博主也在学习阶段,如若发现问题,请告知,非常感谢
同时也非常感谢各位小伙伴们的支持
1、前言2、整合过程
2.1、整合过程用到的依赖2.2、微信账号配置信息2.3、微信支付的WechatPayConfig配置类2.4、微信支付创建预付订单2.5、跳转逻辑2.6、支付页面2.7、异步通知2.8、退款逻辑实现
1、前言在上一篇的 《如何获取微信用户的openId》,在前面的文章中我也说过,微信用户的openId是微信开发的前提。因为往往要涉及到微信的一系列的服务,我们都需要进行微信的网页授权。那么openId就是一个关键了。而在这一篇文章中,我将跟大家介绍如何在自己的项目中整合微信支付。微信支付的话,涉及到money的话,那么就会需要大量的微信官方的限制 (比如:如果需要测试的话,那么就需要微信商户号;如果需要进行退款的话,那么就需要商户号的证书)。当然了,整合微信支付的方式有很多种。在这一篇文章中,我就介绍我最近学习到的一种。 2、整合过程 2.1、整合过程用到的依赖
2.2、微信账号配置信息cn.springboot best-pay-sdk1.1.0 org.springframework.boot spring-boot-starter-freemarker
配置类
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @Data @ConfigurationProperties(prefix = "wechat") public class WechatAccountConfig { private String mpAppId; private String mpAppSecret; private String mchId; private String mchKey; private String keyPath; private String notifyUrl; }
配置信息
wechat: # 测试号的appid mpAppId: 你自己的测试号的appid mpAppSecret: 你自己的测试号的appSecret # 商户号的id mchId: 1483469312 # 商户号的密钥 mchKey: c976503d34ca432c601361f969fd8d85 # 商户号的证书所在路径 一般微信退款需要使用到证书 keyPath: /var/weixin_cert/h5.p12 # 异步通知的url 一般用于处理订单的支付状态 notifyUrl: http://xiao-sell.natapp1.cc/sell/pay/notify
其实微信支付大多的都是权限问题,所以账号的配置尤其重要。由上述代码也可以知道,项目运行时,配置类从配置文件中读取相关信息。 2.3、微信支付的WechatPayConfig配置类
import com.lly835.bestpay.config.WxPayH5Config; import com.lly835.bestpay.service.impl.BestPayServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; @Component public class WechatPayConfig { @Autowired private WechatAccountConfig wechatAccountConfig; @Autowired private WxPayH5Config wxPayH5Config; @Bean public BestPayServiceImpl bestPayService(){ BestPayServiceImpl bestPayService = new BestPayServiceImpl(); bestPayService.setWxPayH5Config(wxPayH5Config); return bestPayService; } @Bean public WxPayH5Config wxPayH5Config(){ WxPayH5Config wxPayH5Config = new WxPayH5Config(); 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接口
PayResponse create(OrderDTO orderDTO);
PayService接口实现类
public static final String ORDER_NAME = "微信点餐"; @Override public PayResponse create(OrderDTO orderDTO) { PayRequest request = new PayRequest(); 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、跳转逻辑
@Autowired private OrderService orderService; @Autowired private PayService payService; // 前端的绿色的支付按钮 配置了该url进行绑定 @GetMapping("/create") public ModelAndView create(@RequestParam("orderId") String orderId, @RequestParam("returnUrl") String returnUrl, Mapmap) { // 1. 查询订单 OrderDTO orderDTO = orderService.findOne(orderId); if(orderDTO == null){ throw new SellException(ResultEnum.ORDER_NOT_EXIST); } // 2. 发起支付 PayResponse payResponse = payService.create(orderDTO); map.put("payResponse",payResponse); map.put("returnUrl",returnUrl); return new ModelAndView("pay/create",map); }
前面我们已经生成了对应的预付订单,那么我们需要跳转至对应的支付页面。而这个方法就是实现的跳转逻辑,携带了一定的参数。 2.6、支付页面
在支付页面中,设置了如果支付完成的话,那么就会实现相关的跳转。会跳转至相关的详情页面。还有就是需要对http://xiao-sell.natapp1.cc/sell/pay/的url进行注册。 2.7、异步通知
虽然我们都实现了支付的大部分内容,但是还有就是我们需要进行支付的异步通知,该异步通知是作用于商家的。在这个异步通知中,我们可以修改订单的支付状态等。
PayService接口
PayResponse notify(String notifyData);
PayService接口实现类
@Override public PayResponse notify(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()); throw new SellException(ResultEnum.ORDER_NOT_EXIST); } // 判断订单金额是否一致 // 这里判断金额的时候存在精度问题,所以我们需要进行改进 if(!MathUtil.equals(orderDTO.getOrderAmount().doublevalue(),payResponse.getOrderAmount())){ log.error("【微信支付】 异步通知 订单金额不一致 orderId = {}, 微信金额={}, 系统金额 = {}", payResponse.getOrderId(), orderDTO.getOrderAmount(), payResponse.getOrderAmount()); throw new SellException(ResultEnum.WXPAY_NOTIFY_MONEY_VERIFY_ERROR); } // 修改订单状态 orderService.paid(orderDTO); return payResponse; }2.8、退款逻辑实现
微信退款需要使用到相关的证书,我们需要将证书放置在我们项目能够扫描到的且在yaml文件中配置了的路径上。
取消订单业务逻辑
@Override @Transactional public OrderDTO cancel(OrderDTO orderDTO) { OrderMaster orderMaster = new OrderMaster(); // 判断订单状态 if(!orderDTO.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())){ log.error("【取消订单】: orderId = {}, orderStatus = {}",orderDTO.getOrderId(),orderDTO.getOrderStatus()); throw new SellException(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); throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); } // 加库存 if(CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){ log.error("【取消订单】: 订单详情为空 orderDTO = {}",orderDTO); throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY); } ListcartDTOList = orderDTO.getOrderDetailList().stream() .map(e -> new CartDTO(e.getProductId(),e.getProductQuantity())).collect(Collectors.toList()); productService.increaseStock(cartDTOList); // 如果已支付,需要进行退款 if(orderDTO.getPayStatus().equals(PayStatusEnum.FINISHED.getCode())){ payService.refund(orderDTO); } return orderDTO; }
PayService接口
RefundResponse refund(OrderDTO orderDTO);
PayService接口实现类
// 该退款接口用于了 取消订单的业务中 @Override public RefundResponse refund(OrderDTO orderDTO) { // 退款接口需要读取微信商户的证书 RefundRequest refundRequest = new RefundRequest(); 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; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)