之前編寫小程式獲取手機號相關的程式碼均為自行封裝,最近發現了 WxJava 的存在,方便了開發。
本篇文章將講解如何使用WxJava進行手機號的獲取。
舊版本微信介面官方文件
思路
需要將 button 元件 open-type
的值設定為 getPhoneNumber
,當使用者點選並同意之後,可以透過 bindgetphonenumber
事件回撥獲取到微信伺服器返回的加密資料, 然後在第三方服務端結合 session_key
以及 app_id
進行解密獲取手機號。
總結為以下兩個步驟:
- 透過使用 button getPhoneNumber 可獲取到 返回的加密資料。
- 然後將加密資料結合 session_key 以及 app_id 進行解密獲取手機號。
因此想要獲得使用者的手機號,我們需要傳入 session_key, app_id 以及 前端呼叫微信伺服器返回的加密資料。
- 如何獲取 session_key 和 app_id 呢?
前端獲取jsCode後並呼叫 auth.code2Session 介面即可。
因此我們只需要將 jsCode 以及 加密資料 傳給介面即可。
整體思路總結
- 前端給後端傳遞 jsCode,加密資料引數(iv,encryptedData)。
- 然後使用 jsCode,繫結的 appId 以及 appSecret 呼叫 auth.code2Session 介面 獲取到 session_key,app_id 。
- 使用 session_key,app_id 對加密資料進行解密獲取到使用者手機號。
程式碼實現
這裡使用了 wxjava。因此程式碼非常的簡潔。我們只需要理解整體的思路就好了。
整體架構
wxMaConfigration
/**
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/@Slf4j
@Configuration
@EnableConfigurationProperties(WxMaProperties.class)
public class WxMaConfiguration {
private final WxMaProperties properties;
@Autowired
public WxMaConfiguration(WxMaProperties properties) {
this.properties = properties;
}
@Bean
public WxMaService wxMaService() {
List<WxMaProperties.Config> configs = this.properties.getConfigs();
if (configs == null) {
throw new WxRuntimeException("大哥,拜託先看下專案首頁的說明(readme檔案),新增下相關配置,注意別配錯了!");
}
WxMaService maService = new WxMaServiceImpl();
maService.setMultiConfigs(
configs.stream()
.map(a -> {
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
// WxMaDefaultConfigImpl config = new WxMaRedisConfigImpl(new JedisPool());
// 使用上面的配置時,需要同時引入jedis-lock的依賴,否則會報類無法找到的異常
config.setAppid(a.getAppid());
config.setSecret(a.getSecret());
config.setToken(a.getToken());
config.setAesKey(a.getAesKey());
config.setMsgDataFormat(a.getMsgDataFormat());
return config;
}).collect(Collectors.toMap(WxMaDefaultConfigImpl::getAppid, a -> a, (o, n) -> o)));
return maService;
}
@Bean
public WxMaMessageRouter wxMaMessageRouter(WxMaService wxMaService) {
final WxMaMessageRouter router = new WxMaMessageRouter(wxMaService);
router
.rule().handler(logHandler).next()
.rule().async(false).content("訂閱訊息").handler(subscribeMsgHandler).end()
.rule().async(false).content("文字").handler(textHandler).end()
.rule().async(false).content("圖片").handler(picHandler).end()
.rule().async(false).content("二維碼").handler(qrcodeHandler).end();
return router;
}
private final WxMaMessageHandler subscribeMsgHandler = (wxMessage, context, service, sessionManager) -> {
service.getMsgService().sendSubscribeMsg(WxMaSubscribeMessage.builder()
.templateId("此處更換為自己的模板id")
.data(Lists.newArrayList(
new WxMaSubscribeMessage.MsgData("keyword1", "339208499")))
.toUser(wxMessage.getFromUser())
.build());
return null;
};
private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
log.info("收到訊息:" + wxMessage.toString());
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到資訊為:" + wxMessage.toJson())
.toUser(wxMessage.getFromUser()).build());
return null;
};
private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> {
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回覆文字訊息")
.toUser(wxMessage.getFromUser()).build());
return null;
};
private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
try {
WxMediaUploadResult uploadResult = service.getMediaService()
.uploadMedia("image", "png",
ClassLoader.getSystemResourceAsStream("tmp.png"));
service.getMsgService().sendKefuMsg(
WxMaKefuMessage
.newImageBuilder()
.mediaId(uploadResult.getMediaId())
.toUser(wxMessage.getFromUser())
.build());
} catch (WxErrorException e) {
e.printStackTrace();
}
return null;
};
private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
try {
final File file = service.getQrcodeService().createQrcode("123", 430);
WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
service.getMsgService().sendKefuMsg(
WxMaKefuMessage
.newImageBuilder()
.mediaId(uploadResult.getMediaId())
.toUser(wxMessage.getFromUser())
.build());
} catch (WxErrorException e) {
e.printStackTrace();
}
return null;
};
}
wxMaProperties
@Data
@ConfigurationProperties(prefix = "wx.miniapp")
public class WxMaProperties {
private List<Config> configs;
@Data
public static class Config {
/**
* 設定微信小程式的appid
*/ private String appid;
/**
* 設定微信小程式的Secret
*/ private String secret;
/**
* 設定微信小程式訊息伺服器配置的token
*/ private String token;
/**
* 設定微信小程式訊息伺服器配置的EncodingAESKey
*/ private String aesKey;
/**
* 訊息格式,XML或者JSON
*/ private String msgDataFormat;
}
}
wxcontroller
@RestController
@RequestMapping("/wx")
@AllArgsConstructor
public class WxController {
private final WxMaService wxMaService;
@PostMapping("/decrypt")
public JSONObject decrypt(@RequestBody AuthDto authDto) throws WxErrorException {
WxMaJscode2SessionResult wxMaJscode2SessionResult = new WxMaJscode2SessionResult();
try{
wxMaJscode2SessionResult = wxMaService.jsCode2SessionInfo(authDto.getJsCode());
}
catch (Exception e){
throw e;
}
WxMaPhoneNumberInfo phoneNumberInfo = wxMaService.getUserService().getPhoneNoInfo(wxMaJscode2SessionResult.getSessionKey(),authDto.getEncryptedData(), authDto.getIv());
JSONObject result = new JSONObject();
HashMap<String,Object> resultMap = new HashMap<>();
resultMap.put("data",phoneNumberInfo);
result.put("result",resultMap);
return result;
}
}
application.yml
wx:
miniapp:
configs:
appid: '自己的小程式appid'
secret: 'appsecret'
token: #微信小程式訊息伺服器配置的token
aesKey: #微信小程式訊息伺服器配置的EncodingAESKey
msgDataFormat: JSON
本作品採用《CC 協議》,轉載必須註明作者和本文連結