网页授权登陆
申请公众号(测试号也行)
需要可以外网访问的域名,没有的话可以搞个内网穿透
开发
使用第三方的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("【微信模版消息】发送失败");
}
}
}