微信发起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;
    }

 

posted @ 2020-06-23 12:04  shouyaya  阅读(1837)  评论(0编辑  收藏  举报