美文网首页androidAndroid
Android 接入微信登录、分享、支付指南

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

作者: 展大侠 | 来源:发表于2016-12-28 16:07 被阅读1594次

1. 申请AppID

请到 开发者应用登记页面 进行登记,登记并选择移动应用进行设置后,将该应用提交审核,只有审核通过的应用才能进行开发。

  • 申请开发者资质认证,年费300RMB。
  • 创建应用,审核通过后即可使用微信登录、分享功能(需要应用的包名和签名)。
  • 微信支付需要额外开通。

审核速度一般很快,1-2个工作日即可完成。建议审核完成后再接入调试,否则可能会产生各种各样的奇葩错误,甚至无法正常唤起。
注意:微信开发平台和公众号平台是不同的两个平台,账号不能互通。

2. 下载SDK及API文档

微信SDK改成通过Gradle的方式发布到jcenter,包名做了相应修改,从原来的com.tencent.mm.sdk修改为com.tencent.mm.opensdk,需要开发者修改对应的import语句。
build.gradle文件中,添加如下依赖即可:

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

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

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

3. 搭建开发环境

在Android Studio中新建你的工程,并保证网络设置可以成功从jcenter下载微信SDK即可。

4. 在代码中使用开发工具包

[1] 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"/>

[2] 注册到微信

要使你的程序启动后微信终端能响应你的程序,必须在代码中向微信终端注册你的id。如下图所示,可以在程序入口Activity的onCreate回调函数处,或其他合适的地方将你的应用id注册到微信。注册函数示例如下图所示。

Paste_Image.png

[3] 发送请求或响应到微信

现在,你的程序要发送请求或发送响应到微信终端,可以通过IWXAPI的sendReqsendResp两个方法来实现。
boolean sendReq(BaseReq req)
sendReq是第三方app主动发送消息给微信,发送完成之后会切回到第三方app界面。
boolean sendResp(BaseResp resp)
sendResp是微信向第三方app请求数据,第三方app回应数据之后会切回到微信界面。
sendReq的实现示例,如下图所示:

Paste_Image.png

具体要发送的内容由第三方app开发者定义,具体可参考微信开发工具包中的SDK Sample Demo源码。

[4] 接收微信的请求及返回值

如果你的程序需要接收微信发送的请求,或者接收发送到微信请求的响应结果,需要下面3步操作:

a. 在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类,该类继承自Activity(例如应用程序的包名为net.sourceforge.simcpux,则新添加的类如下图所示)

Paste_Image.png

并在manifest文件里面加上exported属性,设置为true,例如:

Paste_Image.png
b. 实现IWXAPIEventHandler接口,微信发送的请求将回调到onReq方法,发送到微信请求的响应结果将回调到onResp方法。

c. 在WXEntryActivity中将接收到的intent及实现了IWXAPIEventHandler接口的对象传递给IWXAPI接口的handleIntent方法,示例如下图:

Paste_Image.png

当微信发送请求到你的应用,将通过IWXAPIEventHandler接口的onReq方法进行回调,类似的,应用请求微信的响应结果将通过onResp回调。

5. 代码混淆

为了保证sdk的正常使用,需要在proguard.cfg加上配置:

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

以上是官方文档,接下来是私货。

Android Studio调试时默认会给应用加上Debug签名,这个签名和正式版的Release签名是不同的。只有当应用的签名和开发者平台创建应用时所填的签名一致时才能正常使用,可以测试时使用一个签名,正式上线时修改成正式版的签名。得益于Gradle的足够强大,我们可以使用Release版签名来调试app。

6. 配置方法:

[1] 创建签名文件

AS中,选择 **Build->Generate Signed APK **

[2] 配置Gradle自动打包

拷贝签名文件到app目录下,打开app的build.gradle文件,在android节点下增加如下内容:

android {
    ……
  //签名参数配置
    signingConfigs {
        release {
            storeFile file('keystore.jks') //签名文件
            storePassword ' 123456789 ' //密码
            keyAlias 'jensen' //别名
            keyPassword '123456789' //别名密码
        }
    }
    buildTypes {
        debug {
            //使用Release版签名
            signingConfig signingConfigs.release
        }
        release {
            minifyEnabled true //开启压缩
            shrinkResources true //压缩Resources资源
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
  ……
}

storeFile file:签名文件,如果放在其他路径,需要对应修改
storePassword:密码
keyAlias:别名
keyPassword:别名密码

然后重新build一下工程,展开右边栏Gradle选项卡,如下所示:

Paste_Image.png
assembleRelease,即为正式签名。双击assembleRelease,则会开始执行命令:
执行完毕后展开工程的build文件夹,可以看到app-release.apk即为正式版签名的app。
下次调试的时候就带正式签名了,选择app,不要选底下两个奇怪的东西( ̄m ̄)。 Paste_Image.png

7. 微信分享

  • 分享文字
private void shareText(int shareType, ShareContent shareContent) {
        String text = shareContent.getContent();
        //初始化一个WXTextObject对象
        WXTextObject textObj = new WXTextObject();
        textObj.text = text;
        //用WXTextObject对象初始化一个WXMediaMessage对象
        WXMediaMessage msg = new WXMediaMessage();
        msg.mediaObject = textObj;
        msg.description = text;
        //构造一个Req
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        //transaction字段用于唯一标识一个请求
        req.transaction = buildTransaction("textshare");
        req.message = msg;
        //发送的目标场景, 可以选择发送到会话 WXSceneSession 或者朋友圈 WXSceneTimeline。 默认发送到会话。
        req.scene = shareType;
        wxApi.sendReq(req);
    }
  • 分享链接
 private void shareWebPage(int shareType, ShareContent shareContent) {
        WXWebpageObject webpage = new WXWebpageObject();
        webpage.webpageUrl = shareContent.getURL();
        WXMediaMessage msg = new WXMediaMessage(webpage);
        msg.title = shareContent.getTitle();
        msg.description = shareContent.getContent();

        //不添加图片时默认使用申请appId时上传的图片
        //Bitmap thumb = BitmapFactory.decodeResource(mContext.getResources(), shareContent.getPicResource());
        //if(thumb == null){
        //Toast.makeText(mContext, "图片不能为空", Toast.LENGTH_SHORT).show();
        //}else{
        //msg.thumbData = WeixiShareUtil.bmpToByteArray(thumb, true);}
       
        SendMessageToWX.Req req = new SendMessageToWX.Req();
        req.transaction = buildTransaction("webpage");
        req.message = msg;
        req.scene = shareType;
        wxApi.sendReq(req);
    }

8. 微信登录

注册到微信时建议传入Application作为Context防止内存泄漏

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ......
        IWXAPI api = WXAPIFactory.createWXAPI(getApplicationContext(),Constants.WX_APP_ID, false);
        //最后的参数选ture或false都能够正常使用
        api.registerApp(Constants.WX_APP_ID);
        api.handleIntent(intent, this); //很重要,不要漏了!
    }

    //重写onNewIntent()方法
    @Override
    protected void onNewIntent(Intent intent) {    
        super.onNewIntent(intent);    
        setIntent(intent);    
        api.handleIntent(intent, this);//很重要!
    }

[1] 请求code

在需要微信登录的地方:

private void loginWithWeChat() {
     if (api == null) {
        api = WXAPIFactory.createWXAPI(getApplicationContext(), Constants.WX_APP_ID, false);
    }
    if (!api.isWXAppInstalled()) {//检查是否安装了微信              
        ToastTool.showToast("没有安装微信");    
        return;
    }
    api.registerApp(Constants.WX_APP_ID);
    SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo";//官方固定写法
    req.state = "com.jensen.example";//自定义一个字串
    api.sendReq(req);
}

参数说明

Paste_Image.png

点击之后,向微信发送了请求,会自动跳转到微信的界面,也就是下面的这张图片,这个界面是微信已经写好了的,我们就不用操心了。

Paste_Image.png

返回说明

Paste_Image.png

[2] 通过code获取access_token

利用微信返回的code去请求access_token,在onResp方法下请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

Paste_Image.png

返回说明

{ 
  "access_token":"XXXXXXXXXXXXXXXXXXXX", //接口调用凭证
  "expires_in":7200, //access_token接口调用凭证超时时间,单位(秒)
  "refresh_token":"XXXXXXXXXXXXXXXXXXXX",//用户刷新access_token
  "openid":"XXXXXXXXXX", //授权用户唯一标识
  "scope":"XXXXXXXXXX"//用户授权的作用域,使用逗号(,)分隔
 }

附上WXEntryActivity.java里面的代码:

public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {


    private IWXAPI api;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        api = WXAPIFactory.createWXAPI(getApplicationContext(), Constants.WX_ID, false);
        api.registerApp(Constants.WX_ID);
        api.handleIntent(getIntent(), this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (api != null) {
            api.unregisterApp();
            api.detach();
        }
    }

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

    @Override
    public void onReq(BaseReq req) {}

    @Override
    public void onResp(BaseResp resp) {
        switch (resp.errCode) {
            case BaseResp.ErrCode.ERR_AUTH_DENIED:
            case BaseResp.ErrCode.ERR_USER_CANCEL:
                if (RETURN_MSG_TYPE_SHARE == resp.getType()){
                    showToastMsg("分享失败"); 
                }else {
                    showToastMsg("登录失败");
                }
                break;
            case BaseResp.ErrCode.ERR_OK:
                switch (resp.getType()) { 
                    case RETURN_MSG_TYPE_LOGIN: 
                    //拿到了微信返回的code,立马再去请求access_token 
                        String code = ((SendAuth.Resp) resp).code; 
                         //就在这个地方,用网络库什么的或者自己封的网络api,发请求去咯,注意是get请求 
                        break; 
                    case RETURN_MSG_TYPE_SHARE: 
                        AppData.showToast("微信分享成功"); 
                        finish(); 
                        break; 
                } 
                break;
        }
    }
}

微信验证登录到这里就差不多了,验证的主要目的就是拿到微信给的这个access_token,用来调用微信的各种接口,可以获取用户的基本信息等等。

注意:微信登录返回时默认会回到WXEntryActivity界面,当然你也可以不给该界面设置布局文件,在回调中写好跳转即可。

9. 微信支付

在wxapi目录下新建WXPayEntryActivity,实现IWXAPIEventHandler接口,结构同WXENtryActivity相同,原理同上。
注意:微信支付需要额外开通!需要额外开通!需要额外开通!否则无法唤起!

代码:

PayReq payRequest = new PayReq();
payRequest.appId = Constants.WX_APP_ID;
payRequest.partnerId = partnerid;//商户号
payRequest.prepayId = prepayid;//预支付订单号
payRequest.packageValue = "Sign=WXPay";
payRequest.nonceStr = noncestr;//随机字符串
payRequest.timeStamp = timestamp;//时间戳
payRequest.sign = sign;//签名
api.sendReq(payRequest);

注意:这里用的商户号等是从服务端返回的信息。
支付的坑主要在于服务端,.生成sign时特别需要注意,首先将key-value键值对拼成字符串,注意key都要小写,如appid,noncestr,package,partnerid,prepayid,timestamp,key,并且名字得按上述名称
我自己在做的时候就是遇到了这个坑,开始怎么也调不起来,问了IOS的同学发现也是这样,最后才从服务端入手找到了这个坑。

10. 注意事项

  1. 请求登录,没有回调,可能是由于WXEntryActivity的onCreate()方法里面没有处理intent:api.handleIntent(getIntent(), this)
  2. 获取到code之后,一个code的寿命只有5分钟,而且只能用一次,如果重复利用就会出现{“errcode”:40029,”errmsg”:”invalid code”}的情况。
  3. 拿到code后,如果需要通过自己的服务器向微信发送获取access_token的请求,也要注意code只能用一次(当然不算你给自己服务器的那次),如果你们后台还承担着微信公众号的事务,则要小心不要将微信公众号的appidapp_secret与微信开放平台上的弄混了,否则也会返回{“errcode”:40029,”errmsg”:”invalid code”}

以上,有错误或者更好的方式还请指出来,谢谢。

相关文章

网友评论

本文标题:Android 接入微信登录、分享、支付指南

本文链接:https://www.haomeiwen.com/subject/mtghvttx.html