微信小程序序的代码中提示,使用code换取openid,但官方文档中没有给出进一步的说明。
换取openid的要点:由于安全的原因,必须由自己小程序的服务器端完成。知道了这个要点,实现起来就简单了,服务器端写一个RestController,接收code参数,使用httpclient向微信的服务端换openid就行了。
代码使用了SpringBoot,不会也不难理解。主要代码如下:
package com.wallimn.iteye.sp.asset.common.controller; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.fasterxml.jackson.databind.ObjectMapper; import com.wallimn.iteye.sp.asset.common.util.AesUtil; import com.wallimn.iteye.sp.asset.common.util.HttpUtil; @RestController @RequestMapping("/api/wx") public class WeixinController { private static Logger log = LoggerFactory.getLogger(WeixinController.class); @Value("${wx.appId}") private String appId; @Value("${wx.appSecret}") private String appSecret; @Value("${wx.grantType}") private String grantType; // wx.grantType=authorization_code @Value("${wx.requestUrl}") private String requestUrl; // wx.requestUrl=https://api.weixin.qq.com/sns/jscode2session @RequestMapping("/session") public Map<String, Object> getSession(@RequestParam(required = true) String code) { return this.getSessionByCode(code); } @SuppressWarnings("unchecked") private Map<String, Object> getSessionByCode(String code) { String url = this.requestUrl + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=" + grantType; // 发送请求 String data = HttpUtil.get(url); log.debug("请求地址:{}", url); log.debug("请求结果:{}", data); ObjectMapper mapper = new ObjectMapper(); Map<String, Object> json = null; try { json = mapper.readValue(data, Map.class); } catch (Exception e) { e.printStackTrace(); } // 形如{"session_key":"6w7Br3JsRQzBiGZwvlZAiA==","openid":"oQO565cXXXXXEvc4Q_YChUE8PqB60Y"}的字符串 return json; } }
用到了一个httpclient封闭的工具类,代码如下:
package com.wallimn.iteye.sp.asset.common.util; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; public class HttpUtil { private static final String Charset = "utf-8"; /** * 发送请求,如果失败,会返回null * @param url * @param map * @return */ public static String post(String url, Map<String, String> map) { // 处理请求地址 try { HttpClient client = HttpClientBuilder.create().build(); URI uri = new URI(url); HttpPost post = new HttpPost(uri); // 添加参数 List<NameValuePair> params = new ArrayList<NameValuePair>(); for (String str : map.keySet()) { params.add(new BasicNameValuePair(str, map.get(str))); } post.setEntity(new UrlEncodedFormEntity(params, Charset)); // 执行请求 HttpResponse response = client.execute(post); if (response.getStatusLine().getStatusCode() == 200) { // 处理请求结果 StringBuffer buffer = new StringBuffer(); InputStream in = null; try { in = response.getEntity().getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader(in,Charset)); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭流 if (in != null) try { in.close(); } catch (Exception e) { e.printStackTrace(); } } return buffer.toString(); } else { return null; } } catch (Exception e1) { e1.printStackTrace(); } return null; } /** * 发送请求,如果失败会返回null * @param url * @param str * @return */ public static String post(String url, String str) { // 处理请求地址 try { HttpClient client = HttpClientBuilder.create().build(); URI uri = new URI(url); HttpPost post = new HttpPost(uri); post.setEntity(new StringEntity(str, Charset)); // 执行请求 HttpResponse response = client.execute(post); if (response.getStatusLine().getStatusCode() == 200) { // 处理请求结果 StringBuffer buffer = new StringBuffer(); InputStream in = null; try { in = response.getEntity().getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader(in,"utf-8")); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } } finally { // 关闭流 if (in != null) in.close(); } return buffer.toString(); } else { return null; } } catch (Exception e) { e.printStackTrace(); } return null; } /** * 发送GET方式的请求,并返回结果字符串。 * <br> * 时间:2017年2月27日,作者:http://wallimn.iteye.com * @param url * @return 如果失败,返回为null */ public static String get(String url) { try { HttpClient client = HttpClientBuilder.create().build(); URI uri = new URI(url); HttpGet get = new HttpGet(uri); HttpResponse response = client.execute(get); if (response.getStatusLine().getStatusCode() == 200) { StringBuffer buffer = new StringBuffer(); InputStream in = null; try { in = response.getEntity().getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader(in,Charset)); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } } finally { if (in != null) in.close(); } return buffer.toString(); } else { return null; } } catch (Exception e) { e.printStackTrace(); } return null; } }
小程序中,使用wx.request(url:'https://域名/api/wx/session',....),就可以拿到一个JSON对象,其中有openid。