微信点餐之微信支付(7)
微信支付:(只有企业资质的才可以申请微信支付)
https://pay.weixin.qq.com/
微信支付流程文档:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_4
文档说明
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
依赖说明
在pom文件中要加入第三方sdk依赖
<!--微信支付依赖-->
<dependency>
<groupId>cn.springboot</groupId>
<artifactId>best-pay-sdk</artifactId>
<version>1.1.0</version>
</dependency>
功能实现
微信支付
1:在配置文件appliaction.yml中追加配置信息
wechat:
#商户id
mchId: 1xxxxxx469312
#商户秘钥
mchKey: C5245xxxxx64D494B0735025
#商户证书
keyPath: D:/python/h5.p12
#微信支付异步通知调用的方法
notifyUrl: http://applenst.natapp4.cc/sell/pay/notify
2:在WechatAccountConfig.java配置文件中追加属性配置
com\imooc\config\WechatAccountConfig.java
/*商户号*/
private String mchId;
/*商户秘钥*/
private String mchKey;
/*商户证书路径*/
private String keyPath;
/*微信支付异步通知地址*/
private String notifyUrl;
3:创建微信支付配置类
com\imooc\config\WechatPayConfig.java
package com.imooc.config;
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;
/**
* @author: menghaibin
* @create: 2020-02-23 13:56
* @description: 微信支付配置
**/
Component
public class WechatPayConfig {
@Autowired
private WechatAccountConfig accountConfig;
@Bean
public BestPayServiceImpl bestPayService(){
WxPayH5Config wxPayH5Config = new WxPayH5Config();
wxPayH5Config.setAppId(accountConfig.getMpAppId());
wxPayH5Config.setAppSecret(accountConfig.getMpAppSecret());
wxPayH5Config.setMchId(accountConfig.getMchId());
wxPayH5Config.setMchKey(accountConfig.getMchKey());
wxPayH5Config.setKeyPath(accountConfig.getKeyPath());
wxPayH5Config.setNotifyUrl(accountConfig.getNotifyUrl());
BestPayServiceImpl bestPayService = new BestPayServiceImpl();
bestPayService.setWxPayH5Config(wxPayH5Config);
return bestPayService;
}
}
4:创建微信支付service接口(包括支付和退款)
com\imooc\service\PayService.java
package com.imooc.service;
import com.imooc.dto.OrderDTO;
import com.lly835.bestpay.model.PayResponse;
import com.lly835.bestpay.model.RefundResponse;
public interface PayService {
/*微信支付*/
public PayResponse create(OrderDTO orderDTO);
/*支付成功后的回调方法*/
public PayResponse notify(String notifyData);
/*微信退款*/
public RefundResponse refund(OrderDTO orderDTO);
}
5:创建微信支付service接口实现类
com\imooc\service\imp\PayServiceImp.java
package com.imooc.service.imp;
import com.imooc.dto.OrderDTO;
import com.imooc.exception.SellException;
import com.imooc.service.OrderService;
import com.imooc.service.PayService;
import com.imooc.utils.JsonUtil;
import com.imooc.utils.MathUtil;
import com.imooc.vo.enums.ResultEnum;
import com.lly835.bestpay.enums.BestPayTypeEnum;
import com.lly835.bestpay.model.PayRequest;
import com.lly835.bestpay.model.PayResponse;
import com.lly835.bestpay.model.RefundRequest;
import com.lly835.bestpay.model.RefundResponse;
import com.lly835.bestpay.service.impl.BestPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author: menghaibin
* @create: 2020-02-23 13:15
* @description: 微信支付
**/
Service
@Slf4j
public class PayServiceImp implements PayService{
@Autowired
private BestPayServiceImpl bestPayService;
@Autowired
private OrderService orderService;
private static final String ORDER_NAME = "微信点餐订单";
/*微信支付*/
@Override
public PayResponse create(OrderDTO orderDTO) {
PayRequest payRequest = new PayRequest();
payRequest.setOpenid(orderDTO.getBuyerOpenid());
payRequest.setOrderId(orderDTO.getOrderId());
payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
payRequest.setOrderName(ORDER_NAME);
payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);//公众号支付
log.info("微信支付发起payRequest={}", JsonUtil.toJson(payRequest));
PayResponse payResponse = bestPayService.pay(payRequest);
log.info("微信支付发起payResponse={}",JsonUtil.toJson(payResponse));
return payResponse;
}
/*微信支付异步通知*/
@Override
public PayResponse notify(String notifyData) {
PayResponse payResponse = bestPayService.asyncNotify(notifyData);
log.info("微信支付异步通知notify={}",JsonUtil.toJson(payResponse));
//查询订单
OrderDTO orderDTO = orderService.findOne(payResponse.getOrderId());
if(orderDTO == null){
log.error("微信支付异步通知,订单不存在");
throw new SellException(ResultEnum.ORDER_NOT_EXIST);
}
//判断金额是否一致(由于字段类型不一致,判断精度即可)
if(!MathUtil.equals(payResponse.getOrderAmount(),orderDTO.getOrderAmount().doubleValue())){
log.error("微信支付异步通知,支付金额错误不一致,微信金额={},系统金额={}",payResponse.getOrderAmount(),orderDTO.getOrderAmount());
throw new SellException(ResultEnum.WXPAY_ERROR);
}
//修改订单状态
orderService.paid(orderDTO);
return payResponse;
}
}
6:创建微信支付的controller
com\imooc\controller\PayController.java
package com.imooc.controller;
import com.imooc.dto.OrderDTO;
import com.imooc.exception.SellException;
import com.imooc.service.OrderService;
import com.imooc.service.PayService;
import com.imooc.vo.enums.ResultEnum;
import com.lly835.bestpay.model.PayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
/**
* @author: menghaibin
* @create: 2020-02-23 13:08
* @description: 微信支付
**/
@Controller
@Slf4j
@RequestMapping("/pay")
public class PayController {
@Autowired
private OrderService orderService;
@Autowired
private PayService payService;
/*微信支付*/
@GetMapping("/create")
public ModelAndView create(@RequestParam("orderId") String orderId,
@RequestParam("returnUrl") String returnUrl,
Map<String,Object> map){
//查询订单
OrderDTO orderDTO = orderService.findOne(orderId);
if(orderDTO == null){
log.error("订单不存在");
throw new SellException(ResultEnum.ORDER_NOT_EXIST);
}
//发起支付
PayResponse payResponse = payService.create(orderDTO);
map.put("payResponse",payResponse);
map.put("returnUrl",returnUrl);
//支付成功后会跳转到pay/create页面
return new ModelAndView("pay/create",map);
}
/*支付成功后访问的方法*/
@PostMapping("/notify")
public ModelAndView wxnotify(@RequestBody String notifyData){
//修改订单
payService.notify(notifyData);
//把处理结果返回给微信【规则定义的】
return new ModelAndView("pay/success");
}
}
7:创建微信支付时弹出的支付界面【需要把界面所在的路径加入微信支付白名单中http://域名/pay】
此时要在pom文件中加入freemarker依赖
<!--freemarker依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
创建支付页面和成功页面
resources\templates\pay\create.ftl【/pay/create执行成功后访问】
<script>
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":"${payResponse.appId}", //公众号名称,由商户传入
"timeStamp":"${payResponse.timeStamp}", //时间戳
"nonceStr":"${payResponse.nonceStr}", //随机串
"package":"${payResponse.packAge}",
"signType":"MD5",//微信签名方式:
"paySign":"${payResponse.paySign}" //微信签名
},
function(res){
location.href="${returnUrl}" //支付成功后的回调方法
}
);
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}
</script>
resources\templates\pay\success.ftl【/pay/notify执行成功后访问】
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>
7:项目构建及联调
1>配置虚拟机支付访问路径:
/opt/code/sell_fe_buyer/config/index.js
进入/opt/code/sell_fe_buyer目录执行重新构建命令
npm run build
拷贝文件使其生效
cp -r dist/* /opt/data/wwwrot/sell/
这时候就可以在手机上访问sell.com 下订单了!
微信退款
需要证书认证,详见链接说明:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
在PayServiceImp类中实现refund方法:
/*微信退款*/
@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;
}
被OrderServiceImp中的cancel取消订单方法所调用(取消订单时要做退款)
//如果已支付 需要退款
if(orderDTO.getPayStatus().equals(PayStatusEnum.SUCCESS.getCode())){
//TODO
/*调用微信退款的方法*/
payService.refund(orderDTO);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用