Demandez un compte de test pour le débogage et le développement. Le compte de test dispose des autorisations d'interface de la plupart des comptes de service.
1. Remplissez et vérifiez les informations de configuration de l'interface
Ici, vous devez remplir une URL et une chaîne de vérification du jeton.
J'ai utilisé la pénétration intranet de Natapp pour mapper le service de port 8080 du backend local sur http://x7zws8.natappfree.cc
https://natapp.cn/ sur le site officiel de Natapp. Enregistrez un compte et demandez un tunnel gratuit.
Après avoir postulé, liez le nom de domaine à votre propre
interface backend :
@RequestMapping(value = "/check", produces = "text/plain;charset=UTF-8", method = {
RequestMethod.GET, RequestMethod.POST})
//微信服务器根据配置的token,结合时间戳timestamp和随机数nonce通过SHA1生成签名,发起get请求,检验token的正确性,
//检验正确原样返回随机字符串echostr,失败返回空字符串
public String check(HttpServletRequest request, HttpServletResponse response,
@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
String echostr) throws Exception {
//若是为get请求,则为开发者模式验证
if ("get".equals(request.getMethod().toLowerCase())) {
String checkSignature = SHA1.creatSHA1("token", timestamp, nonce);
if (checkSignature.equals(signature)) {
return echostr;
}
}
return null;
}
SHA1 :
import java.security.MessageDigest;
import java.util.Arrays;
//SHA1加密算法类
public class SHA1 {
/**
*
* @param token
* @param timestamp 时间戳
* @param nonce 随机字符串
* @return 安全签名
* @throws AesException
*/
public static String creatSHA1(String token, String timestamp, String nonce) throws AesException
{
try {
String[] array = new String[] {
token, timestamp, nonce};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 3; i++) {
sb.append(array[i]);
}
String str = sb.toString();
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
return hexstr.toString();
} catch (Exception e) {
e.printStackTrace();
throw new AesException(AesException.ComputeSignatureError);
}
}
}
AesException:
public class AesException extends Exception {
public final static int OK = 0;
public final static int ValidateSignatureError = -40001;
public final static int ParseXmlError = -40002;
public final static int ComputeSignatureError = -40003;
public final static int IllegalAesKey = -40004;
public final static int ValidateAppidError = -40005;
public final static int EncryptAESError = -40006;
public final static int DecryptAESError = -40007;
public final static int IllegalBuffer = -40008;
private int code;
private static String getMessage(int code) {
switch (code) {
case ValidateSignatureError:
return "签名验证错误";
case ParseXmlError:
return "xml解析失败";
case ComputeSignatureError:
return "sha加密生成签名失败";
case IllegalAesKey:
return "SymmetricKey非法";
case ValidateAppidError:
return "appid校验失败";
case EncryptAESError:
return "aes加密失败";
case DecryptAESError:
return "aes解密失败";
case IllegalBuffer:
return "解密后得到的buffer非法";
default:
return null; // cannot be
}
}
public int getCode() {
return code;
}
public AesException(int code) {
super(getMessage(code));
this.code = code;
}
}
Une fois la vérification terminée, configurez l'autorisation de la page Web sous le service de page Web dans le compte de test pour obtenir l'utilisateur de base
Remplissez ici l'adresse de votre projet front-end après l'exécution. Le port de mon projet back-end est 8080. Une fois le front-end uniapp exécuté, le port est 8081, j'ai donc configuré l'adresse IP ipv4 locale + le numéro de port.
2. Configuration du backend + Assemblage de l'URL + Obtention de l'OpenID de l'utilisateur et des informations de base via le code
Introduire des dépendances dans le pom du projet SpringBoot
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.6.0</version>
</dependency>
Créer une classe de configuration
import com.ruoyi.system.domain.WechatConfig;
import com.ruoyi.system.service.IWechatConfigService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WxMpConfig {
@Autowired
private IWechatConfigService wechatConfigService;
@Bean
public WxMpConfigStorage wxMpConfigStorage() {
WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
WechatConfig wechatConfig = wechatConfigService.selectWechatConfigById(1L);
//我这里是做成了获取数据库中保存的AppID和AppSercret正常情况下写死就可以
configStorage.setAppId(wechatConfig.getAppId());
configStorage.setSecret(wechatConfig.getAppSecret());
return configStorage;
}
@Bean
public WxMpService wxMpService(WxMpConfigStorage configStorage) {
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(configStorage);
return wxMpService;
}
}
Après cela, vous pouvez l'utiliser normalement dans le contrôleur.
L'interface /authorize ne fait en fait qu'une seule étape : construire l'url pour obtenir le code. Une fois la construction terminée, elle retourne au front-end. Le front-end redirige directement les
trois paramètres de buildAuthorizationUrl.
Le premier est l'adresse de rappel.
Le second est renseigné. snsapi_base ou snsapi_userinfo
snsapi_base peut obtenir l'openid, tandis que snsapi_userinfo peut obtenir les informations de base de l'utilisateur.
snsapi_base peut être obtenu silencieusement, tandis que snsapi_userinfo demande à l'utilisateur de cliquer pour autorisation.
@RestController
@RequestMapping("/wx")
public class WeChatController extends BaseController {
@GetMapping("/authorize")
public AjaxResult test() {
WxOAuth2Service oAuth2Service = wxMpService.getOAuth2Service();
String redirectUrl = oAuth2Service.buildAuthorizationUrl("http://192.168.1.100:8081", "snsapi_userinfo", null);
return success(redirectUrl);
}
@GetMapping("/userInfo")
public AjaxResult userInfo(@RequestParam("code") String code) throws WxErrorException {
WxOAuth2Service oAuth2Service = wxMpService.getOAuth2Service();
WxOAuth2AccessToken wxMpOAuth2AccessToken = oAuth2Service.getAccessToken(code);
logger.info("【wxMpOAuth2AccessToken:】{}", wxMpOAuth2AccessToken);
String openId = wxMpOAuth2AccessToken.getOpenId();
logger.info("【openid:】{}", openId);
WxOAuth2UserInfo userInfo = oAuth2Service.getUserInfo(wxMpOAuth2AccessToken, "zh_CN");
logger.info("【用户信息:】{}", userInfo.toString());
return success(userInfo);
}
}
2. Appel frontal Uniapp
Le frontal appelle d'abord /authorize pour obtenir l'adresse assemblée, puis redirige et obtient le code
getUrlCode pour déterminer si l'adresse contient du code. Si tel est le cas, utilisez le code pour obtenir les informations de base et l'openid de l'utilisateur.
<template>
<view class="content">
<image class="logo" :src="loginUser.headImgUrl ? loginUser.headImgUrl : '/static/logo.png'"></image>
<view class="text-area">
<text class="title">{
{
loginUser.openid}}</text>
</view>
<button type="default" @click="login">登录</button>
</view>
</template>
<script>
export default {
data() {
return {
loginUser:{
}
}
},
onLoad(query) {
const that = this;
let code = that.getUrlCode();
if (code) {
console.log("有code")
console.log(code)
uni.request({
url: "http://192.168.1.100:8080/wx/userInfo",
data: {
code: code
},
success(res) {
console.log("获取到用户信息")
console.log(res.data.data);
that.loginUser = res.data.data;
}
})
} else {
console.log("没有code")
}
},
methods: {
login() {
uni.request({
url: "http://192.168.1.100:8080/wx/authorize",
success(res) {
window.location.href = res.data.msg;
}
})
},
getUrlCode() {
return (
decodeURIComponent(
(new RegExp("[?|&]" + "code" + "=" + "([^&;]+?)(&|#|;|$)").exec(
location.href
) || [, ""])[1].replace(/\+/g, "%20")
) || null
);
},
}
}
</script>