SpringBoot微信小程序授权登录

SpringBoot微信小程序授权登录

一、appId

1.1、自己是管理者:微信公众平台,申请或登录自己的微信小程序,在开发者管理中即可看到
2.2、自己是开发者:让管理员将自己加入到小程序开发者管理中,用管理者提供的appId和secret,否则没有开发权限
在这里插入图片描述

二、小程序登录页面

2.1、打开HBuilderX开发工具,新建一个uni-app项目
在这里插入图片描述
2.2、在项目根目录下新建config文件夹,创建config.js文件,配置后台访问路径

// 配置后台服务器访问地址:ip:端口/项目名
const hostUrl = ''
export default {
  // 本地持久化存储key
  projectKey: 'XinJiangBS',
  // api请求地址
  // #ifdef H5
  // H5 环境,配合menifest.json中的devServe配置来解决调试时的跨域问题
  baseUrl: process.env.NODE_ENV === 'development' ? '/dev' : hostUrl,
  // #endif
  baseUrl: hostUrl,
  // 盐
  kSalt: 'XDSAKDSALMSD',
}

2.3、新建简单的login.vue页面,调用前端方法获取后台登录需要用的code信息

<button @click="toLogin">获取登录code</button>
// 可以将后台接口统一写在common.js中,页面统一引入
import { } from "@/api/common.js"
methods:{
	toLogin(){
		uni.getProvider({
			service:'oauth',
			success:(provider) => {
			uni.login({
				success:(loginCode) =>{
					console.log("loginCode",loginCode);
					// todo 调用后台登录接口,参数code
				}
			})
		}
	})
	},
}

2.4、下载微信开发者工具,并安装
在这里插入图片描述
2.5、配置HBuilderX,点击manifest.json,再点击微信小程序配置appid
在这里插入图片描述
2.6、配置运行小程序需要用到的微信开发开发者工具,点击HBuilder上面工具栏中的:工具—设置—运行配置,找到微信开发者工具工具路径,配置2.4中安装安装时的路径

三、java代码部分

1.新建微信小程序公用配置文件
@Component
@Slf4j
public class WxDataConfigure {

    /**小程序appId*/
    public static String appId = "";

    /**小程序的秘钥*/
    public static String ** = "";

    /**商户号*/
    public static String mch_id = "";

    /**商户支付秘钥V2*/
    public static String key = "";
    /**商户支付秘钥V3*/
    public static String keyV3 = "";

    /**退款用到*/
    public static String certUrl = "";

    /**商家转账到零钱*/
    public static String pemUrl = "";
    public static String privateKeyPath = "";
    public static String privateCertPath = "";
    public static String sn = "";

    /**商户证书序列号*/
    public static String serial_no = "";

    /**回调通知地址(需内网穿透测试)*/
    public static String notify_url = "";

    /**交易类型*/
    public static  String trade_type = "JSAPI";

    /**统一下单API接口链接*/
    public static String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    /**查询订单API接口链接*/
    public static String query_url = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**退款接口*/
    public static String refund_url = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";

    /**退款回调接口*/
    public static String refund_notify_url = "";

    /**商家转账到零钱*/
    public static String batches_url = "https://api.mch.weixin.qq.com/v3/transfer/batches";

    /**
     * 预支付
     * @return
     */
    public static WxPayService unifiedOrderWxPayService() {
        log.info("======================初始化微信支付接口服务开始======================");
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(appId);
        payConfig.setMchId(mch_id);
        payConfig.setMchKey(key);
        payConfig.setKeyPath(certUrl);
        payConfig.setTradeType(trade_type);

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);

        log.info("======================初始化微信支付接口服务完成======================");
        return wxPayService;
    }

    /**
     * 退款
     * @return
     */
    public static WxPayService wxPayService() {
        //logger.info("======================初始化微信支付接口服务开始======================");
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(appId);
        payConfig.setMchId(mch_id);
        payConfig.setPrivateKeyPath(privateKeyPath);
        payConfig.setNotifyUrl(refund_notify_url);
        payConfig.setApiV3Key(keyV3);
        payConfig.setPrivateCertPath(privateCertPath);
        payConfig.setCertSerialNo(serial_no);

        payConfig.setMchKey(key);
        payConfig.setKeyPath(certUrl);
        payConfig.setTradeType(trade_type);

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);

        //logger.info("======================初始化微信支付接口服务完成======================");
        return wxPayService;
    }

2.调用微信服务器接口的请求方法类

public class HttpRequest {
    //连接超时时间,默认10秒
    private static final int socketTimeout = 10000;

    //传输超时时间,默认30秒
    private static final int connectTimeout = 30000;


    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }


    /**
     * post请求
     *
     * @throws IOException
     * @throws ClientProtocolException
     * @throws NoSuchAlgorithmException
     * @throws KeyStoreException
     * @throws KeyManagementException
     * @throws UnrecoverableKeyException
     */
    public static String sendPost(String url, Object xmlObj) throws ClientProtocolException, IOException, UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException {


        HttpPost httpPost = new HttpPost(url);
        //解决XStream对出现双下划线的bug
        XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
        xStreamForRequestPostData.alias("xml", xmlObj.getClass());
        //将要提交给API的数据对象转换成XML格式数据Post给API
        String postDataXML = xStreamForRequestPostData.toXML(xmlObj);
        System.out.println(postDataXML);
        //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
        StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);

        //设置请求器的配置
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpPost.setConfig(requestConfig);

        HttpClient httpClient = HttpClients.createDefault();
        HttpResponse response = httpClient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        String result = EntityUtils.toString(entity, "UTF-8");
        return result;
    }

    /**
     * http POST 请求
     *
     * @param url:请求地址
     * @param body:     body实体字符串
     * @param certPath: 证书路径
     * @param password: 证书密码
     * @return
     */
    public static String httpPostReflect(String url, String body, InputStream certPath, String password) {
        String xmlRes = "{}";
        HttpClient client = createSSLClientCert(certPath, password);
        HttpPost httpost = new HttpPost(url);
        try {
            //所有请求的body都需采用UTF-8编码
//            StringEntity entity = new StringEntity(body,"UTF-8");
//            httpost.setEntity(entity);
            //支付平台所有的API仅支持JSON格式的请求调用,HTTP请求头Content-Type设为application/json
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/json; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            //httpost.addHeader("Authorization",Configure.sn + " " + data);
            httpost.setEntity(new StringEntity(body, "UTF-8"));
            HttpResponse response = client.execute(httpost);
            //所有响应也采用UTF-8编码
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            xmlRes = result;
        } catch (ClientProtocolException e) {
            System.out.println(e);
        } catch (UnknownHostException e) {
            System.out.println(e);
        } catch (IOException e) {
            System.out.println(e);
        }
        return xmlRes;
    }

    /**
     * 创建带证书的实例
     *
     * @param certPath
     * @return
     */
    public static CloseableHttpClient createSSLClientCert(InputStream certPath, String password) {
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(certPath, password.toCharArray());
            certPath.close();
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有
                public boolean isTrusted(X509Certificate[] chain,
                                         String authType) throws CertificateException {
                    return true;
                }
            }).loadKeyMaterial(keyStore, password.toCharArray()).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1", "TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            System.out.println(e);
        } catch (NoSuchAlgorithmException e) {
            System.out.println(e);
        } catch (KeyStoreException e) {
            System.out.println(e);
        } catch (FileNotFoundException e) {
            System.out.println(e);
        } catch (Exception e) {
            System.out.println(e);
        }
        return HttpClients.createDefault();
    }

    /**
     * 自定义证书管理器,信任所有证书
     *
     * @author pc
     */
    public static class MyX509TrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(
                java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException {

        }

        @Override
        public void checkServerTrusted(
                java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException {

        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }
}

3.微信登录方法,返回用户信息至前端

@Slf4j
@RestController
@RequestMapping("/wx/user")
public class WxController {

    /**
     *  //GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
     *  //https://api.weixin.qq.com/sns/jscode2session
     */
    @GetMapping("/wxLogin")
    public Map<String,String> wxLogin(@RequestParam(name = "code",required = true) String code){
        //小程序登录参数Get请求
        String openidParams = "appid=" + WxDataConfigure.appId + "&secret=" + WxDataConfigure.secret + "&js_code=" + code + "&grant_type=" + "authorization_code";
        String openidUrl = "https://api.weixin.qq.com/sns/jscode2session";
        //获取接口调用凭证参数Get请求
        String accessTokenParams = "appid=" + WxDataConfigure.appId + "&secret=" + WxDataConfigure.secret + "&grant_type=" + "client_credential";
        String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
        //http请求微信服务器
        String openIdResult = HttpRequest.sendGet(openidUrl, openidParams);
        String accessTokenResult = HttpRequest.sendGet(accessTokenUrl, accessTokenParams);
        JSONObject openIdJson = JSONObject.parseObject(openIdResult);
        JSONObject accessTokenJson = JSONObject.parseObject(accessTokenResult);
        //获取openId
        String openid =(String) openIdJson.get("openid");
        //会话秘钥
        String session_key =(String) openIdJson.get("session_key");
        //获取到的凭证
        String access_token =(String) accessTokenJson.get("access_token");
        Integer expiresIn =(Integer) accessTokenJson.get("expires_in");

        Map<String, String> infoMap = new HashMap<>();
        infoMap.put("openid",openid);
        infoMap.put("session_key",session_key);
        infoMap.put("access_token",access_token);
        infoMap.put("expiresIn",expiresIn.toString());
        return infoMap;
    }
}

一个在学习的开发者,勿喷,欢迎交流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值