微信小程序授權微信開放平臺

開放平臺註冊

開發第三方平臺,首先需要到微信開放平臺申請註冊第三方平臺賬號

創建第三方平臺

在這裏插入圖片描述

第三方平臺信息配置

在這裏插入圖片描述

第三方授權流程

詳細流程說明可參照官網授權流程技術說明
在這裏插入圖片描述

授權流程代碼

獲取第三方平臺接口調用憑據“component_verify_ticket”

出於安全考慮,在第三方平臺創建審覈通過後,微信服務器 每隔10分鐘會向第三方的消息接收地址推送一次component_verify_ticket,用於獲取第三方平臺接口調用憑據。

package com.litte.controller.warrant;

import com.litte.entity.reception.TWarrantInfo;
import com.litte.service.warrantinfo.TWarrantInfoService;
import com.litte.service.warrantmerchant.TWarrantMerchantService;
import com.litte.util.DateUtil;
import com.litte.util.WinxinUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Date;

@Controller
@RequestMapping("/warrant")
public class WarrantController {
    private static final Logger LOGGER = LoggerFactory.getLogger(WarrantController.class);
    //公衆號第三方平臺的appid
    private static final String APPID = "wx9681884b28ed7927";
    //第三方平臺申請時填寫的接收消息的校驗token
    private static final String TOKEN = "xinxingshang";
    //    private static final String TOKEN = "xinxingshangstar";
    //第三方平臺申請時填寫的接收消息的加密symmetric_key
    private static final String ENCODINGAESKEY = "xinxingshangstarkeykey11keyxinxingshangstar";
    private static final String SECRET = "a4d75ccc5b9ca0cef697116bc8c2e156";
    //獲取"component_access_token"URL
    private static final String COMPONENT_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
    // 獲取"pre_auth_code"URL
    private static final String PRE_AUTH_CODE = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=componentAccessToken";
    // 刷新令牌
    private static final String AUTHORIZER_REFRESH_TOKEN = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=componentAccessToken";

    @Autowired
    TWarrantInfoService tWarrantInfoService;
    @Autowired
    TWarrantMerchantService TWarrantMerchantService;

    /**
     * 獲取"component_verify_ticket"
     *
     * @Description:
     * @Author: Mr.Jkx
     * @Date: 2019/4/3 16:03
     * 參考鏈接:https://blog.csdn.net/liaoyundababe/article/details/53537417
     * https://blog.csdn.net/zhangdaiscott/article/details/48269837
     */
    @RequestMapping("/responseRequest")
    @ResponseBody
    public void responseRequest(HttpServletRequest request, HttpServletResponse response) throws AesException, IOException {
        LOGGER.info("WeChat third-party platform --------- WeChat push Ticket message 10 minutes-----------");
        output(response, "success"); // 輸出響應的內容。
        processAuthorizeEvent(request);
    }

    /**
     * 處理授權事件的推送
     *
     * @param request
     * @throws IOException
     * @throws AesException
     * @throws DocumentException
     */
    public void processAuthorizeEvent(HttpServletRequest request)
            throws IOException, AesException {
        String nonce = request.getParameter("nonce");
        String timestamp = request.getParameter("timestamp");
        String msgSignature = request.getParameter("msg_signature");
        LOGGER.info("=====WeChat third-party platform======" + nonce + "  " + timestamp + "  " + msgSignature);
        StringBuilder sb = new StringBuilder();
        BufferedReader in = request.getReader();
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        String xml = sb.toString();
        LOGGER.info("Third-party platform is released on the whole network-----------------------original, Xml=" + xml);
        WXBizMsgCrypt pc = new WXBizMsgCrypt(TOKEN, ENCODINGAESKEY, APPID);
        LOGGER.info("Third-party platform is released on the whole network-----------------------decryption WXBizMsgCrypt new 成功");
        String xml1 = pc.decryptMsg(msgSignature, timestamp, nonce, xml);
        LOGGER.info("Third-party platform is released on the whole network-----------------------After decryption, Xml=" + xml1);
        processAuthorizationEvent(xml1);
    }

    /**
     * 保存componentVerifyTicket
     *
     * @param xml
     */
    void processAuthorizationEvent(String xml) {
        Document doc;
        try {
            doc = DocumentHelper.parseText(xml);
            Element rootElt = doc.getRootElement();
            String componentVerifyTicket = rootElt.elementText("ComponentVerifyTicket");
            LOGGER.info("Third-party platform is released on the whole network---------After decryption, ComponentVerifyTicket=" + componentVerifyTicket);
            if (StringUtils.isNotBlank(componentVerifyTicket)) {
                TWarrantInfo tWarrantInfo = new TWarrantInfo();
                tWarrantInfo.setId("053882ef3bed46c795bbd7da470e79cf");
                tWarrantInfo.setComponentVerifyTicket(componentVerifyTicket);
                tWarrantInfo.setTicketCreateTime(DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
                int i = tWarrantInfoService.updateByPrimaryKeySelective(tWarrantInfo);
                if (i > 0) {
                    LOGGER.info("WeChat third-party platform------------component_verify_ticket data save success");
                } else {
                    LOGGER.info("WeChat third-party platform------------component_verify_ticket data save failure");
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
    * @Description: 第三方平臺全網發佈,消息與事件接收URL
    * @Author: Mr.Jkx
    * @Date: 2019/5/8 18:10
    */
    @RequestMapping(value = "/$APPID$/xxsCallback")
    public void acceptMessageAndEvent(HttpServletRequest request, @PathVariable("APPID") String appid,
                                      HttpServletResponse response) throws IOException, DocumentException, AesException {
        LOGGER.info("第三方平臺全網發佈---------{appid}/callback---------驗證開始。。。。");
        String msgSignature = request.getParameter("msg_signature");
        LOGGER.info("第三方平臺全網發佈-------------{appid}/callback-----------驗證開始。。。。msg_signature=" + msgSignature);
        if (!StringUtils.isNotBlank(msgSignature)) {
            return;// 微信推送給第三方開放平臺的消息一定是加過密的,無消息加密無法解密消息
        }
        StringBuilder sb = new StringBuilder();
        BufferedReader in = request.getReader();
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        in.close();

        String xml = sb.toString();
        Document doc = DocumentHelper.parseText(xml);
        Element rootElt = doc.getRootElement();
        String toUserName = rootElt.elementText("ToUserName");

        //微信全網測試賬號
//        if (StringUtils.equalsIgnoreCase(toUserName, APPID)) {
        LOGGER.info("全網發佈接入檢測消息反饋開始---------------APPID=" + appid + "------------------------toUserName=" + toUserName);
        checkWeixinAllNetworkCheck(request, response, xml);
//        }
    }

    public void checkWeixinAllNetworkCheck(HttpServletRequest request, HttpServletResponse response,String xml) throws DocumentException, AesException, IOException {
        String nonce = request.getParameter("nonce");
        String timestamp = request.getParameter("timestamp");
        String msgSignature = request.getParameter("msg_signature");

        WXBizMsgCrypt pc = new WXBizMsgCrypt(TOKEN, ENCODINGAESKEY, APPID);
        xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml);

        Document doc = DocumentHelper.parseText(xml);
        Element rootElt = doc.getRootElement();
        String msgType = rootElt.elementText("MsgType");
        String toUserName = rootElt.elementText("ToUserName");
        String fromUserName = rootElt.elementText("FromUserName");

        LOGGER.info("---全網發佈接入檢測--step.1-----------msgType="+msgType+"-----------------toUserName="+toUserName+"-----------------fromUserName="+fromUserName);
//        LogUtil.info("---全網發佈接入檢測--step.2-----------xml="+xml);
        if("event".equals(msgType)){
//           LogUtil.info("---全網發佈接入檢測--step.3-----------事件消息--------");
            String event = rootElt.elementText("Event");
            replyEventMessage(request,response,event,toUserName,fromUserName);
        }else if("text".equals(msgType)){
//           LogUtil.info("---全網發佈接入檢測--step.3-----------文本消息--------");
            String content = rootElt.elementText("Content");
            processTextMessage(request,response,content,toUserName,fromUserName);
        }
    }

    public void replyEventMessage(HttpServletRequest request, HttpServletResponse response, String event, String toUserName, String fromUserName) throws DocumentException, IOException {
        String content = event + "from_callback";
//        LogUtil.info("---全網發佈接入檢測------step.4-------事件回覆消息  content="+content + "   toUserName="+toUserName+"   fromUserName="+fromUserName);
        replyTextMessage(request,response,content,toUserName,fromUserName);
    }

    public void processTextMessage(HttpServletRequest request, HttpServletResponse response,String content,String toUserName, String fromUserName) throws IOException, DocumentException{
        if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){
            String returnContent = content+"_callback";
            replyTextMessage(request,response,returnContent,toUserName,fromUserName);
        }else if(StringUtils.startsWithIgnoreCase(content, "QUERY_AUTH_CODE")){
            output(response, "");
            //接下來客服API再回復一次消息
            replyApiTextMessage(request,response,content.split(":")[1],fromUserName);
        }
    }

    /**
     * 回覆微信服務器"文本消息"
     * @param request
     * @param response
     * @param content
     * @param toUserName
     * @param fromUserName
     * @throws DocumentException
     * @throws IOException
     */
    public void replyTextMessage(HttpServletRequest request, HttpServletResponse response, String content, String toUserName, String fromUserName) throws DocumentException, IOException {
        Long createTime = Calendar.getInstance().getTimeInMillis() / 1000;
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        sb.append("<ToUserName><![CDATA["+fromUserName+"]]></ToUserName>");
        sb.append("<FromUserName><![CDATA["+toUserName+"]]></FromUserName>");
        sb.append("<CreateTime>"+createTime+"</CreateTime>");
        sb.append("<MsgType><![CDATA[text]]></MsgType>");
        sb.append("<Content><![CDATA["+content+"]]></Content>");
        sb.append("</xml>");
        String replyMsg = sb.toString();

        String returnvaleue = "";
        try {
            WXBizMsgCrypt pc = new WXBizMsgCrypt(TOKEN, ENCODINGAESKEY, APPID);
            returnvaleue = pc.encryptMsg(replyMsg, createTime.toString(), "easemob");
//            LOGGER.info("------------------加密後的返回內容 returnvaleue: "+returnvaleue);
        } catch (AesException e) {
            e.printStackTrace();
        }
        output(response, returnvaleue);
    }

    public void replyApiTextMessage(HttpServletRequest request, HttpServletResponse response, String auth_code, String fromUserName) throws DocumentException, IOException {
        // 得到微信授權成功的消息後,應該立刻進行處理!!相關信息只會在首次授權的時候推送過來
        LOGGER.info("------step.1----使用客服消息接口回覆粉絲----邏輯開始-----------------");
        try {
            LOGGER.info("------step.1----使用客服消息接口回覆粉絲----邏輯開始-------------auth_code: "+auth_code+"  thirdWeixinService.getComponent_access_token:"+TOKEN);
            String url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token="+TOKEN;
            JSONObject jsonObject1 = new JSONObject();
            jsonObject1.put("component_appid", APPID);
            jsonObject1.put("authorization_code", auth_code);
            JSONObject jsonRes = WinxinUtil.doPostStr(url, jsonObject1.toString());
            LOGGER.info("------step.1----使用客服消息接口回覆粉絲----邏輯開始---------------------jsonRes:"+jsonRes.toString());

            String msg = auth_code + "_from_api";
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("touser", fromUserName);
            jsonObject.put("msgtype", "text");
            JSONObject text = new JSONObject();
            text.put("content", msg);
            jsonObject.put("text", text);
            WinxinUtil.doPostStr("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+TOKEN, jsonObject.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 工具類:回覆微信服務器"文本消息"
     * @param response
     * @param returnvaleue
     */
    public void output(HttpServletResponse response, String returnvaleue) {
        try {
            PrintWriter pw = response.getWriter();
            pw.write(returnvaleue);
            pw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

獲取第三方平臺“component_access_token”

第三方平臺通過自己的component_appid(即在微信開放平臺管理中心的第三方平臺詳情頁中的AppID和AppSecret)和component_appsecret,以及component_verify_ticket(每10分鐘推送一次的安全ticket)來獲取自己的接口調用憑據(component_access_token)

/**
     * @Description: “component_access_token”獲取
     * 有效期2小時
     * @Author: Mr.Jkx
     * @Date: 2019/4/19 16:57
     * SpringBoot定時任務,每個110分鐘獲取一次,並保存到數據庫
     */
    @Scheduled(fixedRate = 6600000)
    public void getComponentAccessToken() {
        System.out.println("-------------get component_access_token---------------");
        WarrantController warrantController = new WarrantController();
        try {
            // 從數據庫獲取微信推送的“component_verify_ticket”
            TWarrantInfo tWarrantInfo = tWarrantInfoService.selectByPrimaryKey("053882ef3bed46c795bbd7da470e79cf");
            String componentVerifyTicket = tWarrantInfo.getComponentVerifyTicket();

            // 根據“componentVerifyTicket”獲取“component_access_token”
            String componentAccessToken = getComponentAccessToken(componentVerifyTicket);

            // 數據庫保存微信推送加密信息“component_access_token”
            TWarrantInfo tWarrantInfoData = new TWarrantInfo();
            tWarrantInfoData.setComponentAccessToken(componentAccessToken);
            editWarrantInfo(tWarrantInfoData);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: 編輯授權信息
     * @Author: Mr.Jkx
     * @Date: 2019/4/20 10:12
     */
    public void editWarrantInfo(TWarrantInfo tWarrantInfo) {
        tWarrantInfo.setId("053882ef3bed46c795bbd7da470e79cf");
        if (StringUtils.isNotBlank(tWarrantInfo.getComponentAccessToken())) {
            tWarrantInfo.setTokenCreateTime(DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
        }
        if (StringUtils.isNotBlank(tWarrantInfo.getPreAuthCode())) {
            tWarrantInfo.setCodeCreateTime(DateUtil.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
        }
        int i = tWarrantInfoService.updateByPrimaryKeySelective(tWarrantInfo);
        if (i > 0) {
            LOGGER.info("WeChat third-party platform------------data save success");
        } else {
            LOGGER.info("WeChat third-party platform------------data save failure");
        }
    }

	/**
     * @Description: 獲取"component_access_token"
     * @Author: Mr.Jkx
     * @Date: 2019/4/9 9:45
     */
    public String getComponentAccessToken(String componentVerifyTicket) throws IOException {
        /**拼裝待發送的Json*/
        JSONObject json = new JSONObject();
        json.accumulate("component_appid", APPID);
        json.accumulate("component_appsecret", SECRET);
        json.accumulate("component_verify_ticket", componentVerifyTicket);
        LOGGER.info("第三方授權:獲取component_access_token:getComponentAccessToken:請求參數json={}", json);
        /**發送Https請求到微信*/
        JSONObject retJSONObject = WinxinUtil.doPostStr(COMPONENT_TOKEN_URL, json.toString());
        String component_access_token = retJSONObject.getString("component_access_token");
        LOGGER.info("第三方授權:獲取component_access_token回執數據:getComponentAccessToken:component_access_token={}", component_access_token);

        return component_access_token;
    }

獲取預授權碼“pre_auth_code”

第三方平臺通過自己的接口調用憑據(component_access_token)來獲取用於授權流程準備的預授權碼(pre_auth_code)

/**
     * @Description: 獲取預授權碼“pre_auth_code”
     * 有效期10分鐘
     * @Author: Mr.Jkx
     * @Date: 2019/4/19 16:57
     * SpringBoot定時任務,每隔9分鐘獲取一次,並保存到數據庫
     */
    @Scheduled(fixedRate = 540000)
    public void getpreAuthCode() {
        System.out.println("---------------get pre_auth_code-------------");
        WarrantController warrantController = new WarrantController();
        try {
            // 從數據庫獲取“component_access_token”令牌
            TWarrantInfo tWarrantInfo = tWarrantInfoService.selectByPrimaryKey("053882ef3bed46c795bbd7da470e79cf");
            String component_access_token = tWarrantInfo.getComponentAccessToken();

            // 根據“component_access_token”獲取“pre_auth_code”
            String preAuthCodeData = getPreAuthCodeData(component_access_token);

            // 數據庫保存預授權碼“pre_auth_code”
            TWarrantInfo tWarrantInfoData = new TWarrantInfo();
            tWarrantInfoData.setPreAuthCode(preAuthCodeData);
            editWarrantInfo(tWarrantInfoData);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
	/**
     * @Description: 獲取"pre_auth_code"(預授權碼)
     * @Author: Mr.Jkx
     * @Date: 2019/4/9 10:21
     */
    public String getPreAuthCodeData(String component_access_token) throws IOException {
        JSONObject json = new JSONObject();
        json.accumulate("component_appid", APPID);
        json.accumulate("component_access_token", component_access_token);
        String url = PRE_AUTH_CODE.replace("componentAccessToken", component_access_token);
        /**發送Https請求到微信*/
        JSONObject retStr = WinxinUtil.doPostStr(url, json.toString());
        LOGGER.info("第三方授權:ThirdPartyServiceImpl:getPreAuthCode:retStr={}", retStr);
        JSONObject retJSONObject = JSONObject.fromObject(retStr);
        /**在返回結果中獲取pre_auth_code*/
        String pre_auth_code = retJSONObject.getString("pre_auth_code");
        LOGGER.info("==========第三方授權:獲取pre_auth_code:{}", pre_auth_code);
        return pre_auth_code;
    }

使用授權碼換取公衆號或小程序的接口調用憑據和授權信息

通過授權碼和自己的接口調用憑據(component_access_token),換取公衆號或小程序的接口調用憑據(authorizer_access_token和用於前者快過期時用來刷新它的authorizer_refresh_token)和授權信息(授權了哪些權限等信息)

/**
     * @Description: 刷新令牌“authorizer_refresh_token”
     * 有效期2小時
     * @Author: Mr.Jkx
     * @Date: 2019/4/19 16:57
     */
    @Scheduled(fixedRate = 6600000)
    public void refreshAuthorizerRefreshToken() {
        System.out.println("---------------get authorizer_refresh_token-------------");
        WarrantController warrantController = new WarrantController();
        try {
            // 授權方appid{},接口調用憑據刷新令牌查詢
            List<TWarrantMerchant> tWarrantMerchantList = TWarrantMerchantService.selTWarrantMerchant();
            // 從數據庫獲取“component_access_token”令牌
            TWarrantInfo tWarrantInfo = tWarrantInfoService.selectByPrimaryKey("053882ef3bed46c795bbd7da470e79cf");
            String component_access_token = tWarrantInfo.getComponentAccessToken();
            List<TWarrantMerchant> tWarrantMerchants = refreshAuthorizerRefreshToken(tWarrantMerchantList, component_access_token);

            if (tWarrantMerchants.size() > 0) {
                for (TWarrantMerchant tWarrantMerchant : tWarrantMerchants) {
                    long currentTime = new Date().getTime() + 120 * 60 * 1000;
                    Date date = new Date(currentTime);
                    tWarrantMerchant.setDeadline(date);
                    TWarrantMerchantService.updTWarrantMerchant(tWarrantMerchant);
                }
            } else {
                System.out.println("---------------No authorizer_refresh_token needs to updated-------------");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
	/**
     * @Description: 刷新令牌“authorizer_refresh_token”
     * @Author: Mr.Jkx
     * @Date: 2019/5/6 17:58
     */
    public List<TWarrantMerchant> refreshAuthorizerRefreshToken(List<TWarrantMerchant> tWarrantMerchants, String component_access_token) throws IOException {
        List<TWarrantMerchant> tWarrantMerchantList = new ArrayList<>();
        // 查找需要刷新令牌的數據
        for (TWarrantMerchant tWarrantMerchant : tWarrantMerchants) {
//            Date deadline = tWarrantMerchant.getDeadline();
//            if (deadline.getTime() - new Date().getTime() < 600000) {
                tWarrantMerchantList.add(tWarrantMerchant);
//            }
        }
        // 重新獲取令牌
        List<TWarrantMerchant> authorizerRefreshToken = getAuthorizerRefreshToken(tWarrantMerchantList, component_access_token);
        return authorizerRefreshToken;
    }

    /**
     * @Description: 重新獲取令牌
     * @Author: Mr.Jkx
     * @Date: 2019/5/6 18:39
     */
    private List<TWarrantMerchant> getAuthorizerRefreshToken(List<TWarrantMerchant> tWarrantMerchantList, String component_access_token) throws IOException {
        List<TWarrantMerchant> tWarrantMerchants = new ArrayList<>();
        for (TWarrantMerchant tWarrantMerchant : tWarrantMerchantList) {
            JSONObject json = new JSONObject();
            json.accumulate("component_appid", APPID);
            json.accumulate("authorizer_appid", tWarrantMerchant.getAuthorizationAppid());
            json.accumulate("authorizer_refresh_token", tWarrantMerchant.getAuthorizerRefreshToken());

            /**發送Https請求到微信*/
            String url = AUTHORIZER_REFRESH_TOKEN.replace("componentAccessToken", component_access_token);
            JSONObject retStr = WinxinUtil.doPostStr(url, json.toString());
            LOGGER.info("==========第三方授權: 令牌刷新{}", retStr);

            JSONObject retJSONObject = JSONObject.fromObject(retStr);
            /**在返回結果中獲取pre_auth_code*/
            LOGGER.info("==========第三方授權:令牌刷新:{}", retJSONObject);

            String authorizer_refresh_token = retJSONObject.getString("authorizer_refresh_token");// 接口調用憑據刷新令牌
            String authorizer_access_token = retJSONObject.getString("authorizer_access_token");// 小程序授權令牌
            LOGGER.info("==========第三方授權:獲取到的新令牌:{}", retJSONObject);

            // 授權商戶信息保存
            TWarrantMerchant updTWarrantMerchant = new TWarrantMerchant();
            updTWarrantMerchant.setId(tWarrantMerchant.getId());
            // 接口調用憑據刷新令牌
            updTWarrantMerchant.setAuthorizerRefreshToken(authorizer_refresh_token);
            updTWarrantMerchant.setAuthorizerAccessToken(authorizer_access_token);
            tWarrantMerchants.add(updTWarrantMerchant);
        }
        return tWarrantMerchants;
    }

觸發授權頁面

準備好授權所需的必要信息,請求授權頁面,掃碼授權。
在這裏插入圖片描述

頁面js實現

// 頁面授權完成跳轉頁面“https://www.xxxxx.com/xxx/pages/set1.html”
$(function(){
            $("#bingLink").click(function(){
            	// 請求獲取必要信息
                postCreaterHttp('/warrantPhone/warrantMessage',{},function(res){
                    if("200" == res.errorCode){
                        var url='https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid='+res.message.componentAppid+'&pre_auth_code='+res.message.preAuthCode+'&redirect_uri=https://www.xxxxx.com/xxx/pages/set1.html';
                        window.open(url);// 請求授權頁面
                    }else if("300" == res.errorCode){
                        layui.use('layer', function() {
                            var layer = layui.layer;
                            layer.msg("賬號已經綁定【" + res.appletsName + "】");
                        })
                    }
                })
            })

        })

後臺接口實現

@RequestMapping("warrantPhone")
@Controller
public class WarrantPhoneController {
    // 第三方appid
    private static final String COMPONENT_APPID = "wx9681884b28ed7927";
    //回調地址,此處沒有用到
    private static final String REDIRECT_URI = "https://www.xinxingshangstar.com/warrant/warrantBack";

    @Autowired
    TWarrantInfoMapper tWarrantInfoMapper;
    @Autowired
    TWarrantMerchantMapper tWarrantMerchantMapper;

	/**
	* @Description: 查詢爲授權準備的信息
	* @Author:      Mr.Jkx
	* @UpdateDate:  2019/5/10 15:44
	*/
    @RequestMapping("/warrantMessage")
    @ResponseBody
    public Map<String, Object> getWarrantMessageByPhone(TWarrantMerchant tWarrantMerchant){
        Map<String, Object> resMap = new HashMap<>();
        // 根據授權方APPID查詢此商戶是否授權
        TWarrantMerchant tWarrantMerchantData = tWarrantMerchantMapper.selWarrantMerchant(tWarrantMerchant);
        if(null == tWarrantMerchantData){
            // 數據庫查詢授權信息
            TWarrantInfo warrantMessageByPhone = tWarrantInfoMapper.selectByPrimaryKey("053882ef3bed46c795bbd7da470e79cf");
            warrantMessageByPhone.setComponentAppid(COMPONENT_APPID);
            warrantMessageByPhone.setRedirectUri(REDIRECT_URI);
            resMap.put("errorCode", "200");
            resMap.put("message", warrantMessageByPhone);
            resMap.put("appletsName", "");
        }else{
            resMap.put("errorCode", "300");
            resMap.put("message", JsonUtil.toJsonString(new TWarrantInfo()));
            resMap.put("appletsName", tWarrantMerchantData.getNickName());
        }
        return resMap;
    }
}

在這裏插入圖片描述

授權完成根據“authCode”(授權碼)請求獲取授權信息

請求獲取授權信息,及授權小程序信息;

本項目,前端js實現

    $(function () {
        var src = window.location.href;
        var num = 5
        if (src.indexOf("?auth_code=") > -1) {
            src = src.split("?auth_code=")[1]
        }
        if (src.indexOf("&expires_in=") > -1) {
            src = src.split("&expires_in=")[0]
        }
        // 用授權碼,請求獲取授權信息
        postCreaterHttp('/merchant/addMerchantWarrantInfo', {authCode: src}, function (res) {
            if (res.errorCode == '200') {
                $("#wait").html("配置成功!")
            } else if (res.errorCode == '100') {
                $("#wait").html("賬號已經授權!")
            } else {
                $("#wait").html("配置失敗!請重新授權")
            }
            $(".icon-success,.link").show();
            setInterval(function () {
                num = num - 1
                $(".link span").html(num)
                if (num < 1) {
                    window.location.href = "https://www.xxx.com/xxx/pages/index.html"
                }
            }, 1000)
        })
    })

後端實現

package com.litte.controller.warrantmerchant;

import com.litte.controller.warrant.WarrantController;
import com.litte.entity.reception.TWarrantInfo;
import com.litte.entity.reception.TWarrantMerchant;
import com.litte.service.jurisdiction.UserService;
import com.litte.service.warrantinfo.TWarrantInfoService;
import com.litte.service.warrantmerchant.TWarrantMerchantService;
import com.litte.util.WinxinUtil;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.Map;

/**
* @Description: 授權商戶信息相關
* @Author:      Mr.Jkx
* @UpdateDate:  2019/5/10 15:44
*/
@Controller
@RequestMapping("/merchant")
public class TWarrantMerchantController {
    private static final Logger LOGGER = LoggerFactory.getLogger(WarrantController.class);
    //公衆號第三方平臺的appid
    private static final String APPID = "APPID ";
    // 授權碼獲取授權公衆號小程序信息
    private static final String API_QUERY_AUTH = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=componentAccessToken";
    // 獲取授權商戶信息
    private static final String API_GET_AUTHORIZER_INFO = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=componentAccessToken";

    @Autowired
    TWarrantMerchantService TWarrantMerchantService;
    @Autowired
    TWarrantInfoService tWarrantInfoService;
    @Autowired
    UserService userService;

    @RequestMapping("/addMerchantWarrantInfo")
    @ResponseBody
    public Map<String, String> addMerchantWarrantInfo(TWarrantMerchant tWarrantMerchant) throws IOException {
        int i = 0;
        String auth_code = tWarrantMerchant.getAuthCode(); // 授權碼
        LOGGER.info("==========第三方授權:掃碼授權頁面回調,授權碼:{}", auth_code);
        // 從數據庫獲取“component_access_token”令牌
        TWarrantInfo tWarrantInfo = tWarrantInfoService.selectByPrimaryKey("053882ef3bed46c795bbd7da470e79cf");
        String component_access_token = tWarrantInfo.getComponentAccessToken();

        JSONObject json = new JSONObject();
        json.accumulate("component_appid", APPID);
        json.accumulate("authorization_code", auth_code);
        /**發送Https請求到微信*/
        String url = API_QUERY_AUTH.replace("componentAccessToken", component_access_token);
        JSONObject retStr = WinxinUtil.doPostStr(url, json.toString());
        LOGGER.info("==========第三方授權: 授權碼獲取授權公衆號小程序{}", retStr);

        JSONObject retJSONObject = JSONObject.fromObject(retStr);
        /**在返回結果中獲取pre_auth_code*/
        LOGGER.info("==========第三方授權:獲取授權者信息:{}", retJSONObject);
        String authorization_info = retJSONObject.getString("authorization_info");// 授權方信息載體authorization_info
        JSONObject jsonObject = JSONObject.fromObject(authorization_info);

        String authorizer_appid = jsonObject.getString("authorizer_appid");// 授權方appid
        String authorizerAccessToken = jsonObject.getString("authorizer_access_token");// 授權方令牌(配置小程序服務器域名會用到,隨着令牌刷新,此字段也會刷新)

        // 獲取授權商戶信息
        Map<String, String> resMap = getTWarrantMerchantInfo(authorizer_appid, tWarrantMerchant.getCreater(), authorizerAccessToken);
        if(StringUtils.equals("200", resMap.get("errorCode"))){
            // 修改授權狀態
            i = userService.updateWarrantType(tWarrantMerchant.getCreater());
            if(i > 0){
                resMap.put("errorCode", "200");
            }else{
                resMap.put("errorCode", "400");
            }
        }
        return resMap;
    }

    /**
     * @Description: 獲取授權商戶信息
     * @Author: Mr.Jkx
     * @Date: 2019/5/6 18:57
     */
    private Map<String, String> getTWarrantMerchantInfo(String authorizer_appid, String creater, String authorizerAccessToken) throws IOException {
        // 從數據庫獲取“component_access_token”令牌
        TWarrantInfo tWarrantInfo = tWarrantInfoService.selectByPrimaryKey("053882ef3bed46c795bbd7da470e79cf");
        String component_access_token = tWarrantInfo.getComponentAccessToken();

        JSONObject json = new JSONObject();
        json.accumulate("component_appid", APPID);
        json.accumulate("authorizer_appid", authorizer_appid);

        /**發送Https請求到微信*/
        String url = API_GET_AUTHORIZER_INFO.replace("componentAccessToken", component_access_token);
        JSONObject retStr = WinxinUtil.doPostStr(url, json.toString());
        LOGGER.info("==========第三方授權: 獲取授權商戶信息{}", retStr);

        JSONObject retJSONObject = JSONObject.fromObject(retStr);
        /**在返回結果中獲取pre_auth_code*/
        LOGGER.info("==========第三方授權:獲取授權商戶信息:{}", retJSONObject);

        //授權商戶信息保存數據庫
        Map<String, String> resMap = insertTWarrantMerchantInfo(retJSONObject, creater, authorizerAccessToken);
        return resMap;
    }

    /**
     * @Description: 授權商戶信息保存數據庫
     * @Author: Mr.Jkx
     * @Date: 2019/5/6 19:00
     */
    private Map<String, String> insertTWarrantMerchantInfo(JSONObject retJSONObject, String creater, String authorizerAccessToken) {
        Map<String, String> resMap = TWarrantMerchantService.insertTWarrantMerchant(retJSONObject, creater, authorizerAccessToken);
        return resMap;
    }
}
/**
     * @Description: 授權商戶信息保存數據庫
     * @Author: Mr.Jkx
     * @Date: 2019/5/6 19:00
     */
@Override
    public Map<String, String> insertTWarrantMerchant(JSONObject retJSONObject, String creater, String authorizerAccessToken) {
        Map<String, String> resMap = new HashMap<>();
        int i= 0;
        TWarrantMerchant tWarrantMerchant = new TWarrantMerchant();
        // 有效期
        long currentTime = new Date().getTime() + 120 * 60 * 1000;
        Date date = new Date(currentTime);

        String authorizerInfo = retJSONObject.getString("authorizer_info");// 授權方公衆號小程序具體信息載體authorization_info
        JSONObject jsonObject = JSONObject.fromObject(authorizerInfo);

        String authorizationInfo = retJSONObject.getString("authorization_info");// 授權方公衆號小程序授權信息載體authorization_info
        JSONObject jsonObject1 = JSONObject.fromObject(authorizationInfo);

        String serviceTypeInfo = jsonObject.getString("service_type_info");
        JSONObject jsonObject2 = JSONObject.fromObject(serviceTypeInfo);

        String verifyTypeInfo = jsonObject.getString("verify_type_info"); // 授權方認證類型,-1代表未認證,0代表微信認證
        JSONObject jsonObject3 = JSONObject.fromObject(verifyTypeInfo);

        // 授權方APPID
        String authorizerAppid = jsonObject1.getString("authorizer_appid");

        tWarrantMerchant.setId(UUIDUtil.getUUID());
        tWarrantMerchant.setAuthorizationAppid(authorizerAppid);
        tWarrantMerchant.setAuthorizerRefreshToken(jsonObject1.getString("authorizer_refresh_token"));
        tWarrantMerchant.setNickName(jsonObject.getString("nick_name"));
        tWarrantMerchant.setHeadImg(jsonObject.getString("head_img"));
        tWarrantMerchant.setServiceTypeInfo(jsonObject2.getString("id"));
        tWarrantMerchant.setVerifyTypeInfo(jsonObject3.getString("id"));
        tWarrantMerchant.setUserName(jsonObject.getString("user_name"));
        tWarrantMerchant.setPrincipalName(jsonObject.getString("principal_name"));
        tWarrantMerchant.setAlias(jsonObject.getString("alias"));
//        tWarrantMerchant.setBusinessInfo(jsonObject.getString("business_info"));
        tWarrantMerchant.setQrcodeUrl(jsonObject.getString("qrcode_url"));
//        tWarrantMerchant.setAuthorizationInfo(jsonObject.getString("authorization_info"));
//        tWarrantMerchant.setFuncInfo(jsonObject.getString("func_info"));
//        tWarrantMerchant.setMiniprograminfo(jsonObject.getString("miniprograminfo"));
        tWarrantMerchant.setCreateTime(DateUtil.formatDate(new Date(),"yyyy-MM-dd HH:mm:ss"));
        tWarrantMerchant.setDeadline(date);
        tWarrantMerchant.setCreater(creater);
        tWarrantMerchant.setAuthorizerAccessToken(authorizerAccessToken);

        // 根據授權方APPID查詢此商戶是否授權
//        TWarrantMerchant tWarrantMerchant1 = new TWarrantMerchant();
//        tWarrantMerchant1.setCreater(creater);
//        TWarrantMerchant tWarrantMerchantData1 = tWarrantMerchantMapper.selWarrantMerchant(tWarrantMerchant1);
//        if(null != tWarrantMerchantData1 && StringUtils.equals("1", tWarrantMerchantData1.getWarrantType())){
//            resMap.put("errorCode", "100");
//            return resMap;
//        }else{
            TWarrantMerchant tWarrantMerchant2 = new TWarrantMerchant();
            tWarrantMerchant2.setAuthorizationAppid(authorizerAppid);
            TWarrantMerchant tWarrantMerchantData2 = tWarrantMerchantMapper.selWarrantMerchant(tWarrantMerchant2);
            if(null != tWarrantMerchantData2){
                tWarrantMerchant.setId(tWarrantMerchantData2.getId());
                i = tWarrantMerchantMapper.updateByPrimaryKeySelective(tWarrantMerchant);
            }else{
                i = tWarrantMerchantMapper.insertSelective(tWarrantMerchant);
            }
            if(i>0){
                resMap.put("errorCode", "200");
                LOGGER.info("=======第三方授權:授權商戶信息入庫完畢!!!");
                return resMap;
            }else{
                resMap.put("errorCode", "300");
                LOGGER.info("=======第三方授權:授權商戶信息入庫失敗!!!");
                return resMap;
            }
//        }
    }
發佈了35 篇原創文章 · 獲贊 27 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章