web项目
按顺序一步一步来
准备: 申请了微信支付接口的微信公众号一枚 , 备案的域名网站一枚, (如果有没有的这两个东西会耽误你很久,因为微信支付必须是线上,无法本地调试,)
这里说一下 如果有经济条件的最好申请一台win系统的服务器作为测试服务器这样会使你省去很多的麻烦,装上开发软件直接在线调试很爽.
首先截了几张需要设置的图,了解一下,开发中自己需要的参数常量
图一
图二
图3
图4
图5
这些设置的地方分别在微信公众号平台和微信商户平台,自从2017年8月改版之后微信支付单独拎出来了,有的配置很隐蔽不是很好找还有那个官方给的微信支付的demo
这是微信目前的demo地址 微信支付demo下载 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
demo是maven项目自行配置之后阅读README.md 文件 按这里的提示修改自己的配置 个人感觉相比较v2版的微信支付V3的demo确实简化了不少
配置MyConfig . 微信的demo有点小问题需要自己搞搞,
别忘记下载 (图4) 的证书文件, cert.zip ,安装过程看压缩文件里的教程密码就是公众号的商户号
这里是部分的常量
微信分配的公众账号ID APPID="wxb88888888888be";
/*
* 微信支付商户号
*/
public static final String MCH_ID="14888888888";//必填
/**
* 设备号
*/
public static final String DEVICE_INFO="WEB";//非必填
/**
* 微信服务器回调通知url
*/
public static String NOTIFY_URL="http://localhost:80/paySuccess.do";
/**
* app_select
*/
public static final String APPSELECT="e17706b888888888888888c10";
/**
* token
*/
public static final String TOKEN="MYTOKEN";
/**
* EncodingAESKey
*/
public static final String EncodingAESKey="gXL1RGlDN2KfeCL8888888888888EfB6Tyt3y";
/**
* API秘钥
*/
public static final String APPKEY="JXyrBTnsS8888888888HbaVGhdcXso";
demo配置好之后几乎该有的都有了, 像之前md5加密函数,随机字符串,时间戳等等 微信demo工具类里WXPayUtil.java都提供了
之后就是页面访问调启jsapi支付,
编写后台函数调用统一下单接口
这个后台方法注意了,支付授权目录就是这里
例: http://www.baidu.com/apy/ (授权目录)
这样 这几个fang都可以使用
http://www.baidu.com/pay/doShopScore.do
http://www.baidu.com/pay/doShopScore.do2
http://www.baidu.com/pay/doShopScore.do3
需要注意的一个地方, try {}块里的代码
Map<String, String> mp = wxpay.unifiedOrder(data);
微信处理完之后返回的集合 的使用,
看到返回的值什么都有了就直接拿到jsapi里用,就一直签名验证失败,后来发现 Sign 不是paySign (其实我到现在也不知道你们这个签名是不是一样的含义) ,艹,谁知道还分这玩意儿 ,说真的微信里参数名起名起的一塌糊涂,乱七八糟,
最后反正只从mp里取了一个参数package用了重新生成了签名,居然可以了,乖乖
这个微信真是的,本来参数就不清楚了开发的时候都得懵, 到底是想干嘛,如果是想让自己生成签名(paySign)干嘛返回签名(Sign)
/**
* 用户 购买成为 VIP 产生 (积分) 进入付款页面 (接口)
*/
@ResponseBody
@RequestMapping(value = "/pay/doShopScore.do", method = RequestMethod.POST)
public Map<String,Object> doShopScore(HttpServletRequest request, HttpServletResponse response,Model model) throws Exception {
String custId = Global.ZW_WECHAT_COMPANY_ID;//
Map<String,Object> resultMap = new HashMap<String, Object>();
String openid = (String) this.getSession().getAttribute("customerOpenId");
String body = "科技-物品";//作为订单商品名称使用
String total_fee = "0";//总金额数(分)
//获取物品id
String dbGoodsPriceId = request.getParameter("dbGoodsPriceId");//0 300,1 3000
String referrerOpenid = request.getParameter("referrerOpenId");//推荐人的openid 注意大小写
String referrerPhone = request.getParameter("referrerPhone");//推荐人的注册电话
DbGoodsPrice dbGoodsPrice = null;
if(StringUtils.isNotBlank(dbGoodsPriceId)){
dbGoodsPrice = dbGoodsPriceService.get(new DbGoodsPrice(dbGoodsPriceId));
body = dbGoodsPrice.getDbGoods().getGoodsName();
total_fee = String.valueOf(dbGoodsPrice.getGoodsPrice());
}
String appid = ConstantUtil.APPID;
String mch_id = ConstantUtil.MCH_ID;
String device_info = ConstantUtil.DEVICE_INFO;
String nonce_str = WXPayUtil.generateNonceStr();
String out_trade_no = DateUtils.fmtTime14Date(new Date());//商户订单号
String fee_type = "CNY";//人民币
String spbill_create_ip = request.getRemoteAddr();//终端ip
Date currDate = new Date();//当前日期
String time_stamp = DateUtilsEx.formatToString(currDate,DateUtilsEx.DATE_FORMAT_SEC_U);//交易起始时间
String time_expire = com.jeeplus.common.utils.DateUtils.getCurrTimePushMinute4DateStr(currDate,Integer.valueOf(SetUpUtils.getConfigParam("sys_order_pay_validity_date",custId)));//交易结束时间 当前时间 + 30分钟
String notify_url = ConstantUtil.NOTIFY_URL;
String trade_type = ConstantUtil.TRADE_TYPE;//JSAPI
//预支付订单生成===================start===========================
DbOrder dbOrder = new DbOrder();
dbOrder.setOrderCode(SetUpUtils.BaseSeq(custId,1));//订单序号
dbOrder.setOrderType(DictUtils.getDictValue("订单","zw_order_type","0"));//订单类型0 股份类型
dbOrder.setOutTradeNo(out_trade_no);
dbOrder.setGoodName(body);
dbOrder.setGoodPrice(Integer.valueOf(total_fee));
dbOrder.setGoodsPriceId(dbGoodsPrice.getId());
dbOrder.setGoodsNum(1);//
dbOrder.setIntegralToCash(0);
dbOrder.setTotalPrice(Integer.valueOf(total_fee));
dbOrder.setFeeType(DictUtils.getDictValue("人民币","zw_currency","0"));
dbOrder.setPayType(DictUtils.getDictValue("微信支付","zw_pay_type","0"));//支付类型
dbOrder.setPayState(DictUtils.getDictValue("未支付","zw_pay_state","0"));//订单状态
dbOrder.setCustomerOpenid(openid);
User user = (User) this.getSession().getAttribute("customer");
dbOrder.setOrderPayValidityDate(com.jeeplus.common.utils.DateUtils.getCurrTimePushMinute4Date(currDate,Integer.valueOf(SetUpUtils.getConfigParam("sys_order_pay_validity_date",custId))));//订单支付有效期
dbOrder.setCreateBy(user);
dbOrder.setCreateDate(new Date());//订单创建时间
dbOrder.setReferrerPhone(referrerPhone);//推荐人电话
dbOrder.setReferrerOpenid(referrerOpenid);//推荐人openid
dbOrder.setUpdateBy(user);
dbOrder.setUpdateDate(new Date());
dbOrder.setNonceStr(nonce_str);
dbOrder.setTimeStamp(time_stamp);
dbOrder.setTimeExpire(time_expire);
dbOrder.setSpbillCreateIp(spbill_create_ip);
if(!dbOrder.getIsNewRecord()){//编辑表单保存
DbOrder t = dbOrderService.get(dbOrder.getId());//从数据库取出记录的值
MyBeanUtils.copyBeanNotNull2Bean(dbOrder, t);//将编辑表单中的非NULL值覆盖数据库记录中的值
dbOrderService.save(t);//保存
}else{//新增表单保存
dbOrderService.save(dbOrder);//保存
}
//订单log 未支付
//订单id//单据状态 //状态说明 //操作者id
DbOrderLog dbOrderLog = setDbRepairLogParam(dbOrder.getId(),0,DictUtils.getDictLabel("0","zw_pay_state","未支付"), user.getId());
dbOrderLogService.save(dbOrderLog);//保存
this.getSession().setAttribute("orderId",dbOrder.getId());//订单id
//预支付订单生成===================end===========================
//设置支付参数==============================================
MyConfig config = new MyConfig();
WXPay wxpay = new WXPay(config, notify_url);
Map<String, String> data = new HashMap<String, String>();
data.put("appid",appid);
data.put("mch_id",mch_id);
data.put("device_info",device_info);
data.put("body",body);
data.put("nonce_str",nonce_str);
data.put("openid",openid);
data.put("fee_type", fee_type);
data.put("trade_type",trade_type);//jsAPI 支付
data.put("total_fee", total_fee);
data.put("time_start",String.valueOf(time_stamp));//起始时间
data.put("time_expire",String.valueOf(time_expire));//结束时间
data.put("out_trade_no",out_trade_no);
data.put("spbill_create_ip",spbill_create_ip);
data.put("notify_url",notify_url);
try {
Map<String, String> mp = wxpay.unifiedOrder(data);
/*model.addAttribute("appid",appid);
model.addAttribute("time_stamp",time_stamp);
model.addAttribute("openid",openid);
model.addAttribute("nonce_str",mp.get("nonce_str"));
model.addAttribute("package", "prepay_id="+mp.get("prepay_id").toString().trim());*/
Map<String, String> data2 = new HashMap<String, String>();
data2.put("appId", appid); // 必须
data2.put("timeStamp",String.valueOf(time_stamp));
data2.put("nonceStr", mp.get("nonce_str"));
data2.put("signType", "MD5");
data2.put("package", "prepay_id=" + mp.get("prepay_id").toString().trim());//注意prepay_id的值是一个键值对
//model.addAttribute("paySign",WXPayUtil.generateSignature(data2,ConstantUtil.APPKEY));
resultMap.put("appid",appid);
resultMap.put("time_stamp",time_stamp);
resultMap.put("openid",openid);
resultMap.put("nonce_str",mp.get("nonce_str"));
resultMap.put("packageStr", "prepay_id="+mp.get("prepay_id").toString().trim());
resultMap.put("paySign",WXPayUtil.generateSignature(data2,ConstantUtil.APPKEY));
} catch (Exception e) {
e.printStackTrace();
return null;
}
return resultMap;
}
jsp页面
$.ajax({
url:ctx+"/wechat/pay/doShopScore.do",
type:"POST",
data:{"dbGoodsPriceId":dbGoodsPriceId},
success:function(resultMap){
submit_flag=true;
if(resultMap != null && resultMap !=''){
var appid = resultMap.appid;
var time_stamp = resultMap.time_stamp;
var nonce_str = resultMap.nonce_str;
var packageStr = resultMap.packageStr;
var paySign = resultMap.paySign;
//设置参数
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId":appid, //公众号名称,由商户传入
"timeStamp":time_stamp+"", //时间戳,自1970年以来的秒数
"nonceStr":nonce_str, //随机串
"package":packageStr,
"signType":"MD5",//微信签名方式:
"paySign":paySign
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
//alert("支付成功");
// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
location.replace(ctx+"/wechat/pay/toSuccessVip.do");//跳到订单成功页
}else if (res.err_msg == "get_brand_wcpay_request:cancel") {
//alert("支付过程中用户取消");
//用户取消订单支付返回订单列表
window.location.href=ctx+"/wechat/pay/notPay.do";
}else{
//支付失败
alert(res.err_msg);
}
}
);
}
},
error:function(e){
submit_flag=true;
}
});
支付成功还要有个成功之后的回调函数,不给返回success 代码 还一直不停的回调,注意了
/**
* 微信支付成功后回调方法
* @param request
* @param response
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/pay/paySuccess.do")
public String notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
String result;//返回给微信的处理结果
String inputLine;
String notityXml = "";
request.setCharacterEncoding("UTF-8");
//response.setCharacterEncoding("UTF-8");
//response.setContentType("text/html;charset=UTF-8");
//response.setHeader("Access-Control-Allow-Origin", "*");
//微信给返回的东西
try {
while ((inputLine = request.getReader().readLine()) != null) {
notityXml += inputLine;
}
request.getReader().close();
} catch (Exception e) {
e.printStackTrace();
result = setXml("fail","xml获取失败");
}
if (StringUtils.isEmpty(notityXml)) {
result = setXml("fail","xml为空");
}
System.out.println(notityXml);
Map map = WXPayUtil.xmlToMap(notityXml);
// 解析各种数据
String appid = (String) map.get("appid");//应用ID
String attach = (String) map.get("attach");//商家数据包
String bank_type = (String) map.get("bank_type");//付款银行
String cash_fee = (String) map.get("cash_fee");//现金支付金额
String fee_type = (String) map.get("fee_type");//货币种类
String is_subscribe = (String) map.get("is_subscribe");//是否关注公众账号
String mch_id = (String) map.get("mch_id");//商户号
String nonce_str = (String) map.get("nonce_str");//随机字符串
String openid = (String) map.get("openid");//用户标识
String out_trade_no = (String) map.get("out_trade_no");// 获取商户订单号
String result_code = (String) map.get("result_code");// 业务结果
String return_code = (String) map.get("return_code");// SUCCESS/FAIL
String sign = (String) map.get("sign");// 获取签名
String time_end = (String) map.get("time_end");//支付完成时间
String total_fee = (String) map.get("total_fee");// 获取订单金额
String trade_type = (String) map.get("trade_type");//交易类型
String transaction_id = (String) map.get("transaction_id");//微信支付订单号
User user = systemService.getUserByOpenId(openid);
SortedMap<String, String> parameters = new TreeMap<String, String>();
// 数据加密
parameters.put("appid", appid);//应用ID
parameters.put("attach", attach);//商家数据包
parameters.put("bank_type", bank_type);//付款银行
parameters.put("cash_fee", cash_fee);//现金支付金额
parameters.put("fee_type", fee_type);//货币种类
parameters.put("is_subscribe", is_subscribe);//是否关注公众账号
parameters.put("mch_id", mch_id);//商户号
parameters.put("nonce_str", nonce_str);//随机字符串
parameters.put("openid", openid);//用户标识
parameters.put("out_trade_no", out_trade_no);// 商户订单号
parameters.put("result_code", result_code);// 业务结果
parameters.put("return_code", return_code);// SUCCESS/FAIL
parameters.put("time_end", time_end);// 支付完成时间
parameters.put("total_fee", total_fee);// 获取订单金额
parameters.put("trade_type", trade_type);//交易类型
parameters.put("transaction_id", trade_type);//微信支付订单号
/*System.out.println("**************************************************************************************************");
System.out.println(appid+"-------------------应用ID");
System.out.println(attach+"-------------------商家数据包");
System.out.println(bank_type+"-------------------付款银行");
System.out.println(cash_fee+"-------------------现金支付金额");
System.out.println(fee_type+"-------------------货币种类");
System.out.println(is_subscribe+"-------------------是否关注公众账号");
System.out.println(mch_id+"-------------------商户号");
System.out.println(nonce_str+"-------------------随机字符串");
System.out.println(openid+"-------------------用户标识");
System.out.println(out_trade_no+"-------------------获取商户订单号");
System.out.println(result_code+"-------------------业务结果");
System.out.println(return_code+"------------------- SUCCESS/FAIL");
System.out.println(sign+"-------------------获取签名-微信回调的签名");
System.out.println(time_end+"-------------------支付完成时间");
System.out.println(total_fee+"-------------------获取订单金额");
System.out.println(trade_type+"-------------------交易类型");
System.out.println(transaction_id+"-------------------微信支付订单号");
System.out.println("**************************************************************************************************");
*/
if (result_code.equals("SUCCESS")) {
result = setXml("SUCCESS", "OK");
}else{
result = setXml("fail", "微信返回的交易状态不正确(result_code=" + result_code + ")");
System.err.println("微信返回的交易状态不正确(result_code=" +result_code+ ")");
}
// 如果微信返回的结果是success,则修改订单状态
if (return_code.equals("SUCCESS")) {
result = setXml("SUCCESS", "OK");
//这里是我的业务........................................
}else{
result = setXml("fail", return_code);
}
System.out.println("回调成功----返回给微信的xml:" + result);
return result;
}
//通过xml 发给微信消息
public static String setXml(String return_code, String return_msg) {
SortedMap<String, String> parameters = new TreeMap<String, String>();
parameters.put("return_code", return_code);
parameters.put("return_msg", return_msg);
return "<xml><return_code><![CDATA[" + return_code + "]]>" +
"</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
}
配置域名千万检查清楚不能写错,虽然简单但是很致命,因为那是你很少再会去检查的地方 祝你好运