很多App都是需要用户登录的,例如电商类的APP,用户登录后可以查看自己的购物订单,浏览痕迹等,登陆的话又可以分为多种登录,例如QQ,微信,微博,支付宝等,那么接下来这篇文章讲诉的是应用如何调用微信的支付接口;
要想调用微信登录或者支付等接口首先要在微信公共平台申请一个账号,这是链接微信公众平台,然后再管理中心跟着提示申请一个应用,申请应用的时候包名要跟自己创建的项目的报名一致,否则无法使用,然后就是应用签名,应用签名的话可以下载一个软件到手机上,然后运行自己的项目,两者必须要在同一部手机,然后再软件上输入自己项目的包名,就可以拿到应用签名了(应用链接GenSignature)
应用审核的话一般是一周以内,审核通过之后你就会拿到一个APP_ID和APP_SECRET,这两个在项目里面非常重要,这意味着你的应用能不能调用微信登录接口
创建一个constanst类,用来放APP_ID和APP_SECRET
public class Constants {
// APP_ID 替换为你的应用从官方网站申请到的合法appID
public static final String APP_ID = "XXXXXXXXX";
public static final String APP_SECRET = "XXXXXXXXXXX";
}
移动应用微信登录是基于OAuth2.0协议标准 构建的微信OAuth2.0授权登录系统。微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。
这个是获取access_token时序图:
首先要在MainActivity中的onCreate函数中注册
private void regToWx(){
api = WXAPIFactory.createWXAPI(this,Constants.APP_ID,false);
api.registerApp(Constants.APP_ID);
}
然后先创建WXEntryActivity类
然后重写两个方法onReq以及onResp
在这个类的onCreate函数中接收登录的intent传递handleIntent方法
//接收到分享以及登录的intent传递handleIntent方法,处理结果
api = WXAPIFactory.createWXAPI(this,Constants.APP_ID,false);
api.handleIntent(getIntent(),this);
接下来在onRep()方法里获取回调
用户点击授权后,微信客户端会被拉起,跳转至授权界面,用户在该界面点击允许或取消,SDK通过SendAuth的Resp返回数据给调用方
@Override
//请求回调结果处理
public void onResp(BaseResp baseResp) {
//登录回调
switch (baseResp.errCode){
case BaseResp.ErrCode.ERR_OK:
String code = ((SendAuth.Resp) baseResp).code;
//获取accesstoken
getAccessToken(code);
break;
//用户拒绝授权
case BaseResp.ErrCode.ERR_AUTH_DENIED:
finish();
break;
//用户取消授权
case BaseResp.ErrCode.ERR_USER_CANCEL:
finish();
break;
}
}
通过code来获取access_token,请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
这个是请求上面这个链接返回的正确结果
//access_token 接口调用凭证
//expires_in access_token接口调用凭证超时时间,单位(秒)
//refresh_token 用户刷新access_token
//openid 授权用户唯一标识
//scope 用户授权的作用域,使用逗号(,)分隔
//unionid 当且仅当该移动应用已获得该用户的userinfo授权时,才会出现该字段
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
请求的代码
private void getAccessToken(String code) {
//新建一个progressDialog,避免长时间白屏(因为在进行多次网络请求)造成卡死的假象
// createProgressDialog();
/**
* access_token:接口调用凭证
* appid:应用唯一标识,在微信开放平台提交应用审核通过后获得。
* secret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得。
* code:填写第一步获取的code参数。
* grant_type:填authorization_code。
*/
StringBuffer loginUrl = new StringBuffer();
loginUrl.append("https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code")
.append("?appid=")
.append(Constants.APP_ID)
.append("&secret=")
.append(Constants.APP_SECRET)
.append("&code=")
.append(code)
.append("&grant_type=authorization_code");
Log.d("urlurl", loginUrl.toString());
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
//传入url
.url(loginUrl.toString())
//默认也是发起get请求
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: Fail");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseInfo = response.body().string();
Log.d(TAG, "onResponse: Success");
String access = null;
String openId = null;
//用json去解析返回来的access和token值
try {
JSONObject jsonObject = new JSONObject(responseInfo);
access = jsonObject.getString("access_token");
openId = jsonObject.getString("openid");
Log.d(TAG, "onResponse:"+access + " " + openId);
} catch (JSONException e) {
e.printStackTrace();
}
getUserInfo(access, openId);
}
});
}
access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:
//如果请求成功,我们通过JSON解析获取access和token值,再通过getUserInfo(access, openId)方法获取用户信息
private void getUserInfo(String access,String openid){
String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access + "&openid=" + openid;
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(getUserInfoUrl)
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: Fail(getUserInfo)");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseInfo = response.body().string();
//用SharedPreference来缓存字符串
SharedPreferences.Editor editor = getSharedPreferences("userInfo",MODE_PRIVATE).edit();
editor.putString("responseInfo",responseInfo);
editor.commit();
finish();
}
});
}
MainActivity,重写onResume()
@Override
protected void onResume() {
super.onResume();
String name = null;
String sex = null;
String city = null;
SharedPreferences sharedPreferences = getSharedPreferences("userInfo", MODE_PRIVATE);
String response = sharedPreferences.getString("responseInfo","");
if (!response.isEmpty()){
try {
JSONObject jsonObject = new JSONObject(response);
/**
* 这里可以返回如下数据
* openid 普通用户的标识,对当前开发者帐号唯一
* nickname 普通用户昵称
* sex 普通用户性别,1为男性,2为女性
* province 普通用户个人资料填写的省份
* city 普通用户个人资料填写的城市
* country 国家,如中国为CN
* headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
* privilege 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
* unionid 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。
*/
name = jsonObject.getString("nickname");
sex = jsonObject.getString("sex");
city = jsonObject.getString("city");
} catch (JSONException e) {
e.printStackTrace();
}
tv_city.setText("城市:" + city);
tv_sex.setText("性别:" + sex);
tv_username.setText("用户名:" + name);
}
}
附上全部代码
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
// IWXAPI 是第三方app和微信通信的openApi接口
private IWXAPI api;
private ImageView mImageView;
private TextView tv_sex,tv_city,tv_username;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//onCreate里注册应用
regToWx();
//初始化控件
initView();
//点击按钮,拉起微信登录
mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//先判断用户的手机有没有安装微信,没有的话就弹个Toast
if (!api.isWXAppInstalled()){
Toast.makeText(MainActivity.this,"你的设备没有安装微信,请先下载微信",Toast.LENGTH_SHORT).show();
}else {
//如果有安装则直接发起请求
final SendAuth.Req req = new SendAuth.Req();
//scope是应用授权作用域,如获取用户个人信息则填写snsapi_userinfo
req.scope = "snsapi_userinfo";
//state用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击)
// 建议第三方带上该参数,可设置为简单的随机数加session进行校验
req.state = "wechat_sdk_demo_test";
//发起请求
api.sendReq(req);
}
}
});
}
private void initView() {
mImageView = findViewById(R.id.WeChat_Login);
tv_sex = findViewById(R.id.Sex);
tv_city = findViewById(R.id.City);
tv_username = findViewById(R.id.User_id);
}
private void regToWx(){
api = WXAPIFactory.createWXAPI(this,Constants.APP_ID,false);
api.registerApp(Constants.APP_ID);
}
@Override
protected void onResume() {
super.onResume();
String name = null;
String sex = null;
String city = null;
SharedPreferences sharedPreferences = getSharedPreferences("userInfo", MODE_PRIVATE);
String response = sharedPreferences.getString("responseInfo","");
if (!response.isEmpty()){
try {
JSONObject jsonObject = new JSONObject(response);
/**
* 这里可以返回如下数据
* openid 普通用户的标识,对当前开发者帐号唯一
* nickname 普通用户昵称
* sex 普通用户性别,1为男性,2为女性
* province 普通用户个人资料填写的省份
* city 普通用户个人资料填写的城市
* country 国家,如中国为CN
* headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
* privilege 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
* unionid 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。
*/
name = jsonObject.getString("nickname");
sex = jsonObject.getString("sex");
city = jsonObject.getString("city");
} catch (JSONException e) {
e.printStackTrace();
}
tv_city.setText("城市:" + city);
tv_sex.setText("性别:" + sex);
tv_username.setText("用户名:" + name);
}
}
}
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {
private IWXAPI api;
public static final String TAG = "Log:";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//隐藏状态栏并获取wxapi
getSupportActionBar().hide();
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
//接收到分享以及登录的intent传递handleIntent方法,处理结果
api = WXAPIFactory.createWXAPI(this,Constants.APP_ID,false);
api.handleIntent(getIntent(),this);
}
@Override
public void onReq(BaseReq baseReq) {
}
@Override
//请求回调结果处理
public void onResp(BaseResp baseResp) {
//登录回调
switch (baseResp.errCode){
case BaseResp.ErrCode.ERR_OK:
String code = ((SendAuth.Resp) baseResp).code;
//获取accesstoken
getAccessToken(code);
break;
//用户拒绝授权
case BaseResp.ErrCode.ERR_AUTH_DENIED:
finish();
break;
//用户取消授权
case BaseResp.ErrCode.ERR_USER_CANCEL:
finish();
break;
}
}
private void getAccessToken(String code) {
//新建一个progressDialog,避免长时间白屏(因为在进行多次网络请求)造成卡死的假象
// createProgressDialog();
/**
* access_token:接口调用凭证
* appid:应用唯一标识,在微信开放平台提交应用审核通过后获得。
* secret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得。
* code:填写第一步获取的code参数。
* grant_type:填authorization_code。
*/
StringBuffer loginUrl = new StringBuffer();
loginUrl.append("https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code")
.append("?appid=")
.append(Constants.APP_ID)
.append("&secret=")
.append(Constants.APP_SECRET)
.append("&code=")
.append(code)
.append("&grant_type=authorization_code");
Log.d("urlurl", loginUrl.toString());
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
//传入url
.url(loginUrl.toString())
//默认也是发起get请求
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: Fail");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseInfo = response.body().string();
Log.d(TAG, "onResponse: Success");
String access = null;
String openId = null;
//用json去解析返回来的access和token值
try {
JSONObject jsonObject = new JSONObject(responseInfo);
access = jsonObject.getString("access_token");
openId = jsonObject.getString("openid");
Log.d(TAG, "onResponse:"+access + " " + openId);
} catch (JSONException e) {
e.printStackTrace();
}
getUserInfo(access, openId);
}
});
}
//如果请求成功,我们通过JSON解析获取access和token值,再通过getUserInfo(access, openId)方法获取用户信息
private void getUserInfo(String access,String openid){
String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access + "&openid=" + openid;
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(getUserInfoUrl)
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: Fail(getUserInfo)");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseInfo = response.body().string();
//用SharedPreference来缓存字符串
SharedPreferences.Editor editor = getSharedPreferences("userInfo",MODE_PRIVATE).edit();
editor.putString("responseInfo",responseInfo);
editor.commit();
finish();
}
});
}
}
public class Constants {
// APP_ID 替换为你的应用从官方网站申请到的合法appID
public static final String APP_ID = "wxf380bfb3deb2735f";
public static final String APP_SECRET = "cc25489c2e2ad9ccf0aeb4122d12a9f5";
}
别忘了权限