主頁 > 後端開發 > SoringCloud(四) - 微信獲取用戶資訊

SoringCloud(四) - 微信獲取用戶資訊

2022-10-31 07:07:58 後端開發

1、專案介紹

2、微信公眾平臺 和 微信開放檔案

2.1 微信公眾平臺

2.1.1 網址鏈接

https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

2.1.2 測驗號資訊

2.1.3 微信掃描關注測驗公眾號

2.1.4 授權回呼頁面域名

2.1.4.1 網頁服務->網頁賬號->修改

2.1.4.2 填寫 授權回呼頁面域名

2.1.4.3 內網穿透 NATAPP
2.1.4.3.1 使用教程
NATAPP1分鐘快速新手圖文教程: https://natapp.cn/article/natapp_newbie

下載: https://natapp.cn/#download

使用本地組態檔config.ini: https://natapp.cn/article/config_ini
2.1.4.3.2 authtoken

2.1.4.3.3 授權回呼頁面域名

2.2 微信開放檔案

2.2.1 網址鏈接

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#2

2.2.2 官方 基本步驟教程

1 第一步:用戶同意授權,獲取code

2 第二步:通過 code 換取網頁授權access_token

3 第三步:重繪access_token(如果需要)

4 第四步:拉取用戶資訊(需 scope 為 snsapi_userinfo)

5 附:檢驗授權憑證(access_token)是否有效

3、http請求工具類 HttpClient4Util

HttpClient4Util 用來發http請求;

https://www.cnblogs.com/xiaoqigui/p/16839536.html

4、組態檔 和 配置類

4.1 組態檔

application.yml

#埠
server:
  port: 8096

# 自定義微信授權資訊
wechat:
  auth:
    app-id: wxd4e20add67******   #  appID
    app-secret: a21e97d21d0d6ce408b7a6c******  # appsecret
    code-uri: https://open.weixin.qq.com/connect/oauth2/authorize  # 請求微信官方獲取用戶授權code 的請求地址
    redirect-uri: http://******.natappfree.cc/wechat/auth/codeBack # 微信官方回傳  用戶授權code 的回呼地址
    access-token-uri: https://api.weixin.qq.com/sns/oauth2/access_token # 根據微信回呼的code值,請求微信官方獲取用戶access_token  的請求地址
    user-info-uri: https://api.weixin.qq.com/sns/userinfo #根據用戶的 accessToken 和  openId 拉取用戶資訊  的請求地址

4.2 配置類

//自定義微信授權引數資訊配置類
@Data
@Component
@ConfigurationProperties(prefix = "wechat.auth")
public class WeChatAuthConfig {
    /*
        應用id
     */
    private String appId;
    /*
        應用密鑰
     */
    private String appSecret;
    /*
        請求獲取code的地址
     */
    private String codeUri;
    /*
        微信官方回呼code的地址
     */
    private String redirectUri;
    /**
     * 微信官方獲取access_token地址
     */
    private String accessTokenUri;
    /*
        微信官方獲取userInfo地址
     */
    private String userInfoUri;

}

5、server 層

5.1 微信授權的業務介面

/**
 * Created On : 28/10/2022.
 * <p>
 * Author : huayu
 * <p>
 * Description: 微信授權的業務介面
 */
public interface WeChatAuthService {

    //生成請求微信官方獲取用戶授權code的請求地址
    
    //根據微信回呼的code值,請求微信官方獲取用戶access_token
    
    //根據用戶的 accessToken 和  openId 拉取用戶資訊

}

5.1.1 生成請求微信官方獲取用戶授權code的請求地址

/**
* @author : huayu
* @date   : 28/10/2022
* @param  : []
* @return : java.lang.String
* @description : 生成請求微信官方獲取用戶授權code的請求地址
*/

String generateWeChatAuthCodeUrl();

5.1.2 根據微信回呼的code值,請求微信官方獲取用戶access_token

/**
* @author : huayu
* @date   : 28/10/2022
* @param  : [wechatAuthCode]
* @return : java.lang.String
* @description : 根據微信回呼的code值,請求微信官方獲取用戶access_token
*/
String getAccessTokenFromWechatUseCode(String wechatAuthCode);

5.1.3 根據用戶的 accessToken 和 openId 拉取用戶資訊

/**
* @author : huayu
* @date   : 28/10/2022
* @param  : [accessToken, openId]
* @return : java.lang.String
* @description : 根據用戶的 accessToken 和  openId 拉取用戶資訊
*/
String getUserInfoFromWechatUseAccessToken(String accessToken,String openId);

5.2 微信授權的業務介面 實作類

/**
 * Created On : 28/10/2022.
 * <p>
 * Author : huayu
 * <p>
 * Description: 微信授權的業務介面 實作類
 */
@Service
@Slf4j
public class WeChatAuthServiceImpl implements WeChatAuthService{

    //注入 http請求工具類
    @Autowired
    private WeChatAuthConfig weChatAuthConfig;
	
    //生成請求微信官方獲取用戶授權code的請求地址
    
    //根據微信回呼的code值,請求微信官方獲取用戶access_token
    
    //根據用戶的 accessToken 和  openId 拉取用戶資訊

}

5.2.1 生成請求微信官方獲取用戶授權code的請求地址

/**
* @author : huayu
* @date   : 29/10/2022
* @param  : []
* @return : java.lang.String
* @description : 生成請求微信官方獲取用戶授權code的請求地址
*/
@Override
public String generateWeChatAuthCodeUrl() {

    //微信官方引導用戶打開授權頁面,獲取code的完整路徑
    //https://open.weixin.qq.com/connect/oauth2/authorize
    // ?appid=APPID
    // &redirect_uri=REDIRECT_URI
    // &response_type=code
    // &scope=SCOPE
    // &state=STATE
    // #wechat_redirect
    //尤其注意:由于授權操作安全等級較高,所以在發起授權請求時,微信會對授權鏈接做正則強匹配校驗,如果鏈接的引數順序不對,授權頁面將無法正常訪問

    //生成請求衛星官方獲取用戶code的完整地址
    StringBuilder weCharAuthCodeUrl = new StringBuilder(weChatAuthConfig.getCodeUri());
    weCharAuthCodeUrl.append("?appid=").append(weChatAuthConfig.getAppId())
        .append("&redirect_uri=").append(weChatAuthConfig.getRedirectUri())
        .append("&response_type=code")
        //&scope=snsapi_userinfo&state=STATE
        .append("&scope=").append("snsapi_userinfo")
        .append("&state=").append("kh96_wechat_auth")
        .append("#wechat_redirect");

    log.info("------ 請求微信官方授權網站地址:{}  ------",weCharAuthCodeUrl.toString());

    //返貨完整的請求地址
    return weCharAuthCodeUrl.toString();

}

5.2.2 根據微信回呼的code值,請求微信官方獲取用戶access_token

/**
* @author : huayu
* @date   : 29/10/2022
* @param  : [wechatAuthCode]
* @return : java.lang.String
* @description : 根據微信回呼的code值,請求微信官方獲取用戶access_token
*/
@Override
public String getAccessTokenFromWechatUseCode(String wechatAuthCode) {
    // 尤其注意:由于公眾號的 secret 和獲取到的access_token安全級別都非常高,必須只保存在服務器,不允許傳給客戶端,
    // 請求方法:獲取 code 后,請求以下鏈接獲取access_token:
    // https://api.weixin.qq.com/sns/oauth2/access_token
    // ?appid=APPID
    // &secret=SECRET
    // &code=CODE
    // &grant_type=authorization_code

    // 封裝根據code,請求微信官方獲取access_token的完整地址
    StringBuilder accessTokenUrl = new StringBuilder(weChatAuthConfig.getAccessTokenUri());
    accessTokenUrl.append("?appid=").append(weChatAuthConfig.getAppId())
        .append("&secret=").append(weChatAuthConfig.getAppSecret())
        .append("&code=").append(wechatAuthCode)
        .append("&grant_type=authorization_code");

    log.info("------ 根據code,請求微信官方獲取access_token的完整地址:{} ------", accessTokenUrl.toString());

    // 根據code,請求微信官方獲取access_token,回傳結果是同步回傳的,不再是異步回呼
    // 請求是服務器內部發起的,也就是說:在程式中,要根據上面完整的請求地址,主動發送請求到微信官方,介面同步會回傳一個json格式的字串結果,程式內要決議獲取的結果

    // 程式內主動發起http請求,獲取access_token
    return HttpClient4Util.getResponse4GetAsString(accessTokenUrl.toString(), "utf-8");
}

5.2.3 根據用戶的 accessToken 和 openId 拉取用戶資訊

/**
* @author : huayu
* @date   : 29/10/2022
* @param  : [accessToken, openId]
* @return : java.lang.String
* @description : 根據用戶的 accessToken 和  openId 拉取用戶資訊
*/
@Override
public String getUserInfoFromWechatUseAccessToken(String accessToken, String openId) {

    // 如果網頁授權作用域為snsapi_userinfo,則此時開發者可以通過access_token和 openid 拉取用戶資訊了,
    // http:GET(請使用 https 協議):
    // https://api.weixin.qq.com/sns/userinfo
    // ?access_token=ACCESS_TOKEN
    // &openid=OPENID
    // &lang=zh_CN

    // 封裝根據accessToken和openId,請求微信官方獲取用戶資訊詳情地址
    StringBuilder userInfoUrl = new StringBuilder(weChatAuthConfig.getUserInfoUri());
    userInfoUrl.append("?access_token=").append(accessToken)
        .append("&openid=").append(openId)
        .append("&lang=zh_CN");
    log.info("------ 根據access_token,請求微信官方獲取userinfo的完整地址:{} ------", userInfoUrl.toString());

    // 程式內主動發起http請求,獲取用戶詳情
    return HttpClient4Util.getResponse4GetAsString(userInfoUrl.toString(), "utf-8");
}

6、controller 層

/**
 * Created On : 28/10/2022.
 * <p>
 * Author : huayu
 * <p>
 * Description: 測驗微信授權登錄操作入口
 */
//@SuppressWarnings("all")
@Slf4j
@RestController
@RequestMapping("/wechat/auth")
public class WeChatAuthController {

    //注入service層實作類
    @Autowired
    private WeChatAuthService weChatAuthService;

}

6.1 獲取請求微信官方貨物code的完整地址,用戶訪問該地址

/**
* @author : huayu
* @date   : 28/10/2022
* @param  : []
* @return : com.kgc.scd.uitl.RequestResult<java.lang.String>
* @description :  獲取請求微信官方貨物code的完整地址,用戶訪問該地址,可以進行授權操作(把地址交給前端生成二維碼給用戶掃碼,或者后端生成)
*/
@GetMapping("/codeUrl")
public RequestResult<String> codeUrl(){

    //呼叫業務介面,獲取完整用戶授權訪問的地址
    return ResultBuildUtil.success(weChatAuthService.generateWeChatAuthCodeUrl());

}

6.2 獲取用戶詳情資訊

用戶授權后,接收微信官方異步回呼請求,獲取用戶授權的code:(code,state)
	1.通過 code 換取網頁授權access_token
	2.拉取用戶資訊(需 scope 為 snsapi_userinfo)
	3.介面回傳用戶詳情資訊
/**
* @author : huayu
* @date   : 28/10/2022
* @param  : []
* @return : com.kgc.scd.uitl.RequestResult<java.util.Map<java.lang.String,java.lang.Object>>
* @description : 接收微信官方異步回呼請求,獲取用戶授權的code
* 流程:用戶先根據上一步回傳請求地址,進行授權操作,如果用戶統一授權,微信官方自動根據上一步請求帶過去的回呼地址redirectUri,進行結果回呼
*/
@RequestMapping("/codeBack")
public RequestResult<Map<String, Object>> codeBack(HttpServletRequest request){

    // 用戶同意授權后,如果用戶同意授權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE,
    // code說明:code作為換取access_token的票據,每次用戶授權帶上的 code 將不一樣,code只能使用一次,5分鐘未被使用自動過期,

    // 從官方回呼的請求中,獲取用戶授權后的code引數值
    String wechatAuthCode = request.getParameter("code");
    // 從官方回呼的請求中,獲取用戶授權時的自定義引數state
    String wechatAuthState = request.getParameter("state");

    log.info("------ 微信授權后,官方異步回呼結果:code={},state={} ------", wechatAuthCode, wechatAuthState);

    // 定義介面回傳集合物件
    Map<String, Object> resultMap = new HashMap<>();

    // 引數非空校驗
    if(StringUtils.isBlank(wechatAuthCode)){
        resultMap.put("msg", "授權code為空!");
        return ResultBuildUtil.fail(resultMap);
    }

    // 1. 呼叫業務介面,通過 code 換取網頁授權access_token
    String accessTokenJson = weChatAuthService.getAccessTokenFromWechatUseCode(wechatAuthCode);
    log.info("------ 通過 code 換取網頁授權access_token回傳結果:{} ------", accessTokenJson);

    // 正確時回傳的 JSON 資料包如下:
    // {"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE"}
    // 錯誤時回傳的 JSON 資料包如下:
    // {"errcode":40029,"errmsg":"invalid code"}

    // 決議回傳的json資料
    JSONObject accessTokenJsonObj = JSON.parseObject(accessTokenJson);

    // 判斷獲取access_token結果是否正確,如果錯誤,直接結束,如果正確,獲取對應的access_token
    if(StringUtils.isNotBlank(accessTokenJsonObj.getString("errcode"))){
        resultMap.put("wxCode", accessTokenJsonObj.getString("errcode"));
        resultMap.put("wxMsg", accessTokenJsonObj.getString("errmsg"));
        return ResultBuildUtil.fail(resultMap);
    }

    // 2. 拉取用戶資訊(需 scope 為 snsapi_userinfo)
    // 根據上一步回傳json,獲取拉取用戶資訊憑證-access_token和用戶唯一標識-openid
    String accessToken = accessTokenJsonObj.getString("access_token");
    String openId = accessTokenJsonObj.getString("openid");

    //  呼叫業務介面,通過access_token和openId,拉取用戶詳情
    String userInfoJson = weChatAuthService.getUserInfoFromWechatUseAccessToken(accessToken, openId);
    log.info("------ 通過access_token和openId,拉取用戶詳情:{} ------", userInfoJson);

    // 3.介面回傳用戶詳情資訊
    resultMap.put("userInfo", userInfoJson);

    // TODO 獲取成功用戶資訊后,系統要完成靜默注冊-把用戶資訊注冊到系統資料中,存盤用戶的頭像,昵稱,openId資訊,并給系統用戶表增加其它的基本資訊

    //回傳用戶詳情
    return ResultBuildUtil.success(resultMap);
}

7、測驗

7.1 生成請求微信官方獲取用戶授權code的請求地址

7.2 獲取用戶資訊




轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/523157.html

標籤:其他

上一篇:【C Primer PLus 摘錄】第 10 章 陣列和指標(未完)

下一篇:SpringBoot 階段測驗 1

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more