微信登录支付

http://blog.csdn.net/lowprofile_coding/article/details/78004224

微信sdk现在支持Android Studio在线引用了,之前都是添加jar的方法。需要访问微信的接口获取用户信息,所以把我们之前封装的okhttp也一起在线引用。okhttp需要在自定义的Application中初始化这个我就不贴代码了。之前已经讲过很多次。在app/build.gradle文件dependencies标签中加入以下两行代码:

compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
compile 'com.ansen.http:okhttpencapsulation:1.0.1'
  
  
  • 1
  • 2

需要用到网络,所以在AndroidManifest.xml文件中加入网络权限:

<uses-permission android:name="android.permission.INTERNET" />
  
  
  • 1

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录之后信息在这里显示"/>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_nickname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="昵称:"/>

        <TextView
            android:id="@+id/tv_age"
            android:layout_below="@+id/tv_nickname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="年龄:"/>
    </RelativeLayout>

    <Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="微信登录"/>

    <Button
        android:id="@+id/btn_share_friend_circle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="分享到朋友圈"/>

    <Button
        android:id="@+id/btn_share_friend"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="分享给好友"/>

    <Button
        android:id="@+id/btn_pay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="微信支付"/>
</LinearLayout>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

布局文件很简单,就LinearLayout里面放了几个TextView,跟几个按钮。

WeiXin.java 用于EventBus来传送消息,微信sdk有个很奇怪的地方,就是不管登录、分享、支付之后都得用一个Activity来接收,所以我们还得从接收的那个activity把结果信息通过EventBus传递给MainActivity。虽然用广播也能实现,但是个人喜欢用EventBus,使用灵活。简单轻量。

public class WeiXin {
    private int type;//1:登录 2.分享 3:微信支付
    private int errCode;//微信返回的错误码
    private String code;//登录成功才会有的code

    public WeiXin() {
    }

    public WeiXin(int type,int errCode, String code) {
        this.type = type;
        this.errCode=errCode;
        this.code = code;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public int getErrCode() {
        return errCode;
    }

    public void setErrCode(int errCode) {
        this.errCode = errCode;
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

Constant.java 常量类,微信appid跟secret的值用两个常量保存。为了保护隐私这两个值我已经修改过。

public class Constant {
    public static String WECHAT_APPID="wxda6db2aec81389af";
    public static String WECHAT_SECRET="8fed5a2d510022587ef8a6194c965be3";
}
  
  
  • 1
  • 2
  • 3
  • 4

MainActivity.java 全部代码贴出来比较乱,暂时贴出MainActivity部分代码。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private IWXAPI wxAPI;
    private TextView tvNickname,tvAge;
    public static final int IMAGE_SIZE=32768;//微信分享图片大小限制

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EventBus.getDefault().register(this);//注册
        wxAPI = WXAPIFactory.createWXAPI(this,Constant.WECHAT_APPID,true);
        wxAPI.registerApp(Constant.WECHAT_APPID);

        findViewById(R.id.btn_login).setOnClickListener(this);
        findViewById(R.id.btn_share_friend_circle).setOnClickListener(this);
        findViewById(R.id.btn_share_friend).setOnClickListener(this);
        findViewById(R.id.btn_pay).setOnClickListener(this);

        tvNickname= (TextView) findViewById(R.id.tv_nickname);
        tvAge=(TextView) findViewById(R.id.tv_age);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_login://微信登录
                login();
                break;
            case R.id.btn_share_friend_circle://微信分享到朋友圈
                share(true);
                break;
            case R.id.btn_share_friend://微信分享给朋友
                share(false);
                break;
            case R.id.btn_pay://微信支付
//              先去服务器获取支付信息,返回一个WeiXinPay对象,然后调用pay方法
                showToast("微信支付需要服务器支持");
                break;
        }
    }

    /**
     * 这里用到的了EventBus框架
     * @param weiXin
     */
    @Subscribe
    public void onEventMainThread(WeiXin weiXin){
        Log.i("ansen","收到eventbus请求 type:"+weiXin.getType());
        if(weiXin.getType()==1){//登录
            getAccessToken(weiXin.getCode());
        }else if(weiXin.getType()==2){//分享
            switch (weiXin.getErrCode()){
                case BaseResp.ErrCode.ERR_OK:
                    Log.i("ansen", "微信分享成功.....");
                    break;
                case BaseResp.ErrCode.ERR_USER_CANCEL://分享取消
                    Log.i("ansen", "微信分享取消.....");
                    break;
                case BaseResp.ErrCode.ERR_AUTH_DENIED://分享被拒绝
                    Log.i("ansen", "微信分享被拒绝.....");
                    break;
            }
        }else if(weiXin.getType()==3){//微信支付
            if(weiXin.getErrCode()==BaseResp.ErrCode.ERR_OK){//成功
                Log.i("ansen", "微信支付成功.....");
            }
        }
    }

    ..........

    public void showToast(String message){
        Toast.makeText(this,message,Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);//取消注册
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • onCreate 注册EventBus,通过WXAPIFactory创建IWXAPI类,并且注册appid,给四个按钮按钮设置点击事件。查找显示名字跟年龄的两个TextView。
  • onClick 点击事件监听,根据id来判断点击不同的按钮,跳转到相应的方法,这些方法没贴出来来,等会单独讲。
  • onEventMainThread(WeiXin weiXin) 用来接收消息,这个方法有个参数,用来判断类型,就是我们用EventBus发送时参数必须是WeiXin类型。首先判断type,是登录还是分享还是支付。登录成功情况下会获取到code,根据code然后我们就能获取到微信用户信息。
  • showToast Toast提示
  • onDestroy 取消EventBus注册

微信登录

微信登录流程有以下三个步骤: 
- 微信授权登陆 
- 根据授权登陆code 获取该用户token 
- 根据token获取用户资料

当我们点击登录按钮的时候,调用的是login方法。这个方法就在MainActivity里面。就是给微信发起一个登录请求,弹出一个授权界面。

public void login(){
    SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo";
    req.state = String.valueOf(System.currentTimeMillis());
    wxAPI.sendReq(req);
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在你的包名相应目录下新建一个wxapi目录,然后在wxapi目录下新增一个WXEntryActivity类,用来接收登录授权以及分享时微信的回调信息。这个类继承自Activity,需要实现IWXAPIEventHandler接口。

package com.ansen.shoenet.wxapi;
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
    private IWXAPI wxAPI;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        wxAPI = WXAPIFactory.createWXAPI(this,Constant.WECHAT_APPID,true);
        wxAPI.registerApp(Constant.WECHAT_APPID);
        wxAPI.handleIntent(getIntent(), this);
    }

    @Override
    protected void onNewIntent(Intent intent){
        super.onNewIntent(intent);
        wxAPI.handleIntent(getIntent(),this);
        Log.i("ansen","WXEntryActivity onNewIntent");
    }

    @Override
    public void onReq(BaseReq arg0) {
        Log.i("ansen","WXEntryActivity onReq:"+arg0);
    }

    @Override
    public void onResp(BaseResp resp){
        if(resp.getType()== ConstantsAPI.COMMAND_SENDMESSAGE_TO_WX){//分享
            Log.i("ansen","微信分享操作.....");
            WeiXin weiXin=new WeiXin(2,resp.errCode,"");
            EventBus.getDefault().post(weiXin);
        }else if(resp.getType()==ConstantsAPI.COMMAND_SENDAUTH){//登陆
            Log.i("ansen", "微信登录操作.....");
            SendAuth.Resp authResp = (SendAuth.Resp) resp;
            WeiXin weiXin=new WeiXin(1,resp.errCode,authResp.code);
            EventBus.getDefault().post(weiXin);
        }
        finish();
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

onCreate、onNewIntent、onReq这三个方法是固定写法。onResp方法接收微信结果信息,首先判断类型,根据不同的类型去封装WeiXin对象,如果是登录操作,把code传入进去,然后把封装好的WeiXin对象通过EventBus发送出去。MainActivity的onEventMainThread方法就会接收到这个消息。最后调用finish关闭当前的activity。

WXEntryActivity记得在AndroidManifest.xml中注册

<activity
    android:exported="true"
    android:name=".wxapi.WXEntryActivity"/>
  
  
  • 1
  • 2
  • 3

继续回到首页的onEventMainThread,如果登录类型调用getAccessToken(),并且传入code。根据code获取access_token,这个url是微信公开的,需要传入三个参数,appid、secret、code。请求成功之后会返回access_token跟openid等信息。

public void getAccessToken(String code){
    String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
            "appid="+Constant.WECHAT_APPID+"&secret="+Constant.WECHAT_SECRET+
            "&code="+code+"&grant_type=authorization_code";
    HTTPCaller.getInstance().get(WeiXinToken.class, url, null, new RequestDataCallback<WeiXinToken>() {
        @Override
        public void dataCallback(WeiXinToken obj) {
            if(obj.getErrcode()==0){//请求成功
                getWeiXinUserInfo(obj);
            }else{//请求失败
                showToast(obj.getErrmsg());
            }
        }
    });
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

获取到access_token跟openid之后继续调用getWeiXinUserInfo方法获取用户信息。这样就能取到当前微信app登录的用户一些信息。有昵称、年龄、头像地址、语言等基本信息。在企业开发中,到了这一步就可以拿着这些信息调用自己服务器的登录接口。当然我们这边就把昵称跟年龄给TextView显示下。

public void getWeiXinUserInfo(WeiXinToken weiXinToken){
    String url = "https://api.weixin.qq.com/sns/userinfo?access_token="+
            weiXinToken.getAccess_token()+"&openid="+weiXinToken.getOpenid();
    HTTPCaller.getInstance().get(WeiXinInfo.class, url, null, new RequestDataCallback<WeiXinInfo>() {
        @Override
        public void dataCallback(WeiXinInfo obj) {
            tvNickname.setText("昵称:"+obj.getNickname());
            tvAge.setText("年龄:"+obj.getAge());
            Log.i("ansen","头像地址:"+obj.getHeadimgurl());
        }
    });
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

WeiXinToken跟WeiXinInfo这两个实体类就不贴代码了,WeiXinToken用来映射获取访问token接口返回的json。WeiXinInfo用来映射获取用户接口返回的json。

微信分享

分享有两种分享到朋友圈跟分享给好友,统一调用share方法。传入一个boolean类型来判断是否分享到朋友圈。


  • 感谢分享1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值