Uniapp + SpringBoot は WeChat H5 プロジェクトを開発し、WeChat パブリック アカウントが JAVA バックエンドにログインできるようにします (1. WeChat パブリック プラットフォームを構成して使用し、パブリック アカウントをテストします)

デバッグと開発用のテスト アカウントを申請します。テスト アカウントには、ほとんどのサービス アカウントのインターフェイス権限が与えられます。

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>

おすすめ

転載: blog.csdn.net/qq_43193513/article/details/136558126