资讯专栏INFORMATION COLUMN

spring——微信开发

苏丹 / 2012人阅读

摘要:网页授权登陆申请公众号测试号也行申请测试号链接申请后得到和配置需要可以外网访问的域名,没有的话可以搞个内网穿透开发使用第三方的进行开发,避免重复造轮子,微信的开发文档如下第三方流程构造链接,获取到,拿到配置接口调用跳转到授权链接跳转链接配置

网页授权登陆 申请公众号(测试号也行)

申请测试号链接


申请后得到appID和appsecret
配置:

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

开发

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


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

配置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;
    }
}

接口调用

    //跳转到授权链接
     @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

配置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

配置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;
    }
}

编写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 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("【微信模版消息】发送失败");
        }
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76064.html

相关文章

  • Java 程序员必备的 15 个框架,前 3 个地位无可动摇!

    摘要:官网源码推荐从开始手写一个框架更多请在技术栈微信公众号后台回复关键字。是一个开放源代码的对象关系映射框架,它对进行了非常轻量级的对象封装,它将与数据库表建立映射关系,是一个全自动的框架。 Java 程序员方向太多,且不说移动开发、大数据、区块链、人工智能这些,大部分 Java 程序员都是 Java Web/后端开发。那作为一名 Java Web 开发程序员必须需要熟悉哪些框架呢? 今天...

    galaxy_robot 评论0 收藏0
  • 推荐10个Java方向最热门的开源项目(8月)

    摘要:设计模式可以通过提供经过验证的经过验证的开发范例来加速开发过程。将流程作为突破点,并在多个领域工作,包括流量控制,并发,断路和负载保护,以保护服务稳定性。 1. JCSprout(Java核心知识库) Github地址: https://github.com/crossoverJie/JCSprout star: 12k 介绍: 处于萌芽阶段的 Java 核心知识库。 2....

    wushuiyong 评论0 收藏0
  • 一份最中肯的Java学习路线+资源分享(拒绝傻逼式分享)

    摘要:因为某些原因,不方便在这里直接发送百度链接,关注我的微信公众号面试通关手册回复资源分享第一波即可领取。然后大家还有什么问题的话,可以在我的微信公众号后台面试通关手册给我说或者加我微信,我会根据自己的学习经验给了说一下自己的看法。 这是一篇针对Java初学者,或者说在Java学习路线上出了一些问题(不知道该学什么、不知道整体的学习路线是什么样的) 第一步:Java基础(一个月左右) 推荐...

    hearaway 评论0 收藏0
  • Spring Boot 配置加载顺序详解

    摘要:使用会涉及到各种各样的配置,如开发测试线上就至少套配置信息了。本章内容基于进行详解。添加测试类运行单元测试,程序输出根据以上参数动态调整,发现参数会被正确被覆盖。了解了各种配置的加载顺序,如果配置被覆盖了我们就知道是什么问题了。 使用 Spring Boot 会涉及到各种各样的配置,如开发、测试、线上就至少 3 套配置信息了。Spring Boot 可以轻松的帮助我们使用相同的代码就能...

    BetaRabbit 评论0 收藏0
  • 厉害了,Spring Cloud for Alibaba 来了!

    摘要:栈长有话说其实项目就是为了阿里的项目能很好的结合融入使用,这个项目目前由阿里维护。对同时使用和阿里巴巴项目的人来说无疑带来了巨大的便利,一方面能结合无缝接入,另一方面还能使用阿里巴巴的组件,也带来了更多的可选择性。 最近,Spring Cloud 发布了 Spring Cloud Alibaba 首个预览版本:Spring Cloud for Alibaba 0.2.0. 大家都好奇,...

    lbool 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<