详解APP微信支付(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 block
			e.printStackTrace();
		}
    String openId = "";

    Map<String, String> map = weixinPrePay(trade_no,totalAmount,description,openId,request);
    SortedMap<String, Object> finalpackage = new TreeMap<String, Object>();
    //应用ID
    finalpackage.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"));
    //预支付交易会话ID
    finalpackage.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)); //接口中参数支付金额单位为【分】,参数值不能带小数,所以乘以100
    java.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("支付回调地址")
  @ResponseBody
  public 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()));
      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" };

}
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);
   //过滤空 设置 TreeMap
    SortedMap<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后台_统一下单和回调)详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 微信支付java版本之获取Access_token

    access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存.access_token的存储至少要保留512个字符空间.access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效. 公众平台的API调用所需的access_token的使用及生成方式说明: 1.为了保密appsecrect,第三方需要一个access_token获取和刷新的中控服务器.而其他业务逻辑服务器所使用的ac

  • Java微信支付之公众号支付、扫码支付实例

    微信支付现在已经变得越来越流行了,随之也出现了很多以可以快速接入微信支付为噱头的产品,不过方便之余也使得我们做东西慢慢依赖第三方,丧失了独立思考的能力,这次打算分享下我之前开发过的微信支付. 一 .H5公众号支付 要点:正确获取openId以及统一下单接口,正确处理支付结果通知,正确配置支付授权目录 H5的支付方式是使用较为广泛的方式,这种支付方式主要用于微信内自定义菜单的网页,依赖手机上安装的微信客户端,高版本的微信才支持微信支付,下面按我的流程注意说明 1  编写用于支付的页面,由于是测试用

  • java实现微信支付(服务端)

    废话不多说,直接看代码. RequestHandler requestHandler = new RequestHandler(super.getRequest(),super.getResponse()); //获取token //两小时内有效,两小时后重新获取 Token = requestHandler.GetToken(); //更新token 到应用中 requestHandler.getTokenReal(); System.out.println("微信支付获取token=====

  • Java微信支付-微信红包

    微信红包的使用已经很广泛,本篇文章介绍了微信发红包的实例,需要有认证的公众号,且开通了微信支付,商户平台且开通了现金红包的权限即可. https://pay.weixin.qq.com商户登陆地址.选择查看营销中心的现金红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1 现金红包的官网文档说明 先看几个图 简单的测试.前提需要你去商户平台先充值.不支持预支付.本文只是总结微信现金红包接口的调用与

  • Java编程调用微信支付功能的方法详解

    本文实例讲述了Java编程调用微信支付功能的方法.分享给大家供大家参考,具体如下: 微信开发文档地址:https://mp.weixin.qq.com/wiki/home/ 从调用处开始 我的流程: 1.点击"支付"按钮,去后台 --> 2.后台生成支付所需数据返回页面 --> 3.页面点击"确认支付"调用微信支付js.完成支付功能. 支付按钮 <div class="button" id="pay" onc

  • 微信支付H5调用支付详解(java版)

    最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验. 一.配置公众号微信支付  需要我们配置微信公众号支付地址和测试白名单. 比如:支付JS页面的地址为 http://www.xxx.com/shop/pay/ 那此处配置www.xxx.com/shop/pay/ 二.开发流程 借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/d

  • 微信支付java版本之查询订单

    本文实例为大家分享了微信支付订单的查询接口,供大家参考,具体内容如下 1.接口简介 2.代码实现 package com.zhrd.bussinss.platform.controller.shop; import java.io.File; import java.io.FileInputStream; import java.security.KeyStore; import java.text.SimpleDateFormat; import java.util.Date; import

  • 微信支付java版本之JSAPI支付+发送模板消息

    本文为大家分享了java版本之JSAPI支付+发送模板消息的相关资料,供大家参考,具体内容如下 1.工具类 工具类见:微信支付JAVA版本之Native付款 2.公众账号设置 3.代码实现 openId:openId为用户与该公众账号之间代表用户的唯一标示  以下类中涉及到生成token,关闭订单接口调用,获取配置文件信息,和工具类,在其他文章中有具体代码实现 package com.zhrd.bussinss.platform.controller.rest; import java.io.F

  • Java通过JsApi方式实现微信支付

    要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回.由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分. 示例代码如下: function onBridgeReady(){ WeixinJSBridge

  • 使用weixin-java-tools完成微信授权登录、微信支付的示例

    本文为学习记录weixin-java-tools实现公众号微信支付. 码云地址:点我 // 授权登录用到 <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>3.1.0</version> </dependency> // 微信支付用到 <depende

随机推荐