<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Android微信登錄、分享、支付

      轉載需要著名出處:

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

      之前寫過微信登錄分享支付第一版:

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

      前言

      大部分的app都有接入第三方sdk的需求。例如第三方登錄需要接入微信、QQ、微博。第三方支付需要接入微信、支付寶、銀聯。

      這些我都有使用過,都有使用過他們的sdk,感覺最麻煩的就是微信,不能直接調試,得用正式的簽名進行簽名才能調試。還有他們官方的demo也是跑不起來的,因為沒有簽名文件。需要注意的地方也很多。

      代碼實現

      微信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'
      

      需要用到網絡,所以在AndroidManifest.xml文件中加入網絡權限:

      <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,跟幾個按鈕。

      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;
          }
      }
      

      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);//取消注冊
          }
      }
      
      • 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);
      }
      

      在你的包名相應目錄下新建一個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的名字也是固定寫法。

      project_structure

      簽名

      微信登錄分享支付都有一個簽名驗證,這個很麻煩,導致每次調試都需要重新簽名。

      首先用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按鈕.效果圖如下:
      get_signature

      把那行綠色的16進制數炒下來保存到txt文本中。

      微信sdk官網后臺配置

      官網地址:

      https://open.weixin.qq.com/
      

      在微信sdk首頁,有個管理中心點擊之后默認就是移動應用,如果還沒有創建移動應用就先創建一個,如果有了就點擊當前的應用后面的查看按鈕,就會進入應用詳細界面。

      在應用詳細界面一直往下滾動,滾到最底部有個開發信息。點擊修改,進入修改界面,在修改界面滾動到最下面,效果圖如下所示:
      app_info
      首先我們在Android應用這里打上勾,然后填寫應用簽名,這個簽名都是我之前要你們保存到記事本上的那個值,包名就是app包名。點擊保存。

      運行軟件

      登錄之后效果圖如下:

      login_success

      分享到朋友圈如下:

      share_friend_circle

      分享給朋友:

      share_friend

      微信支付沒法測試,因為需要服務器支持。

      微信官方開發文檔

      我這偏文章只是針對現在微信的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有很多需要注意的地方,這里我們最后再來做一個總結。

      • 微信登陸,分享,支付回調的Activity包名跟類名一定要嚴格按照要求去寫
      • 接收回調的是Activity一定要在AndroidManifest.xml中中注冊
      • Constant里面兩個常量的值要去微信申請并且創建應用才有的,這里需要改成你們申請的值。
      • 需要訪問網絡所以記得在AndroidManifest.xml中添加權限
      • 調用微信的登陸,分享,支付你的安裝包一定要有簽名,簽名信息一定要跟你在微信官網上配置的簽名信息一致
      • 微信沒有客服支持.....如果出了問題看官方的Demo或者官方API
      • 微信SDK經常升級,如果你開發的時候有最新的就用最新的吧.....

      最后的最后

      你們直接運行我的demo是不行的,因為你們沒有的jks文件,沒法簽名,并且源碼中的appid跟secret被我修改過了,是不能使用的,但是你們可能又想看運行效果,所以我在項目下建了個apk文件夾,里面放了一個可以測試微信登錄分享的apk安裝包。

      源碼下載

      如果你想第一時間看我的后期文章,掃碼關注公眾號,每周不定期推送Android開發實戰教程文章...

            Android開發666 - 安卓開發技術分享
                   掃描二維碼加關注
      

      Android開發666

      posted @ 2017-09-16 16:14  安輝  閱讀(10726)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 中文字幕日韩精品有码| 成人国产精品日本在线观看| 日本电影一区二区三区| 国内揄拍国内精品对久久| 国产一二三五区不在卡| 云龙县| 蜜桃久久精品成人无码av| 欧美人与动人物牲交免费观看| 日韩av综合中文字幕| av在线播放无码线| 九九久久自然熟的香蕉图片| 亚洲国产av区一区二| 一区二区三区精品偷拍| 黄平县| 国产成人精品一区二区秒拍1o| 久久综合久中文字幕青草| 安达市| 97久久久精品综合88久久| 欧美视频在线播放观看免费福利资源| 日韩有码精品中文字幕| 亚洲国产成人无码影片在线播放| 精品熟女亚洲av在线观看| 亚洲va久久久噜噜噜久久狠狠| 99久久亚洲综合精品成人网| 精品久久久久国产免费| 亚洲老妇女亚洲老熟女久| 国产在线乱子伦一区二区| 欧美老少配性行为| 亚洲高清av一区二区| 国产成人精品一区二区秒拍1o| 欧洲精品码一区二区三区| 久久精品国产亚洲av麻豆不卡| 荃湾区| 中文字幕无码不卡在线| 国产精品自拍一二三四区| 亚洲欧美综合中文| 国内自拍视频一区二区三区| 风韵丰满熟妇啪啪区老熟熟女| 粉嫩一区二区三区粉嫩视频| 四虎永久精品在线视频| 人妻综合专区第一页|