微信发起h5支付(公众号支付)步骤
1.查看微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
2. 使用sdk获取预订单信息,通过预订单信息发起支付
a.引用sdk依赖,该支付sdk文档:https://github.com/Pay-Group/best-pay-sdk
<dependency> <groupId>cn.springboot</groupId> <artifactId>best-pay-sdk</artifactId> <version>1.1.0</version> </dependency>
b. 给sdk的bestPayService添加配置:
@Component public class WechatPayConfig { @Autowired private WechatAccountConfig wechatAccountConfig; @Bean public BestPayServiceImpl bestPayService(){ BestPayServiceImpl bestPayService=new BestPayServiceImpl(); bestPayService.setWxPayH5Config(wxPayH5Config()); return bestPayService; } private WxPayH5Config wxPayH5Config(){ WxPayH5Config wxPayH5Config = new WxPayH5Config(); //wechatAccountConfig是通过 // @ConfigurationProperties(prefix = "wechat")读取yml文件的配置文件对象 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; } }
c.编写本地的payservice
@Service public class PayServiceImpl implements PayService { private static final String ORDER_NAME = "微信点餐订单"; @Autowired BestPayServiceImpl bestPayService; @Override public PayResponse create(OrderDTO orderDTO) { PayRequest request=new PayRequest(); //通过查询出的order信息,设置支付的必填项 request.setOpenid("oTgZpwU8hDPxbUjXmwLXp6TiBqK4"); request.setOrderAmount(orderDTO.getOrderAmount().doubleValue()); request.setOrderId(orderDTO.getOrderId()); request.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5); request.setOrderName(ORDER_NAME); PayResponse payResponse = bestPayService.pay(request); return payResponse; } }
d.编写controller获取payResponse,里面包含信息如下
@Controller @Slf4j @RequestMapping("/pay") public class PayController { @Autowired OrderService orderService; @Autowired PayService payService; @GetMapping("/create") public ModelAndView create(@RequestParam("orderId") String orderId, @RequestParam("returnUrl") String returnUrl) { //1. 查询订单 OrderDTO orderDTO = orderService.findOne(orderId); if (orderDTO == null) { throw new SellException(ResultEnum.ORDER_NOT_EXIST); } //发起支付 PayResponse payResponse = payService.create(orderDTO); //通过查询的订单创建支付 log.info("payResponse={}", JsonUtil.toJson(payResponse)); Map<String,Object> result=new HashMap<>(); result.put("payResponse",payResponse); result.put("returnUrl",returnUrl); return new ModelAndView("pay/create",result); //将数据传输至freemark文件(前端) } }
e.通过payResponse获取的信息传输给前端,在前端发起支付(只有在微信才可支付)
<script> function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId":"${payResponse.appId}", //公众号名称,由商户传入 "timeStamp":"${payResponse.timeStamp}", //时间戳,自1970年以来的秒数 "nonceStr":"${payResponse.nonceStr}", //随机串 "package":"${payResponse.packAge}", "signType":"${payResponse.signType}", //微信签名方式: "paySign":"${payResponse.paySign}" //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ){ // 使用以上方式判断前端返回,微信团队郑重提示: //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 } }); } 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>
f.支付成功,微信异步通知:
配置接收异步信息的service:
public void notify(String notifyData){ //验证签名 sdk已验证 //支付的状态 sdk已验证 //支付金额 PayResponse payResponse = bestPayService.asyncNotify(notifyData); //解析微信返回的xml文件 OrderDTO orderDTO = orderService.findOne(payResponse.getOrderId()); if(orderDTO==null){ log.error("异步通知,订单不存在 orderId={}",payResponse.getOrderId()); throw new SellException(ResultEnum.ORDER_NOT_EXIST); } if(!MathUtil.equals(payResponse.getOrderAmount(),orderDTO.getOrderAmount().doubleValue())){ log.error("异步通知,金额不相等 payResponse={}", JsonUtil.toJson(payResponse)); throw new SellException(ResultEnum.WXPAY_NOTIFY_MONEY_VERIFY_ERROR); } orderService.paid(orderDTO); }
配置相应的controller层
@PostMapping("/notify") public ModelAndView notify(@RequestBody String notifyData){//获取微信服务器传来的xml文件 payService.notify(notifyData); return new ModelAndView("pay/success"); //给微信服务器返回成功的接收的信息,不再发送通知信息 }
g.退款操作
配置相应的service层,需退款调用即可:
@Override public RefundResponse refund(OrderDTO orderDTO) { RefundRequest refundRequest = new RefundRequest(); refundRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue()); refundRequest.setOrderId(orderDTO.getOrderId()); refundRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5); log.info("【微信退款】request={}",JsonUtil.toJson(refundRequest)); RefundResponse refund = bestPayService.refund(refundRequest); log.info("【微信退款】response={}",JsonUtil.toJson(refund)); //收到outRefundNo表示退款成功 return refund; }