MiniProgram获取用户信息(java后台获取)

流程梳理:

code - 请求微信接口 - 获得session_key - AES解密 - 获得信息

小程序端通过open-tye(具体百度),用户授权后,返回code,iv,encrypteData传参到后台,通过微信小程序接口(https://api.weixin.qq.com/sns/jscode2session?appId=" + xgxAppid + "&secret=" + xgxSecret + "&js_code=" + code + "&grant_type=" + grant_type)请求微信,获取会话密钥(session_key),通过AES对称解密(

AesMiniProgramUtil.decrypt(encryptedData, session_key, iv, "UTF-8")

),获得用户基本信息

 

小坑:

code得有效期为5分钟。

在开发阶段,创建小程序项目的时候的appId必须和解密时的appId对应,因为获取用户code的时候时通过appid去获取的,得到的加密数据时通过appid加密的,AES解密的时候得对应。并且得设置体验者权限。

上代码:

需要导入的maven

<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>


<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>





接口:

/**
 * 获取小程序用户信息
 *
 * @param codeDto
 * @return
 */
@RequestMapping(value = "miniprogram")
@ResponseBody
@Transactional(readOnly = false)
public Object getMiniProgramUserInfo(HttpServletResponse response, HttpServletRequest request, Model model, @RequestBody WxCodeDto codeDto) {
   //response.setHeader("Access-Control-Allow-Origin", "*");
   try {
      logger.info("miniprogram  WxCodeDto  >>  " + codeDto);
      Map<String, String> unionIdForXgx = WeixinKit.getUnionIdForXgx(codeDto.getEncryptedData(), codeDto.getIv(), codeDto.getCode(), "wx4533db2ce8b7c8ff", "f0037f13c01b49f1ae66d25e8a5df79f");
      logger.info("miniprogram  userinfo   >>  " + unionIdForXgx);
      if(Integer.parseInt(unionIdForXgx.get("status"))==1) {
         return DtoUtils.setSuccess("录入数据成功", unionIdForXgx);
      }else {
         return DtoUtils.setError("解密失败");
      }
   } catch (Exception e) {
      return DtoUtils.setError("请求微信服务端异常");
   }

}


工具类:

import com.alibaba.fastjson.JSONObject;
import com.thinkgem.jeesite.common.mapper.JsonMapper;
import com.thinkgem.jeesite.pc.web.WeiXin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by weck on  2017/2/27
 */
public class WeixinKit {
    /**
     * 日志对象
     */
    protected Logger log = LoggerFactory.getLogger(WeixinKit.class);

    /**
     * 小程序使用授权getUserInfo获取unionID的加密数据,这里是解密操作
     * 官方文档https://developers.weixin.qq.com/miniprogram/dev/api/open.html#wxgetuserinfoobject
     * https://developers.weixin.qq.com/miniprogram/dev/api/signature.html
     * @param encryptedData
     * @param iv
     * @param code
     * @param xgxAppid
     * @param xgxSecret
     * @return
     */
    public static Map<String,String> getUnionIdForXgx(String encryptedData, String iv, String code, String xgxAppid, String xgxSecret)throws Exception {
        Map map = new HashMap();
        if (StringUtils.isNotBlank(encryptedData) && StringUtils.isNotBlank(iv) && StringUtils.isNotBlank(code) && StringUtils.isNotBlank(xgxAppid) && StringUtils.isNotBlank(xgxSecret)) {
            String grant_type = "authorization_code";
            String url = "https://api.weixin.qq.com/sns/jscode2session?appId=" + xgxAppid + "&secret=" + xgxSecret + "&js_code=" + code + "&grant_type=" + grant_type;
            String jsonCode = sendGet(url, null);//请求获得token
            WeiXin resDto = (WeiXin) JsonMapper.fromJsonString(jsonCode, WeiXin.class);//获得json格式,转换实体
            if (resDto!=null) {
                String session_key = resDto.getSession_key();
                try {
                    String result = AesMiniProgramUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
                    if (null != result && result.length() > 0) {
                        JSONObject userInfoJSON = JSONObject.parseObject(result);
                        Map userInfo = new HashMap();
                        userInfo.put("openId", userInfoJSON.get("openId"));
                        userInfo.put("nickName", userInfoJSON.get("nickName"));
                        userInfo.put("gender", userInfoJSON.get("gender"));
                        userInfo.put("city", userInfoJSON.get("city"));
                        userInfo.put("province", userInfoJSON.get("province"));
                        userInfo.put("country", userInfoJSON.get("country"));
                        userInfo.put("avatarUrl", userInfoJSON.get("avatarUrl"));
                        userInfo.put("unionId", userInfoJSON.get("unionId"));

                        map.put("userInfo", userInfo);
                        map.put("status", 1);
                        map.put("msg", "解密成功");
                        return map;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    map.put("status", 0);
                    map.put("msg", "解密失败!");
                    return map;
                }
                map.put("status", 0);
                map.put("msg", "解密失败!");
                return map;
            } else {
                map.put("status", 0);
                map.put("msg", "请求失败,请重试!");
            }
        } else {
            map.put("status", 0);
            map.put("msg", "请上传正确的参数!");
        }
        return map;
    }


    public static String sendGet(String url, String param) throws Exception {
        String result = "";
        BufferedReader in = null;
        try {
            URL realUrl = new URL(url);
            // 打开和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();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
                throw e2;
            }
        }
        return result;
    }

}
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;

/**
 * @author Weck on 2018/06/28
 * 小程序getUserInfo接口加密数据解密工具
 */
public class AesMiniProgramUtil {

    static {
        //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * AES解密
     *
     * @param data           //密文,被加密的数据
     * @param key            //秘钥
     * @param iv             //偏移量
     * @param encodingFormat //解密后的结果需要进行的编码
     * @return
     * @throws Exception
     */
    public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {

        //被加密的数据
        byte[] dataByte = Base64.decodeBase64(data);
        //加密秘钥
        byte[] keyByte = Base64.decodeBase64(key);
        //偏移量
        byte[] ivByte = Base64.decodeBase64(iv);
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, encodingFormat);
                return result;
            }
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

}


DTO:

public class WxCodeDto {
    private String code;
    private String encryptedData;
    private String iv;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getEncryptedData() {
        return encryptedData;
    }

    public void setEncryptedData(String encryptedData) {
        this.encryptedData = encryptedData;
    }

    public String getIv() {
        return iv;
    }

    public void setIv(String iv) {
        this.iv = iv;
    }

    @Override
    public String toString() {
        return "WxCodeDto{" +
                "code='" + code + '\'' +
                ", encryptedData='" + encryptedData + '\'' +
                ", iv='" + iv + '\'' +
                '}';
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值