微信开发文档简直一神坑,网上也没几个跑的通的流程,讲解也没看见有几个详细的,所以决定整理一下微信公众号支付,关于微信的其他支付例如扫码和非微信内置浏览器H5支付这些,有时间的话会陆续更新,关于微信支付这边有没看懂的也可以骚扰QQ:1329538287
一、流程:
1. 已认证微信号,且通过微信支付认证,关于配置支付的路径最后会说到。
2. 公众号支付API中用户的openId是一个必须传送的参数,所以我们首先获取的是用户的openId。
2.1. 获取用户openId就是用户的授权,配置OAuth2.0网页授权。直接配置域名,例如:www.qq.com 不要加http:// 等协议头。这一点微信的API中说的很明白,在这里我们只要获取到用户的openId就可以了,第一步是获取code,用code去换取openId。
配置域名: 在公众号的接口权限中找到 网页授权 配置你的域名
获取code 参数 snsapi_base为静默授权,用户看不到界面 snsapi_userinfo此参数需要用户同意,可获取其用户信息
https://open.weixin.qq.com/connect/oauth2/authorize?
appid=XXXXX 这个是appid 可以在你微信公众平台中的 基础配置中找到
&
redirect_uri=这里填写的是回调地址 也就是微信登录后 返回访问的地址 一般会填写后台地址 因为回调是会带有code值然后后台可以通过code拿到 用户access_token *重点是回调地址需要使用urlEncode进行连接处理
&
response_type=code 这个是返回类型,不能改变
&
scope= 类别 snsapi_base(静默)/snsapi_userinfo(用户同意)
&
state=123 自定义参数
#wechat_redirect 微信必填参数不能改变
代码如下:
/*
* 获取用户微信授权第一步获取code参数 参数 snsapi_base此参数为静默授权,用户看不到授权页面
* snsapi_userinfo此参数需要用户同意,可获取其用户信息
*
* 方法参数 url为回调地址 scope 为授权类型
*/
public static String getRequestCodeUrl(String url, String scope) throws Exception {
// scope 为获取授权类型,null为默认授权
if (scope == null) {
scope = "snsapi_base";
} else {
scope = "snsapi_userinfo";
}
String code = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeiXinUtils.APP_ID + "&redirect_uri=" + URLEncoder.encode(url, "UTF-8") + "&response_type=code&scope=" + scope + "#wechat_redirect";
return code;
}
/*
* 获取用户微信授权第二步获取access_token 根据第一步获取到的code去换取access_token
* 根据实现步骤不同,此方法只获取到用户openId即为结束 注意,此access_token与基础参数access_token不一样
*
* 如若,今后开发需要用户信息等,根据微信API去实现剩余步骤
*/
public static Map<String, String> getAccessToken(String code) throws Exception {
long start = System.currentTimeMillis();
String url = " https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WeiXinUtils.APP_ID + "&secret=" + WeiXinUtils.AppSecret + "&code=" + code + "&grant_type=authorization_code ";
String result = null;
try {
result = Http.sendGet(url, "utf-8", 1000);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("发起网络请求出错");
}
if (!result.equals("")) {
JSONObject json = JSON.parseObject(result);
if (json.get("access_token") != null) {
Map<String, String> authData = new HashMap<String, String>();
authData.put("access_token", json.getString("access_token"));
authData.put("expires_in", json.getString("expires_in"));
authData.put("refresh_token", json.getString("refresh_token"));
authData.put("openid", json.getString("openid"));
authData.put("scope", json.getString("scope"));
System.out.println("调用获取网页授权accessToken接口耗时-->" + (System.currentTimeMillis() - start) + "毫秒");
System.out.println("-------------------我是获取openId方法:" + json.getString("openid"));
return authData;
} else {
System.out.println("调用获取网页授权accessToken接口失败-->" + result);
throw new Exception(result);
}
} else {
throw new Exception("调用获取网页授权accessToken接口返回数据为空");
}
}
注意:access_token: 登录授权会得到一个 access_token, 这个是用于标识登录用户(没有使用次数限制),绑定流程中用的都是 登录 access_token。
普通 access_token: 调用其它微信应用接口时需要带上的 access_token,普通 access_token时效为 2H, 每个应用每天调用次数<= 2000次。对于普通的建议存储
工具类:
/*
* 模拟get请求
*/
public static String sendGet(String url, String charset, int timeout) {
String result = "";
try {
URL u = new URL(url);
try {
URLConnection conn = u.openConnection();
conn.connect();
conn.setConnectTimeout(timeout);
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
String line = "";
while ((line = in.readLine()) != null) {
result = result + line;
}
in.close();
} catch (Exception e) {
return result;
}
} catch (Exception e) {
return result;
}
return result;
}