MonkeyKing helps you to post messages to Chinese Social Networks.

Overview

MonkeyKing

MonkeyKing helps you post SNS messages to Chinese Social Networks, without their buggy SDKs.

MonkeyKing uses the same analysis process of openshare. We also use some reverse engineering tools such as Hopper Disassembler to unveil several undocumented authentication mechanisms under the hood. It supports sharing Text, URL, Image, Audio, Video, and File to WeChat, QQ, Alipay or Weibo. MonkeyKing can also post messages to Weibo by a web page. (Note: Audio and Video are exclusive to WeChat or QQ, and File is exclusive to QQ Dataline)

MonkeyKing also supports OAuth and Mobile payment via WeChat and Alipay!

Requirements

Swift 5, iOS 9

(For Swift 4.2, use version 1.13.0)

(For Swift 4.1/4.0, use version 1.11.0)

(For Swift 3, use version 1.3.0)

Examples

Share

Example: Share to WeChat (微信):

  1. In your Project Target's Info.plist, set URL Type, LSApplicationQueriesSchemes as follow:

    You should also add weixinULAPI once you enabled Universal Link of your WeChat App.

  2. Register account: // it's not necessary to do it here, but for the sake of convenience

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        MonkeyKing.regsiterAccount(
            .weChat(
                appID: "xxx",
                appKey: "yyy",
                miniAppID: nil,
                universalLink: nil // FIXME: You have to adopt Universal Link otherwise your app name becomes "Unauthorized App"(未验证应用)...
            )
        )
        return true
    }
  3. Append the following code to handle callbacks:

    // AppDelegate.swift
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    //func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { // only for iOS 8
        return MonkeyKing.handleOpenURL(url)
    }

    Remember to handle userActivities if you are using UIScene in your project:

    // SceneDelegate.swift
    
    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        MonkeyKing.handleOpenUserActivity(userActivity)
    }
  4. Prepare your message and ask MonkeyKing to deliver it:

    @IBAction func shareURLToWeChatSession(sender: UIButton) {
    
        MonkeyKing.registerAccount(.weChat(appID: "xxx", appKey: "yyy", miniAppID: nil)) // you can do it here (just before deliver)
    
        let message = MonkeyKing.Message.weChat(.session(info: (
            title: "Session",
            description: "Hello Session",
            thumbnail: UIImage(named: "rabbit"),
            media: .url(URL(string: "http://www.apple.com/cn")!)
        )))
    
        MonkeyKing.deliver(message) { success in
            print("shareURLToWeChatSession success: \(success)")
        }
    }

It's done!

OAuth

Example: Weibo OAuth

MonkeyKing.oauth(for: .weibo) { (oauthInfo, response, error) -> Void in
    print("OAuthInfo \(oauthInfo) error \(error)")
    // Now, you can use the token to fetch info.
}

or, WeChat OAuth for code only

MonkeyKing.weChatOAuthForCode { [weak self] (code, error) in
    guard let code = code else {
        return
    }
    // TODO: fetch info with code
}

If the user doesn't have Weibo App installed on their devices then MonkeyKing will use web OAuth:

Pay

Example: Alipay

let order = MonkeyKing.Order.alipay(urlString: urlString, scheme: nil)
MonkeyKing.deliver(order) { result in
    print("result: \(result)")
}

You need to configure pay.php in a remote server. You can find an example of pay.php at the Demo project.


Launch WeChat Mini App

let path = "..."
MonkeyKing.launch(.weChat(.miniApp(username: "gh_XXX", path: path, type: .release))) { result in
    switch result {
    case .success:
        break
    case .failure(let error):
        print("error:", error)
    }
}

Note that username has a gh_ prefix (原始ID).

More

If you like to use UIActivityViewController for sharing then MonkeyKing has AnyActivity which can help you.

Check the demo for more information.

Installation

Carthage

github "nixzhu/MonkeyKing"

CocoaPods

pod 'MonkeyKing'

Swift Package Manager

https://github.com/nixzhu/MonkeyKing

Contributors

Thanks to all the contributors.

Credits

WeChat logos from WeChat-Logo by Ray.

License

MonkeyKing is available under the MIT License. See the LICENSE file for more info.

Comments
  • 支持微信 Universal Link

    支持微信 Universal Link

    为了解决『未验证应用』的问题,需要支持 Universal Link。 通过逆向分析 libWeChatSDK.a,找到 wechat_auth_tokenwechat_auth_context_id 的生成方式,生成有效的微信 Universal Link。

    为保证兼容官方 SDK,也使用相同的 KeyChain 存储了 wechat_auth_token

    由于 SHA1 不可逆,且 hash 的字符串有部分是用 timeIntervalSince1970 生成,所以并没有按照微信的方法来生成 wechat_auth_context_id,理论上微信端是无法检测出来的。

    目前只实现了以下功能:

    • [x] sendreq - 分享,亲测上线后成功通过 universal link 分享后第二天可以去除『未验证应用』
    • [x] refreshToken - 用于刷新 wechat_auth_token
    • [x] oauth

    还有以下 universal link 功能没有处理:

    • [ ] pay - 仅兼容了 universal link 的接收,发送部分没有帐号可测试
    • [ ] resendContextReqByScheme
    • [ ] jointpay
    • [ ] offlinepay
    • [ ] cardPackage
    • [ ] choosecard
    • [ ] chooseinvoice
    • [ ] openwebview
    • [ ] openbusinesswebview
    • [ ] openranklist
    • [ ] opentypewebview

    不依赖这些功能的话可以暂时直接使用我的分支

    opened by lexrus 23
  • 为什么不需要处理didFailProvisionalNavigation代理方法

    为什么不需要处理didFailProvisionalNavigation代理方法

    public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
    
        // Pocket OAuth
        if let errorString = (error as NSError).userInfo["NSErrorFailingURLStringKey"] as? String, errorString.hasSuffix(":authorizationFinished") {
            removeWebView(webView, tuples: (nil, nil, nil))
        }
    }
    

    这里为什么不需要做removeWebview的处理的? 对WKWebview的这个回调的机制还不是特别清楚. 请教作者?

    opened by dourgulf 14
  • How to handle Weibo Web OAuth

    How to handle Weibo Web OAuth

    作者好, 首先感谢开源. 最近试用没有安装微博APP情况下的OAuth授权. 看了代码的基本原理是用一个webview直接打开"https://open.weibo.cn/oauth2/authorize?client_id", 当代理方法要跳转到我们的redirectURI的时候, 关闭webview. 但是, 没有看明白是怎么把授权的结果返回给APP的?包括授权状态,用户ID等信息.

    opened by dourgulf 10
  • MonkeyKing.SupportedPlatform.weibo.isAppInstalled is not update with Cocoapods

    MonkeyKing.SupportedPlatform.weibo.isAppInstalled is not update with Cocoapods

    MonkeyKing.SupportedPlatform.weibo.isAppInstalled in demo is ok, but not work in cocopods.

    I find source code, in demo SupportedPlatform has isAppInstalled, but not in cocoapods.

    Is cocoapods not update?

    opened by yeziahehe 9
  • QQ 国际版 / 日本版支持

    QQ 国际版 / 日本版支持

    今天在尝试使用的时候发现 QQ 分享的 Activity 一直不出现,然后发现是 canOpenURL 失败了。于是下载了一个日本版的 QQ(帐号正好在日区),打开 Info.plist 发现 URL Scheme 都是 mqqi* 或者 QQi*,估计国际版的也一样。

    我正在尝试自己用暴力的方式魔改(加一个 QQi 的类型),但是感觉这方式很……不优雅。

    请问是否有考虑支持国际版的 QQ 分享?

    opened by HarukaMa 8
  • fix: QQ 登录与分享顺序错误

    fix: QQ 登录与分享顺序错误

    环境:

    • iOS 14.3
    • QQ 8.4.17.638
    1. 当 AASA 文件没有加载完成时,QQ 使用 URL Scheme 处理登录请求,不应该调用 shared.oauthCompletionHandler?(.success(nil)) 返回空数据;
    2. 原先的分享回调一定会命中,导致下面的登录回调无法执行,现在提到更前面并增加 response_from_qq 判断。
    opened by nuomi1 7
  • QQ 分享没有收到回调,会不会是因为。。。

    QQ 分享没有收到回调,会不会是因为。。。

    QQ 成功分享并返回到 app 中,MonkeyKing.handleOpenURL 方法中 urlScheme 为 "tencent...",并没有进入到下面代码中 // QQ Share if urlScheme.hasPrefix("QQ") { ... }

    而是进入了 // QQ OAuth if urlScheme.hasPrefix("tencent") { ... } 并且发生了 OAuth Error 所以 return false 并且没有回调 deliverCompletionHandler

    分享的回调 url tencentxxxxxxx://response_from_qq?source=qq&source_scheme=mqqapi&error=0&version=1&sdkv=3.3.5_lite OAuth的回调url tencentxxxxxxx://qzapp/mqzone/0?generalpastboard=1

    opened by lijingcheng 7
  • MonkeyKing not callback

    MonkeyKing not callback

    My app can share data to other platforms successfully. However, when coming back to my app, MonkeyKing has performed the programs below.

    MonkeyKing.shareMessage(message) { result in print("result: (result)") }

    The demo hasn't such problems and shareSDK is also O.K. Any idea about this?

    opened by transcope 6
  • 代码重构

    代码重构

    因为要添加支付宝分享, 所以仔细审视了一下代码, 觉得以前的代码结构设计不适合做出大的扩展. 所以进行了大面积的重构, 大概内容

    1. 将分享内容的搭建抽离了出来.
    2. 稍微选用了些 struct 类型
    3. 使用协议完成不同类型的分享, 分类管理.
    4. 对 UIActivity 做了些扩展.

    还有工作没完成:

    1. 有些小的细节处理需要完善.
    2. 打算将 web view 和网络抽成协议, 毕竟每个应用都有自己的组件, 让他们(可选)用自己的组件完成
    3. 完整的注释

    因为完成这部分重构有点匆忙,可能会有些小问题, 但是觉得这种方式可能更适合以后这个框架的扩展和管理. 所以请看下, 如果你们不打算采用的话, 我想是不是可以借用下你们的成果,自己发一个第三方的分享包.

    opened by inatu 6
  • QQ授权登录返回成功,但是info是nil

    QQ授权登录返回成功,但是info是nil

    MonkeyKing.oauth(for: .qq, scope: "get_user_info") { (result) in switch result { case .success(let info): guard let unwrappedInfo = info, let token = unwrappedInfo["access_token"] as? String, let openID = unwrappedInfo["openid"] as? String else { return }

                let url = URL(string: "https://graph.qq.com/user/get_user_info?openid=\(openID)&access_token=\(token)&oauth_consumer_key=\(ConstantsAppKey.QQAppID)")
                var request = URLRequest(url: url!)
                request.httpMethod = "GET"
                let configuration: URLSessionConfiguration = URLSessionConfiguration.default
                let session: URLSession = URLSession(configuration: configuration)
                session.dataTask(with: request) { (data, _, error) in
                    if error != nil { completionHandler(false, String(describing: error), nil)
                    } else { doData(platform: .tecentQQ, openID: openID, data: data!, completionHandler: completionHandler)
                    }
                }.resume()
            case .failure(let error):
                completionHandler(false, String(describing: error), nil)
            }
        }
    

    调起qq以后走 .success(let info)回调,但是info是nil,请问怎么解决?谢谢

    opened by HanXiaoTeng 5
  • 微博Weibo图片和链接是否可以同时分享?

    微博Weibo图片和链接是否可以同时分享?

    1.这种方式只能分享带media图和文本 ` @IBAction func shareImage(_ sender: UIButton) {

        let message = MonkeyKing.Message.weibo(.default(info: (
            title: "Image",
            description: "Rabbit",
            thumbnail: nil,
            media: .image(UIImage(named: "rabbit")!)
        ), accessToken: accessToken))
    
        MonkeyKing.deliver(message) { result in
            print("result: \(result)")
        }
    }`
    

    2.这种只能分享文本和带链接,但是thumbnail的image无效 ` @IBAction func shareURL(_ sender: UIButton) {

        let message = MonkeyKing.Message.weibo(.default(info: (
            title: "News",
            description: "Hello Yep",
            thumbnail: UIImage(named: "rabbit"),
            media: .url(URL(string: "http://soyep.com")!)
        ), accessToken: accessToken))
    
        MonkeyKing.deliver(message) { result in
            print("result: \(result)")
        }
    }`
    
    opened by aloveric 5
  • 支付宝SDK15.8.03 url更新

    支付宝SDK15.8.03 url更新

    https://render.alipay.com/p/s/ulink/?scheme=alipay://alipayclient/?{
      "fromAppUrlScheme" : "fromAppUrlScheme",
      "requestType" : "SafePay",
      "extra" : "{\"call_type\":\"authV2\",\"app_name\":\"bundleId\",\"ts_callsp_type\":\"ulink\",\"token\":\"EP12123c661ceb75d67fd1147c05c0a9fc0_1631092619473\",\"ts_api_invoke\":\"1631092619496\",\"sdk_ver\":\"15.8.03\",\"ts_callsp\":\"1631092619497\"}",
      "dataString" : "apiname=com.alipay.account.auth&app_id=2021001157682362&app_name
    
    • 支付宝新的SDK url已经更新了,token不知道怎么生成的
    • 支付宝新的SDK支持了网页授权

    网页地址

    https://authweb.alipay.com/mobile/auth?v=h5&auth_type=LOGIN&method=alipay.open.auth.sdk.code.get&biz_type=openservice&apdid_token=apdid_token&sign=sign&pid=2088831132164735&target_id=1631096598&app_name=mc&apiname=com.alipay.account.auth&msp_type=sdk-ios-lite&product_id=APP_FAST_LOGIN&scope=kuaijie&app_id=app_id&timestamp=1631096631245
    
    opened by huangboju 0
  • 支付宝支付相关

    支付宝支付相关

    MonkeyKing 对于后台返回了签名字符串进行支付宝支付没有进行相关的文档,只是在【请问支持现在支付宝最新的APP支付吗?】这个问题的回复中找到了相关步骤说明,已成功调起支付,在此贡献一下粗略的代码,给后面集成支付宝支付的朋友节省点时间

    // 1、拿到服务端生成的字符串 let dataString = json["data"].stringValue

    // 2、拼接成一个json let json: [String: Any] = ["fromAppUrlScheme":"ap11111111","requestType":"SafePay","dataString":dataString]

    // 3、拼接完后,对整个json进行 url encode let encodeString = json.jsonString()?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

    // 4、最前面加上:alipay://alipayclient/? let url = URL(string: "alipay://alipayclient/?(encodeString ?? "")") let order = MonkeyKing.Order.alipay(url: url!) MonkeyKing.deliver(order) { (result) in

    }

    opened by sjxt 3
Releases(2.2.1)
Owner
null
The Oakland Post iOS app, written in pure Swift

Now available on the App Store! Check it out! The Oakland Post App The mobile companion for The Oakland Post's website, written entirely in Swift! Scr

Andrew Clissold 280 Dec 13, 2022
Easy and lightweight network layer for creating different set of network requests like GET, POST, PUT, DELETE customizable with coders conforming to TopLevelDecoder, TopLevelEncoder

Easy and lightweight network layer for creating different set of network requests like GET, POST, PUT, DELETE customizable with coders conforming to TopLevelDecoder, TopLevelEncoder

Igor 2 Sep 16, 2022
A frida tool that capture GET/POST HTTP requests of iOS Swift library 'Alamofire' and disable SSL Pinning.

FridaHookSwiftAlamofire A frida tool that capture GET/POST HTTP requests of iOS Swift library 'Alamofire' and disable SSL Pinning. 中文文档及过程 Features Ca

neilwu 69 Dec 16, 2022
🌐 Makes Internet connectivity detection more robust by detecting Wi-Fi networks without Internet access.

Connectivity is a wrapper for Apple's Reachability providing a reliable measure of whether Internet connectivity is available where Reachability alone

Ross Butler 1.6k Dec 30, 2022
Circles: E2E encrypted social networking

E2E encrypted social networking built on Matrix. Safe, private sharing for your friends, family, and community.

Kombucha Digital Privacy Systems 51 Nov 29, 2022
Swift Paging is a framework that helps you load and display pages of data from a larger dataset from local storage or over network.

Swift Paging is a framework that helps you load and display pages of data from a larger dataset from local storage or over network. This approach allows your app to use both network bandwidth and system resources more efficiently. It's built on top of Combine, allowing you to harness its full power, handle errors easily, etc.

Gordan Glavaš 12 Dec 9, 2022
This generic SOAP client allows you to access web services using a your iOS app, Mac OS X app and AppleTV app.

This generic SOAP client allows you to access web services using a your iOS app, Mac OS X app and Apple TV app. With this Framework you can create iPh

Prioregroup.com 479 Nov 22, 2022
ADVANCED APP DESIGN The main goal of this mini project is to inspire you on what we can accomplish with the SwiftUI framework.

Restart-App.0.2 ADVANCED APP DESIGN The main goal of this mini project is to inspire you on what we can accomplish with the SwiftUI framework. COMPLEX

Noye Samuel 1 Dec 11, 2021
Approov Integration Examples 0 Jan 26, 2022
An easy to integrate Model Based Google Maps Helper (SVHTTPClient, AFNetworking) That lets you Geo Code , Reverse Geocode, Get Directions , Places Autocomplete.

GoogleMapsHelper Read Me in Russian : http://gargo.of.by/googlemapshelper/ A GOOGLE MAPS Helper that help you do multiple tasks like HOW TO USE // usi

Zeeshan Haider 21 Jul 28, 2022
VFNetwork is a protocol-oriented network layer that will help you assemble your requests in just a few steps.

Simple, Fast and Easy. Introduction VFNetwork is a protocol-oriented network layer that will help you assemble your requests in just a few steps. How

Victor Freitas 4 Aug 22, 2022
A Chinese keyboard for iOS that helps Chinese language learners remember tones.

ToneBoard ToneBoard is a Chinese keyboard for iOS that requires you to enter the correct tones while typing simplified Chinese with Pinyin. It is avai

Kevin Bell 7 Sep 27, 2022
null 13 Oct 28, 2022
Takes those cursed usernames you see on social networks and lets them be accessible to screen readers.

AccessibleAuthorLabel ?? Takes those cursed usernames you see on social networks and lets them be accessible to screen readers so everyone can partake

Christian Selig 40 Jan 25, 2022
Jogendra 113 Nov 28, 2022
The SwiftUI Messages Clone consists of layout and composition clones of the iOS Messages app.

The SwiftUI Messages Clone consists of layout and composition clones of the iOS Messages app. It has Messages-like bubble and screen effects, reactions, and animations, all created with SwiftUI.

Stream 20 Dec 24, 2022
Unified API Library for: Cloud Storage, Social Log-In, Social Interaction, Payment, Email, SMS, POIs, Video & Messaging.

Unified API Library for: Cloud Storage, Social Log-In, Social Interaction, Payment, Email, SMS, POIs, Video & Messaging. Included services are Dropbox, Google Drive, OneDrive, OneDrive for Business, Box, Egnyte, PayPal, Stripe, Google Places, Foursquare, Yelp, YouTube, Vimeo, Twitch, Facebook Messenger, Telegram, Line, Viber, Facebook, GitHub, Google+, LinkedIn, Slack, Twitter, Windows Live, Yahoo, Mailjet, Sendgrid, Twilio, Nexmo, Twizo.

CloudRail 195 Nov 29, 2021
An iOS App to generate phonetic keys for your Chinese contacts. Written in Swift.

An iOS App to add phonetic keys with Pinyin for Chinese(SC & TC) names. Your Contacts will be sorted by alphabet automatically even under English System.

iAugus 595 Dec 27, 2022
GRE3000 - Simple GRE 3000 words app for Chinese

GRE3000 Simple GRE 3000 words app for Chinese Usage Tap Left half Screen for pre

Changhao Song 0 Mar 16, 2022
Mandarin Chinese to Pinyin, IRT.

About Hi, I'm Max! I made Ponkan to help me study Mandarin. Nǐ hǎo, wǒ jiào Max! Wǒ zhìzuò “Ponkan” yīnwèi wǒ yào xuéxí zhōngwén. (Obviously, I still

Max Humber 6 Dec 7, 2022