栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

微信小程序后端(java)开发流程的详细步骤

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

微信小程序后端(java)开发流程的详细步骤

微信小程序后端开发流程根据官网总结为两个步骤

1、前端调用 wx.login 返回了code,然后调用wx.getUserInfo获取到用户的昵称 头像

 2、服务端根据code去微信获取openid, 接口地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html%EF%BC%9B%E5%90%8C%E6%97%B6%EF%BC%8C%E6%9B%B4%E6%96%B0%E7%94%A8%E6%88%B7%E6%98%B5%E7%A7%B0%E5%A4%B4%E5%83%8F%E7%AD%89%E8%B5%84%E6%96%99

微信小程序后端接口开发

controller层

public class OauthController {

  @Autowired
  private WeChatService weChatService;

  
  @GetMapping("/code2Session")
  public baseResponse code2Session(String code) {
    log.info("code2Session,code={}", code);
    if (StringUtil.isEmpty(code)) {
      return baseResponse.buildFail("参数异常");
    }
    Code2SessionResponse res = weChatService.code2Session(code);
    log.info("code2Session,res={}", res);
    if (!res.isSuccess()) {
      return baseResponse.buildFail(res.getErrCode(), res.getErrMsg());
    }
    return baseResponse.buildSuccess(res);
  }


 
  public baseResponse decryptGetPhone(HttpServletRequest request, HttpServletResponse response,
    @RequestBody OauthParam param) {
  
      if (!StringUtil.isEmpty(param.getOpenId())) {//微信授权登录
 String sessionKey = weChatService.getSessionKey(param.getOpenId());
 if (StringUtil.isEmpty(sessionKey)) {
   return baseResponse.buildFail("会话不存在");
 }
 Sha1Utils sha = new Sha1Utils();
 // 获取用户信息
 log.debug("微信登陆 sessionKey = {}", sessionKey);
 String userInfoStr = sha.decryptWXAppletInfo(sessionKey, param.getEncryptedData(), param.getIv());
 if (StringUtil.isEmpty(userInfoStr)) {
   return baseResponse.buildFail("无法获取用户信息");
 }
 JSonObject json = JSONObject.parseObject(userInfoStr);
 //绑定微信的手机号
 String tel = json.getString("purePhoneNumber");
 Assert.isTrue(!StringUtils.isEmpty(tel), "无法获取用户手机号");
 baseResponse baseResponse=new baseResponse();
 baseResponse.setResultInfo(tel);
 baseResponse.setState(0);
 return baseResponse;
      }

  }
}

接口

public interface WeChatService {


  
  Code2SessionResponse code2Session(String code);


  
  String getAccessToken();


  
  String getAccessToken(boolean isForce);


  String getSessionKey(String openId);

}

实现类

public class WeChatServiceImpl implements WeChatService {

  //获取配置文件数据
  @Value("${wechat.miniprogram.id}")
  private String appId;

  @Value("${wechat.miniprogram.secret}")
  private String appSecret;

  @Reference
  private SysUserService sysUserService;


  @Override
  public Code2SessionResponse code2Session(String code) {
    String rawResponse = HttpClientUtil
 .get(String.format(WechatConstant.URL_CODE2SESSION, appId, appSecret, code));
    log.info("rawResponse====={}", rawResponse);
    Code2SessionResponse response = JSON.parseObject(rawResponse, Code2SessionResponse.class);
    if (response.isSuccess()) {
      cacheSessionKey(response);
    }
    return response;
  }

  private void cacheSessionKey(Code2SessionResponse response) {
    RedisCache redisCache = RedisCache.getInstance();
    String key = RedisCacheKeys.getWxSessionKeyKey(response.getOpenId());
    redisCache.setCache(key, 2147483647, response.getSessionKey());
  }

  @Override
  public String getAccessToken() {
    return getAccessToken(false);
  }

  @Override
  public String getAccessToken(boolean isForce) {
    RedisCache redisCache = RedisCache.getInstance();
    String accessToken = null;
    if (!isForce) {
      accessToken = redisCache.getCache(RedisCacheKeys.getWxAccessTokenKey(appId));
    }
    if (StringUtil.isNotEmpty(accessToken)) {
      return accessToken;
    }
    String rawResponse = HttpClientUtil
 .get(String.format(WechatConstant.URL_GET_ACCESS_TOKEN, appId, appSecret));
    AccessTokenResponse response = JSON.parseObject(rawResponse, AccessTokenResponse.class);
    log.info("getAccessToken:response={}", response);
    if (response.isSuccess()) {
      redisCache.setCache(RedisCacheKeys.getWxAccessTokenKey(appId), 7000, response.getAcessToken());
      return response.getAcessToken();
    }
    return null;
  }


  @Override
  public String getSessionKey(String openId) {
    RedisCache redisCache = RedisCache.getInstance();
    String key = RedisCacheKeys.getWxSessionKeyKey(openId);
    String sessionKey = redisCache.getCache(key);
    return sessionKey;
  }
}

用到的解密工具类

public class Sha1Utils {
  public static String decryptWXAppletInfo(String sessionKey, String encryptedData, String iv) {
    String result = null;
    try {
      byte[] encrypData = base64.decodebase64(encryptedData);
      byte[] ivData = base64.decodebase64(iv);
      byte[] sessionKeyB = base64.decodebase64(sessionKey);

      AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      SecretKeySpec keySpec = new SecretKeySpec(sessionKeyB, "AES");
      cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
      byte[] doFinal = cipher.doFinal(encrypData);
      result = new String(doFinal);
      return result;
    } catch (Exception e) {
      //e.printStackTrace();
      log.error("decryptWXAppletInfo error",e);
    }
    return null;
  }

}

网络请求工具类

public class HttpClientUtil {

  // utf-8字符编码
  public static final String     CHARSET_UTF_8     = "utf-8";

  // HTTP内容类型。
  public static final String     CONTENT_TYPE_TEXT_HTML = "text/xml";

  // HTTP内容类型。相当于form表单的形式,提交数据
  public static final String     CONTENT_TYPE_FORM_URL = "application/x-www-form-urlencoded";

  // HTTP内容类型。相当于form表单的形式,提交数据
  public static final String     CONTENT_TYPE_JSON_URL = "application/json;charset=utf-8";

  // 连接管理器
  private static PoolingHttpClientConnectionManager pool;

  // 请求配置
  private static volatile RequestConfig requestConfig;

  private static CloseableHttpClient getNewHttpClient() {

    CloseableHttpClient httpClient = HttpClients.custom()
      // 设置连接池管理
      .setConnectionManager(pool)
      // 设置请求配置
      .setDefaultRequestConfig(getRequestConfig())
      // 设置重试次数
      .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();

    return httpClient;
  }

  
  public static String post(String httpUrl) {
    // 创建httpPost
    HttpPost httpPost = new HttpPost(httpUrl);
    return request(httpPost);
  }

  public static byte[] postRaw(String httpUrl) {
    // 创建httpPost
    HttpPost httpPost = new HttpPost(httpUrl);
    return requestRaw(httpPost);
  }

  
  public static String get(String httpUrl) {
    // 创建get请求
    HttpGet httpGet = new HttpGet(httpUrl);
    return request(httpGet);
  }

  
  public static String post(String httpUrl, Map maps, List fileLists,
 String fileName) {
    HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
    MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();
    if (maps != null) {
      for (String key : maps.keySet()) {
 meBuilder.addPart(key, new StringBody(maps.get(key), ContentType.TEXT_PLAIN));
      }
    }
    if (fileLists != null) {
      for (File file : fileLists) {
 FileBody fileBody = new FileBody(file);
 meBuilder.addPart(fileName, fileBody);
      }
    }
    HttpEntity reqEntity = meBuilder.build();
    httpPost.setEntity(reqEntity);
    return request(httpPost);
  }

  public static String post(String httpUrl, Map maps, List fileLists) {
    return post(httpUrl, maps, fileLists, "file");
  }

  public static String post(String httpUrl, List fileLists) {
    return post(httpUrl, Collections.emptyMap(), fileLists, "file");
  }

  
  public static String post(String httpUrl, String params) {
    HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
    try {
      // 设置参数
      if (params != null && params.trim().length() > 0) {
 StringEntity stringEntity = new StringEntity(params, "UTF-8");
 stringEntity.setContentType(CONTENT_TYPE_FORM_URL);
 httpPost.setEntity(stringEntity);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return request(httpPost);
  }

  
  public static String post(String httpUrl, Map maps) {
    String param = convertStringParamter(maps);
    return post(httpUrl, param);
  }



  
  public static String post(String httpUrl, String content, String contentType) {
    //    HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
    //    try {
    //      // 设置参数
    //      if (StringUtils.isNotEmpty(content)) {
    // StringEntity stringEntity = new StringEntity(content, "UTF-8");
    // stringEntity.setContentType(contentType);
    // httpPost.setEntity(stringEntity);
    //      }
    //    } catch (Exception e) {
    //      e.printStackTrace();
    //    }
    //    return request(httpPost);
    return new String(postRaw(httpUrl, content, contentType), StandardCharsets.UTF_8);
  }

  public static byte[] postRaw(String httpUrl, String content, String contentType) {
    HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
    try {
      // 设置参数
      if (StringUtils.isNotEmpty(content)) {
 StringEntity stringEntity = new StringEntity(content, "UTF-8");
 stringEntity.setContentType(contentType);
 httpPost.setEntity(stringEntity);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return requestRaw(httpPost);
  }

  
  public static String postJson(String httpUrl, String paramsJson) {
    return post(httpUrl, paramsJson, CONTENT_TYPE_JSON_URL);
  }

  public static byte[] postJsonRaw(String httpUrl, String paramsJson) {
    return postRaw(httpUrl, paramsJson, CONTENT_TYPE_JSON_URL);
  }

  
  public static String postXml(String url, String paramsXml) {
    return post(url, paramsXml, CONTENT_TYPE_TEXT_HTML);
  }

  
  public static String convertStringParamter(Map parameterMap) {
    StringBuilder parameterBuffer = new StringBuilder();
    if (parameterMap != null) {
      Iterator iterator = parameterMap.keySet().iterator();
      String key = null;
      String value = null;
      while (iterator.hasNext()) {
 key = (String) iterator.next();
 if (parameterMap.get(key) != null) {
   value = (String) parameterMap.get(key);
 } else {
   value = "";
 }
 parameterBuffer.append(key).append("=").append(value);
 if (iterator.hasNext()) {
   parameterBuffer.append("&");
 }
      }
    }
    return parameterBuffer.toString();
  }

  
  public static byte[] requestRaw(HttpRequestbase request) {

    CloseableHttpClient httpClient;
    CloseableHttpResponse response = null;
    // 响应内容
    //    String responseContent = null;
    byte[] rawResponse = null;
    try {
      // 创建默认的httpClient实例.
      httpClient = getNewHttpClient();
      // 配置请求信息
      request.setConfig(requestConfig);
      // 执行请求
      response = httpClient.execute(request);
      // 得到响应实例
      HttpEntity entity = response.getEntity();

      // 可以获得响应头
      // Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);
      // for (Header header : headers) {
      // System.out.println(header.getName());
      // }

      // 得到响应类型
      // System.out.println(ContentType.getOrDefault(response.getEntity()).getMimeType());

      // 判断响应状态
      if (response.getStatusLine().getStatusCode() >= 300) {
 throw new Exception("HTTP Request is not success, Response code is "
    + response.getStatusLine().getStatusCode());
      }

      if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
 rawResponse = EntityUtils.toByteArray(entity);
 // responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);
 EntityUtils.consume(entity);
      }

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
 // 释放资源
 if (response != null) {
   response.close();
 }
      } catch (IOException e) {
 e.printStackTrace();
      }
    }
    return rawResponse;
  }

  private static String request(HttpRequestbase req) {
    return new String(requestRaw(req), StandardCharsets.UTF_8);
  }

  private static RequestConfig getRequestConfig() {

    if (requestConfig == null) {
      synchronized (HttpClientUtil.class) {
 if (requestConfig == null) {
   try {
     //System.out.println("初始化HttpClientTest~~~开始");
     SSLContextBuilder builder = new SSLContextBuilder();
     builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
     SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
builder.build());
     // 配置同时支持 HTTP 和 HTPPS
     Registry socketFactoryRegistry = RegistryBuilder
. create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslsf).build();
     // 初始化连接管理器
     pool = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
     // 将最大连接数增加到200,实际项目最好从配置文件中读取这个值
     pool.setMaxTotal(200);
     // 设置最大路由
     pool.setDefaultMaxPerRoute(2);
     // 根据默认超时限制初始化requestConfig
     int socketTimeout = 10000;
     int connectTimeout = 10000;
     int connectionRequestTimeout = 10000;
     requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(connectionRequestTimeout)
.setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout)
.build();

   } catch (NoSuchAlgorithmException e) {
     e.printStackTrace();
   } catch (KeyStoreException e) {
     e.printStackTrace();
   } catch (KeyManagementException e) {
     e.printStackTrace();
   }

   // 设置请求超时时间
   requestConfig = RequestConfig.custom().setSocketTimeout(50000)
     .setConnectTimeout(50000).setConnectionRequestTimeout(50000).build();
 }
      }
    }
    return requestConfig;
  }
}

常量

public interface WechatConstant {
  Integer OK_STATUS      = 0;
  String URL_CODE2SESSION   = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";


  String URL_GET_ACCESS_TOKEN   = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";


  String URL_GET_IMAGE = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s";
  
  
  
  String URL_SEND_TO_CHANNEL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
  String URL_SEND_MESSAGE   = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s";
  
  
  String URL_SEND_TEMPLATE_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=%s";

  String URL_QR_CODE_UNLIMTED = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s";
  
  String URL_QR_CODE = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%s";

  
  String URL_ALL_FANS_OPENID = "https://api.weixin.qq.com/cgi-bin/user/tag/get?access_token=%s";
  
  String URL_ALL_TAGS = "https://api.weixin.qq.com/cgi-bin/tags/get?access_token=%s";

}

使用到的实体类

public class Code2SessionResponse implements Serializable {
  public static Integer RESPONSE_OK = 0;

  @JSonField(name = "openid")
  private String    openId;
  @JSonField(name = "session_key")
  private String    sessionKey;
  @JSonField(name = "unionid")
  private String    unionId;
  @JSonField(name = "errcode")
  private Integer   errCode;
  @JSonField(name = "errmsg")
  private String   errMsg;



  public boolean isSuccess() {
    return this.errCode == null || RESPONSE_OK.equals(this.errCode);
  }
}

总结:微信小程序的后端开发主要就是对用户进行授权 , 1、前端调用 wx.login 返回了code,然后调用wx.getUserInfo获取到用户的昵称 头像 2.首先通过微信授权用js_code换取openId,来获取openId,前端传微信的参数 code字段 3.然后解密获取手机号 前端需要传openId encryptedData iv 等字段来获取用户的的授权手机号

这些信息都获取后 接着就是调用后端的登陆接口,登陆接口如果只有授权登录就是我们将接口参数为下图最后三个字段为前端必填字段

 

主要步骤是根据前端的openId获取sessionKey 然后根据sessionKey 和其他参数进行解密获取用户手机号

通过解密获取授权登录的手机号,然后根据自己的业务逻辑处理即可,这样我们就可以根据授权的手机号进行授权登录

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/72439.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号