Uniapp + SpringBoot는 WeChat H5 프로젝트를 개발하고 WeChat 공개 계정에 JAVA 백엔드에 로그인할 수 있는 권한을 부여합니다. (1. WeChat 공개 플랫폼을 구성 및 사용하여 공개 계정을 테스트합니다.)

디버깅 및 개발을 위한 테스트 계정을 신청하세요. 테스트 계정에는 대부분의 서비스 계정의 인터페이스 권한이 있습니다.

1. 인터페이스 구성 정보를 입력하고 확인합니다.

여기에는 URL과 토큰 확인 문자열을 입력해야 합니다.
저는 natapp 인트라넷 침투를 사용하여 로컬 백엔드 8080 포트 서비스를 natapp 공식 웹사이트의 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;
    }
}

검증이 완료되면 테스트 계정의 웹페이지 서비스에서 웹페이지 인증을 구성하여 기본 사용자를 획득합니다.
여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

여기에는 실행 후 프론트엔드 프로젝트의 주소를 입력합니다.제 백엔드 프로젝트 포트는 8080입니다.uniapp 프론트엔드 실행 후 포트는 8081이므로 로컬 ipv4 ip + 포트 번호를 구성했습니다.

2. 백엔드 설정 + URL 조합 + Code를 통해 사용자 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을 작성하는 한 단계만 수행합니다. 구성이 완료되면 프런트 엔드로 돌아갑니다. 프런트 엔드는 세 가지를 직접 리디렉션합니다
. buildAuthorizationUrl의 매개변수
첫 번째는 콜백 주소입니다.
두 번째는 채워집니다. 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. 유니앱 프론트엔드 콜

프론트엔드에서는 먼저 /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>

추천

출처blog.csdn.net/qq_43193513/article/details/136558126