Android接入微信登录、分享、支付

      发布在:Android      评论:0 条评论

申请微信开放平台AppID之前,需要把项目的debug和release包都设置为正式签名密钥。此举是为了在开发过程中能够调试程序,出现问题可以根据错误码来排查(errCode为-6时多数是因为两个版本的签名不一致)

准备工作:在build.gradle文件里相应的标签中添加下列代码片段(***代表你原有的代码)

android {
    ***
    signingConfigs {
        config {
            keyAlias 'll'
            keyPassword 'longli'
            storeFile file('D:/longli/sign.jks')
            storePassword 'longli'
        }
    }
    buildTypes {
        ***
        debug {
            ***
            signingConfig signingConfigs.config
        }
        ***
    }
    ***
}

当通过微信审核并得到AppId和AppSecret之后就可以开始集成sdk了,步骤如下:

1.引入sdk文件。在build.gradle文件中,添加如下依赖即可:

dependencies {
    ***
    compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
    ***
}

dependencies {
    ***
    compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
    ***
}

(其中,前者包含统计功能)

2.AndroidManifest.xml文件中添加必要的权限支持:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

3.为了保证sdk的正常使用,需要添加以下规则到混淆文件proguard-rules.pro中

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

4.创建唯一的访问微信的接口引用(可选,如果你有自定义的Application的话)
示例代码:

public class BaseApplication extends Application {
    ***
    public static IWXAPI sIWXAPI;

    @Override
    public void onCreate() {
        ***
        sIWXAPI = WXAPIFactory.createWXAPI(this, "你的AppID");
        sIWXAPI.registerApp(AppID);
    }
    ***
}

5.创建响应微信回调的Activity
在项目的源码主package下新建一个wxapi包,并在其中新建一个WXEntryActivity类,一个WXPayEntryActivity类,如图
Android接入微信登录、分享、支付
其中WXEntryActivity是用来响应“登录”和“分享”的结果,而WXPayEntryActivity响应“支付”的结果。此外两者均需要实现IWXAPIEventHandler接口,示例代码将在下面贴出。

6.修改两个Activity在AndroidManifest.xml中的属性

<activity
    android:name=".wxapi.WXEntryActivity"
    android:exported="true"
    android:launchMode="singleTop"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.NoDisplay" />
<activity
    android:name=".wxapi.WXPayEntryActivity"
    android:exported="true"
    android:launchMode="singleTop"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.NoDisplay" />

因为这两个Activity都不需要显示内容,所以设置一个透明主题Theme.NoDisplay,否则会出现白屏令到用户怀疑是不是我们的app有毛病
当所有准备工作都做好后,就可以开始编写业务代码了

登录

1.首先,创建一个调用微信登录的方法:

private void wxLogin() {
    mIWXAPI = BaseApplication.sIWXAPI;
    if (!mIWXAPI.isWXAppInstalled()) {  //调用此方法判断是否安装了微信
        Toast.makeText(this, "未安装微信客户端,无法使用微信登录", Toast.LENGTH_SHORT).show();
        return;
    }
    SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo";
    req.state = "longli_wx_login";
    mIWXAPI.sendReq(req);   //此方法将调起微信
}

可以看出只用4行代码就可以调起微信登录了。IWXAPI的sendReq方法是你的app向微信发送数据的通道,其中的req.scope构建SendAuth.Req的必需变量,详细说明可以在官网文档文档中找到:
Android接入微信登录、分享、支付
此时,如果之前设置的签名没问题的话,应该能成功调起微信的授权界面了。经过授权后,微信会调用sendResp方法向你的app发送数据,我们需要在WXEntryActivity中处理返回的数据

2.完善WXEntryActivity,处理结果
微信向我们的app发送完消息后会调用WXEntryActivity中的onResp方法。因此我们需要重写以下4个方法:

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
    ***
    private IWXAPI api;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        api = BaseApplication.sIWXAPI;
        api.handleIntent(getIntent(), this);
        ***
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
        ***
    }

    @Override
    public void onReq(BaseReq baseReq) {
        ***
    }

    @Override
    public void onResp(BaseResp baseResp) {     //接收返回的数据
        if (baseResp != null) {
            if (baseResp instanceof SendAuth.Resp) {     //认证授权的响应
                if (baseResp.getType() == ConstantsAPI.COMMAND_SENDAUTH) {  //响应的类型是授权类型
                    switch (baseResp.errCode) { //判断返回的错误码,以下3种是比较常见的
                        case BaseResp.ErrCode.ERR_OK:   //用户允许授权
                            String state = ((SendAuth.Resp) baseResp).state;
                            String code = ((SendAuth.Resp) baseResp).code;
                            if (!TextUtils.isEmpty(state)) {
                                if (state.equals("longli_wx_login")) {
                                    //当state和此前设置的req.state相同是就证明请求成功。
                                    //我们的目的是拿到code去进行下一步的操作
                                    //todo
                                }
                            }
                            break;
                        case BaseResp.ErrCode.ERR_USER_CANCEL:  //用户放弃授权
                            //todo
                            break;
                        case BaseResp.ErrCode.ERR_AUTH_DENIED:  //用户拒绝授权
                           //todo
                            break;
                        default:
                            break;
                    }
                    finish();
                }
            }
        }
    }
}

返回数据的详细说明如下:
Android接入微信登录、分享、支付

最后就可以通过判断baseResp.errCode的值来实现不同的操作。如果是用户授权成功,那么就可以把获得的code传回去,还有记得finish掉这个Activity.

3.利用上一步获得的code去换取openId
如果你公司的后台小哥是比较有经验的话,你就可以直接把这个code传给他,然后他就会自己去获取openId和相关微信用户的信息,最后通过业务后台接口返回用户的token给你, 这样就实现了微信登录流程了,这种方式是比较合理和简单的。

如果后台偷懒,一定要你在app端实现获取openId的功能的话,那就只能根据官方文档去做了。(因为这种方式略显麻烦和不合理,这里就省略了,并且建议你可以准备跳槽了)

分享

由于分享和登录都是共用WXEntryActivity来处理响应,所以先写出调起分享功能的代码,再去完善WXEntryActivity中的回调方法。微信可以分享文字、图片、音乐、视频、网页等到朋友圈或者聊天窗口,相关官方说明和示例代码可以看这里。调起分享的方法是一样的,不同的只是一些变量。本次示例是分享一张图片
1.创建调起分享功能的方法(也可以封装成一个工具类)

public void sharePhoto(Bitmap bm) {
    IWXAPI mIWXAPI = BaseApplication.sIWXAPI;
    WXImageObject mImgObj = new WXImageObject(bm);  //分享图片
    Bitmap thumb = Bitmap.createScaledBitmap(bm, width, height, true);  //创建缩略图bitmap

    WXMediaMessage mMediaMsg = new WXMediaMessage();
    mMediaMsg.mediaObject = mImgObj;    //设置原图对象
    mMediaMsg.thumbData = bmpToByteArray(thumb, true);  //设置缩略图对象

    SendMessageToWX.Req req = new SendMessageToWX.Req();
    req.transaction = System.currentTimeMillis() + ".img";
    req.message = mMediaMsg;
    req.scene = SendMessageToWX.Req.WXSceneSession; //分享到聊天界面

    mIWXAPI.sendReq(req);   //发送到微信
}

2.在WXEntryActivity处理分享结果

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
    ***

    //分享也是在这个方法内处理响应
    @Override
    public void onResp(BaseResp baseResp) {
        ***
        if (baseResp instanceof SendMessageToWX.Resp) {       //微信分享
            if (baseResp.getType() == ConstantsAPI.COMMAND_SENDMESSAGE_TO_WX) {     //响应的类型是发消息类型
                switch (baseResp.errCode) {
                    case BaseResp.ErrCode.ERR_OK:   //成功分享
                        //分享结束后,如果选择了"留在微信",则不会有此回调
                        //todo
                        break;
                    case BaseResp.ErrCode.ERR_USER_CANCEL:  //用户取消分享
                        //todo
                        break;
                    default:
                        break;
                }
            finish();
            }
        }
    }
}

分享流程结束

支付

支付需要比登录和分享多做一步工作:将要支付的的金额传给业务后台,然后获取以下参数去继续完成支付流程:
Android接入微信登录、分享、支付
官方示例:APP端开发说明

1.当获取到所需参数后,创建一个调起支付的方法:

private void wxPay(Param param) {   //Param是你从业务后台获取的实体类
    IWXAPI mIWXAPI = BaseApplication.sIWXAPI;
    if (!mIWXAPI.isWXAppInstalled()) {
        Toast.makeText(GameCoinActivity.this, "未安装微信客户端,无法使用微信支付", Toast.LENGTH_SHORT).show();
        return;
    }
    PayReq payReq = new PayReq();
    payReq.appId = "你的AppID";
    payReq.partnerId = param.getPartnerid();
    payReq.prepayId = param.getPrepayid();
    payReq.nonceStr = param.getNoncestr();
    payReq.timeStamp = param.getTimestamp();
    payReq.packageValue = param.getPackages();
    payReq.sign = param.getSign();
    mIWXAPI.sendReq(payReq);    //调起微信支付
}

2.在之前创建的WXPayEntryActivity处理支付结果
示例代码:

public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
    ***
    private IWXAPI api;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        api = BaseApplication.sIWXAPI;
        api.handleIntent(getIntent(), this);
        ***
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
        ***
    }

    @Override
    public void onReq(BaseReq baseReq) {
        ***
    }

    @Override
    public void onResp(BaseResp baseResp) {
        ***
        if(baseResp != null && baseResp instanceof PayResp) {   //支付的响应
            if(baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {  //响应的类型是支付类型
                switch (baseResp.errCode) {
                    case BaseResp.ErrCode.ERR_OK:           //支付成功
                        //todo
                        break;
                    case BaseResp.ErrCode.ERR_COMM:         //支付失败
                        //todo
                        break;
                    case BaseResp.ErrCode.ERR_USER_CANCEL:  //用户取消支付
                        //todo
                        break;
                    default:
                        break;
                }
                finish();
            }
        }
    }
}

到此,原生微信SDK三大功能已经接入,cheers!

Responses