微信(Android)- 绑定、解绑、登录、分享、前往小程序

这篇内容去年的时候就想写了,但是一直没交作业,蹭着还有一些空闲时间,抓紧总结一下,希望能帮到你一丢丢

关于三方登录和三方分享的功能很常见,之前也用过一些三方平台,如下

近一年左右,我分别在普通项目和模块化项目中实现了 微信登录、绑定、解绑功能,所以我将分类说明

基础集成

集成之初首先要 将我们的应用注册到微信平台,以此获得 AppIDAppSecret ,这俩个key都很重要,在注册、鉴权等请求中都有用到

一切以 官方文档 为准 ,仅说明部分关键文档

OAuth2.0 协议

在微信SDK中主要用到了 OAuth2.0,务必了解这个协议的整个流程

我记得有一次面试,被问到了微信登录 → OAuth2.0流程 ,我是这么回答的

  1. 在微信平台注册App,获取 AppID 和 AppSecret
  2. 在应用内调用三方登录,将 AppID 等信息传给微信
  3. 微信获取到AppID 后,从微信端数据库获取应用信息
  4. 在鉴权页显示用户信息与是否授权的操作
  5. 当用户授权后,返回临时code,然后加上AppID和AppSecret获取token(也可由后端执行)
  6. 将临时code传给我方后端,我方后端调用微信后端获取token(可返回到客户端,也可自我消费)
  7. 后端(客户端)通过token获取用户信息

在5-7步骤中客户端也可以直接发请求给微信,以此获取用户信息;但如果是涉及到绑定、解绑微信那么就需要临时code

在这里插入图片描述

关联场景:点击三方登录时,发起请求

在这里插入图片描述
在这里插入图片描述

关联场景:鉴权,确认授权后获取临时票据(code)

在这里插入图片描述

关联场景:通过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 有效期

关于access_token有效期的问题,有的人直接设置最长有效期(30天),有的又要去通过刷新refresh_token动态去给access_token续期,反正考虑的越多,问题就越多,我此处仅做记录

在这里插入图片描述
在这里插入图片描述

注册到微信

自述总结:相当于SDK的注册方式,只不过一般SDK注册在Application,而微信SDK在Activity组件

要使你的程序启动后微信终端能响应你的程序,必须在代码中向微信终端注册你的 id(一般在 Activity 的 onCreate 中进行注册 )

// APP_ID 替换为你的应用从官方网站申请到的合法appID
private static final String APP_ID = "wx88888888";
// IWXAPI 是第三方app和微信通信的openApi接口
private IWXAPI api;

private regToWx() {
    
    
    // 通过WXAPIFactory工厂,获取IWXAPI的实例
    api = WXAPIFactory.createWXAPI(this, APP_ID, true);
    // 将应用的appId注册到微信
    api.registerApp(APP_ID);
    //建议动态监听微信启动广播进行注册到微信
    registerReceiver(new BroadcastReceiver () {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            // 将该app注册到微信
            api.registerApp(Constants.APP_ID);
        }
    }, new IntentFilter (ConstantsAPI.ACTION_REFRESH_WXAPP));
}

发送请求、响应到微信

自述总结:sendReq(BaseReq req) 一般用于业务相关功能调用处,而关于sendResp(BaseResp resp)并未用到!

发送请求或发送响应到微信终端,可以通过 IWXAPIsendReqsendResp 两个方法来实现

  • boolean sendReq(BaseReq req);sendReq 是第三方 app 主动发送消息给微信,发送完成之后会切回到第三方 app 界面。
  • boolean sendResp(BaseResp resp);sendResp 是微信向第三方 app 请求数据,第三方 app 回应数据之后会切回到微信界面。

sendReq 的实现示例

//初始化一个 WXTextObject 对象,填写分享的文本内容
WXTextObject textObj = new WXTextObject();
textObj.text = text;

//用 WXTextObject 对象初始化一个 WXMediaMessage 对象
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = textObj;
msg.description = text;

SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = String.valueOf(System.currentTimeMillis());  //transaction字段用与唯一标示一个请求
req.message = msg;
req.scene = mTargetScene;

//调用api接口,发送数据到微信
api.sendReq(req);

sendResp 的实现与 SendReq 类似,如下所示

// 初始化一个 WXTextObject 对象
WXTextObject textObj = new WXTextObject();
textObj.text = text;

// 用 WXTextObject 对象初始化一个 WXMediaMessage 对象
WXMediaMessage msg = new WXMediaMessage(textObj);
msg.description = text;

// 构造一个Resp
GetMessageFromWX.Resp resp = new GetMessageFromWX.Resp();
// 将req的transaction设置到resp对象中,其中bundle为微信传递过来的Intent所带的内容,通过getExtras()方法获取
resp.transaction = new GetMessageFromWX.Req(bundle).transaction;
resp.message = msg;

//调用api接口,发送数据到微信
api.sendResp (resp) ;

接收微信的请求及返回值

在这里插入图片描述
自述如下

  1. 在相应目录下新建一个 wxapi目录,并在该 wxapi 目录下新增一个 WXEntryActivity 类,该类继承自 Activity
  2. AndroidManifest 进行注册
<activity
    android:name=".wxapi.WXEntryActivity"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.Translucent.NoTitleBar"
    android:exported="true"
    android:taskAffinity="填写你的包名"
    android:launchMode="singleTask">
</activity>
  1. WXEntryActivity 实现 IWXAPIEventHandler接口,重写onReq(一般用于请求微信方面的接口)、onResp(一般用于接收微信方面返回的数据)

注意事项:如果需要混淆代码,为了保证 sdk 的正常使用,需要在 proguard.cfg 加上下面两行配置

-keep class com.tencent.mm.opensdk.** {
    
    
    *;
}
-keep class com.tencent.wxop.** {
    
    
    *;
}
-keep class com.tencent.mm.sdk.** {
    
    
    *;
}

普通项目

我并不确定每个人遇到的业务需求是否相同,不过我习惯性记录一下我遇到的问题

  • 常规的微信登录中,在用户鉴权后可以直接请求微信后端获取到用户信息,但是当初在这个项目中是先获取到临时票据(code),然后请求自己公司的后端接口,由双方后端交互获取数据后再将用户信息返回给客户端
  • WXEntryActivityonResp 监听微信返回后通过 SendAuth.Respstate 校验,执行对应逻辑
  • 因为微信的返回数据都在WXEntryActivity 中,而最终数据的调用方都在其他组件,为了方便我在这里使用的是 EventBus 组件

绑定、解绑微信

在此项目中不论是登录、绑定、解绑都是依赖于code和后端,所以俩者区别除了发送请求时的state不同之外,只有对应的业务操作不同而已

自述总结:其实绑定、解绑微信,并不是微信直接提供的功能!而是很多公司衍生出来的附属功能

绑定微信时需要前往微信鉴权,解绑时因为是已方操作所以并不需要调用微信!(仅需在对应需求功能点加入以下微信请求即可)

    //微信登陆,获取授权code(临时票据),每次都变更
    var req = SendAuth.Req()
    req.scope = "snsapi_userinfo";
    req.state = "bindWx";
    WxUtil.getApi(this.sendReq(req)

WxUtil

import static com.alipay.tianyan.mobilesdk.TianyanMonitorAbility.registerReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;

import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.xiaomi.mipush.sdk.Constants;

//这个工具当时写的很鸡肋...
public class WxUtil {
    
    

    // APP_ID 替换为你的应用从官方网站申请到的合法appID
    public static final String APP_ID = "appID";

    // IWXAPI 是第三方 app 和微信通信的 openApi 接口
    public static IWXAPI api;

    public static IWXAPI getApi(Context context){
    
    
        if (api!=null){
    
    
            return api;
        }
        return WXAPIFactory.createWXAPI(context, APP_ID, true);
    }

    // 当前未用到
    public static void regToWx(Context context) {
    
    
        // 通过 WXAPIFactory 工厂,获取 IWXAPI 的实例
        api = WXAPIFactory.createWXAPI(context, APP_ID, true);
        // 将应用的 appId 注册到微信
        api.registerApp(APP_ID);

        //建议动态监听微信启动广播进行注册到微信
        registerReceiver(new BroadcastReceiver() {
    
    
            @Override
            public void onReceive(Context context, Intent intent) {
    
    
                // 将该 app 注册到微信
                api.registerApp(Constants.APP_ID);
                Log.e("wx", "微信已注册");
            }
        }, new IntentFilter(ConstantsAPI.ACTION_REFRESH_WXAPP));

    }
}

WXEntryActivity

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.util.Log
import android.widget.Toast
import com.tencent.mm.opensdk.constants.ConstantsAPI
import com.tencent.mm.opensdk.modelbase.BaseReq
import com.tencent.mm.opensdk.modelbase.BaseResp
import com.tencent.mm.opensdk.modelbiz.SubscribeMessage
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
import com.tencent.mm.opensdk.modelbiz.WXOpenBusinessView
import com.tencent.mm.opensdk.modelbiz.WXOpenBusinessWebview
import com.tencent.mm.opensdk.modelmsg.SendAuth
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import org.greenrobot.eventbus.EventBus
import java.lang.ref.WeakReference

class WXEntryActivity : Activity(), IWXAPIEventHandler {
    
    
    private var api: IWXAPI? = null
    private val TAG = "WXEntryActivity"

    private var handler: MyHandler? = null

    private class MyHandler(wxEntryActivity: WXEntryActivity) : Handler() {
    
    
        private val wxEntryActivityWeakReference: WeakReference<WXEntryActivity> = WeakReference(wxEntryActivity)

        override fun handleMessage(msg: Message) {
    
    
            when (msg.what) {
    
    
                6, 7 -> {
    
    
                    val loginData = msg.data
                    val loginCode: String? = loginData.getString("code")
                    EventBus.getDefault().post(loginCode?.let {
    
     AuthorCodeEvent(it) })
                }
                8 -> {
    
    
                    val loginData = msg.data
                    val loginCode: String? = loginData.getString("code")
                    EventBus.getDefault().post(loginCode?.let {
    
     BindAuthorCodeEvent(it) })
                }
            }
        }
    }

    public override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        api = WXAPIFactory.createWXAPI(this, "wxappid", false)
        handler = MyHandler(this)
        try {
    
    
            val intent = intent
            api!!.handleIntent(intent, this)
        } catch (e: Exception) {
    
    
            e.printStackTrace()
        }
    }

    override fun onNewIntent(intent: Intent) {
    
    
        super.onNewIntent(intent)
        setIntent(intent)
        api!!.handleIntent(intent, this)
    }

    override fun onReq(baseReq: BaseReq) {
    
    
        when (baseReq.type) {
    
    
            ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX -> {
    
    
            }
            ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX -> {
    
    
            }
            BaseResp.ErrCode.ERR_OK ->
                Toast.makeText(this@WXEntryActivity, "分享成功", Toast.LENGTH_LONG).show()
            BaseResp.ErrCode.ERR_USER_CANCEL ->                //分享取消
                Toast.makeText(this@WXEntryActivity, "分享取消", Toast.LENGTH_LONG).show()
            BaseResp.ErrCode.ERR_AUTH_DENIED ->                //分享拒绝
                Toast.makeText(this@WXEntryActivity, "分享拒绝", Toast.LENGTH_LONG).show()
            else -> {
    
    
            }
        }
        finish()
    }

    override fun onResp(resp: BaseResp) {
    
    
        var result = 0
        result = when (resp.errCode) {
    
    
            BaseResp.ErrCode.ERR_OK -> R.string.errcode_success
            BaseResp.ErrCode.ERR_USER_CANCEL -> R.string.errcode_cancel
            BaseResp.ErrCode.ERR_AUTH_DENIED -> R.string.errcode_deny
            BaseResp.ErrCode.ERR_UNSUPPORT -> R.string.errcode_unsupported
            else -> R.string.errcode_unknown
        }
        Log.e(TAG, getString(result) + ", type=" + resp.type)
    
        if (resp.type == ConstantsAPI.COMMAND_SENDAUTH) {
    
    
            val authResp = resp as SendAuth.Resp
            Log.d(TAG, "onResp: " + authResp.state)
            if (authResp.state != null) {
    
     //默认返回是空
                if (authResp.state == "sharesdk_wechat_auth") {
    
     //微信分享
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 6
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                } else if (authResp.state == "none") {
    
    
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 0
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                } else if (authResp.state == "login2") {
    
     //微信登录
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 7
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                } else if (authResp.state == "bindWx") {
    
     //绑定微信
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 8
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                }
            }
        }
        finish()
    }
}

有部分代码非我所写,留个备份,各位可忽略

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.util.Log
import android.widget.Toast
import com.tencent.mm.opensdk.constants.ConstantsAPI
import com.tencent.mm.opensdk.modelbase.BaseReq
import com.tencent.mm.opensdk.modelbase.BaseResp
import com.tencent.mm.opensdk.modelbiz.SubscribeMessage
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
import com.tencent.mm.opensdk.modelbiz.WXOpenBusinessView
import com.tencent.mm.opensdk.modelbiz.WXOpenBusinessWebview
import com.tencent.mm.opensdk.modelmsg.SendAuth
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import org.greenrobot.eventbus.EventBus
import java.lang.ref.WeakReference

class WXEntryActivity : Activity(), IWXAPIEventHandler {
    
    
    private var api: IWXAPI? = null
    private val TAG = "WXEntryActivity"

    private var handler: MyHandler? = null

    private class MyHandler(wxEntryActivity: WXEntryActivity) : Handler() {
    
    
        private val wxEntryActivityWeakReference: WeakReference<WXEntryActivity> =
            WeakReference(wxEntryActivity)

        override fun handleMessage(msg: Message) {
    
    
            when (msg.what) {
    
    
                /*  NetworkUtil.GET_TOKEN -> {
                      val data = msg.data
                      var json: JSONObject? = null
                      try {
                          json = JSONObject(data.getString("result"))
                          val openId: String
                          val accessToken: String
                          val refreshToken: String
                          val scope: String
                          openId = json.getString("openid")
                          accessToken = json.getString("access_token")
                          refreshToken = json.getString("refresh_token")
                          scope = json.getString("scope")
                          val intent = Intent(
                              wxEntryActivityWeakReference.get(),
                              AboutActivity::class.java
                          )
                          intent.putExtra("openId", openId)
                          intent.putExtra("accessToken", accessToken)
                          intent.putExtra("refreshToken", refreshToken)
                          intent.putExtra("scope", scope)
                          wxEntryActivityWeakReference.get()!!.startActivity(intent)
                      } catch (e: JSONException) {
                          Log.e(WXEntryActivity.TAG, e.message)
                      }
                  }
                  0 -> {
                      val data = msg.data
                      val code: String?
                      code = data.getString("code")
                      val intent = Intent(
                          wxEntryActivityWeakReference.get(),
                          WithdrawActivity::class.java
                      )
                      intent.putExtra("code", code)
                      wxEntryActivityWeakReference.get()!!.startActivity(intent)
                  }*/
                6, 7 -> {
    
    
                    val loginData = msg.data
                    val loginCode: String? = loginData.getString("code")
                    /* val loginIntent = Intent(
                         wxEntryActivityWeakReference.get(),
                         PhoneLoginActivity::class.java
                     )
                     loginIntent.putExtra("code", loginCode)
                     wxEntryActivityWeakReference.get()!!.startActivity(loginIntent)*/
                    EventBus.getDefault().post(loginCode?.let {
    
     AuthorCodeEvent(it) })
                }
                8 -> {
    
    
                    val loginData = msg.data
                    val loginCode: String? = loginData.getString("code")
                    /* val loginIntent = Intent(
                         wxEntryActivityWeakReference.get(),
                         PhoneLoginActivity::class.java
                     )
                     loginIntent.putExtra("code", loginCode)
                     wxEntryActivityWeakReference.get()!!.startActivity(loginIntent)*/
                    EventBus.getDefault().post(loginCode?.let {
    
     BindAuthorCodeEvent(it) })
                }
                /*  7 -> {
                      val login2data = msg.data
                      val login2code: String?
                      login2code = login2data.getString("code")
                      val login2intent = Intent(
                          wxEntryActivityWeakReference.get(),
                          NLoginActivity::class.java
                      )
                      login2intent.putExtra("code", login2code)
                      wxEntryActivityWeakReference.get()!!.startActivity(login2intent)
                  }
                  8 -> {
                      val binddata = msg.data
                      val bindcode: String?
                      bindcode = binddata.getString("code")
                      val bindintent = Intent(
                          wxEntryActivityWeakReference.get(),
                          ProfileDetailActivity::class.java
                      )
                      bindintent.putExtra("code", bindcode)
                      wxEntryActivityWeakReference.get()!!.startActivity(bindintent)
                  }*/
            }
        }

    }

    public override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        api = WXAPIFactory.createWXAPI(this, "wxappid", false)
        handler = MyHandler(this)
        try {
    
    
            val intent = intent
            api!!.handleIntent(intent, this)
        } catch (e: Exception) {
    
    
            e.printStackTrace()
        }
    }

    override fun onNewIntent(intent: Intent) {
    
    
        super.onNewIntent(intent)
        setIntent(intent)
        api!!.handleIntent(intent, this)
    }

    override fun onReq(baseReq: BaseReq) {
    
    
        when (baseReq.type) {
    
    
            ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX -> {
    
    
            }
            ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX -> {
    
    
            }
            BaseResp.ErrCode.ERR_OK ->
                Toast.makeText(this@WXEntryActivity, "分享成功", Toast.LENGTH_LONG).show()
            BaseResp.ErrCode.ERR_USER_CANCEL ->                //分享取消
                Toast.makeText(this@WXEntryActivity, "分享取消", Toast.LENGTH_LONG).show()
            BaseResp.ErrCode.ERR_AUTH_DENIED ->                //分享拒绝
                Toast.makeText(this@WXEntryActivity, "分享拒绝", Toast.LENGTH_LONG).show()
            else -> {
    
    
            }
        }
        finish()
    }

    override fun onResp(resp: BaseResp) {
    
    
        var result = 0
        result = when (resp.errCode) {
    
    
            BaseResp.ErrCode.ERR_OK -> R.string.errcode_success
            BaseResp.ErrCode.ERR_USER_CANCEL -> R.string.errcode_cancel
            BaseResp.ErrCode.ERR_AUTH_DENIED -> R.string.errcode_deny
            BaseResp.ErrCode.ERR_UNSUPPORT -> R.string.errcode_unsupported
            else -> R.string.errcode_unknown
        }
        Log.e(TAG, getString(result) + ", type=" + resp.type)
        if (resp.type == ConstantsAPI.COMMAND_SUBSCRIBE_MESSAGE) {
    
    
            val subscribeMsgResp = resp as SubscribeMessage.Resp
            val text = String.format(
                "openid=%s\ntemplate_id=%s\nscene=%d\naction=%s\nreserved=%s",
                subscribeMsgResp.openId,
                subscribeMsgResp.templateID,
                subscribeMsgResp.scene,
                subscribeMsgResp.action,
                subscribeMsgResp.reserved
            )
            Log.e(TAG, text)
        }
        if (resp.type == ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM) {
    
    
            val launchMiniProgramResp = resp as WXLaunchMiniProgram.Resp
            val text = String.format(
                "openid=%s\nextMsg=%s\nerrStr=%s",
                launchMiniProgramResp.openId,
                launchMiniProgramResp.extMsg,
                launchMiniProgramResp.errStr
            )
            Log.e(TAG, text)
        }
        if (resp.type == ConstantsAPI.COMMAND_OPEN_BUSINESS_VIEW) {
    
    
            val launchMiniProgramResp = resp as WXOpenBusinessView.Resp
            val text = String.format(
                "openid=%s\nextMsg=%s\nerrStr=%s\nbusinessType=%s",
                launchMiniProgramResp.openId,
                launchMiniProgramResp.extMsg,
                launchMiniProgramResp.errStr,
                launchMiniProgramResp.businessType
            )
            Log.e(TAG, text)
        }
        if (resp.type == ConstantsAPI.COMMAND_OPEN_BUSINESS_WEBVIEW) {
    
    
            val response = resp as WXOpenBusinessWebview.Resp
            val text = String.format(
                "businessType=%d\nresultInfo=%s\nret=%d",
                response.businessType,
                response.resultInfo,
                response.errCode
            )
            Log.e(TAG, text)
        }
        if (resp.type == ConstantsAPI.COMMAND_SENDAUTH) {
    
    
            val authResp = resp as SendAuth.Resp
            Log.d(TAG, "onResp: " + authResp.state)
            if (authResp.state != null) {
    
     //默认返回是空
                if (authResp.state == "sharesdk_wechat_auth") {
    
    
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 6
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                } else if (authResp.state == "none") {
    
    
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 0
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                } else if (authResp.state == "login2") {
    
    
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 7
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                } else if (authResp.state == "bindWx") {
    
    
                    val code = authResp.code
                    val msg = Message.obtain()
                    msg.what = 8
                    val data = Bundle()
                    data.putString("code", code)
                    msg.data = data
                    handler?.sendMessage(msg)
                }
            }
        }
        finish()
    }
}

模块化项目

在组件化和模块化的架构项目中就会涉及到组件间通信,再想通过像之前一样的 EventBus 组件通信就不太合适了,所以在当前项目中用到了 Hilt+接口 的方式

关于 WXEntryActivity 的监听处理并不是很关键,更多的可以看看这种架构de封装方式,因为并不是由我完全封装,一起来学习一下吧

封装架构

可以通过这种方式学习一下设计思想

调用方法

import android.content.Context

interface WeChatService {
    
    

    fun startAuth(context: Context, black: (String) -> Unit)

    fun authSuccess(code: String)

    fun authFail()

    fun startMiniProgram(context: Context, userName: String, path: String, miniprogramType: String, black: (String) -> Unit)

    fun miniSuccess(res: String)
}

方法实现

import android.content.Context
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
import com.tencent.mm.opensdk.modelmsg.SendAuth
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import timber.log.Timber
import javax.inject.Inject


class WeChatServiceImpl @Inject constructor() : WeChatService {
    
    

    companion object {
    
    
        const val WX_APP_ID = "appID" // 微信appID
    }

    init {
    
    
        WXAPIFactory.createWXAPI(AppContext, WX_APP_ID, true).registerApp(WX_APP_ID)
    }

    private var authBlackListener: ((String) -> Unit)? = null

    private var miniBlackListener: ((String) -> Unit)? = null

    override fun startAuth(context: Context, black: (String) -> Unit) {
    
    
        val iWXAPI = WXAPIFactory.createWXAPI(context, WX_APP_ID, true)
        if (!iWXAPI.isWXAppInstalled) {
    
    
            context.neutralDialog(message = "您还没有安装微信")
            return
        }
        authBlackListener = black
        //微信登陆,获取授权code(临时票据),每次都变更
        val req = SendAuth.Req()
        req.scope = "snsapi_userinfo"
        req.state = "bindWx"
        Timber.e("WxHaServiceImp 开始发起授权")
        iWXAPI.sendReq(req)
    }

    override fun authSuccess(code: String) {
    
    
        authBlackListener?.invoke(code)
        authBlackListener = null
    }

    override fun authFail() {
    
    
        authBlackListener = null
    }

    override fun miniSuccess(res: String) {
    
    
        miniBlackListener?.invoke(res)
        miniBlackListener = null
    }

    override fun startMiniProgram(context: Context, userName: String, path: String, miniprogramType: String, black: (String) -> Unit) {
    
    
        val iWXAPI = WXAPIFactory.createWXAPI(context, WX_APP_ID, true)
        if (!iWXAPI.isWXAppInstalled) {
    
    
            context.neutralDialog(message = "您还没有安装微信")
            return
        }
        miniBlackListener = black
        iWXAPI.sendReq(WXLaunchMiniProgram.Req().apply {
    
    
            // 填小程序原始id
            this.userName = userName
            //拉起小程序页面的可带参路径,不填默认拉起小程序首页,对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar"。
            this.path = path
            // 可选打开 开发版,体验版和正式版
            this.miniprogramType = miniprogramType.toInt()
        })
    }

}

场景使用

如果以后遇到更多场景的话,也会持续集成于此处

鉴权(登录、绑定)

      weChatService.startAuth(requireContext()) {
    
     code ->
           //通过临时票据(code)请求我方后端接口,执行对应业务逻辑
        }

前往小程序

        javascriptMethod.openWXminiProgram.observe(this) {
    
     params -> //  调用小程序
            try {
    
    
                val userName = params["userName"].string()
                val path = params["path"].string()
                val miniProgramType = params["miniProgramType"].string()
                val callbackId = params["callbackId"].string()
             	//微信小程序所需参数
                ServiceManager.weChatService().startMiniProgram(this, userName, path, miniProgramType){
    
     res ->
                    Timber.e("observe - res监听:$res" )
                    javascriptMethod.evaluateJavascript(callbackId, res)
                }
            } catch (throwable: Throwable) {
    
    
                Timber.e(throwable)
            }
        }

WXEntryActivity

import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import androidx.appcompat.app.AppCompatActivity
import com.tencent.mm.opensdk.constants.ConstantsAPI
import com.tencent.mm.opensdk.modelbase.BaseReq
import com.tencent.mm.opensdk.modelbase.BaseResp
import com.tencent.mm.opensdk.modelbiz.WXLaunchMiniProgram
import com.tencent.mm.opensdk.modelmsg.SendAuth
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import timber.log.Timber


internal class WXEntryActivity : AppCompatActivity(), IWXAPIEventHandler {
    
    

    private val wxapi: IWXAPI by lazy {
    
    
        WXAPIFactory.createWXAPI(this, "appID")// 微信appID
    }

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        wxapi.handleIntent(intent, this)
    }

    @SuppressLint("MissingSuperCall")
    override fun onNewIntent(intent: Intent?) {
    
    
        super.onNewIntent(intent)
        setIntent(intent)
        wxapi.handleIntent(intent, this)
    }

    override fun onReq(baseReq: BaseReq?) = finish()

    override fun onResp(baseResp: BaseResp?) {
    
    
        if (baseResp?.type == ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX) {
    
       // 微信分享
//            when (baseResp.errCode) {
    
    
//                BaseResp.ErrCode.ERR_OK -> "微信分享成功"
//                BaseResp.ErrCode.ERR_USER_CANCEL -> "微信分享被取消"
//                BaseResp.ErrCode.ERR_AUTH_DENIED -> "微信分享失败"
//                else -> "微信分享未知"
//            }.apply {
    
    
//                ToastUtils.showToast(this)
//            }
        } else if (baseResp?.type == ConstantsAPI.COMMAND_SENDAUTH) {
    
           // 微信授权
            val result = when (baseResp.errCode) {
    
    
                BaseResp.ErrCode.ERR_OK -> "发送成功"
                BaseResp.ErrCode.ERR_USER_CANCEL -> "发送取消"
                BaseResp.ErrCode.ERR_AUTH_DENIED -> "发送被拒绝"
                BaseResp.ErrCode.ERR_UNSUPPORT -> "不支持错误"
                else -> "发送返回"
            }
            Timber.e("baseRespErrCode =$result")
            if (baseResp.errCode == BaseResp.ErrCode.ERR_OK) {
    
      // 微信授权成功
                ServiceManager.weChatService().authSuccess((baseResp as SendAuth.Resp).code)
            } else {
    
        // 微信授权失败
                ServiceManager.weChatService().authFail()
            }
        } else if (baseResp?.type == ConstantsAPI.COMMAND_LAUNCH_WX_MINIPROGRAM) {
    
    
            val launchMiniProResp = baseResp as WXLaunchMiniProgram.Resp
            val extraData = launchMiniProResp.extMsg //对应小程序组件 <button open-type="launchApp"> 中的 app-parameter 属性
            Timber.e("小程序返回数据:" + extraData.string())
            if (!TextUtils.isEmpty(extraData)) {
    
    
                Timber.e("小程序返回数据不为空内部回调:" + extraData.string())
                ServiceManager.weChatService().miniSuccess(extraData.string())
            }
        }
        this.finish()
    }

}

猜你喜欢

转载自blog.csdn.net/qq_20451879/article/details/123858796
今日推荐