首先 这个微信支付 官网的demo 是有bug的 研究了好几天 吸取了一些大神的指点才成功,还有csdn一些人发的代码都不全太坑,资源还少,今天我就整合一下,
把我的一些心得分享给大家 。
之前遇到的一些问题:
预支付id获取失败,签名失败,您没有JSAPI支付权
预支付id获取失败的原因是: 交易类型这是成默认APP ,一些 随机数位数 都要跟api 对应上,加密的时候api的那些字段都要排序好按照(a-b),获取的时候 需要传递两个参数 (统一下单接口地址,拼接成的xml)。
签名失败的原因是:预支付id获取失败,加密的时候排序的顺序,加密用MD5 32位转换大写!
您没有JSAPI支付权: 商户的一些id 一些号 都要对应上
以上就是大致的错误! 现在上代码 !
首先 这个微信支付 官网的demo 是有bug的 研究了好几天 吸取了一些大神的指点才成功,还有csdn一些人发的代码都不全太坑,资源还少,今天我就整合一下,
把我的一些心得分享给大家 。
实体层代码
[java] view plain copy
package com.model;
/**
* 微信支付实体
* @author 裴广庭
*
*/
public class WxPay {
private String orderId;//订单号
private String totalFee;//金额
//private String spbillCreateIp;//订单生成的机器 IP
private String notifyUrl;//这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等
private String body;// 商品描述根据情况修改
private String openId;//微信用户对一个公众号唯一
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getTotalFee() {
return totalFee;
}
public void setTotalFee(String totalFee) {
this.totalFee = totalFee;
}
// public String getSpbillCreateIp() {
// return spbillCreateIp;
// }
// public void setSpbillCreateIp(String spbillCreateIp) {
// this.spbillCreateIp = spbillCreateIp;
// }
public String getNotifyUrl() {
return notifyUrl;
}
public void setNotifyUrl(String notifyUrl) {
this.notifyUrl = notifyUrl;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
}
单独写的微信商户平台信息的类
[java] view plain copy
package com.util.weixin;
public class WeixinPayConstants {
//微信支付商户开通后 微信会提供appid和appsecret和商户号partner
public static final String appid = "****";//在微信开发平台登记的app应用
public static final String appsecret = "****";
public static final String partner = "****";//商户号
//这个参数partnerkey是在商户后台配置的一个32位的key,微信商户平台-账户设置-安全设置-api安全
public static final String partnerkey = "****";
public static final String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//openId 是微信用户针对公众号的标识,授权的部分这里不解释
public static final String openId = "";
//微信支付成功后通知地址 必须要求80端口并且地址不能带参数
public static final String notifyurl = "https://**.**.**.**:8080/zhihuishe/weixin/notify";
}
后台请求入口
[java] view plain copy
// 商户相关资料
private static String appid = WeixinPayConstants.appid;
private static String appsecret = WeixinPayConstants.appsecret;
private static String partner = WeixinPayConstants.partner;
private static String partnerkey = WeixinPayConstants.partnerkey;
private static String notifyurl = WeixinPayConstants.notifyurl;
@RequestMapping(value = "/wxPay", method = RequestMethod.GET)
public void wxPay(HttpServletRequest request, HttpSession session,
HttpServletResponse response) throws IOException {
Tool tool = new Tool();
String totalFee = request.getParameter("totalFee");
String body = request.getParameter("body");
WxPay tpWxPay = new WxPay();
tpWxPay.setTotalFee(totalFee);
tpWxPay.setBody(body);
tpWxPay.setOrderId(tool.orderNo());
Object obj = getPackage(request,response, tpWxPay);
JSONArray json = JSONArray.fromObject(obj);
response.setCharacterEncoding(Constants.ENCODING_UTF8);
response.getWriter().print(json.toString());
}
getPackage方法 加密,生成签名,请求手机端,吊起微信支付!
[java] view plain copy
/**
* 获取请求预支付id报文
* @return
* @throws IOException
*/
public static Object getPackage(HttpServletRequest request,HttpServletResponse response,WxPay tpWxPay)
throws IOException {
JSONObject retMsgJson = new JSONObject();
String openId = WeixinPayConstants.openId;
// 订单号
String orderId = tpWxPay.getOrderId();
// 附加数据 原样返回
String attach = "";
// 总金额以分为单位,不带小数点
String totalFee = getMoney(tpWxPay.getTotalFee());
// 订单生成的机器 IP
//String spbill_create_ip = tpWxPay.getSpbillCreateIp();
// 这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。
String notify_url = notifyurl;
//交易类型
String trade_type = "APP";
// ---必须参数
// 商户号
String mch_id = partner;
// 随机字符串
String nonce_str = Tool.getRandom();
// 商品描述根据情况修改
String body = tpWxPay.getBody();
// 商户订单号
String out_trade_no = orderId;
SortedMap<String, String> packageParams = new TreeMap<String, String>();
packageParams.put("appid", appid);//应用ID ---微信开放平台审核通过的应用APPID
packageParams.put("attach", attach);//附加数 ---附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
packageParams.put("body", body);//商品描述
packageParams.put("mch_id", mch_id);//商户号
packageParams.put("nonce_str", nonce_str);//随机字符串
packageParams.put("notify_url", notify_url);//通知地址 ---微信给发的回调地址,要放在公网
packageParams.put("openid", openId);////用户标识
packageParams.put("out_trade_no", out_trade_no);//商户订单号
//packageParams.put("spbill_create_ip", spbill_create_ip);//手机端ip
packageParams.put("total_fee", totalFee);//总金额
packageParams.put("trade_type", trade_type);//交易类型
RequestHandler reqHandler = new RequestHandler(request, response);
reqHandler.init(appid, appsecret, partnerkey);
//MD5加密
String sign = reqHandler.createSign(packageParams);
//拼接成xml 形式 生成预支付id---prepay_id
String xml = "<xml>" + "<appid><![CDATA[" + appid + "]]></appid>"
+ "<attach><![CDATA[" + attach + "]]></attach>"
+ "<body><![CDATA[" + body + "]]></body>"
+ "<mch_id><![CDATA[" +mch_id + "]]></mch_id>"
+ "<nonce_str><![CDATA[" + nonce_str + "]]></nonce_str>"
+ "<notify_url><![CDATA[" + notify_url + "]]></notify_url>"
+ "<out_trade_no><![CDATA[" + out_trade_no + "]]></out_trade_no>"
//+ "<spbill_create_ip><![CDATA[" + spbill_create_ip + "]]></spbill_create_ip>"
+ "<total_fee><![CDATA[" + totalFee + "]]></total_fee>"
+ "<trade_type><![CDATA[" + trade_type + "]]></trade_type>"
+ "<sign><![CDATA[" + sign + "]]></sign>" + "</xml>";
String prepay_id = "";
//统一下单接口地址
String createOrderURL = WeixinPayConstants.createOrderURL;
//获取预支付id
prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
System.out.println("获取到的预支付ID:" + prepay_id);
// 获取到prepayid后对以下字段进行签名最终发送给app
SortedMap<String, String> finalpackage = new TreeMap<String, String>();
String timestamp = Sha1Util.getTimeStamp();
finalpackage.put("appid", appid);
finalpackage.put("timestamp", timestamp);
finalpackage.put("noncestr", nonce_str);
finalpackage.put("package", "Sign=WXPay");
finalpackage.put("partnerid", mch_id);
finalpackage.put("prepayid", prepay_id);
//MD5签名
String finalsign = reqHandler.createSign(finalpackage);
System.out.println("签名" + finalsign);
//打印方便看
String finaPackage = "appid=" + appid + "&partnerid=" + mch_id
+ "&prepayid=" + prepay_id + "&package=" + "Sign=WXPay"
+ "&noncestr=" + nonce_str + "×tamp=" + timestamp
+ "&sign=" + finalsign;
System.out.println("V3 jsApi package:" + finaPackage);
//最后发给发给手机端
retMsgJson.put("msg", "ok");
retMsgJson.put("appid", appid);
retMsgJson.put("prepayid", prepay_id);
retMsgJson.put("partnerid", mch_id);
retMsgJson.put("package", "Sign=WXPay");
retMsgJson.put("noncestr", nonce_str);
retMsgJson.put("timestamp", timestamp);
retMsgJson.put("sign", finalsign);
retMsgJson.put("sendUrl", notify_url);
return retMsgJson;
}
以上是 微信支付 , 支付完成后 微信会回调一些服务器 首先这里 项目一定要放在公网上面 因为 方便 微信访问! 下面是回调代码!
方便在服务器上排除错 我用最笨的方法 就是加打印 都打印到日志上了。。 shell 没有研究明白
在声明一下 !! 这个回调地址 必须放在公网上 言外之意 你想测试项目 必须把项目放在公网上 注意 端口号必须是8080!!!!!!!!!!!
public static final String notifyurl = "https://123.**.**.**:8080/zhihuishe/weixin/notify";
微信异步通知
[java] view plain copy
// 微信异步通知
@RequestMapping(value = "/notify")
@ResponseBody
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为空");
}
Map map = new GetWxOrderno().doXMLParse(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");//微信支付订单号
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);//微信支付订单号
//加密前验证notify支付订单网关---https://gw.tenpay.com/gateway/simpleverifynotifyid.xml
RequestHandler reqHandler = new RequestHandler(request, response);
reqHandler.init(appid, appsecret, partnerkey);
//MD5加密
String endsign = reqHandler.createSign(parameters);
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(endsign+"-------------------第二次加密sign");
System.out.println("**************************************************************************************************");
// 验证签名
if (sign.equals(endsign)) {
result = setXml("SUCCESS", "OK");
} else {
System.err.println("签名不一致!");
result = setXml("fail", "签名不一致!");
}
if (!"SUCCESS".equals("SUCCESS")) {
System.err.println("微信返回的交易状态不正确(result_code=" + "SUCCESS" + ")");
result = setXml("fail", "微信返回的交易状态不正确(result_code=" + "SUCCESS" + ")");
}
//如果成功写入数据库
if ("SUCCESS".equals("SUCCESS")) {// 如果微信返回的结果是success,则修改订单状态
//判断订单号是否重复
List<CapitalTable> userList = cpitalTableService.queryOrder(out_trade_no);
if (userList.size() > 0) {
result = setXml("fail", "订单号重复");
}else{
CapitalTable capitalTable = new CapitalTable();
UserAdmin userAdmin = new UserAdmin();
userAdmin.setId(6);
capitalTable.setCapital(total_fee);//金币
capitalTable.setState("1");//类型:1充值2提问3回答
capitalTable.setDatetime(new Date());//流入时间
capitalTable.setOrderNo(out_trade_no);
capitalTable.setUserAdmin(userAdmin);
cpitalTableService.insertCapital(capitalTable);
}
}
System.out.println("回调成功");
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>";
}
有的需求需要将元转成分
[java] view plain copy
/**
* 元转换成分
* @param money
* @return
*/
public static String getMoney(String amount) {
if(amount==null){
return "";
}
// 金额转化为分为单位
String currency = amount.replaceAll("\\$|\\¥|\\,", ""); //处理包含, ¥ 或者$的金额
int index = currency.indexOf(".");
int length = currency.length();
Long amLong = 0l;
if(index == -1){
amLong = Long.valueOf(currency+"00");
}else if(length - index >= 3){
amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));
}else if(length - index == 2){
amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);
}else{
amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");
}
return amLong.toString();
}
以上就是 微信支付的全过程