デバッグと開発用のテスト アカウントを申請します。テスト アカウントには、ほとんどのサービス アカウントのインターフェイス権限が与えられます。
1. インターフェース構成情報を入力して確認します。
ここで URL とトークン検証文字列を入力する必要があります。
私は natapp イントラネット ペネトレーションを使用して、ローカル バックエンド 8080 ポート サービスをnatapp 公式 Web サイトのhttp://x7zws8.natappfree.cc
https://natapp.cn/にマッピングしました。アカウントを登録し、無料のトンネルを申請します。
申請後、ドメイン名を独自のバックエンド
バックエンド インターフェイスにバインドします。
@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);
}
}
}
Aes例外:
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;
}
}
検証が完了したら、テスト アカウントの Web ページ サービスで Web ページの認証を構成し、基本ユーザーを取得します。
ここに、実行後のフロントエンド プロジェクトのアドレスを入力します。バックエンド プロジェクトのポートは 8080 です。uniapp フロントエンドの実行後、ポートは 8081 なので、ローカル ipv4 ip + ポート番号を構成しました。
2. バックエンド設定 + URL の組み立て + コードを介したユーザー OpenID と基本情報の取得
SpringBoot プロジェクトの pom に依存関係を導入します。
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.6.0</version>
</dependency>
構成クラスの作成
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;
}
}
その後、コントローラーで通常どおり使用できます。/authorize
インターフェイスは、実際には、コードを取得するための URL の構築という 1 つのステップだけを実行します。構築が完了すると、フロントエンドに戻ります。フロントエンドは、3 つの URL を直接リダイレクトします
。 buildAuthorizationUrl のパラメーター。
最初のアドレスはコールバック アドレスです。2
番目のアドレスは入力されます。 snsapi_base または snsapi_userinfo
snsapi_base は openid を取得できますが、snsapi_userinfo は基本的なユーザー情報を取得できます。
snsapi_base はサイレントに取得できますが、snsapi_userinfo はユーザーのクリックが必要です認可のため。
@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. Uniapp フロントエンド呼び出し
フロントエンドは、最初に /authorize を呼び出して組み立てられたアドレスを取得し、次にリダイレクトしてコード
getUrlCode を取得して、アドレスにコードが含まれているかどうかを判断します。含まれている場合は、そのコードを使用してユーザーの基本情報と openid を取得します。
<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>