详解APP微信⽀付(java后台_统⼀下单和回调)
1.微信配置信息 global.properties
2.⽅法wxpay⽤于⽣成预⽀付订单信息
⽅法notifyWeiXinPay⽤于微信⽀付成功后的回调, 注意: 在⼿机端使⽤微信⽀付成功后,微信服务器会根据提供的回调地址进⾏回调, parameterMap.put("notify_url", wxnotify); (见下⾯代码)
在局域⽹是⽆法进⾏回调的,必须将你的服务端放在公⽹上进⾏测试,回调函数会被多次调⽤,如果第⼀次成功后,你可以将业务数据状态标志为已处理, 对于相同订单的其它回调就不需要再次处理了;
package ller;
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.rvlet.http.HttpServletRequest;
import javax.rvlet.http.HttpServletRespon;
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.ResponBody;
import del.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 = RandomString(32);
//⽀付成功后的回调函数
public static String wxnotify = "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)
地下连续墙导墙@ResponBody
public Result wxpay(HttpServletRequest request) {
Result result = new Result();
Long urId = new Long(1);//UrId();
try {
trade_no = new Parameter("orderNum").getBytes("ISO-8859-1"),"UTF-8");
description = Parameter("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", Instance().getConfigItem("WXAppID")/*PayCommonUtil.APPID*/);
//商户号
finalpackage.put("partnerid", Instance().getConfigItem("MCH_ID"));
Long time = (System.currentTimeMillis() / 1000);
//时间戳
finalpackage.put("timestamp", String());
//随机字符串
finalpackage.put("noncestr", ("nonce_str"));
//预⽀付交易会话ID
finalpackage.put("prepayid", ("prepay_id"));
//扩展字段
finalpackage.put("package", "Sign=WXPay");
WeiXinPrePay prePay = new WeiXinPrePay();
prePay.Instance().getConfigItem("WXAppID"));
prePay.Instance().getConfigItem("MCH_ID"));
prePay.String());
prePay.("nonce_str"));
prePay.("prepay_id"));
prePay.tSignType("MD5");
prePay.tPaySign(sign);
result.tData(prePay);
result.tStateCode(GeneralConstant.SUCCESS);
result.tDesc("微信⽀付加载成功");
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", Instance().getConfigItem("WXAppID")); //应⽤appid
parameterMap.put("mch_id", Instance().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 DecimalFormat df=DecimalFormat("0");
parameterMap.put("total_fee", df.format(total));
System.out.println("jiner2");
parameterMap.put("spbill_create_ip", RemoteHost(request));
parameterMap.put("notify_url", wxnotify);
parameterMap.put("trade_type", "APP");//"JSAPI"
//trade_type为JSAPI是 openid为必填项
//parameterMap.put("openid", openid);
parameterMap.put("sign", sign);
String requestXML = RequestXml(parameterMap);
System.out.println(requestXML);
String result = PayCommonUtil.httpsRequest(
"h./pay/unifiedorder", "POST",
requestXML);个人履职情况报告
System.out.println(result);
Map<String, String> map = null;
try {
map = PayCommonUtil.doXMLPar(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 respon
* @return
* @throws IOException
* @throws JDOMException
*/
@RequestMapping(value = "notifyWeiXinPay", produces = MediaType.APPLICATION_JSON_VALUE)
// @RequestDescription("⽀付回调地址")
@ResponBody
public String notifyWeiXinPay(HttpServletRequest request, HttpServletRespon respon) throws IOException, JDOMException { System.out.println("微信⽀付回调");
InputStream inStream = InputStream();
提琴曲
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = ad(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String resultxml = new ByteArray(), "utf-8");
Map<String, String> params = PayCommonUtil.doXMLPar(resultxml);
outSteam.clo();
inStream.clo();
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);
} el {
System.out.println("===============付款成功==============");
// ------------------------------观音菩萨坐骑
守株待兔作者// 处理业务开始
// ------------------------------
// 此处处理订单状态,结合⾃⼰的订单数据完成订单状态的更新
// ------------------------------
String total_fee = ("total_fee");
double v = Double.valueOf(total_fee) / 100;
String out_trade_no = String.valueOf(Long.("out_trade_no").split("O")[0]));
Date accountTime = DateUtil.("time_end"), "yyyyMMddHHmmss");
String ordertime = DateUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss");
String totalAmount = String.valueOf(v);
String appId = ("appid");
String tradeNo = ("transaction_id");
return_data.put("return_code", "SUCCESS");
return_data.put("return_msg", "OK");
}
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 = Properties(); //获取系统属性
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> keyt = m_props.keySet();
Iterator<Object> it = keyt.iterator();
while(it.hasNext()){
String nextkey = it.next().toString();
configMap.put(nextkey,getConfigItem(nextkey));
}
return configMap;
}
public String getConfigItem(String name) {
String val = Property(name).trim();
if("fileSavePath".equals(name)){
Property("os.name").startsWith("Windows")){
val = val.split("#")[0].toString().trim();
}el{
val = val.split("#")[1].toString().trim();
}
}
return val;
}
public Map<String,String> getConfigMap(){
return configMap;
DateFormat;
ParPosition;
SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import 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.tLenient(fal);
d = formater.par(dateStr);
} catch (Exception e) {
// (e);
d = null;
}
return d;
}