直接上代码--关键就是PayCommonUtil.java核心类

1、ConfigUtil.java 微信支付相关信息

    /*** 微信支付服务号相关信息*/public final static String APPID = "wx********";//服务号的应用号public final static String MCH_ID = "148*****";//商户号public final static String API_KEY = "LtRzm*******";//API密钥public final static String SIGN_TYPE = "MD5";//签名加密方式public final static String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//请求下单的httppublic final static String NOTIFY_URL = "http://域名/wxpay/returnmsg.do";//回调地址public final static String WXLOGIN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";

2、MyX509TrustManager.java信任管理器

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/*** 信任管理器*/
public class MyX509TrustManager implements X509TrustManager {// 检查客户端证书public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}// 检查服务器端证书public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}// 返回受信任的X509证书数组public X509Certificate[] getAcceptedIssuers() {return null;}
}

3、XMLUtil.java    xml解析工具类

public class XMLUtil {/*** 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。** @param strxml* @return* @throws JDOMException* @throws IOException*/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 = XMLUtil.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(XMLUtil.getChildrenText(list));}sb.append(value);sb.append("</" + name + ">");}}return sb.toString();}
}

4、MD5Util 加密工具类


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()));elseresultString = 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" };
}

5、PayCommonUtil.java 进行2此签名核心工具类

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;public class PayCommonUtil
{/*** 创建支付宝交易对象*/public static AlipayClient getAliClient(){AlipayClient alipayClient = new DefaultAlipayClient(ConfigUtil.ALIPAY_PAYURL,ConfigUtil.ALIPAY_APPID,ConfigUtil.ALIPAY_PRIVATE_KEY, ConfigUtil.ALIPAY_FORMAT, ConfigUtil.ALIPAY_CHARSET,ConfigUtil.ALIPAY_PUBLIC_KEY, ConfigUtil.ALIPAY_SIGN_TYPE);return alipayClient;}/*** 创建微信交易对象*/public static SortedMap<Object, Object> getWXPrePayID(){SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();parameters.put("appid", ConfigUtil.APPID);//应用IDparameters.put("mch_id", ConfigUtil.MCH_ID);//商户号parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());//随机字符串parameters.put("fee_type", "CNY");//货币类型,默认类型人民币parameters.put("notify_url", ConfigUtil.NOTIFY_URL);//接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。parameters.put("trade_type", "APP");//支付类型:APPreturn parameters;}/*** 支付统一下单接口返回正常的prepay_id,* 再按签名规范重新生成签名后,将数据传输给APP。* 参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。* 注意:package的值格式为Sign=WXPay*/public static SortedMap<Object, Object> startWXPay(String result){try{Map<String, String> map = XMLUtil.doXMLParse(result);SortedMap<Object, Object> parameterMap = new TreeMap<Object, Object>();parameterMap.put("appid", ConfigUtil.APPID);parameterMap.put("partnerid", ConfigUtil.MCH_ID);parameterMap.put("prepayid", map.get("prepay_id"));parameterMap.put("package", "Sign=WXPay");parameterMap.put("noncestr", PayCommonUtil.CreateNoncestr());// 本来生成的时间戳是13位,但是ios必须是10位,所以截取了一下parameterMap.put("timestamp",Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10)));String sign = PayCommonUtil.createSign("UTF-8", parameterMap);parameterMap.put("sign", sign);return parameterMap;} catch (Exception e){e.printStackTrace();}return null;}/*** 创建sign签名-- Utf-8格式* @param characterEncoding 编码格式* @param parameters 请求参数* @return*/public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){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=" + ConfigUtil.API_KEY);String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();return sign;}/*** 将请求参数转换为xml格式的string* @param parameters 请求参数* @return*/public static String getRequestXml(SortedMap<Object, 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();String v = (String) entry.getValue();if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k)){sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");} else{sb.append("<" + k + ">" + v + "</" + k + ">");}}sb.append("</xml>");return sb.toString();}/*** SSL协议发起http请求* @param requestUrl 请求地址* @param requestMethod 请求方式(GET、POST)* @param outputStr 提交的数据* @return 返回微信服务器响应的信息*/public static String httpsRequest(String requestUrl, String requestMethod, String outputStr){try{// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = {new MyX509TrustManager()};SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());//从上述SSLContext对象中得到SSLSocketFactory对象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);// 设置请求方式(GET/POST)conn.setRequestMethod(requestMethod);conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");// 当outputStr不为null时向输出流写数据if (null != outputStr) {OutputStream outputStream = conn.getOutputStream();// 注意编码格式outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}//从输入流读取返回内容InputStream inputStream = conn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;StringBuffer buffer = new StringBuffer();while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}//释放资源bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;conn.disconnect();return buffer.toString();}catch(ConnectException ce){System.out.println("连接超时:"+ce.getMessage());}catch(Exception e){System.out.println("https请求异常:"+ e.getMessage());}return null;}/*** 创建随机数* @return*/public static String CreateNoncestr(){String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";String res = "";for (int i = 0; i < 16; i++){Random rd = new Random();res += chars.charAt(rd.nextInt(chars.length() - 1));}return res;}/*** 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。* @return boolean*/public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams){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=" + ConfigUtil.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);}
}

6、微信支付下单接口

    /*** 微信支付下单* @param body:商品描述* @param detail:商品详情* @param attach:附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据* @param out_trade_no:商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号* @param total_price:订单总金额,单位为分,详见支付金额* @param spbill_create_ip:用户端实际ip* @return* @throws Exception*/@RequestMapping(value="/wxPayOrder",produces = "text/html;charset=UTF-8",method={RequestMethod.POST}) @ResponseBodypublic String wxPayOrder() throws Exception{logBefore(logger, "微信支付--下单");Map<String,Object> map = new HashMap<String,Object>();PageData pd = new PageData();pd = this.getPageData();String result = WeixinConsts.FAIL;String returnStr="";try{String body = "会员充值";String detail ="加入VIP会员";//获取充值金额String price = pd.getString("AMOUNT");SortedMap<Object,Object> parameters = PayCommonUtil.getWXPrePayID(); // 获取预付单,此处已做封装,需要工具类parameters.put("body", body);//商品描述parameters.put("detail", detail);//商品详情parameters.put("out_trade_no", UUID.randomUUID().toString().substring(0, 15)); //商品订单id//parameters.put("total_fee", "1");//总金额,每次支付一分钱parameters.put("spbill_create_ip", "127.0.0.1");//终端IP,支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP//微信默认从单位为分,所以用此方法将单位调整成元int price100 = new BigDecimal(price).multiply(new BigDecimal(100)).intValue();parameters.put("total_fee", String.valueOf(price100));// 设置签名String sign = PayCommonUtil.createSign("UTF-8", parameters);parameters.put("sign", sign);//封装请求参数结束,获取xml结果String requestXML = PayCommonUtil.getRequestXml(parameters);//调用统一下单接口String payResult = PayCommonUtil.httpsRequest(ConfigUtil.UNIFIED_ORDER_URL, "POST",requestXML);System.out.println("\n调用统一下单接口,结果:"+payResult);SortedMap<Object, Object> parMap = PayCommonUtil.startWXPay(payResult);System.out.println("最终的map是:" + parMap.toString());net.sf.json.JSONObject jsonObj = net.sf.json.JSONObject.fromObject(parMap);StringBuilder msg = new StringBuilder();msg.append("{\"code\":\"200\",");msg.append("\"msg\":\"查询成功!\",");msg.append("\"datas\":");msg.append(jsonObj.toString());msg.append("}");System.out.println(msg.toString());returnStr = msg.toString();}catch(Exception e){e.printStackTrace();}finally{map.put("result", result);logAfter(logger);}return returnStr;}/*** 微信支付--回调通知业务处理* @param request* @param response* @return* @throws Exception*/@ResponseBody@RequestMapping(value = "/returnmsg.do", produces = "text/html;charset=UTF-8",method={RequestMethod.POST})public String returnmsg(HttpServletRequest request, HttpServletResponse response) throws Exception{String msg = "";//解析结果存储在HashMapMap<String,String> map = new HashMap<String,String>();InputStream inputStream = request.getInputStream();//读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);//得到xml根元素Element root = document.getRootElement();//得到根元素的所有子节点List<Element> elementList = root.elements();//遍历所有子节点for(Element e:elementList){map.put(e.getName(), e.getText());}net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(map);System.out.println("===消息通知的结果:" + json.toString() + "==========================");System.out.println("===return_code===" + map.get("return_code"));System.out.println("===return_msg===" + map.get("return_msg"));System.out.println("===out_trade_no===" + map.get("out_trade_no"));//验证签名的过程//判断是否支付成功String returnCode = map.get("return_code");if("SUCCESS".equals(returnCode)){/*** 支付成功之后的业务处理*/msg = "SUCCESS";}else if("FAIL".equals(returnCode)){/*** 支付失败后的业务处理*/msg = "FAIL";}//释放资源inputStream.close();inputStream = null;return msg;}

相关文档:

Unity IOS 接入微信登录

Unity Android 接入微信登录

如有问题可以微信咨询,可扫描下方微信添加互相沟通:

如果对你有帮助,请给点赞助支持下奥!

服务端(java)实现微信支付二次签名相关推荐

  1. 行业寒冬:java生成微信支付二维码

    01 Redis面试问题常见划分(6个部分) Redis 的概念理解 Redis 基本数据结构详解 Redis 高并发问题策略 Redis 集群结构以及设计理念 Redis 持久化机制 Redis 应 ...

  2. Java利用HttpClient发送请求生成微信支付二维码、查询支付状态

    一.HttpClient工具类 import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache. ...

  3. 微信支付之01------获取订单微信支付二维码的接口------Java实现

    [ 前言:以前写过一个获取微信二维码支付的接口,发现最近公司新开的项目会经常用到,现在我又翻出代码看了一遍,觉得还是把整个代码流程记下来的好 ] 借鉴博客: 他这篇博客写得不错,挺全的:https:/ ...

  4. 魔坊APP项目-15-邀请好友(业务逻辑流程图、服务端提供邀请好友的二维码生成接口、客户端通过第三方识别微信二维码,服务端提供接口允许访问、App配置私有协议,允许第三方应用通过私有协议,唤醒APP)

    邀请好友 1.业务逻辑流程图 客户端提供点击"邀请好友"以后的页面frame,html/invite.html,代码: <!DOCTYPE html> <html ...

  5. Java对接微信支付(完整全流程)

    Java对接微信支付及支付回调通知的全流程 一.所用框架.对接微信支付我们技术组用的是payment框架,因为该框架已整合springboot因此很方便快捷 <dependency>< ...

  6. Java接入微信支付超级详细教程——从入门到精通

    源码下载 源码获取邮箱:xiaoshu1024@qq.com 本文介绍了"二维码付款"的代码.其他微信支付方式的代码都在源码中. 一.准备开发所需的账号以及配置信息 解释:想要接入 ...

  7. 微信小程序-JAVA实现微信支付功能(微信支付2.0)

    微信小程序-JAVA实现微信支付功能(微信支付2.0) 一.前言 本博客主要介绍JAVA后台与微信小程序(UNI-APP或者原生微信小程序)的微信支付的实现,如果是APP或者H5的开发暂时不支持,具体 ...

  8. 微信支付:支付流程分析、微信扫码支付(HttpClient)、微信支付二维码生成、检测支付状态、订单状态操作准备工作、支付信息回调、MQ处理支付回调状态、定时处理订单状态

    微信支付 微信支付开发的整体思路 生成支付二维码 查询支付状态(微信的服务器) 实现订单状态的修改.删除订单 支付状态回查->微信服务器将支付状态返回给支付微服务 MQ处理支付回调状态 Rabb ...

  9. 微信支付-java实现微信支付-后端篇

    微信支付系列文章 微信支付-java后端实现 微信支付-vue 前端实现 java demo: 下载地址文章底部 技术栈 Spring boot java XML (微信在http协议中数据传输方案) ...

  10. 微信服务号开发-整合微信支付

    最近的项目在对接微信支付,所以抽出一些时间,将方法总结一下: 欢迎加群交流:724225958 官方开发文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi. ...

最新文章

  1. JDK, JRE 和JVM的区别
  2. 微信翻译生日快乐的代码_微信「隐藏彩蛋」,你发现了没?
  3. Warning: mysqli_connect()_php链接MySQL8.0_异常
  4. 容器编排技术 -- Kubernetes Labels 和 Selectors
  5. assertion failed:concurrent update to the log .mutiple streaming jobs delete 4
  6. 如何使用windows自带的远程协助
  7. Spark + Hadoop,基于WIFI探针的大数据分析系统
  8. 前端学习之--CSS
  9. MySQL Oracle默认排序_PostgreSQL、MySQL、Oracle,查询的默认排序是怎样的?
  10. Java编译器使用入门
  11. FMI飞马网 |【线上直播】京东商城的通用代码质量提升方案
  12. 概率分布 ---- 泊松分布
  13. 收款神器!解读聚合收款码背后的原理
  14. 阿里云播放器AliyunPlayer的走马灯组件的位置
  15. 豆瓣读书top250数据爬取与可视化
  16. java矩形_JAVA实现矩形(长方形)的周长面积计算
  17. Unix学习记录(一)
  18. Oracle 函数使用:CURSOR游标简单案例
  19. android 性格测试 csdn,华为加密状态码查询脚本
  20. 如何用深度学习处理结构化数据?

热门文章

  1. ubuntu处理视频 将视频转换成图片帧
  2. 多目标跟踪算法方案总结
  3. Spark学习总结(一)
  4. 如何将pdf文件压缩变小?
  5. AI快捷键大全 2020
  6. java jpg转png 模糊_Java JPG转换为Png
  7. 微信小程序文本输入<input/> 详解
  8. VOIP Codec 三剑客之 ISAC/ILBC -- ISAC (1) 介绍
  9. 联通4g满格但是网速慢_手机网速太慢怎么办 教你一招(4g信号满格网速很慢)...
  10. iOS 10 通知 --UserNotifications