1.获取code
https://open.weixin.qq.com/connect/oauth2/authorize?appid=首款微信账户的appid&redirect_uri=域名&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
例:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe6dcb0b3g15e89992&redirect_uri=https%3A%2F%2Fpay.baidu.com%2F&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
注意:域名要加密:
/*
* urlEnodeUTF8处理方法
* */
public static String urlEnodeUTF8(String str){
String result = str;
try {
result = URLEncoder.encode(str,"UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
System.out.println(urlEnodeUTF8("http://pay.baidu.com/"));
}
2.截图以上路径的url中的code
3.获取openId
public Object getOpenId(@PathVariable("code") String code) {
log.info("code的值为:----->>>>>>>>" + code);
Map<String, Object> params = new HashMap<>();
params.put("appid", appId);
params.put("secret", secret);
params.put("grant_type", "authorization_code");
params.put("code", code);
String str = HttpUtils.doPost("https://api.weixin.qq.com/sns/oauth2/access_token?", params);
com.alibaba.fastjson.JSONObject object = com.alibaba.fastjson.JSONObject.parseObject(str);
log.info("根据code,获取openid数据-------->>>>>>>" + object.toString());
String access_token = object.getString("access_token");
String openid = object.getString("openid");
return openid;
}
4.支付下单调用
public Object wxPay(Order order) {
log.info("openId--------------->>>>>>>>>" + order.getOpenId());
Map<String, Object> param = new HashMap<>();
param.put("appid", appId); //appid
param.put("mch_id", mchId); //商户号
param.put("nonce_str", SignUtil.generateNonceStr());
param.put("body", "body"); //商品描述
param.put("out_trade_no", order.getWxNo()); //商户订单号,切记订单号为String类型
param.put("total_fee", order.getAmount()); //金额
param.put("spbill_create_ip", "127.0.0.1");
param.put("notify_url", notifyUrl); //回调接口地址
param.put("trade_type", "JSAPI"); //:交易类型
param.put("openid", order.getOpenId()); //openId
String keyValueStr = SignUtil.getKeyValueStr(param) + "&key=" + md5Key;
String signStr = SignUtil.enCode1(keyValueStr).toUpperCase();
param.put("sign", signStr); //签名
String xmlmap = XmlUtils.parseXML(param);
String resultStr = HttpUtils.sendPost(pathUrl, xmlmap);
cn.hutool.json.JSONObject jsonObject = XML.toJSONObject(resultStr);
com.alibaba.fastjson.JSONObject xml = com.alibaba.fastjson.JSONObject.parseObject(jsonObject.get("xml").toString());
Map<String, Object> result = new TreeMap<>();
result.put("appId", xml.getString("appid"));
result.put("timeStamp", Long.toString(System.currentTimeMillis() / 1000));
result.put("nonceStr", xml.getString("nonce_str"));
result.put("package", "prepay_id=" + xml.get("prepay_id"));
result.put("signType", "MD5");
String keyValueStr2 = SignUtil.getKeyValueStr(result) + "&key=" + md5Key;
String signStr2 = SignUtil.enCode1(keyValueStr2).toUpperCase();
result.put("prepay_id", xml.getString("prepay_id"));
result.put("paySign", signStr2);
return result;
}
工具类
public static String generateNonceStr() {
char[] nonceChars = new char[32];
for (int index = 0; index < nonceChars.length; ++index) {
nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
}
return new String(nonceChars);
}
private static final String SIGN_FILTER_KEYS = "|sign|";
public static String getKeyValueStr(Map<String, Object> params) {
StringBuilder sb = new StringBuilder();
Set<String> keySets = params.keySet();
List<String> keys = new ArrayList<String>(keySets);
// Collections.sort(keys); //首字母排序
// 全名排序
Comparator<Object> CHINA_COMPARE = Collator.getInstance(Locale.CHINA);
keys.sort((o1, o2) -> ((Collator) CHINA_COMPARE).compare(o1, o2));
int n = 0;
for (String key : keys) {
if (key.equals("sign")) {
continue;
}
if (null == params.get(key)) {
continue;
}
String val = params.get(key).toString();
if (StringUtils.isEmpty(val)) {
continue;
}
if (SIGN_FILTER_KEYS.indexOf("|" + key + "|") >= 0) {
continue;
}
if (n > 0) {
sb.append("&");
// sb.append(val);
}
sb.append(key).append("=").append(val);
n++;
}
return sb.toString();
}
public static String enCode1(String strObj){
String resultString = null;
try
{
resultString = new String(strObj);
MessageDigest md = MessageDigest.getInstance("MD5");
resultString = byteToString(md.digest(strObj.getBytes("utf-8")));
}
catch (NoSuchAlgorithmException e)
{
LOG.error("MD5出现异常,加密失败.", e);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return resultString;
}
//copy上面的方法,传参类型改成 Map<String, Object>
public static String parseXML(Map<String, Object> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v) && !"appkey".equals(k)) {
sb.append("<" + k + ">" + parameters.get(k) + "</" + k + ">\n");
}
}
sb.append("</xml>");
return sb.toString();
}
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("contentType", "text/xml");
conn.setRequestProperty("Charsert", "utf-8");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
5.回调:
/**
* 微信JSAPI,支付回调
**/
public String callback(@RequestBody String param) {
//里面处理业务逻辑
}
注意:回掉地址要放到请求参数中发送过去(notify_url字段就是回掉地址路径)