spring——微信开发

Java框架

浏览数:62

2019-8-16

网页授权登陆

申请公众号(测试号也行)

申请测试号链接


申请后得到appID和appsecret
配置:

需要可以外网访问的域名,没有的话可以搞个内网穿透

开发

使用第三方的SDK进行开发,避免重复造轮子,微信的开发文档如下:


第三方SDK
流程:构造链接,获取到AccessToken,拿到openId

  1. 配置WxMpServiceImpl

    @Component
    public class WechatMpConfig {
        @Autowired
        private WechatAccountConfig wechatAccountConfig;
    
        @Bean
        public WxMpService wxMpService() {
            WxMpService wxMpService = new WxMpServiceImpl();
            wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
            return wxMpService;
        }
    
        @Bean
        public WxMpConfigStorage wxMpConfigStorage() {
            WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
            wxMpConfigStorage.setAppId(wechatAccountConfig.getMpAppId());
            wxMpConfigStorage.setSecret(wechatAccountConfig.getMpAppSecret());
            return wxMpConfigStorage;
        }
    }
  2. 接口调用

        //跳转到授权链接
         @GetMapping("/authorize")
            public String authorize( @ApiParam(name = "returnUrl", value = "跳转链接")@RequestParam("returnUrl") String returnUrl) {
                //1. 配置
                //2. 调用方法
                String url = projectUrlConfig.getWechatMpAuthorize() + "/wechat/userInfo";
                String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_BASE, URLEncoder.encode(returnUrl));
                return "redirect:" + redirectUrl;
        }
        //确定授权后的处理方法
        @GetMapping("/userInfo")
        public String userInfo(@ApiParam(name = "code", value = "code")@RequestParam("returnUrl") String code,
                               @ApiParam(name = "returnUrl", value = "跳转链接")@RequestParam("returnUrl") String returnUrl ){
            WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
            try {
                wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
            } catch (WxErrorException e) {
                log.error("[微信页面授权失败]{}",e);
                throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(),e.getError().getErrorMsg());
            }
            String openId = wxMpOAuth2AccessToken.getOpenId();
    
            return "redirect:" + returnUrl + "openId = " + openId;
        }

第三方网页扫码登陆

开发前准备

微信开放平台,需要自己去申请一个应用,审核通过后得到

开发

生成二维码,拿到openId
第三方SDK

  1. 配置WxMpServiceImpl

    @Component
    public class WechatOpenConfig {
        @Autowired
        private WechatAccountConfig accountConfig;
    
        @Bean
        public WxMpService wxOpenService() {
            WxMpService wxOpenService = new WxMpServiceImpl();
            wxOpenService.setWxMpConfigStorage(wxOpenConfigStorage());
            return wxOpenService;
        }
    
        @Bean
        public WxMpConfigStorage wxOpenConfigStorage() {
            WxMpInMemoryConfigStorage wxMpInMemoryConfigStorage = new WxMpInMemoryConfigStorage();
            wxMpInMemoryConfigStorage.setAppId(accountConfig.getOpenAppId());
            wxMpInMemoryConfigStorage.setSecret(accountConfig.getOpenAppSecret());
            return wxMpInMemoryConfigStorage;
        }
2. 接口调用
    //跳转二维码页面,生成二维码
    @GetMapping("/qrAuthorize")
    public String qrAuthorize(@RequestParam("returnUrl") String returnUrl) {
        String url = projectUrlConfig.getWechatOpenAuthorize() + "/sell/wechat/qrUserInfo";
        String redirectUrl = wxOpenService.buildQrConnectUrl(url, WxConsts.QrConnectScope.SNSAPI_LOGIN, URLEncoder.encode(returnUrl));
        return "redirect:" + redirectUrl;
    }

    //扫码后逻辑登陆
    @GetMapping("/qrUserInfo")
    public String qrUserInfo(@RequestParam("code") String code,
                             @RequestParam("state") String returnUrl) {
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken();
        try {
            wxMpOAuth2AccessToken = wxOpenService.oauth2getAccessToken(code);
        } catch (WxErrorException e) {
            log.error("【微信网页授权】{}", e);
            throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(), e.getError().getErrorMsg());
        }
        log.info("wxMpOAuth2AccessToken={}", wxMpOAuth2AccessToken);
        String openId = wxMpOAuth2AccessToken.getOpenId();

        return "redirect:" + returnUrl + "?openid=" + openId;
    }
```

微信支付

微信支付SDK,这个SDK是上方的SDK对支付的进一步封装
微信支付官方开发文档
需要申请一个具有商家资质的账号,等到mchId和mchKey

  1. 配置BestPayServiceImpl

    @Component
    public class WechatPayConfig {
    
        @Autowired
        private WechatAccountConfig wechatAccountConfig;
    
        @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. 编写Service

    @Service
    @Slf4j
    public class PayServiceImpl implements PayService {
    
        private static final String ORDER_NAME = "微信点餐订单";
    
        @Autowired
        private BestPayServiceImpl bestPayService;
    
        @Autowired
        private OrderService orderService;
    
        //发起支付
        @Override
        public PayResponse create(OrderDTO orderDTO) {
            PayRequest payRequest = new PayRequest();
            payRequest.setOpenid(orderDTO.getBuyerOpenid());
            payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
            payRequest.setOrderId(orderDTO.getOrderId());
            payRequest.setOrderName(ORDER_NAME);
            payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);
            log.info("【微信支付】发起支付, request={}", JsonUtil.toJson(payRequest));
    
            PayResponse payResponse = bestPayService.pay(payRequest);
            log.info("【微信支付】发起支付, response={}", JsonUtil.toJson(payResponse));
            return payResponse;
        }
    
        //支付后微信异步通知,告之微信支付结果
        @Override
        public PayResponse notify(String notifyData) {
            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);
            }
    
            //判断金额是否一致(0.10   0.1)
            if (!MathUtil.equals(payResponse.getOrderAmount(), orderDTO.getOrderAmount().doubleValue())) {
                log.error("【微信支付】异步通知, 订单金额不一致, orderId={}, 微信通知金额={}, 系统金额={}",
                        payResponse.getOrderId(),
                        payResponse.getOrderAmount(),
                        orderDTO.getOrderAmount());
                throw new SellException(ResultEnum.WXPAY_NOTIFY_MONEY_VERIFY_ERROR);
            }
    
            //修改订单的支付状态
            orderService.paid(orderDTO);
            return payResponse;
        }
    
        //退款
        @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("【微信退款】request={}", JsonUtil.toJson(refundRequest));
            RefundResponse refundResponse = bestPayService.refund(refundRequest);
            return refundResponse;
        }
    }

微信模版消息通知

在公众号管理设置好消息模版
编写service

   @Override
    public void orderStatus(OrderDTO orderDTO) {
        WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
        templateMessage.setTemplateId(wechatAccountConfig.getTemplateId().get("orderStatus"));
        templateMessage.setToUser(orderDTO.getBuyerOpenid());
        List<WxMpTemplateData> data = Arrays.asList(
                new WxMpTemplateData("first","111"),
                new WxMpTemplateData("keyword1", "微信点餐"),
                new WxMpTemplateData("keyword2", "18868812345"),
                new WxMpTemplateData("keyword3", orderDTO.getOrderId()),
                new WxMpTemplateData("keyword4", orderDTO.getOrderStatusEnum().getMessage()),
                new WxMpTemplateData("keyword5", "¥" + orderDTO.getOrderAmount()),
                new WxMpTemplateData("remark", "欢迎再次光临!")
        );
        try{
            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        }catch (WxErrorException e){
            log.error("【微信模版消息】发送失败");
        }
    }
}

作者:liudenny