转载须要著名出处:html
http://blog.csdn.net/lowprofile_coding/article/details/78004224
以前写过微信登陆分享支付初版:java
http://blog.csdn.net/lowprofile_coding/article/details/48086381
大部分的app都有接入第三方sdk的需求。例如第三方登陆须要接入微信、QQ、微博。第三方支付须要接入微信、支付宝、银联。android
这些我都有使用过,都有使用过他们的sdk,感受最麻烦的就是微信,不能直接调试,得用正式的签名进行签名才能调试。还有他们官方的demo也是跑不起来的,由于没有签名文件。须要注意的地方也不少。git
微信sdk如今支持Android Studio在线引用了,以前都是添加jar的方法。须要访问微信的接口获取用户信息,因此把咱们以前封装的okhttp也一块儿在线引用。okhttp须要在自定义的Application中初始化这个我就不贴代码了。以前已经讲过不少次。在app/build.gradle文件dependencies标签中加入如下两行代码:github
compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+' compile 'com.ansen.http:okhttpencapsulation:1.0.1'
须要用到网络,因此在AndroidManifest.xml文件中加入网络权限:web
<uses-permission android:name="android.permission.INTERNET" />
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>
布局文件很简单,就LinearLayout里面放了几个TextView,跟几个按钮。json
WeiXin.java 用于EventBus来传送消息,微信sdk有个很奇怪的地方,就是无论登陆、分享、支付以后都得用一个Activity来接收,因此咱们还得从接收的那个activity把结果信息经过EventBus传递给MainActivity。虽然用广播也能实现,可是我的喜欢用EventBus,使用灵活。简单轻量。api
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; } }
Constant.java 常量类,微信appid跟secret的值用两个常量保存。为了保护隐私这两个值我已经修改过。数组
public class Constant { public static String WECHAT_APPID="wxda6db2aec81389af"; public static String WECHAT_SECRET="8fed5a2d510022587ef8a6194c965be3"; }
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);//取消注册 } }
微信登陆
微信登陆流程有如下三个步骤:
当咱们点击登陆按钮的时候,调用的是login方法。这个方法就在MainActivity里面。就是给微信发起一个登陆请求,弹出一个受权界面。
public void login(){ SendAuth.Req req = new SendAuth.Req(); req.scope = "snsapi_userinfo"; req.state = String.valueOf(System.currentTimeMillis()); wxAPI.sendReq(req); }
在你的包名相应目录下新建一个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(); } }
onCreate、onNewIntent、onReq这三个方法是固定写法。onResp方法接收微信结果信息,首先判断类型,根据不一样的类型去封装WeiXin对象,若是是登陆操做,把code传入进去,而后把封装好的WeiXin对象经过EventBus发送出去。MainActivity的onEventMainThread方法就会接收到这个消息。最后调用finish关闭当前的activity。
WXEntryActivity记得在AndroidManifest.xml中注册
<activity android:exported="true" android:name=".wxapi.WXEntryActivity"/>
继续回到首页的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()); } } }); }
获取到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()); } }); }
WeiXinToken跟WeiXinInfo这两个实体类就不贴代码了,WeiXinToken用来映射获取访问token接口返回的json。WeiXinInfo用来映射获取用户接口返回的json。
微信分享
分享有两种分享到朋友圈跟分享给好友,统一调用share方法。传入一个boolean类型来判断是否分享到朋友圈。
public void share(boolean friendsCircle){ WXWebpageObject webpage = new WXWebpageObject(); webpage.webpageUrl = "www.baidu.com";//分享url WXMediaMessage msg = new WXMediaMessage(webpage); msg.title = "分享标题"; msg.description = "分享描述"; msg.thumbData =getThumbData();//封面图片byte数组 SendMessageToWX.Req req = new SendMessageToWX.Req(); req.transaction = String.valueOf(System.currentTimeMillis()); req.message = msg; req.scene = friendsCircle ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession; wxAPI.sendReq(req); }
分享内容有不少格式,分享图片、分享视频、分享消息。咱们这边就分享消息为例,也是分享比较常见的格式。首先new一个WXWebpageObject对象,设置标题、内容、打开连接、封面等。最后调用wxAPI的sendReq放松一个请求。
分享跟登陆同样,都会回调WXEntryActivity,而后又把分享结果发送给MainActivity.onEventMainThread方法。
支付
支付首先须要请求咱们本身的服务器,获取支付信息。获取成功以后调用pay方法。
public void pay(WeiXinPay weiXinPay){ PayReq req = new PayReq(); req.appId = Constant.WECHAT_APPID;//appid req.nonceStr=weiXinPay.getNoncestr();//随机字符串,不长于32位。推荐随机数生成算法 req.packageValue=weiXinPay.getPackage_value();//暂填写固定值Sign=WXPay req.sign=weiXinPay.getSign();//签名 req.partnerId=weiXinPay.getPartnerid();//微信支付分配的商户号 req.prepayId=weiXinPay.getPrepayid();//微信返回的支付交易会话ID req.timeStamp=weiXinPay.getTimestamp();//时间戳 wxAPI.registerApp(Constant.WECHAT_APPID); wxAPI.sendReq(req); }
weiXinPay的值应该是咱们从本身服务器获取的,而后把返回信息封装到PayReq对象中,最后调用wxAPI的sendReq方法发起请求。
在wxapi目录下新增一个WXPayEntryActivity类,这个类跟WXEntryActivity同级,用来接收微信支付的回调信息。这个类继承自Activity,须要实现IWXAPIEventHandler接口。
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler { private IWXAPI wxAPI; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); wxAPI = WXAPIFactory.createWXAPI(this, Constant.WECHAT_APPID); wxAPI.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent){ super.onNewIntent(intent); setIntent(intent); wxAPI.handleIntent(intent, this); } @Override public void onReq(BaseReq baseReq) {} @Override public void onResp(BaseResp resp) { Log.i("ansen", "微信支付回调 返回错误码:"+resp.errCode+" 错误名称:"+resp.errStr); if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX){//微信支付 WeiXin weiXin=new WeiXin(3,resp.errCode,""); EventBus.getDefault().post(weiXin); } finish(); } }
其余方法都是固定写法,在onResp中判断若是是微信登陆,就封装一个WeiXin对象,而后发送EventBus请求。这样MainActivity的onEventMainThread就会接收到这个WeiXin对象。
WXPayEntryActivity记得在AndroidManifest.xml中注册。
<activity android:exported="true" android:name=".wxapi.WXPayEntryActivity"/>
项目结构图以下所示,从图中咱们看到软件包名是com.ansen.shoenet。接收微信登陆支付返回的Activity的包名必须是com.ansen.shoenet.wxapi。两个activity的名字也是固定写法。
微信登陆分享支付都有一个签名验证,这个很麻烦,致使每次调试都须要从新签名。
首先用android studio生成一个正式的签名文件,签名文件是.jks结尾的,这个签名文件是你之后打线上包一直要用到的。而后用这个签名文件生成apk。这个时候咱们的app就有了正式签名。把正式签名的apk发送到手机上进行安装。
而且下载一个签名生成工具安装,这个工具用于获取安装到手机的第三方应用签名的apk包。微信官方下载地址:
https://res.wx.qq.com/open/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android2.apk
以上两个app都安装好了以后打开从微信下载的那个app,软件名字叫「GenSignature」,有一个输入框,输入咱们软件的包名,点击Get Signature按钮.效果图以下:
把那行绿色的16进制数炒下来保存到txt文本中。
官网地址:
https://open.weixin.qq.com/
在微信sdk首页,有个管理中心点击以后默认就是移动应用,若是尚未建立移动应用就先建立一个,若是有了就点击当前的应用后面的查看按钮,就会进入应用详细界面。
在应用详细界面一直往下滚动,滚到最底部有个开发信息。点击修改,进入修改界面,在修改界面滚动到最下面,效果图以下所示:
首先咱们在Android应用这里打上勾,而后填写应用签名,这个签名都是我以前要大家保存到记事本上的那个值,包名就是app包名。点击保存。
登陆以后效果图以下:
分享到朋友圈以下:
分享给朋友:
微信支付无法测试,由于须要服务器支持。
我这偏文章只是针对如今微信的sdk版本接入,可是sdk是有可能变化的,版本变化、接口变化等。因此建议你们仍是以官方文档为主。个人文章提供参考。
移动应用微信登陆开发指南
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=219192a54f13e8e7011ced8e4ce5b36b699629c4&lang=zh_CN
Android微信支付开发手册
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317784&token=219192a54f13e8e7011ced8e4ce5b36b699629c4&lang=zh_CN
接入微信sdk有不少须要注意的地方,这里咱们最后再来作一个总结。
大家直接运行个人demo是不行的,由于大家没有的jks文件,无法签名,而且源码中的appid跟secret被我修改过了,是不能使用的,可是大家可能又想看运行效果,因此我在项目下建了个apk文件夹,里面放了一个能够测试微信登陆分享的apk安装包。
若是你想第一时间看个人后期文章,扫码关注公众号,每周不按期推送Android开发实战教程文章...
Android开发666 - 安卓开发技术分享 扫描二维码加关注