天天看點

Android調用微信登陸、分享、支付

前言:用了微信sdk各種痛苦,感覺比qq sdk調用麻煩多了,回調過于麻煩,還必須要在指定包名下的actvity進行回調,是以我在這裡寫一篇部落格,有這個需求的朋友可以借鑒一下,以後自己别的項目有用到也有個找資料的地方.

一.微信登陸分三個步驟:

  1).微信授權登陸

  2).根據授權登陸code 擷取該使用者token

  3).根據token擷取使用者資料

  4).接收微信的請求及傳回值 如果你的程式需要接收微信發送的請求,或者接收發送到微信請求的響應結果,需要下面3步操作:

  a. 在你的包名相應目錄下建立一個wxapi目錄,并在該wxapi目錄下新增一個wxentryactivity類,該類繼承自activity(例如應用程式的包名為net.sourceforge.simcpux,

        則新添加的類如下圖所示)

Android調用微信登陸、分享、支付

        并在manifest檔案裡面加上exported屬性,設定為true,例如:

Android調用微信登陸、分享、支付

      b. 實作iwxapieventhandler接口,微信發送的請求将回調到onreq方法,發送到微信請求的響應結果将回調到onresp方法

      c. 在wxentryactivity中将接收到的intent及實作了iwxapieventhandler接口的對象傳遞給iwxapi接口的handleintent方法,示例如下圖:

Android調用微信登陸、分享、支付

    微信官網登陸教程:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=&lang=zh_cn

    微信官網接入指南:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417751808&token=&lang=zh_cn

二.微信分享直接調用sdk就行,回調跟登陸回調的類是一樣的,根據baseresp的類型來區分是登陸還是分享。

三.微信支付

    1).發送一個支付請求

    2).接收微信支付的傳回值(跟接收微信登陸.分享的傳回值類似,我就不寫詳細操作步驟了) 

        官網參考位址:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_5 

四.貼上代碼進行講解

    我把微信登陸,分享,支付都封裝到了一個類裡面了,你們可以參考這個類.封裝了6個方法,我對幾個需要的方法介紹一下

    1).構造方法:初始化對象的時候,順便初始化微信對象,把app_id注冊到微信

    2).login()  發起一個登陸的請求  在微信登陸監聽actviity中擷取code

    3).getaccesstoken(string code)  當你從監聽activity中擷取了code之後就可以通過這個方法擷取微信通路token了

    4).getweixinuserinfo(final weixintoken obj)  擷取微信使用者資訊   傳入一個weixintoken對象,這個對象是第三步的傳回值

    5).share(final boolean friendscircle,final videob videob)   分享給朋友或者朋友圈  如果你有分享圖檔,圖檔過大的時候一定要經過壓縮,微信官網說明圖檔不能大

         于32kb

    6).iswxappinstalled()  檢查微信是否安裝

    7).wxpay(final baseactivity activity,string order_id,string paytype)  微信支付   我們項目微信支付的一些參數儲存在伺服器上,是以我這邊還請求了自己的

        伺服器,如果你們是放在本地,直接copy回調函數裡面的代碼即可.在微信支付監聽actviity中擷取支付的狀态碼

        payreq類屬性對應含義請參考微信官方文檔:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_12

/** 

 * 微信分享,登陸,支付 

 * @author ansen  

 * @create time 2015-08-29 

 */  

public class weixinpresenter extends presenter{  

    public static final int image_size=32768;//微信分享圖檔大小限制  

    public static final string app_id = "";//應用唯一辨別,在微信開放平台送出應用稽核通過後獲得  

    public static final string secret="";//應用密鑰appsecret,在微信開放平台送出應用稽核通過後獲得  

    private  iwxapi wxapi;  

    private  iview iview;  

    private  iusercontroller usercontroller;  

    @override  

    public iview getiview() {  

        return iview;  

    }  

    public weixinpresenter(context context){  

        if(context!=null && context instanceof  iview)  

            iview =(iview) context;  

        if(wxapi==null){  

            wxapi = wxapifactory.createwxapi(context,app_id,true);  

            wxapi.registerapp(app_id);  

        }  

        if(null==usercontroller)  

            usercontroller=controllerfactory.getusercontroller();  

    /** 

     * 微信登陸(三個步驟) 

     * 1.微信授權登陸 

     * 2.根據授權登陸code 擷取該使用者token 

     * 3.根據token擷取使用者資料 

     * @param activity 

     */  

    public void login(){  

        sendauth.req req = new sendauth.req();  

        req.scope = "snsapi_userinfo";  

        req.state = string.valueof(system.currenttimemillis());  

        wxapi.sendreq(req);  

     * 擷取微信通路token 

    public void getaccesstoken(string code){  

        if(!usercontroller.islogin()){//沒有登陸的情況用第三方登陸  

            usercontroller.getweixinaccesstoken(app_id,secret,code,new requestdatacallback<weixintoken>(){  

                @override  

                public void datacallback(weixintoken obj){  

                    if(obj!=null){  

                        if(obj.geterrcode()==0){  

                            if(mlog.debug)  

                                iview.showtoast("授權使用者唯一辨別:"+obj.getopenid());  

                            getweixinuserinfo(obj);  

                        }else{  

                            iview.showtoast(obj.geterrmsg());  

                        }  

                    }else{  

                    }  

                }  

            });  

        }else{//使用者已登陸  

     * 擷取微信使用者資訊 

    private void getweixinuserinfo(final weixintoken obj){  

        usercontroller.getweixinuserinfo(obj.getaccess_token(), obj.getopenid(), new requestdatacallback<registerb>() {  

            @override  

            public void datacallback(registerb registerb){  

                registerb.setaccess_token(obj.getaccess_token());  

                registerb.settoken_expire_at(obj.getexpires_in());  

                if(registerb.geterrcode()==0){  

                    registerb.setthird_type_name(constants.wei_xin);  

                    thirdlogin(registerb);  

                }else{  

                    iview.showtoast(registerb.geterrmsg());  

            }  

        });  

     * 調用我們自己的伺服器進行登入 

     * @param registerb 

    private void thirdlogin(registerb registerb){  

        usercontroller.thirdauth(registerb,new requestdatacallback<userp>(){  

            public void datacallback(userp user){  

                if(checkcallbackdata(user, true)){  

                    if(user.geterror()==user.errornone){  

                        iview.showtoast(r.string.login_success);  

                        getappcontroller().sendloginchangeintent();  

                        usercontroller.saveloginuser(user,fileutil.getfilepath());  

                        ((iloginview)iview).tomain();  

                        iview.showtoast(user.geterror_reason());  

     * 微信分享 

     * @param friendscircle  是否分享到朋友圈 

    public void share(final boolean friendscircle,final  videob videob){  

        new loadpicthread(videob.getcover_url(),new handler(){  

            public void handlemessage(message msg) {  

                byte[] bytes=(byte[]) msg.obj;  

                if(bytes.length>image_size){  

                    iview.showtoast(r.string.image_no_big);  

                    return;  

                system.out.println("圖檔長度:"+bytes.length);  

                wxvideoobject videoobject = new wxvideoobject();//視訊類型  

                videoobject.videourl = videob.getshare_url() + constants.wei_xin + "&share_from="+com.kaka.utils.constants.android;// 視訊播放url  

                wxmediamessage wxmessage = new wxmediamessage(videoobject);  

                wxmessage.title = videob.getcontent();  

                wxmessage.thumbdata = bytes;  

                sendmessagetowx.req req = new sendmessagetowx.req();  

                //transaction字段用于唯一辨別一個請求  

                req.transaction = string.valueof(videob.getid() + system.currenttimemillis());  

                req.message = wxmessage;  

                req.scene = friendscircle ? sendmessagetowx.req.wxscenetimeline : sendmessagetowx.req.wxscenesession;  

                wxapi.sendreq(req);  

        }).start();  

    private class loadpicthread extends thread{  

        private string url;  

        private handler handler;  

        public loadpicthread(string url,handler handler){  

            this.url=url;  

            this.handler=handler;  

        @override  

        public void run(){  

            try {  

                url picurl = new url(url);   

                httpurlconnection conn = (httpurlconnection)picurl.openconnection(); // 獲得連接配接   

                conn.setconnecttimeout(6000);//設定逾時   

                conn.setdoinput(true);   

                conn.setusecaches(false);//不緩存   

                conn.connect();  

                bitmap bmp=bitmapfactory.decodestream(conn.getinputstream());  

                bytearrayoutputstream output = new bytearrayoutputstream();  

                bmp.compress(bitmap.compressformat.jpeg, 100, output);  

                int options = 100;  

                while (output.tobytearray().length > image_size && options != 10) {   

                    output.reset();  // 清空baos  

                    bmp.compress(bitmap.compressformat.jpeg, options, output);// 這裡壓縮options%,把壓縮後的資料存放到baos中    

                    options -= 10;  

                bmp.recycle();  

                byte[] result = output.tobytearray();  

                output.close();  

                message message=handler.obtainmessage();  

                message.obj=result;  

                message.sendtotarget();  

            } catch (exception e) {  

                e.printstacktrace();  

    //檢查微信是否安裝  

    public boolean iswxappinstalled(){  

        return wxapi.iswxappinstalled();  

    public void wxpay(final baseactivity activity,string order_id,string paytype){  

        activity.showprogress("");  

        controllerfactory.getwalletscontroller().getpayments(order_id, paytype, new requestdatacallback<paymentsp>() {  

            public void datacallback(paymentsp obj) {  

                if(checkcallbackdata(obj, true)){  

                    if(obj.geterror()==obj.errornone){  

                        payreq req = new payreq();//待修改  

                        req.appid = obj.getappid();  

                        req.noncestr=obj.getnoncestr();  

                        req.packagevalue=obj.getpackage_value();  

                        req.sign=obj.getsign();  

                        req.partnerid=obj.getpartnerid();  

                        req.prepayid=obj.getprepayid();  

                        req.timestamp=obj.gettimestamp();  

                        wxapi.registerapp(obj.getappid());  

                        wxapi.sendreq(req);  

                        mlog.i("ansen", "開始進行微信支付..");  

                        iview.showtoast("開始進行微信支付..");  

                    iview.showtoast(obj.geterror_reason());  

                activity.hideprogress();  

}  

微信登陸以及分享 請求跟傳回值的接收   我這邊登陸.分享的狀态都是發送廣播出去,然後結束目前的activity.

 * 微信登陸分享回調activity 

 * @author ansen 

 * @create time 2015-05-25 

public class wxentryactivity extends activity implements iwxapieventhandler{  

    private iwxapi wxapi;  

    protected void oncreate(bundle savedinstancestate) {  

        super.oncreate(savedinstancestate);  

        if(mlog.debug)  

            system.out.println("wxentryactivity oncreate");  

        wxapi = wxapifactory.createwxapi(this,weixinpresenter.app_id,true);  

        wxapi.registerapp(weixinpresenter.app_id);  

        wxapi.handleintent(getintent(), this);  

    protected void onnewintent(intent intent){  

        super.onnewintent(intent);  

        wxapi.handleintent(getintent(),this);  

            system.out.println("wxentryactivity onnewintent");  

    public void onreq(basereq arg0) {  

            system.out.println("wxentryactivity onreq:"+arg0);  

            toast.maketext(this, "onreq 方法運作", 0).show();  

    public void onresp(baseresp resp){  

        mlog.d("ansen", "onresp.....");  

            toast.maketext(this,"onresp 方法運作", 0).show();  

        if(resp.gettype()==constantsapi.command_sendmessage_to_wx){//分享  

            switch (resp.errcode){  

            case baseresp.errcode.err_ok:  

                    if(mlog.debug)  

                        toast.maketext(wxentryactivity.this, "分享成功!", toast.length_short).show();  

                break;  

            case baseresp.errcode.err_user_cancel:  

//                toast.maketext(wxentryactivity.this, "分享取消!", toast.length_short).show();  

            case baseresp.errcode.err_auth_denied:  

            intent intent = new intent();  

            intent.setaction(apidefineconst.broadcast_action_weixin_share);  

                localbroadcastmanager lbm = localbroadcastmanager.getinstance(this);  

                lbm.sendbroadcast(intent);  

        }else if(resp.gettype()==constantsapi.command_sendauth){//登陸發送廣播  

                sendauth.resp authresp = (resp) resp;  

            string code = authresp.code;  

            intent.setaction(apidefineconst.broadcast_action_weixin_token);  

            intent.putextra("errcode", authresp.errcode);  

            if (authresp.errcode == baseresp.errcode.err_ok){//使用者同意  

                    intent.putextra("code", code);  

                if(mlog.debug)  

                    toast.maketext(this, "wxentryactivity 發送登陸廣播!!!!", 0).show();  

                if (android.os.build.version.sdk_int >= 12) {  

                     intent.setflags(32);//3.1以後的版本需要設定intent.flag_include_stopped_packages  

        finish();  

微信支付 請求跟傳回值的接收   微信支付也是發送廣播,如果你們還有需求判斷支付成功或者失敗,可以在廣播的intent中進行傳參

 * 微信支付回調activity 

public class wxpayentryactivity extends activity  implements iwxapieventhandler{  

        wxapi = wxapifactory.createwxapi(this, weixinpresenter.app_id);  

        setintent(intent);  

        wxapi.handleintent(intent, this);  

    public void onresp(baseresp resp) {  

        mlog.i("微信支付回調..", "ansen onresp");  

        if (resp.gettype() == constantsapi.command_pay_by_wx){//微信支付回調  

            if(resp.errcode==baseresp.errcode.err_ok){//微信支付成功  

                intent intent = new intent();  

                intent.setaction(apidefineconst.broadcast_action_weixin_pay);  

                    localbroadcastmanager lbm = localbroadcastmanager.getinstance(this);  

                    lbm.sendbroadcast(intent);  

                //成功  

//              toast.maketext(this,r.string.wxpay_success, 0).show();  

            }else{  

強調一點,一定要注意 接收微信的請求及傳回值 的包名跟類名,包名是應用程式的包名+".wxapi"  類名必須是微信指定的類名   并且這兩個activity一定要在androidmanifest.xml中注冊,上傳一張是我做的app中包名跟類名的截圖

Android調用微信登陸、分享、支付

如何在activity中調用微信登陸

1).登陸廣播監聽内部類  如果接收到了廣播就去擷取微信token

private class wxentryreceiver extends broadcastreceiver {  

    public void onreceive(context context, intent intent){  

        mlog.i("wxentryreceiver", "接收微信登陸廣播");  

            showtoast("接收微信登陸廣播");  

        if(intent.getaction().equals(apidefineconst.broadcast_action_weixin_token)){  

            int errcode = intent.getextras().getint("errcode");  

            if(mlog.debug)  

                system.out.println("擷取錯誤碼:"+errcode);  

            if(errcode==baseresp.errcode.err_user_cancel||errcode==baseresp.errcode.err_auth_denied){  

                requestdatafinish();  

                string code = intent.getextras().getstring("code");  

                xintestpresenter.getaccesstoken(code);  

2).定義成員變量

private wxentryreceiver wxentryreceiver=null;  

3).在oncreate中注冊廣播

//微信登陸廣播  

wxentryreceiver= new wxentryreceiver();  

localbroadcastmanager lbm = localbroadcastmanager.getinstance(this);  

intentfilter filter = new intentfilter();  

filter.addaction(apidefineconst.broadcast_action_weixin_token);  

lbm.registerreceiver(wxentryreceiver,filter);  

4).調用微信登陸

weixinpresenter xintestpresenter=new weixinpresenter(this);  

xintestpresenter.login();  

在activity中調用微信分享跟調用微信支付的代碼我就不貼出來了,我這篇部落格隻是給大家一個參考的地方,遇到問題還是建議第一時間看官方文檔.

說說我在做微信登陸碰到的問題

1.微信登陸、分享、支付    回調的activity    包名跟類名一定要嚴格按照要求去寫

2.接收回調的是activity  一定要在androidmanifest.xml中注冊

3.weixinpresenter中有兩個常量   app_id跟secret  要去微信申請的時候才有的.你們copy代碼的時候要給這兩個常量指派

4.可能通路網絡神馬的還需要一些權限   記得在androidmanifest.xml添權重限

5.調用微信的登陸、分享、支付   你的安裝包一定要有簽名,簽名資訊一定要跟你在微信官網上申請時簽名資訊一緻

6.微信沒有客服支援。。。。。如果出了問題看官方demo   或者 官方api

7.微信sdk經常更新,如果你開發的時候有最新的就用最新的吧.....

說了那麼多,感覺說了一大堆廢話......希望能幫到大家....有神馬問題可以給我留言....

推薦下自己建立的android qq群:202928390 歡迎大家的加入.

繼續閱讀