Day22 Plugin 从零开始到上架 - 取得权杖(iOS)

iOS这边在取得授权码後,一样准备取得权杖

Modules:

struct ShortAccessTokenResponse: Decodable {
    var accessToken : String
    var userId : Int
}

struct LongAccessTokenResponse: Decodable {
    var accessToken : String
    var tokenType : String
    var expiresIn: Int64
}

AccessTokenRepository:

    
    func getShortAccessTokenInfo(clientId: String, clientSecret: String, code: String, redirectUri: String, completionHandler: @escaping (ShortAccessTokenResponse) -> Void) {
        
        let url = URL(string: "https://api.instagram.com/oauth/access_token")!
        
        
        let headers = [
            "content-type": "multipart/form-data; boundary=\(boundary)"
        ]
        let parameters = [
            [
                "name": "client_id",
                "value": clientId
            ],
            [
                "name": "client_secret",
                "value": clientSecret
            ],
            [
                "name": "grant_type",
                "value": "authorization_code"
            ],
            [
                "name": "redirect_uri",
                "value": redirectUri
            ],
            [
                "name": "code",
                "value": code
            ]
        ]
        
        var request = URLRequest(url: url)
        let postData = getFormBody(parameters, boundary)
        
        request.allHTTPHeaderFields = headers
        request.httpMethod = "POST"
        
        request.httpBody = postData
        
        URLSession.shared.dataTask(with: request) {
            data, response, error in
            if let data = data {
                let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                do {
                    let response = try decoder.decode(ShortAccessTokenResponse.self, from: data)
                    completionHandler(response)
                } catch {
                    print(error.localizedDescription)
                }
            } else {
                print("No Data")
            }
        }.resume()
    }
    
    func getLongAccessTokenInfo(accessToken: String,clientSecret: String,grantType: String, completionHandler: @escaping (LongAccessTokenResponse) -> Void) {
        
        let url = URL(string: "https://graph.instagram.com/access_token?access_token=\(accessToken)&client_secret=\(clientSecret)&grant_type=\(grantType)")!
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request) {
            data, response, error in
            if let data = data {
                do {
                    let decoder = JSONDecoder()
                    decoder.keyDecodingStrategy = .convertFromSnakeCase
                    
                    let response = try decoder.decode(LongAccessTokenResponse.self, from: data)
                    
                    completionHandler(response)
                    
                }catch(let error) {
                    print(error.localizedDescription)
                }
            } else {
                print("No Data")
            }
        }.resume()
    }
    
    func logout() {
        instagramUser = nil
    }

AccessTokenViewModel:

    enum State {
        case isLoading
        case failed(Error)
        case loaded(UserInfoResponse)
    }
    
    @Published private(set) var state :State? = nil
    
    func getAccessToken(clientId: String, clientSecret: String, code: String, redirectUri: String) {
        state = State.isLoading
        
        AccessTokenRepository.shared.getShortAccessTokenInfo(clientId: clientId, clientSecret: clientSecret, code: code, redirectUri: redirectUri) { response in
            DispatchQueue.main.async {
                AccessTokenRepository.shared.getLongAccessTokenInfo(accessToken: response.accessToken, clientSecret: clientSecret, grantType: "ig_exchange_token") { longAccessTokenResponse in
                    
                    AccessTokenRepository.shared.saveInstagramInfo(userId: clientId, accessToken: longAccessTokenResponse.accessToken, expiresIn: longAccessTokenResponse.expiresIn)
                    
                    do {
                        try AccessTokenRepository.shared.getUserInfo { response in
                            self.state = State.loaded(response)
                        }
                    }catch(let error) {
                        print(error.localizedDescription)
                        self.state = State.failed(error)
                    }

                }
            }
        }
    }

<<:  用React刻自己的投资Dashboard Day23 - 非同步呼叫API,完成首页资料串接

>>:  DAY 23 Typography, Hover 以及 Extend

[想试试看JavaScript ] 资料型态 与字串

年初我开始学程序的时候,就是去网路上随意翻阅文章就开始学了。 很常会被一堆专有名词吓傻。即使努力默记...

[Day 11] 简单的单元测试实作(五)

接下来我们要测试100的倍数, 我们这次直接加两个数字, public function input...

EAP-TLS身份验证协议最能支持零信任原则

-零信任网路安全范式 EAP-TLS、EAP-TTLS 和 PEAP 是 WPA2 中使用的合法身...

Day 16 - SNMP、Banner Grabbing 与 Firewall Rules

出於书本 Chapter 8. Network Infrastructure SNMP 扫描 什麽是...

DAY 6 『 TableView 』Part1

TableView:Storyboard + Table View + Table View Cel...