微信支付Java后台

1.微信配置信息 global.properties

2.方法wxpay用于生成预支付订单信息

方法notifyWeiXinPay用于微信支付成功后的回调, 注意: 在手机端使用微信支付成功后,微信服务器会根据提供的回调地址进行回调, parameterMap.put("notify_url", wxnotify); (见下面代码)

在局域网是无法进行回调的,必须将你的服务端放在公网上进行测试, 回调函数会被多次调用,如果第一次成功后,你可以将业务数据状态标志为已处理, 对于相同订单的其它回调就不需要再次处理了;

package com.main.controller;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.jdom.JDOMException;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import com.main.model.WeiXinPrePay;
import com.main.util.ConfigManager;
import com.main.util.DateUtil;
import com.main.util.GeneralConstant;
import com.main.util.PayCommonUtil;
import com.main.util.Result;
import com.main.util.StringUtil;@Controller
@RequestMapping("/pay")
public class PayController {String randomString = PayCommonUtil.getRandomString(32);//支付成功后的回调函数public static String wxnotify = "http://com.zhuohuicalss/pay/notifyWeiXinPay";public PayController() {System.out.println("MainController构造函数");}/*** @param totalAmount    支付金额* @param description    描述* @param request* @return*/@RequestMapping(value = "/wxpay", produces = MediaType.APPLICATION_JSON_VALUE)@ResponseBody    public Result wxpay(HttpServletRequest request) {Result result = new Result();Long userId = new Long(1);//baseController.getUserId();BigDecimal totalAmount = new BigDecimal(request.getParameter("totalPrice"));String trade_no = "";String description="";try {trade_no = new String(request.getParameter("orderNum").getBytes("ISO-8859-1"),"UTF-8");description = request.getParameter("description");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}String openId = "";Map<String, String> map = weixinPrePay(trade_no,totalAmount,description,openId,request);  SortedMap<String, Object> finalpackage = new TreeMap<String, Object>();//应用IDfinalpackage.put("appid", ConfigManager.getInstance().getConfigItem("WXAppID")/*PayCommonUtil.APPID*/);//商户号finalpackage.put("partnerid", ConfigManager.getInstance().getConfigItem("MCH_ID"));Long time = (System.currentTimeMillis() / 1000);//时间戳finalpackage.put("timestamp", time.toString());//随机字符串finalpackage.put("noncestr", map.get("nonce_str"));//预支付交易会话IDfinalpackage.put("prepayid", map.get("prepay_id"));//扩展字段finalpackage.put("package", "Sign=WXPay");WeiXinPrePay prePay = new WeiXinPrePay();prePay.setAppId(ConfigManager.getInstance().getConfigItem("WXAppID"));prePay.setMchId(ConfigManager.getInstance().getConfigItem("MCH_ID"));prePay.setTimeStamp(time.toString());prePay.setNonceStr(map.get("nonce_str"));prePay.setPrepayId(map.get("prepay_id"));prePay.setSignType("MD5");prePay.setPaySign(sign);result.setData(prePay);result.setStateCode(GeneralConstant.SUCCESS);result.setDesc("微信支付加载成功");return result;} /*** 统一下单 * 应用场景:商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付。* @param trade_no* @param totalAmount* @param description* @param openid* @param sym* @param request* @return*/@SuppressWarnings("unchecked")public Map<String, String> weixinPrePay(String trade_no,BigDecimal totalAmount,  String description, String openid, HttpServletRequest request) { SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();  parameterMap.put("appid", ConfigManager.getInstance().getConfigItem("WXAppID"));  //应用appid parameterMap.put("mch_id", ConfigManager.getInstance().getConfigItem("MCH_ID")/*PayCommonUtil.MCH_ID*/);  //商户号//parameterMap.put("device_info", "WEB");parameterMap.put("nonce_str", randomString);  parameterMap.put("body", description);parameterMap.put("out_trade_no", trade_no);parameterMap.put("fee_type", "CNY");  System.out.println("jiner");  BigDecimal total = totalAmount.multiply(new BigDecimal(100));  //接口中参数支付金额单位为【分】,参数值不能带小数,所以乘以100java.text.DecimalFormat df=new java.text.DecimalFormat("0");  parameterMap.put("total_fee", df.format(total));  System.out.println("jiner2");  parameterMap.put("spbill_create_ip", PayCommonUtil.getRemoteHost(request));  parameterMap.put("notify_url", wxnotify);parameterMap.put("trade_type", "APP");//"JSAPI"//trade_type为JSAPI是 openid为必填项//parameterMap.put("openid", openid);System.out.println("");  String sign = PayCommonUtil.createSign("UTF-8", parameterMap); System.out.println("jiner2");  parameterMap.put("sign", sign);  String requestXML = PayCommonUtil.getRequestXml(parameterMap);  System.out.println(requestXML);  String result = PayCommonUtil.httpsRequest(  "https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",  requestXML);  System.out.println(result);  Map<String, String> map = null;  try {  map = PayCommonUtil.doXMLParse(result);  } catch (JDOMException e) {  // TODO Auto-generated catch block  e.printStackTrace();  } catch (IOException e) {  // TODO Auto-generated catch block  e.printStackTrace();  }  return map;        }/*** 此函数会被执行多次,如果支付状态已经修改为已支付,则下次再调的时候判断是否已经支付,如果已经支付了,则什么也执行* @param request* @param response* @return* @throws IOException* @throws JDOMException*/@RequestMapping(value = "notifyWeiXinPay", produces = MediaType.APPLICATION_JSON_VALUE)// @RequestDescription("支付回调地址")@ResponseBodypublic String notifyWeiXinPay(HttpServletRequest request, HttpServletResponse response) throws IOException, JDOMException {System.out.println("微信支付回调");InputStream inStream = request.getInputStream();ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}String resultxml = new String(outSteam.toByteArray(), "utf-8");Map<String, String> params = PayCommonUtil.doXMLParse(resultxml);outSteam.close();inStream.close();Map<String,String> return_data = new HashMap<String,String>();  if (!PayCommonUtil.isTenpaySign(params)) {// 支付失败return_data.put("return_code", "FAIL");  return_data.put("return_msg", "return_code不正确");return StringUtil.GetMapToXML(return_data);} else {System.out.println("===============付款成功==============");// ------------------------------// 处理业务开始// ------------------------------// 此处处理订单状态,结合自己的订单数据完成订单状态的更新// ------------------------------String total_fee = params.get("total_fee");double v = Double.valueOf(total_fee) / 100;String out_trade_no = String.valueOf(Long.parseLong(params.get("out_trade_no").split("O")[0]));Date accountTime = DateUtil.stringtoDate(params.get("time_end"), "yyyyMMddHHmmss");String ordertime = DateUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss");String totalAmount = String.valueOf(v);String appId = params.get("appid");String tradeNo = params.get("transaction_id");return_data.put("return_code", "SUCCESS");  return_data.put("return_msg", "OK");  return StringUtil.GetMapToXML(return_data);}}}

3.用到的一些工具类

import java.io.InputStream;
import java.util.*;/*** 读取配置文件的类 单例类* @author Administrator**/
public class ConfigManager {// 属性文件命名private Properties m_props = null;private static  Map<String,String> configMap;private static  ConfigManager m_instance = null;private static   Properties props = null; private ConfigManager() {m_props = new Properties();configMap = new HashMap<String,String>();try {props = System.getProperties(); //获取系统属性m_props.load(getInputStream());getSysConfigMsg();} catch (Exception e) {e.printStackTrace();}}public synchronized static ConfigManager getInstance() {if(m_instance == null){m_instance = new ConfigManager();}return m_instance;}public InputStream getInputStream() {InputStream is = null;try {is = getClass().getClassLoader().getResourceAsStream("global.properties");} catch (Exception e) {e.printStackTrace();}return is;}public Map<String,String> getSysConfigMsg(){Set<Object> keyset = m_props.keySet();Iterator<Object> it = keyset.iterator();while(it.hasNext()){String nextkey = it.next().toString();configMap.put(nextkey,getConfigItem(nextkey));}return configMap;}public String getConfigItem(String name) {String val = m_props.getProperty(name).trim();if("fileSavePath".equals(name)){if(props.getProperty("os.name").startsWith("Windows")){val  =  val.split("#")[0].toString().trim();}else{val  =  val.split("#")[1].toString().trim();}}return val;}public Map<String,String> getConfigMap(){return configMap;}}
import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Pattern;public class DateUtil {// 格式:年-月-日 小时:分钟:秒public static final String FORMAT_ONE = "yyyy-MM-dd HH:mm:ss";// 格式:年-月-日 小时:分钟public static final String FORMAT_TWO = "yyyy-MM-dd HH:mm";// 格式:年月日 小时分钟秒public static final String FORMAT_THREE = "yyyyMMdd-HHmmss";// 格式:年月日public static final String FORMAT_FOUR = "yyyyMMdd";// 格式:年-月-日public static final String LONG_DATE_FORMAT = "yyyy-MM-dd";// 格式:月-日public static final String SHORT_DATE_FORMAT = "MM-dd";// 格式:小时:分钟:秒public static final String LONG_TIME_FORMAT = "HH:mm:ss";//格式:年-月public static final String MONTG_DATE_FORMAT = "yyyy-MM";// 年的加减public static final int SUB_YEAR = Calendar.YEAR;// 月加减public static final int SUB_MONTH = Calendar.MONTH;// 天的加减public static final int SUB_DAY = Calendar.DATE;// 小时的加减public static final int SUB_HOUR = Calendar.HOUR;// 分钟的加减public static final int SUB_MINUTE = Calendar.MINUTE;// 秒的加减public static final int SUB_SECOND = Calendar.SECOND;static final String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四","星期五", "星期六" };public DateUtil() {}/*** 把符合日期格式的字符串转换为日期类型*/public static Date stringtoDate(String dateStr, String format) {Date d = null;SimpleDateFormat formater = new SimpleDateFormat(format);try {formater.setLenient(false);d = formater.parse(dateStr);} catch (Exception e) {// log.error(e);d = null;}return d;}/*** 把符合日期格式的字符串转换为日期类型*/public static Date stringtoDate(String dateStr, String format,ParsePosition pos) {Date d = null;SimpleDateFormat formater = new SimpleDateFormat(format);try {formater.setLenient(false);d = formater.parse(dateStr, pos);} catch (Exception e) {d = null;}return d;}/*** 把日期转换为字符串*/public static String dateToString(Date date, String format) {String result = "";SimpleDateFormat formater = new SimpleDateFormat(format);try {result = formater.format(date);} catch (Exception e) {// log.error(e);}return result;}/*** 获取当前时间的指定格式*/public static String getCurrDate(String format) {return dateToString(new Date(), format);}/*** * @Title:        dateSub* @Date          2014-1-9 上午10:44:02* @Description:  得到指定日期前(后)的日期* @param:        @param dateKind  例:Calendar.DAY_OF_MONTH* @param:        @param dateStr  指定日期* @param:        @param amount   增加(减去)的时间量* @param:        @return   * @return:       String   * @throws* @author        mtf*/public static String dateSub(int dateKind, String dateStr, int amount) {Date date = stringtoDate(dateStr, MONTG_DATE_FORMAT);Calendar calendar = Calendar.getInstance();calendar.setTime(date);calendar.add(dateKind, amount);return dateToString(calendar.getTime(), FORMAT_ONE);}/*** 昨日日期* @return*/public static String yearthDate(String dateStr){Date date = stringtoDate(dateStr, LONG_DATE_FORMAT);//取时间 Calendar calendar = Calendar.getInstance();calendar.setTime(date); calendar.add(calendar.DATE,-1);//把日期往后增加一天.整数往后推,负数往前移动 //date=calendar.getTime();   //这个时间就是日期往后推一天的结果 return dateToString(calendar.getTime(), LONG_DATE_FORMAT);}/*** 两个日期相减* @return 相减得到的秒数*/public static long timeSub(String firstTime, String secTime) {long first = stringtoDate(firstTime, FORMAT_ONE).getTime();long second = stringtoDate(secTime, FORMAT_ONE).getTime();return (second - first) / 1000;}/*** 两个日期相减* 参数地DATE* second 两个日期相差的秒* @return 相减得到的秒数 * 后面时间减去前面时间  再减去 相差秒数    如果大于0 返回 FASLE*/public static boolean timeSub(Date firstTime, Date secTime,long  secs) {long first = firstTime.getTime();long second = secTime.getTime();// 判断两个时间 是否间隔那么长 secs。return (second - first - secs) > 0 ? false:true;}/*** 两个日期相减* 参数地DATE* @return 相减得到的秒数 * 后面时间减去前面时间  如果大于0 返回 false*/public static boolean timeSub(Date firstTime, Date secTime) {long first = firstTime.getTime();long second = secTime.getTime();return (second - first)>0?false:true;}/*** 获得某月的天数*/public static int getDaysOfMonth(String year, String month) {int days = 0;if (month.equals("1") || month.equals("3") || month.equals("5")|| month.equals("7") || month.equals("8") || month.equals("10")|| month.equals("12")) {days = 31;} else if (month.equals("4") || month.equals("6") || month.equals("9")|| month.equals("11")) {days = 30;} else {if ((Integer.parseInt(year) % 4 == 0 && Integer.parseInt(year) % 100 != 0)|| Integer.parseInt(year) % 400 == 0) {days = 29;} else {days = 28;}}return days;}/*** 获取某年某月的天数*/public static int getDaysOfMonth(int year, int month) {Calendar calendar = Calendar.getInstance();calendar.set(year, month - 1, 1);return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);}/*** 获得当前日期*/public static int getToday() {Calendar calendar = Calendar.getInstance();return calendar.get(Calendar.DATE);}/*** 获得当前月份*/public static int getToMonth() {Calendar calendar = Calendar.getInstance();return calendar.get(Calendar.MONTH) + 1;}/*** 获得当前年份*/public static int getToYear() {Calendar calendar = Calendar.getInstance();return calendar.get(Calendar.YEAR);}/*** 返回日期的天*/public static int getDay(Date date) {Calendar calendar = Calendar.getInstance();calendar.setTime(date);return calendar.get(Calendar.DATE);}/*** 返回日期的年*/public static int getYear(Date date) {Calendar calendar = Calendar.getInstance();calendar.setTime(date);return calendar.get(Calendar.YEAR);}/*** 返回日期的月份,1-12*/public static int getMonth(Date date) {Calendar calendar = Calendar.getInstance();calendar.setTime(date);return calendar.get(Calendar.MONTH) + 1;}/*** 计算两个日期相差的天数,如果date2 > date1 返回正数,否则返回负数*/public static long dayDiff(Date date1, Date date2) {return (date2.getTime() - date1.getTime()) / 86400000;}/*** 比较两个日期的年差*/public static int yearDiff(String before, String after) {Date beforeDay = stringtoDate(before, LONG_DATE_FORMAT);Date afterDay = stringtoDate(after, LONG_DATE_FORMAT);return getYear(afterDay) - getYear(beforeDay);}/*** 比较指定日期与当前日期的差*/public static int yearDiffCurr(String after) {Date beforeDay = new Date();Date afterDay = stringtoDate(after, LONG_DATE_FORMAT);return getYear(beforeDay) - getYear(afterDay);}/*** 获取每月的第一周*/public static int getFirstWeekdayOfMonth(int year, int month) {Calendar c = Calendar.getInstance();c.setFirstDayOfWeek(Calendar.SATURDAY); // 星期天为第一天c.set(year, month - 1, 1);return c.get(Calendar.DAY_OF_WEEK);}/*** 获取每月的最后一周*/public static int getLastWeekdayOfMonth(int year, int month) {Calendar c = Calendar.getInstance();c.setFirstDayOfWeek(Calendar.SATURDAY); // 星期天为第一天c.set(year, month - 1, getDaysOfMonth(year, month));return c.get(Calendar.DAY_OF_WEEK);}/*** 获得当前日期字符串,格式"yyyy-MM-dd HH:mm:ss"* * @return*/public static String getNow() {Calendar today = Calendar.getInstance();return dateToString(today.getTime(), FORMAT_ONE);}/*** 判断日期是否有效,包括闰年的情况* * @param date*          YYYY-mm-dd* @return*/public static boolean isDate(String date) {StringBuffer reg = new StringBuffer("^((\\d{2}(([02468][048])|([13579][26]))-?((((0?");reg.append("[13578])|(1[02]))-?((0?[1-9])|([1-2][0-9])|(3[01])))");reg.append("|(((0?[469])|(11))-?((0?[1-9])|([1-2][0-9])|(30)))|");reg.append("(0?2-?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][12");reg.append("35679])|([13579][01345789]))-?((((0?[13578])|(1[02]))");reg.append("-?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))");reg.append("-?((0?[1-9])|([1-2][0-9])|(30)))|(0?2-?((0?[");reg.append("1-9])|(1[0-9])|(2[0-8]))))))");Pattern p = Pattern.compile(reg.toString());return p.matcher(date).matches();}/****** 时间 增加、减少 n个小时以后时间* @param date*          YYYY-mm-dd HH:mm:ss* @param num>0  小时         * @param type  增加和减少标志  * **/public static Date adjustDateByHour(Date d ,Integer num, int  type) {Calendar Cal= Calendar.getInstance();DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  Cal.setTime(d);  if(type==0){Cal.add(Calendar.MINUTE,-num);// System.out.println("date:"+df.format(Cal.getTime()));}else{Cal.add(Calendar.MINUTE,num);//System.out.println("date:"+df.format(Cal.getTime()));}return Cal.getTime();}/****** 时间 增加、减少 n个分钟以后时间* @param date*          YYYY-mm-dd HH:mm:ss* @param num>0  分钟       * @param type  增加和减少标志  * **/public static Date adjustDateByMinutes(Date d ,Integer num, int  type) {Calendar Cal= Calendar.getInstance();DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  Cal.setTime(d);  if(type==0){Cal.add(Calendar.MINUTE,-num);//  System.out.println("date:"+df.format(Cal.getTime()));}else{Cal.add(Calendar.MINUTE,num);//   System.out.println("date:"+df.format(Cal.getTime()));}return Cal.getTime();}public static void main(String[] args){
//      String dateStr = DateUtil.yearthDate("2017-05-30");
//      System.out.println(dateStr);
//      long min = DateUtil.timeSub("2017-04-12 00:00:00", "2017-04-13 00:00:00")/60;
//      System.out.println(min);String settlementDate = DateUtil.dateToString(new Date(), "yyyy-MM-dd");long day = DateUtil.dayDiff(DateUtil.stringtoDate("2017-06-22", "yyyy-MM-dd"),DateUtil.stringtoDate(settlementDate, "yyyy-MM-dd"));if(day >= 0){System.out.println(day);}String goodsArriveTime = "2017-04-02 17:00-18:00";int space_index = goodsArriveTime.indexOf(" ");String arrive_date = goodsArriveTime.substring(0, space_index);String arrive_time = goodsArriveTime.substring(space_index+1, goodsArriveTime.length());System.out.println(arrive_date);System.out.println(arrive_time);String arrive_start_time = arrive_time.substring(0, 2);String arrive_end_time = arrive_time.substring(6,8);System.out.println(arrive_start_time);System.out.println(arrive_end_time);String Time = DateUtil.getCurrDate("HH");System.out.println(Time);String Time2 = DateUtil.getCurrDate("mm");System.out.println(Time2);}}
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" };}
import org.apache.http.Consts;
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.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.util.*;public class PayCommonUtil {//微信参数配置  public static String API_KEY = ConfigManager.getInstance().getConfigItem("API_KEY");//随机字符串生成  public static String getRandomString(int length) { //length表示生成字符串的长度      String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";         Random random = new Random();         StringBuffer sb = new StringBuffer();         for (int i = 0; i < length; i++) {         int number = random.nextInt(base.length());         sb.append(base.charAt(number));         }         return sb.toString();         }    //请求xml组装  public static String getRequestXml(SortedMap<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 key = (String)entry.getKey();  String value = (String)entry.getValue();  if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {  sb.append("<"+key+">"+"<![CDATA["+value+"]]></"+key+">");  }else {  sb.append("<"+key+">"+value+"</"+key+">");  }  }  sb.append("</xml>");  return sb.toString();  } //生成签名  public static String createSign(String characterEncoding,SortedMap<String,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=" + API_KEY);  System.out.println(sb.toString());String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();  return sign;  }/*** 验证回调签名* @return*/public static boolean isTenpaySign(Map<String, String> map) {String characterEncoding="utf-8";String charset = "utf-8";String signFromAPIResponse = map.get("sign");if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!"); return false;}System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);//过滤空 设置 TreeMapSortedMap<String,String> packageParams = new TreeMap();for (String parameter : map.keySet()) {String parameterValue = map.get(parameter);String v = "";if (null != parameterValue) {v = parameterValue.trim();}packageParams.put(parameter, v);}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);//将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较//算出签名String resultSign = "";String tobesign = sb.toString();if (null == charset || "".equals(charset)) {resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();}else{try{resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();}catch (Exception e) {resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();}}String tenpaySign = ((String)packageParams.get("sign")).toUpperCase();return tenpaySign.equals(resultSign);}//请求方法  public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {  try {  URL url = new URL(requestUrl);  HttpURLConnection conn = (HttpURLConnection) 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);  } catch (Exception e) {  System.out.println("https请求异常:{}"+ e);  }  return null;  }  //退款的请求方法  public static String httpsRequest2(String requestUrl, String requestMethod, String outputStr) throws Exception {  KeyStore keyStore  = KeyStore.getInstance("PKCS12");  StringBuilder res = new StringBuilder("");  FileInputStream instream = new FileInputStream(new File("/home/apiclient_cert.p12"));  try {  keyStore.load(instream, "".toCharArray());  } finally {  instream.close();  }  // Trust own CA and all self-signed certs  SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, "1313329201".toCharArray())  .build();  // Allow TLSv1 protocol only  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("https://api.mch.weixin.qq.com/secapi/pay/refund");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) ");  StringEntity entity2 = new StringEntity(outputStr , Consts.UTF_8);httpost.setEntity(entity2);  System.out.println("executing request" + httpost.getRequestLine());  CloseableHttpResponse response = httpclient.execute(httpost);try {  HttpEntity entity = response.getEntity();System.out.println("----------------------------------------");  System.out.println(response.getStatusLine());  if (entity != null) {  System.out.println("Response content length: " + entity.getContentLength());  BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));  String text = "";res.append(text);  while ((text = bufferedReader.readLine()) != null) {  res.append(text);  System.out.println(text);  }  }  EntityUtils.consume(entity);} finally {  response.close();  }  } finally {  httpclient.close();  }  return  res.toString(); }//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 = getChildrenText(children);  }  m.put(k, v);  }  //关闭流  in.close();  return m;  }  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(getChildrenText(list));  }  sb.append(value);  sb.append("</" + name + ">");  }  }  return sb.toString();  }public static String getRemoteHost(HttpServletRequest request){String ip = request.getHeader("x-forwarded-for");if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getHeader("Proxy-Client-IP");}if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getHeader("WL-Proxy-Client-IP");}if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ip = request.getRemoteAddr();}return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;}
}
package com.lemonjr.api.utils;import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class StringUtil {/*** 数值类型前面补零(共13位)* @param num* @return*/public static String supplementZeroGenerateThirteen(int num){String str = String.format("%013d", num); return str;}/*** 数值类型前面补零(共16位)* @param num* @return*/public static String supplementZeroGenerateSixteen(int num){String str = String.format("%016d", num); return str;}/*** 数值类型前面补零(共3位)* @param num* @return*/public static String supplementZeroGenerateThree(int num){String str = String.format("%03d", num); return str;}/*** 判断字符串是不是double型* @param str* @return*/public static boolean isNumeric(String str){ Pattern pattern = Pattern.compile("[0-9]+[.]{0,1}[0-9]*[dD]{0,1}"); Matcher isNum = pattern.matcher(str);if( !isNum.matches() ){return false; } return true; }public static String trim(String str, boolean nullFlag){String tempStr = null;if (str != null){tempStr = str.trim();}if (nullFlag){if ("".equals(tempStr) || "null".equals(tempStr)){tempStr = null;}}else{if (tempStr == null){tempStr = "";}}return tempStr;}public static String replace(String strSource, String strFrom, String strTo) {if(strSource==null){return null;}int i = 0;if ((i = strSource.indexOf(strFrom, i)) >= 0) {char[] cSrc = strSource.toCharArray();char[] cTo = strTo.toCharArray();int len = strFrom.length();StringBuffer buf = new StringBuffer(cSrc.length);buf.append(cSrc, 0, i).append(cTo);i += len;int j = i;while ((i = strSource.indexOf(strFrom, i)) > 0) {buf.append(cSrc, j, i - j).append(cTo);i += len;j = i;}buf.append(cSrc, j, cSrc.length - j);return buf.toString();}return strSource;}public static String deal(String str) {str = replace(str, "\\", "\\\\");str = replace(str, "'", "\\'");str = replace(str, "\r", "\\r");str = replace(str, "\n", "\\n");str = replace(str, "\"", "\\\"");return str;}public static String GetMapToXML(Map<String,String> param){  StringBuffer sb = new StringBuffer();  sb.append("<xml>");  for (Map.Entry<String,String> entry : param.entrySet()) {   sb.append("<"+ entry.getKey() +">");  sb.append(entry.getValue());  sb.append("</"+ entry.getKey() +">");  }    sb.append("</xml>");  return sb.toString();  }  public static void main(String[] args){//String a = StringUtil.supplementZeroGenerateThirteen(1000);double a = 32.;System.out.println(StringUtil.isNumeric("32."));System.out.println(a);}}

4.用到的jar包

<!--微信 --><dependency><groupId>com.github.liyiorg</groupId><artifactId>weixin-popular</artifactId><version>2.8.5</version></dependency>
<!--httpclient--><dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version></dependency><dependency><groupId>org.jdom</groupId><artifactId>jdom2</artifactId><version>2.0.6</version></dependency>

以上是所有代码。不明白的留言!

APP微信支付(java后台_统一下单和回调)相关推荐

  1. 微信回调 java_详解APP微信支付(java后台_统一下单和回调)

    1.微信配置信息 global.properties 2.方法wxpay用于生成预支付订单信息 方法notifyWeiXinPay用于微信支付成功后的回调, 注意: 在手机端使用微信支付成功后,微信服 ...

  2. 微信统一下单 java_微信支付(java版本)_统一下单

    最近工作接触到微信支付,刚开始解决微信支付很神秘,接触之后发现并没有那么神秘,就是有很多坑,在开发的时候需要注意,整理出来: 1.准备工作 首先需要登录微信支付公众平台阅读接口文档,地址:https: ...

  3. app支付宝支付java后台_支付宝app支付java后台流程demo

    支付宝app支付java后台流程demo 使用ssm框架实现支付宝支付功能. 支付宝测试环境代码测试 源代码 https://github.com/OUYANGSIHAI/sihai-maven-ss ...

  4. APP 微信支付java后台代码(解决支付失败返回-1)

    开发之前的准备工作: APP支付申请条件 申请成为APP支付商户需要满足以下条件: 1.APP支付商户,须拥有微信开放平台(http://open.weixin.qq.com)的APPID: 2.AP ...

  5. app微信支付-java服务端接口 支付/查询/退款

    app微信支付-java服务端接口 支付-查询-退款 个人看微信的文档,看了很多前辈的写法,终于调通了,在这里做一下记录. 首先来定义各种处理类(微信支付不需要特殊jar包,很多处理需要自己封装,当然 ...

  6. 微信支付报错:统一下单和拉起支付的appid不一致(原创)

    微信支付报错:统一下单和拉起支付的appid不一致 错误码:-2 提示参考: 参考统一下单的API (谦信君原创,转载请注明来源) 原因排查: 我们做的是APP微信支付 客户端向我服务端发请求,获取预 ...

  7. 微信支付常见错误和统一下单错误码详情

    微信支付常见错误和统一下单错误码详情 微信支付常见问题描述及解决方法 微信调用统一下单接口,当result_code=FAIL时,错误代码及错误描述 参考链接: 微信支付常见问题描述及解决方法 序号 ...

  8. 视频教程-企业微信支付JAVA版_向员工收款-微信开发

    企业微信支付JAVA版_向员工收款 微信企业号星级会员.10多年软件从业经历,国家级软件项目负责人,主要从事软件研发.软件企业员工技能培训.已经取得计算机技术与软件资格考试(软考)--"信息 ...

  9. APP微信支付的后台实现

    参阅微信支付文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5 这一部分说的已经很详细了: 1.app将订单信息传给自己 ...

最新文章

  1. nginx检查配置文件语法是否正常,需要检查主配置文件
  2. 使用信号量实现进程间同步
  3. 医疗在线服务InQuicker,融资0元年盈利400万美元!拒绝风投与炒作
  4. visio交换机图标_分享 | 华为交换机开局配置一本通,弱电新人学习!
  5. 我的第一个web开发框架
  6. Angular 基于自定义指令的内容投影 content projection 问题的单步调试
  7. 忘记token怎么加入k8s集群
  8. Linux 监控命令之 vmstat
  9. 《嵌入式系统Linux内核开发实战指南(ARM平台)》书评
  10. 三菱plc 毕设_三菱plc编程上传/下载程序步骤
  11. matlab中常用符号
  12. MCSA 70-740 windows存储相关的基本概念
  13. 加壳、脱壳以及如何病毒免杀技术与原理
  14. 基于特征的真菌分解木材的理解
  15. 【信息学奥赛一本通 提高组】第三章 深搜的剪枝技巧
  16. win7 破解后找不到活动分区以及bootmsr missing
  17. Ruby语言的优点和缺点
  18. win7休眠设置在哪里_win7系统休眠功能如何关闭 win7系统休眠功能关闭步骤【图解】...
  19. MySQL学习记录(导入Excel表到数据库,并筛选条件输出)
  20. 交换机与路由器技术-05-路由器工作原理

热门文章

  1. 利用 Amazon IoT Greengrass 在边缘 DIY 自动浇花系统
  2. MTK之Flash篇二---如何调整Flash中FAT的配置
  3. Uber无模式数据存储
  4. 数据分析师的工资水平如何?
  5. 硬盘分类及挂载硬盘知识补充和介绍
  6. 物联网传感技术-----无线传感网概述
  7. Python中的Monkey Patching (猴子补丁)
  8. 微信公众平台开发之微商城
  9. 机器人学:操作臂运动学(Manipulator Forward Kinematics)
  10. 修改mysql8.0中数据库的名字