mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-11-04 06:07:59 +08:00 
			
		
		
		
	#515 小程序新增获取微信用户绑定手机号信息的解密方法
This commit is contained in:
		@ -1,6 +1,7 @@
 | 
				
			|||||||
package cn.binarywang.wx.miniapp.api;
 | 
					package cn.binarywang.wx.miniapp.api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 | 
				
			||||||
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
 | 
				
			||||||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 | 
				
			||||||
import me.chanjar.weixin.common.exception.WxErrorException;
 | 
					import me.chanjar.weixin.common.exception.WxErrorException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,6 +28,15 @@ public interface WxMaUserService {
 | 
				
			|||||||
   */
 | 
					   */
 | 
				
			||||||
  WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr);
 | 
					  WxMaUserInfo getUserInfo(String sessionKey, String encryptedData, String ivStr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * 解密用户手机号信息.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param sessionKey    会话密钥
 | 
				
			||||||
 | 
					   * @param encryptedData 消息密文
 | 
				
			||||||
 | 
					   * @param ivStr         加密算法的初始向量
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * 验证用户信息完整性.
 | 
					   * 验证用户信息完整性.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,13 @@
 | 
				
			|||||||
package cn.binarywang.wx.miniapp.api.impl;
 | 
					package cn.binarywang.wx.miniapp.api.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.apache.commons.codec.digest.DigestUtils;
 | 
					import org.apache.commons.codec.digest.DigestUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.binarywang.wx.miniapp.api.WxMaService;
 | 
					import cn.binarywang.wx.miniapp.api.WxMaService;
 | 
				
			||||||
import cn.binarywang.wx.miniapp.api.WxMaUserService;
 | 
					import cn.binarywang.wx.miniapp.api.WxMaUserService;
 | 
				
			||||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 | 
				
			||||||
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
 | 
				
			||||||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 | 
				
			||||||
import cn.binarywang.wx.miniapp.config.WxMaConfig;
 | 
					 | 
				
			||||||
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
 | 
					import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
 | 
				
			||||||
import com.google.common.base.Joiner;
 | 
					 | 
				
			||||||
import me.chanjar.weixin.common.exception.WxErrorException;
 | 
					import me.chanjar.weixin.common.exception.WxErrorException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -34,6 +30,11 @@ public class WxMaUserServiceImpl implements WxMaUserService {
 | 
				
			|||||||
    return WxMaUserInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr));
 | 
					    return WxMaUserInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public WxMaPhoneNumberInfo getPhoneNoInfo(String sessionKey, String encryptedData, String ivStr) {
 | 
				
			||||||
 | 
					    return WxMaPhoneNumberInfo.fromJson(WxMaCryptUtils.decrypt(sessionKey, encryptedData, ivStr));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public boolean checkUserInfo(String sessionKey, String rawData, String signature) {
 | 
					  public boolean checkUserInfo(String sessionKey, String rawData, String signature) {
 | 
				
			||||||
    final String generatedSignature = DigestUtils.sha1Hex(rawData + sessionKey);
 | 
					    final String generatedSignature = DigestUtils.sha1Hex(rawData + sessionKey);
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package cn.binarywang.wx.miniapp.bean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.Serializable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder;
 | 
				
			||||||
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 微信用户绑定的手机号相关信息
 | 
				
			||||||
 | 
					 * @author <a href="https://github.com/binarywang">Binary Wang</a>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Data
 | 
				
			||||||
 | 
					public class WxMaPhoneNumberInfo implements Serializable {
 | 
				
			||||||
 | 
					  private static final long serialVersionUID = 6719822331555402137L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private String phoneNumber;
 | 
				
			||||||
 | 
					  private String purePhoneNumber;
 | 
				
			||||||
 | 
					  private String countryCode;
 | 
				
			||||||
 | 
					  private Watermark watermark;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public static WxMaPhoneNumberInfo fromJson(String json) {
 | 
				
			||||||
 | 
					    return WxMaGsonBuilder.create().fromJson(json, WxMaPhoneNumberInfo.class);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Data
 | 
				
			||||||
 | 
					  public static class Watermark {
 | 
				
			||||||
 | 
					    private String timestamp;
 | 
				
			||||||
 | 
					    private String appid;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,14 +1,14 @@
 | 
				
			|||||||
package cn.binarywang.wx.miniapp.api.impl;
 | 
					package cn.binarywang.wx.miniapp.api.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.testng.annotations.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.binarywang.wx.miniapp.api.WxMaService;
 | 
					import cn.binarywang.wx.miniapp.api.WxMaService;
 | 
				
			||||||
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
 | 
				
			||||||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 | 
					import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 | 
				
			||||||
import cn.binarywang.wx.miniapp.test.ApiTestModule;
 | 
					import cn.binarywang.wx.miniapp.test.ApiTestModule;
 | 
				
			||||||
import com.google.inject.Inject;
 | 
					import com.google.inject.Inject;
 | 
				
			||||||
import org.testng.annotations.Guice;
 | 
					 | 
				
			||||||
import org.testng.annotations.Test;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.testng.Assert.assertNotNull;
 | 
					import static org.testng.Assert.*;
 | 
				
			||||||
import static org.testng.Assert.assertTrue;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 测试用户相关的接口
 | 
					 * 测试用户相关的接口
 | 
				
			||||||
@ -28,7 +28,7 @@ public class WxMaUserServiceImplTest {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Test
 | 
					  @Test
 | 
				
			||||||
  public void testGetUserInfo() throws Exception {
 | 
					  public void testGetUserInfo() {
 | 
				
			||||||
    WxMaUserInfo userInfo = this.wxService.getUserService().getUserInfo("tiihtNczf5v6AKRyjwEUhQ==",
 | 
					    WxMaUserInfo userInfo = this.wxService.getUserService().getUserInfo("tiihtNczf5v6AKRyjwEUhQ==",
 | 
				
			||||||
      "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==",
 | 
					      "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==",
 | 
				
			||||||
      "r7BXXKkLb8qrSNn05n0qiA==");
 | 
					      "r7BXXKkLb8qrSNn05n0qiA==");
 | 
				
			||||||
@ -37,10 +37,21 @@ public class WxMaUserServiceImplTest {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Test
 | 
					  @Test
 | 
				
			||||||
  public void testCheckUserInfo() throws Exception {
 | 
					  public void testCheckUserInfo() {
 | 
				
			||||||
    assertTrue(this.wxService.getUserService().checkUserInfo("HyVFkGl5F5OQWJZZaNzBBg==",
 | 
					    assertTrue(this.wxService.getUserService().checkUserInfo("HyVFkGl5F5OQWJZZaNzBBg==",
 | 
				
			||||||
      "{\"nickName\":\"Band\",\"gender\":1,\"language\":\"zh_CN\",\"city\":\"Guangzhou\",\"province\":\"Guangdong\",\"country\":\"CN\",\"avatarUrl\":\"http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0\"}",
 | 
					      "{\"nickName\":\"Band\",\"gender\":1,\"language\":\"zh_CN\",\"city\":\"Guangzhou\",\"province\":\"Guangdong\",\"country\":\"CN\",\"avatarUrl\":\"http://wx.qlogo.cn/mmopen/vi_32/1vZvI39NWFQ9XM4LtQpFrQJ1xlgZxx3w7bQxKARol6503Iuswjjn6nIGBiaycAjAtpujxyzYsrztuuICqIM5ibXQ/0\"}",
 | 
				
			||||||
      "75e81ceda165f4ffa64f4068af58c64b8f54b88c"));
 | 
					      "75e81ceda165f4ffa64f4068af58c64b8f54b88c"));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * TODO 测试数据有问题,需要替换为正确的数据
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  public void testGetPhoneNoInfo() {
 | 
				
			||||||
 | 
					    WxMaPhoneNumberInfo phoneNoInfo = this.wxService.getUserService().getPhoneNoInfo("tiihtNczf5v6AKRyjwEUhQ==",
 | 
				
			||||||
 | 
					      "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==",
 | 
				
			||||||
 | 
					      "r7BXXKkLb8qrSNn05n0qiA==");
 | 
				
			||||||
 | 
					    assertNotNull(phoneNoInfo);
 | 
				
			||||||
 | 
					    System.out.println(phoneNoInfo.toString());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user