Android Wechat Login, Sharing, Payment

Posted by networkthis on Sat, 25 May 2019 02:09:10 +0200

Reproduction requires well-known sources:

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

Previously, I wrote the first edition of Weimai Login Sharing Payment:

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

Preface

Most app s have the need to access third-party sdk s. For example, third party login requires access to Weixin, QQ and Weibo. The third party payment needs access to WeChat, Alipay and UnionPay.

I have used all of these, and have used their sdk. The most troublesome thing is Weixin, which can not be debugged directly. It can only be debugged by using formal signature. And their official demo couldn't run because there were no signatures. There are many things to be noted.

code implementation

Wechat sdk now supports Android Studio online references, which used to be the way to add jar s. We need to access the interface of Wechat to get user information, so we also refer to the okhttp we encapsulated earlier online. Okhttp needs to initialize this in a custom Application, so I won't post the code. I've talked about it many times before. Add the following two lines of code to the dependencies tag of the app/build.gradle file:

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

You need to use the network, so add network privileges to the AndroidManifest.xml file:

<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="The information is displayed here after login."/>

    <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="Nickname?:"/>

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

    <Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="WeChat login"/>

    <Button
        android:id="@+id/btn_share_friend_circle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Share in the circle of friends"/>

    <Button
        android:id="@+id/btn_share_friend"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Share it with friends"/>

    <Button
        android:id="@+id/btn_pay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="WeChat payment"/>
</LinearLayout>

The layout file is very simple. Just put a few TextView s and buttons in Linear Layout.

WeiXin.java is used for EventBus to send messages. One strange thing about Wechat sdk is that it uses an activity to receive messages regardless of login, share and payment, so we have to pass the result information through EventBus to MainActivity from the activity we receive. Although broadcasting can also be achieved, individuals prefer to use EventBus, which is flexible. Simple and lightweight.

public class WeiXin {
    private int type;//1: Login 2. Share 3: Wechat Payment
    private int errCode;//Error code returned by wechat
    private String code;//code only if login succeeds

    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 Constant class. The values of Wechat appid and secret are stored in two constants. I've changed these two values to protect privacy.

public class Constant {
    public static String WECHAT_APPID="wxda6db2aec81389af";
    public static String WECHAT_SECRET="8fed5a2d510022587ef8a6194c965be3";
}

MainActivity.java all the code pasted out is messy, temporarily pasted out part of the MainActivity code.

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private IWXAPI wxAPI;
    private TextView tvNickname,tvAge;
    public static final int IMAGE_SIZE=32768;//Wechat Sharing Picture Size Limitation

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

        EventBus.getDefault().register(this);//register
        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://WeChat login
                login();
                break;
            case R.id.btn_share_friend_circle://Wechat Shares with Friends
                share(true);
                break;
            case R.id.btn_share_friend://Wechat Sharing to Friends
                share(false);
                break;
            case R.id.btn_pay://WeChat payment
//              First go to the server to get payment information, return a WeiXinPay object, and then call the pay method
                showToast("Wechat Payment Needs Server Support");
                break;
        }
    }

    /**
     * The EventBus framework is used here
     * @param weiXin
     */
    @Subscribe
    public void onEventMainThread(WeiXin weiXin){
        Log.i("ansen","Received eventbus request type:"+weiXin.getType());
        if(weiXin.getType()==1){//Sign in
            getAccessToken(weiXin.getCode());
        }else if(weiXin.getType()==2){//share
            switch (weiXin.getErrCode()){
                case BaseResp.ErrCode.ERR_OK:
                    Log.i("ansen", "Wechat Shares Success.....");
                    break;
                case BaseResp.ErrCode.ERR_USER_CANCEL://Share cancel
                    Log.i("ansen", "Wechat Sharing Canceled.....");
                    break;
                case BaseResp.ErrCode.ERR_AUTH_DENIED://Sharing rejected
                    Log.i("ansen", "Wechat Sharing Rejected.....");
                    break;
            }
        }else if(weiXin.getType()==3){//WeChat payment
            if(weiXin.getErrCode()==BaseResp.ErrCode.ERR_OK){//Success
                Log.i("ansen", "Wechat Payment Successful.....");
            }
        }
    }
    
    ..........

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);//Cancellation of registration
    }
}
  • onCreate registers EventBus, creates IWX API classes through WXAPIFactory, registers appid, and sets click events for four buttons. Find two TextView s that show names and ages.
  • onClick clicks on event monitoring, judges clicking on different buttons according to id, and jumps to the corresponding methods, which are not posted, and will be discussed separately.
  • onEventMainThread(WeiXin weiXin) is used to receive messages. This method has a parameter to determine the type, that is, when we send with EventBus, the parameter must be WeiXin type. First, decide whether to log in or share or pay. If the login is successful, we will get the code. According to the code, we can get the information of micro-credit users.
  • Show Toast Toast prompt
  • onDestroy cancels EventBus registration

WeChat login

Wechat login process has three steps:

  • Wechat Authorized Landing
  • Get the user token according to the authorized login code
  • Obtain user information from token

When we click the login button, we call the login method. This method is in MainActivity. It is to launch a login request for Wechat and pop up an authorization interface.

public void login(){
    SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo";
    req.state = String.valueOf(System.currentTimeMillis());
    wxAPI.sendReq(req);
}

Create a new wxapi directory under your package name, and then add a new WXEntryActivity class under the wxapi directory to receive login authorization and callback information for sharing tweets. This class inherits from Activity and needs to implement the IWXAPIEventHandler interface.

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){//share
            Log.i("ansen","Wechat Sharing Operation.....");
            WeiXin weiXin=new WeiXin(2,resp.errCode,"");
            EventBus.getDefault().post(weiXin);
        }else if(resp.getType()==ConstantsAPI.COMMAND_SENDAUTH){//Land
            Log.i("ansen", "Wechat login operation.....");
            SendAuth.Resp authResp = (SendAuth.Resp) resp;
            WeiXin weiXin=new WeiXin(1,resp.errCode,authResp.code);
            EventBus.getDefault().post(weiXin);
        }
        finish();
    }
}

The three methods of onCreate, onNewIntent and onReq are fixed writing. The onResp method receives the result information of Wechat. First, it determines the type and encapsulates WeiXin objects according to different types. If it is a login operation, it passes in the code, and then sends the encapsulated WeiXin objects through EventBus. MainActivity's onEventMainThread method receives this message. Finally, call finish to close the current activity.

WXEntry Activity remembers to register in Android Manifest. XML

<activity
    android:exported="true"
    android:name=".wxapi.WXEntryActivity"/>

Continue back to onEventMainThread on the home page, if the login type calls getAccessToken(), and passes in the code. Access_token is obtained according to code. This url is open to Wechat. It needs to pass in three parameters, appid, secret and code. When the request succeeds, information such as access_token and openid will be returned.

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){//Request successful
                getWeiXinUserInfo(obj);
            }else{//request was aborted
                showToast(obj.getErrmsg());
            }
        }
    });
}

After obtaining access_token and openid, continue to call the getWeiXinUserInfo method to get user information. In this way, we can get some information about the users who are currently logged in by Wechat app. There are basic information such as nickname, age, Avatar address, language and so on. In enterprise development, at this stage, you can use this information to call the login interface of your server. Of course, we show the nickname and age to TextView on this side.

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("Nickname?:"+obj.getNickname());
            tvAge.setText("Age:"+obj.getAge());
            Log.i("ansen","Head address:"+obj.getHeadimgurl());
        }
    });
}

The two entity classes WeiXinToken and WeiXinInfo no longer stick codes. WeiXinToken is used to map the json returned from accessing the token interface. WeiXinInfo is used to map the json returned from the user interface.

WeChat share

There are two kinds of sharing to friends and to friends, calling share method in a unified way. Input a boolean type to determine whether to share in the circle of friends.

public void share(boolean friendsCircle){
    WXWebpageObject webpage = new WXWebpageObject();
    webpage.webpageUrl = "www.baidu.com";//Share url
    WXMediaMessage msg = new WXMediaMessage(webpage);
    msg.title = "Share title";
    msg.description = "Sharing description";
    msg.thumbData =getThumbData();//Cover image byte array

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

Sharing content has many formats, such as sharing pictures, videos and news. Let's take sharing news as an example. It's also a common format for sharing. First, new is a WX Web pageObject object, setting the title, content, opening links, cover, etc. Finally, call sendReq of the wxAPI to relax a request.

Sharing, like login, calls back WXEntryActivity and sends the results to the MainActivity.onEventMainThread method.

payment
Payment begins with requesting our own servers for payment information. Call the pay method after obtaining success.

public void pay(WeiXinPay weiXinPay){
    PayReq req = new PayReq();
    req.appId = Constant.WECHAT_APPID;//appid
    req.nonceStr=weiXinPay.getNoncestr();//Random string, not longer than 32 bits. Recommended Random Number Generation Algorithms
    req.packageValue=weiXinPay.getPackage_value();//Fill in the fixed value Sign=WXPay temporarily
    req.sign=weiXinPay.getSign();//autograph
    req.partnerId=weiXinPay.getPartnerid();//Wechat Payment Distribution Business Number
    req.prepayId=weiXinPay.getPrepayid();//Payment transaction session ID returned by Wechat
    req.timeStamp=weiXinPay.getTimestamp();//time stamp

    wxAPI.registerApp(Constant.WECHAT_APPID);
    wxAPI.sendReq(req);
}

The weiXinPay value should be obtained from our own server, then encapsulated the return information into the PayReq object, and finally invoked the sendReq method of the Wx API to initiate the request.

In the wxapi directory, a new WXPayEntry Activity class is added, which is the same level as WXEntry Activity and receives the callback information of Wechat Payment. This class inherits from Activity and needs to implement the IWXAPIEventHandler interface.

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", "Wechat Payment Callback Returns Error Code:"+resp.errCode+" Wrong name:"+resp.errStr);
        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX){//WeChat payment
            WeiXin weiXin=new WeiXin(3,resp.errCode,"");
            EventBus.getDefault().post(weiXin);
        }
        finish();
    }
}

Other methods are fixed writing. In onResp, if it is a Wechat login, it will encapsulate a WeiXin object and send an EventBus request. This way, the onEventMainThread of MainActivity will receive the WeiXin object.

WXPayEntry Activity remembers to register in Android Manifest. xml.

<activity
    android:exported="true"
    android:name=".wxapi.WXPayEntryActivity"/>

The project structure diagram is shown below, from which we can see that the package name is com.ansen.shoenet. The package name of the Activity returned from the receipt of Wechat login payment must be com.ansen.shoenet.wxapi. The names of the two activities are also fixed.

autograph

There is a signature verification for Weichat login and share payment, which is very troublesome, leading to re-signature for every debugging.

First, use android studio to generate a formal signature file. The signature file is at the end of. jks. This signature file is what you will use in your future online package. The signature file is then used to generate the apk. At this time, our app will be officially signed. Send the signed APK to the mobile phone for installation.

And download a signature generation tool installation, which is used to get the apk package of third-party application signatures installed on the mobile phone. Official download address of Wechat:

https://res.wx.qq.com/open/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android2.apk

After the above two apps are installed, open the app downloaded from Wechat. The software name is GenSignature. There is an input box, enter the package name of our software, and click the Get Signature button.

Save that line of green hexadecimal numbers in txt text.

Background Configuration of Wechat sdk Official Network

Official address:

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

In the home page of Wechat sdk, a management center clicks on the default is the mobile application, if it has not created a mobile application first, if it has, click the view button behind the current application, it will enter the application details interface.

Scroll down to the bottom of the application details interface with development information. Click on the modification and enter the modification interface. Scroll to the bottom of the modification interface. The effect chart is as follows:

First, we tick the Android application and fill in the application signature, which is the value I asked you to save on the notebook. The package name is the app package name. Click Save.

Running software

After login, the effect is as follows:

Share in the circle of friends as follows:

Share it with friends:

Wechat payment cannot be tested because of the need for server support.

Official Development Document of Wechat

This part of my article only aims at the sdk version access of Wechat, but the sdk may change, version change, interface change and so on. So it is suggested that we should focus on official documents. My article provides a reference.

Mobile Application Wechat Login Development Guide

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 Wechat Payment Development Manual

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317784&token=219192a54f13e8e7011ced8e4ce5b36b699629c4&lang=zh_CN

Matters needing attention

There are many things to pay attention to when accessing the Wechat sdk. Here we conclude with a summary.

  • Active package name and class name must be written strictly in accordance with the requirements of Weixin landing, sharing and payment callback.
  • The callback is that Activity must be registered in Android Manifest. XML
  • The two constants in Constant have to be applied for by Wechat and created by the application. Here you need to change the value of your application.
  • You need to access the network, so remember to add permissions in AndroidManifest.xml
  • Call Weixin login, share, pay your installation package must have a signature, signature information must be consistent with the signature information you configure on Weixin official website.
  • Wechat does not have customer service support.... If something goes wrong, look at the official Demo or the official API.
  • Wechat SDK is often upgraded. If you have the latest one when you develop it, use the latest one.

Last but not least

You can't run my demo directly, because you don't have a jks file, can't sign, and the appid and secret in the source code have been modified by me, can't be used, but you may want to see the effect of the operation, so I built an apk folder under the project, which contains an apk installation package that can test the Weixin login and share.

Source download

Topics: Android SDK xml Mobile