1.授权登录需要获取到用户的唯一标识openid以及session_key会话密钥 /** * @Description: 获取openid用户唯一标识以及session_key会话密钥 */ @PostMapping("/getOpenId") public MapgetOpenId(String code){ Map map = new HashMap<>(); //登录凭证不能为空 if (null == code || code.length() == 0){ map.put("errMessage","code 不能为空!"); return map; } //1.向微信服务器 试用登录凭证 code 获取session_key 和openid //请求参数 Map params = new HashMap<>(); params.put("appid",StringInfo.APPID); params.put("secret",StringInfo.APPSECRET); params.put("js_code",code); params.put("grant_type","authorization_code"); String result = HttpClientUtil.doGet("https://api.weixin.qq.com/sns/jscode2session?",params); JSONObject json = JSON.parseObject(result); System.out.println(json); if (json != null) { //当请求成功 if (json.getString("errcode")==null) { map.put("openid",json.getString("openid"));//用户的唯一标识 map.put("sessionKey",json.getString("session_key"));//会话密钥 if (json.getString("unionid") != null) { map.put("unionid", json.getString("unionid"));//用户在开放平台的唯一标识符 } }else{ //当请求不成功的时候,将错误信息 map.put("errMessage",json.getString("errmsg")); } } System.out.println(JSON.toJSON(map)); return map; }
/** * @Description: 获取AccessToken */ @PostMapping("/getAccessToken") public MapgetAccessToken(){ Map map = new HashMap<>(); Map params = new HashMap<>(); //请求参数 params.put("grant_type","client_credential"); params.put("appid", StringInfo.APPID); params.put("secret",StringInfo.APPSECRET); //向微信服务端发起请求 String result = HttpClientUtil.doGet("https://api.weixin.qq.com/cgi-bin/token?",params); //将结果转为json对象 JSONObject json = JSON.parseObject(result); if (json != null) { if (json.getString("errcode") == null){ map.put("accessToken",json.getString("access_token")); map.put("expiresIn",json.getString("expires_in")); }else { map.put("errMessage",json.getString("errmsg")); } } return map; }
/** * 支付接口 * @param openid 用户的唯一标识 * @param body1 商品描述信息 * @param total_fee1 金额 * @return */ @RequestMapping("/WeiXinPay") public @ResponseBody Object WeiXinPay(String openid,String body1,int total_fee1 ) { try { String appid = userService.getUser().getAppid(); // 微信小程序--》“开发者ID” String mch_id = userService.getUser().getMchId(); // 商户号,将该值赋值给partner String key = userService.getUser().getMchKey(); // 微信支付商户平台登录)--》“API安全”--》“API密钥”--“设置密钥”(设置之后的那个值就是partnerkey,32位) LOGGER.debug(appid); LOGGER.debug(mch_id); LOGGER.debug(key); String body = body1; // 描述 int total_fee = total_fee1; // 支付金额 Date data = new Date(); String notify_url = "https://www.baidu.com/weixinpay/notify"; // 自己发布在公网回调链接,不然无法访问 String out_trade_no = IdUtils.genOrderName();//IdUtils-->见下面 LOGGER.debug(out_trade_no); Map
/** * * @param request * @param database * @param out_trade_no * @param all_total_fee * @param refund_fee * @return */ @RequestMapping("/WeiXinRefund") public @ResponseBody Object WeiXinRefund(HttpServletRequest request, @RequestParam("out_trade_no") String out_trade_no, @RequestParam("all_total_fee") int all_total_fee, @RequestParam("refund_fee") int refund_fee) { try { LOGGER.debug("订单号是--->"+out_trade_no); LOGGER.debug("总金额--->"+all_total_fee); LOGGER.debug("剩余金额--->"+refund_fee); // out_trade_no 退款订单号 // all_total_fee 订单金额 // refund_fee 输0 all_total_fee-refund_fee=退款的金额 String appid = userService.getUser().getAppid(); // 微信小程序--》“开发者ID” String mch_id = userService.getUser().getMchId(); // 商户号,将该值赋值给partner String key = userService.getUser().getMchKey(); // 微信支付商户平台登录)--》“API安全”--》“API密钥”--“设置密钥”(设置之后的那个值就是partnerkey,32位) Maprefundmap = WeiXinAtcion.me.wechatRefund( request, mch_id, appid, key, out_trade_no, all_total_fee, refund_fee, userService.getUser().getCert()); if (refundmap.get("return_code").equals("SUCCESS")) { if (refundmap.get("result_code").equals("FAIL")) { LOGGER.debug("退款失败:原因" + refundmap.get("err_code_des")); } else { LOGGER.debug("退款成功"); return TTResult.ok(); } } else { LOGGER.debug("退款失败:原因" + refundmap.get("return_ms")); return TTResult.fail(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return TTResult.fail(); }
import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.mj.mall.user.service.UserService; import com.mj.pay.util.WXUtil; @Controller public class WeiXinAtcion { public static final WeiXinAtcion me = new WeiXinAtcion(); private static final Logger LOGGER = LoggerFactory .getLogger(WeiXinAtcion.class); @Autowired private UserService userService; /** * 退款 */ public static MapwechatRefund(HttpServletRequest request, String mch_id, String appid, String key, String out_trade_no, int all_total_fee, int refund_fee, String apiclient_certLocationp12) throws Exception { SortedMap
import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; import java.security.KeyStore; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.UUID; import javax.net.ssl.SSLContext; import javax.servlet.http.HttpServletRequest; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class WXUtil { private static final Logger LOGGER = LoggerFactory.getLogger(WXUtil.class); /** * 随机字符串 * @return */ public static String generate() { return UUID.randomUUID().toString().trim().replaceAll("-", ""); } /** * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 */ public static Map doXMLParse(String strxml) throws JDOMException, IOException { strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); if(null == strxml || "".equals(strxml)) { return null; } Map m = new HashMap(); InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8")); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(in); Element root = doc.getRootElement(); List list = root.getChildren(); Iterator it = list.iterator(); while(it.hasNext()) { Element e = (Element) it.next(); String k = e.getName(); String v = ""; List children = e.getChildren(); if(children.isEmpty()) { v = e.getTextNormalize(); } else { v = WXUtil.getChildrenText(children); } m.put(k, v); } //关闭流 in.close(); return m; } /** * 获取子结点的xml * @param children * @return String */ public static String getChildrenText(List children) { StringBuffer sb = new StringBuffer(); if(!children.isEmpty()) { Iterator it = children.iterator(); while(it.hasNext()) { Element e = (Element) it.next(); String name = e.getName(); String value = e.getTextNormalize(); List list = e.getChildren(); sb.append("<" + name + ">"); if(!list.isEmpty()) { sb.append(WXUtil.getChildrenText(list)); } sb.append(value); sb.append("" + name + ">"); } } return sb.toString(); } /** * 将请求参数转换为xml格式的string字符串,微信服务器接收的是xml格式的字符串 */ public static String getRequestXml(SortedMapparameters) { StringBuffer sb = new StringBuffer(); sb.append(" "); Set "); return sb.toString(); } /** * sign签名,必须使用MD5签名,且编码为UTF-8 */ public static String createSign_ChooseWXPay(String characterEncoding, SortedMap> es = parameters.entrySet(); Iterator > it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry ) it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) { sb.append("<" + k + ">" + "" + k + ">"); } else { sb.append("<" + k + ">" + v + "" + k + ">"); } } sb.append(" parameters, String key) { StringBuffer sb = new StringBuffer(); 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) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } /** 支付密钥必须参与加密,放在字符串最后面 */ sb.append("key=" + key); String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; } /** * * @param requestUrl 请求地址 * @param requestMethod 请求方法 * @param outputStr 参数 */ public static String httpRequest(String requestUrl,String requestMethod,String outputStr){ // 创建SSLContext StringBuffer buffer=null; try{ URL url = new URL(requestUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod(requestMethod); conn.setDoOutput(true); conn.setDoInput(true); conn.connect(); //往服务器端写内容 if(null !=outputStr){ OutputStream os=conn.getOutputStream(); os.write(outputStr.getBytes("utf-8")); os.close(); } // 读取服务器端返回的内容 InputStream is = conn.getInputStream(); InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); buffer = new StringBuffer(); String line = null; while ((line = br.readLine()) != null) { buffer.append(line); } }catch(Exception e){ e.printStackTrace(); } return buffer.toString(); } public static String urlEncodeUTF8(String source){ String result=source; try { result=java.net.URLEncoder.encode(source, "UTF-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } /** * 退款 */ public static Map doRefund(HttpServletRequest request,String url,String data,String partner,String apiclient_certLocation) throws Exception { // p12证书的位置 // 微信公众平台:“微信支付”--》“商户信息”--》“交易数据”--》“详情请登录微信支付商户平台查看”(登录)--》“API安全”--》“API证书”--》“下载证书” // 下载证书后将apiclient_cert.p12放在src目录下面(出于安全考虑,请自行下载自己的证书) KeyStore keyStore = KeyStore.getInstance("PKCS12"); String url2 = request.getSession().getServletContext().getRealPath("/") + "images/cert/" + apiclient_certLocation; LOGGER.debug("url2--->"+url2); File file=new File(url2); LOGGER.debug("new了一个file"); FileInputStream instream = new FileInputStream(file);// P12文件目录 LOGGER.debug("退款路径结束"); try { keyStore.load(instream, partner.toCharArray()); } finally { instream.close(); } SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, partner.toCharArray()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" }, null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); try { HttpPost httpost = new HttpPost(url); // 设置响应头信息 httpost.addHeader("Connection", "keep-alive"); httpost.addHeader("Accept", "*/*"); httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); httpost.addHeader("Host", "api.mch.weixin.qq.com"); httpost.addHeader("X-Requested-With", "XMLHttpRequest"); httpost.addHeader("Cache-Control", "max-age=0"); httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) "); httpost.setEntity(new StringEntity(data, "UTF-8")); CloseableHttpResponse response = httpclient.execute(httpost); try { HttpEntity entity = response.getEntity(); String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8"); EntityUtils.consume(entity); return WXUtil.doXMLParse(jsonStr); } finally { response.close(); } } finally { httpclient.close(); } } /** * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 */ public static boolean isTenpaySign(String characterEncoding, SortedMap packageParams, String API_KEY) { StringBuffer sb = new StringBuffer(); Set es = packageParams.entrySet(); Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); String v = (String)entry.getValue(); if(!"sign".equals(k) && null != v && !"".equals(v)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + API_KEY); //算出摘要 String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); String tenpaySign = ((String)packageParams.get("sign")).toLowerCase(); //System.out.println(tenpaySign + " " + mysign); return tenpaySign.equals(mysign); } }
import java.util.Random; public class IdUtils { /** * 图片名生成 */ public static String genImageName() { //取当前时间的长整形值包含毫秒 long millis = System.currentTimeMillis(); //long millis = System.nanoTime(); //加上三位随机数 Random random = new Random(); int end3 = random.nextInt(999); //如果不足三位前面补0 String str = millis + String.format("%03d", end3); return str; } /** * 订单号生成 * @return */ public static String genOrderName() { //取当前时间的长整形值包含毫秒 long millis = System.currentTimeMillis(); //long millis = System.nanoTime(); //加上六位随机数 Random random = new Random(); long end6 = random.nextInt(999999); //如果不足三位前面补0 String str = millis + String.format("%06d", end6); return str; } }
import java.security.MessageDigest;
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}