摘要:網(wǎng)頁授權(quán)登陸申請(qǐng)公眾號(hào)測(cè)試號(hào)也行申請(qǐng)測(cè)試號(hào)鏈接申請(qǐng)后得到和配置需要可以外網(wǎng)訪問的域名,沒有的話可以搞個(gè)內(nèi)網(wǎng)穿透開發(fā)使用第三方的進(jìn)行開發(fā),避免重復(fù)造輪子,微信的開發(fā)文檔如下第三方流程構(gòu)造鏈接,獲取到,拿到配置接口調(diào)用跳轉(zhuǎn)到授權(quán)鏈接跳轉(zhuǎn)鏈接配置
網(wǎng)頁授權(quán)登陸 申請(qǐng)公眾號(hào)(測(cè)試號(hào)也行)
申請(qǐng)測(cè)試號(hào)鏈接
申請(qǐng)后得到appID和appsecret
配置:
需要可以外網(wǎng)訪問的域名,沒有的話可以搞個(gè)內(nèi)網(wǎng)穿透
開發(fā)使用第三方的SDK進(jìn)行開發(fā),避免重復(fù)造輪子,微信的開發(fā)文檔如下:
第三方SDK
流程:構(gòu)造鏈接,獲取到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; } }
接口調(diào)用
//跳轉(zhuǎn)到授權(quán)鏈接 @GetMapping("/authorize") public String authorize( @ApiParam(name = "returnUrl", value = "跳轉(zhuǎn)鏈接")@RequestParam("returnUrl") String returnUrl) { //1. 配置 //2. 調(diào)用方法 String url = projectUrlConfig.getWechatMpAuthorize() + "/wechat/userInfo"; String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_BASE, URLEncoder.encode(returnUrl)); return "redirect:" + redirectUrl; } //確定授權(quán)后的處理方法 @GetMapping("/userInfo") public String userInfo(@ApiParam(name = "code", value = "code")@RequestParam("returnUrl") String code, @ApiParam(name = "returnUrl", value = "跳轉(zhuǎn)鏈接")@RequestParam("returnUrl") String returnUrl ){ WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken(); try { wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code); } catch (WxErrorException e) { log.error("[微信頁面授權(quán)失敗]{}",e); throw new SellException(ResultEnum.WECHAT_MP_ERROR.getCode(),e.getError().getErrorMsg()); } String openId = wxMpOAuth2AccessToken.getOpenId(); return "redirect:" + returnUrl + "openId = " + openId; }第三方網(wǎng)頁掃碼登陸 開發(fā)前準(zhǔn)備
微信開放平臺(tái),需要自己去申請(qǐng)一個(gè)應(yīng)用,審核通過后得到
開發(fā)生成二維碼,拿到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. 接口調(diào)用
//跳轉(zhuǎn)二維碼頁面,生成二維碼 @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("【微信網(wǎng)頁授權(quán)】{}", 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,這個(gè)SDK是上方的SDK對(duì)支付的進(jìn)一步封裝
微信支付官方開發(fā)文檔
需要申請(qǐng)一個(gè)具有商家資質(zhì)的賬號(hào),等到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 = "微信點(diǎn)餐訂單"; @Autowired private BestPayServiceImpl bestPayService; @Autowired private OrderService orderService; //發(fā)起支付 @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("【微信支付】發(fā)起支付, request={}", JsonUtil.toJson(payRequest)); PayResponse payResponse = bestPayService.pay(payRequest); log.info("【微信支付】發(fā)起支付, response={}", JsonUtil.toJson(payResponse)); return payResponse; } //支付后微信異步通知,告之微信支付結(jié)果 @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={}, 微信通知金額={}, 系統(tǒng)金額={}", payResponse.getOrderId(), payResponse.getOrderAmount(), orderDTO.getOrderAmount()); throw new SellException(ResultEnum.WXPAY_NOTIFY_MONEY_VERIFY_ERROR); } //修改訂單的支付狀態(tài) 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; } }微信模版消息通知
在公眾號(hào)管理設(shè)置好消息模版
編寫service
@Override public void orderStatus(OrderDTO orderDTO) { WxMpTemplateMessage templateMessage = new WxMpTemplateMessage(); templateMessage.setTemplateId(wechatAccountConfig.getTemplateId().get("orderStatus")); templateMessage.setToUser(orderDTO.getBuyerOpenid()); Listdata = Arrays.asList( new WxMpTemplateData("first","111"), new WxMpTemplateData("keyword1", "微信點(diǎn)餐"), 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("【微信模版消息】發(fā)送失敗"); } } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76064.html
摘要:官網(wǎng)源碼推薦從開始手寫一個(gè)框架更多請(qǐng)?jiān)诩夹g(shù)棧微信公眾號(hào)后臺(tái)回復(fù)關(guān)鍵字。是一個(gè)開放源代碼的對(duì)象關(guān)系映射框架,它對(duì)進(jìn)行了非常輕量級(jí)的對(duì)象封裝,它將與數(shù)據(jù)庫表建立映射關(guān)系,是一個(gè)全自動(dòng)的框架。 Java 程序員方向太多,且不說移動(dòng)開發(fā)、大數(shù)據(jù)、區(qū)塊鏈、人工智能這些,大部分 Java 程序員都是 Java Web/后端開發(fā)。那作為一名 Java Web 開發(fā)程序員必須需要熟悉哪些框架呢? 今天...
摘要:設(shè)計(jì)模式可以通過提供經(jīng)過驗(yàn)證的經(jīng)過驗(yàn)證的開發(fā)范例來加速開發(fā)過程。將流程作為突破點(diǎn),并在多個(gè)領(lǐng)域工作,包括流量控制,并發(fā),斷路和負(fù)載保護(hù),以保護(hù)服務(wù)穩(wěn)定性。 1. JCSprout(Java核心知識(shí)庫) Github地址: https://github.com/crossoverJie/JCSprout star: 12k 介紹: 處于萌芽階段的 Java 核心知識(shí)庫。 2....
摘要:因?yàn)槟承┰颍环奖阍谶@里直接發(fā)送百度鏈接,關(guān)注我的微信公眾號(hào)面試通關(guān)手冊(cè)回復(fù)資源分享第一波即可領(lǐng)取。然后大家還有什么問題的話,可以在我的微信公眾號(hào)后臺(tái)面試通關(guān)手冊(cè)給我說或者加我微信,我會(huì)根據(jù)自己的學(xué)習(xí)經(jīng)驗(yàn)給了說一下自己的看法。 這是一篇針對(duì)Java初學(xué)者,或者說在Java學(xué)習(xí)路線上出了一些問題(不知道該學(xué)什么、不知道整體的學(xué)習(xí)路線是什么樣的) 第一步:Java基礎(chǔ)(一個(gè)月左右) 推薦...
摘要:使用會(huì)涉及到各種各樣的配置,如開發(fā)測(cè)試線上就至少套配置信息了。本章內(nèi)容基于進(jìn)行詳解。添加測(cè)試類運(yùn)行單元測(cè)試,程序輸出根據(jù)以上參數(shù)動(dòng)態(tài)調(diào)整,發(fā)現(xiàn)參數(shù)會(huì)被正確被覆蓋。了解了各種配置的加載順序,如果配置被覆蓋了我們就知道是什么問題了。 使用 Spring Boot 會(huì)涉及到各種各樣的配置,如開發(fā)、測(cè)試、線上就至少 3 套配置信息了。Spring Boot 可以輕松的幫助我們使用相同的代碼就能...
摘要:棧長(zhǎng)有話說其實(shí)項(xiàng)目就是為了阿里的項(xiàng)目能很好的結(jié)合融入使用,這個(gè)項(xiàng)目目前由阿里維護(hù)。對(duì)同時(shí)使用和阿里巴巴項(xiàng)目的人來說無疑帶來了巨大的便利,一方面能結(jié)合無縫接入,另一方面還能使用阿里巴巴的組件,也帶來了更多的可選擇性。 最近,Spring Cloud 發(fā)布了 Spring Cloud Alibaba 首個(gè)預(yù)覽版本:Spring Cloud for Alibaba 0.2.0. 大家都好奇,...
閱讀 3573·2021-11-15 11:36
閱讀 1067·2021-11-11 16:55
閱讀 701·2021-10-20 13:47
閱讀 2998·2021-09-29 09:35
閱讀 3449·2021-09-08 10:45
閱讀 2556·2019-08-30 15:44
閱讀 853·2019-08-30 11:10
閱讀 1435·2019-08-29 13:43