java-微信公众号充值
来源:互联网 发布:企业网络机房建设标准 编辑:程序博客网 时间:2024/05/16 16:21
实现功能:公众号内H5页面调用微信支付实现充值,
1.开发流程
1) 申请公众号 并且认证 (这个是前提 自行百度有很多方法)
2)获取用户授权 获取openid (上一篇文章有介绍怎么获取)
3)调用统一下单接口获取预支付id 微信统一接口API https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
4)H5调起微信支付的内置JS
5)支付完成后,微信回调URL的处理
第1).2)步就不在介绍了....
2.统一接口参数介绍
appid ==应用ID==登陆微信公众号后台-开发-基本配置
mch_id == 微信支付商户号==登陆微信支付后台,即可看到
body==商品描述==商品或支付单简要描述
spbill_create_ip==获取发起电脑ip
代码如下
String spbill_create_ip = LLPayUtil.getIpAddr(request).replace("_", ".");
/**
*
* 功能描述:获取真实的IP地址
* @param request
* @return
* @author guoyx
*/
public static String getIpAddr(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();
}
if (!isnull(ip) && ip.contains(","))
{
String[] ips = ip.split(",");
ip = ips[ips.length - 1];
}
//转换IP 格式
if(!isnull(ip)){
ip=ip.replace(".", "_");
}
return ip;
}
trade_type==交易类型==取值如下:JSAPI,NATIVE,APP。我们这里使用的JSAPI。标题已经说了,是微信公众号支付。他们的区别,请参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2
ps:JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里。MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口
nonce_str==随机字符串==随机字符串,不长于32位
代码如下
/**
* 获取随机字符串 Nonce Str
*
* @return String 随机字符串
*/
public static String generateNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
notify_url==通知地址==接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
out_trade_no==商户订单号==商户系统内部的订单号,32个字符内、可包含字母
代码如下
/**
* 生成订单号,格式:XX(前缀) + yyyyMMddHHmmss + 10位数
* @param prefix
* @return
*/
public static String generate(String prefix) {
synchronized(locker) {
if (sn == 999999999) {
sn = 0;
} else {
sn ++;
}
String str = String.format("%010d", sn);
return prefix + sdf.format(new Date()) + str;
}
}
total_fee==总金额==订单总金额
代码如下 money金额
String.valueOf((int)(money*100))
openid==用户标识==trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
sign==签名==官方给的签名算法
代码如下
key==key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
/**
* @author
* @date 2016-4-22
* @Description:sign签名
* @param characterEncoding
* 编码格式
* @param parameters
* 请求参数
* @return
*/
public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
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 (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + API_KEY);
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
封装成XML参数
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
packageParams.put("appid", appid);
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str",nonce_str );
packageParams.put("body", body);
packageParams.put("out_trade_no", out_trade_no);
packageParams.put("total_fee", String.valueOf((int)(money*100)));// 价格(注意:价格的单位是分)
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", "JSAPI"); //交易类型 JSAPI--公众号支付
packageParams.put("openid", openid); //微信ID
packageParams.put("sign", sign)
准备好以上参数之后,封装成XML
格式如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><xml> <appid>wxb1427ebebexxxxxx</appid> <body>XXX费用</body> <device_info>WEB</device_info> <mch_id>132186xxxx</mch_id> <nonce_str>6AED000AF86A084F9CB0264161E29DD3</nonce_str> <notify_url>https://一个域名/api/wechatPay/jsapiPayNotify</notify_url> <openid>oo8WUt0taCqjt552htW1vw-xxxxx</openid> <out_trade_no>1</out_trade_no> <sign>各种排序+key生成的那个sign</sign> <total_fee>1</total_fee> <trade_type>JSAPI</trade_type></xml>
代码如下
String requestXML = PayCommonUtil.getRequestXml(packageParams);
/** * @author * @date 2016-4-22 * @Description:将请求参数转换为xml格式的string * @param parameters * 请求参数 * @return */public static String getRequestXml(SortedMap<Object, 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 k = (String) entry.getKey();String v = (String) entry.getValue();if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");} else {sb.append("<" + k + ">" + v + "</" + k + ">");}}sb.append("</xml>");return sb.toString();}
调用微信的统一下单地址:https://api.mch.weixin.qq.com/pay/unifiedorder调用代码如下String resXml = HttpUtil.postData(PropertiesHandler.getConfigValue("UFDODER_URL").toString(), requestXML);见证奇迹的时刻。如果以上参数都神奇的对了,那么会收到微信返回的XML字符串,格式如下<xml><return_code><![CDATA[SUCCESS]]></return_co de> <return_msg><![CDATA[OK]]></return_msg><appid><![CDATA[wxb1427ebebexxxxxx]]></appid><mch_id><![CDATA[132186xxxx]]></mch_id><device_info><![CDATA[WEB]]></device_info><nonce_str><![CDATA[Hh4LFHUUvtDYtNdp]]></nonce_str><sign><![CDATA[079F8A915FD3044F4A17D75F4945E955]]></sign><result_code><![CDATA[SUCCESS]]></result_co de> <prepay_id><![CDATA[wx20160617155030d9e6a0e48b0533061255]]></prepay_id><trade_type><![CDATA[JSAPI]]></trade_type></xml>
我们需要的,就是这货
prepay_id
拿到prepay_id后 进行下一步 生成paySign 签名 代码如下
SortedMap<Object, Object> packagePara = new TreeMap<Object, Object>();//自1970年1月1日 0点0分0秒以来的秒数。注意:部分系统取到的值为毫秒级,需要转换成秒(10位数字)。long timeSt = (LLPayUtil.getPhoneCurrentDateTimeStr()); String timeStr = Long.toString(timeSt);packagePara.put("appId", appid); //公众号名称,由商户传入 packagePara.put("timeStamp",timeStr); //时间戳,自1970年以来的秒数 packagePara.put("nonceStr", nonce_str); // 随机串 packagePara.put("package", "prepay_id="+urlCode); //prepay_idpackagePara.put("signType", "MD5");//微信签名方式String paySign = PayCommonUtil.createSign("UTF-8", packagePara, key); // 微信签名
/** * @author * @date 2016-4-22 * @Description:paySign 签名 * @param characterEncoding * 编码格式 * @param parameters * 请求参数 * @return */public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {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 (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + API_KEY);String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();return sign;}
拼接好参数之后 传回给前台
if(null != paySign){model.put("res", true);model.put("appId", appid);model.put("timeStamp", timeStr);model.put("nonceStr", nonce_str);model.put("packag","prepay_id="+urlCode);model.put("signType", "MD5");model.put("paySign", paySign);return model;}
注意:记得添加授权目录
前台JSP代码
//微信充值function wechat(){var phone = '${userInfo.phone}';var money = $("#money").val();if(money == "" || money == 0){ layer.msg("充值的金额不能为空");return false;}var moneyCheck = /^[0-9]+(.[0-9]{1,2})?$/;if(!moneyCheck.test(money)){ layer.msg("请保留两位小数!");return;}$.ajax({url: '<%=WEBPATH%>/fund/phoenWechatpay',type: "post",async: false, data: {"money" : money},success: function(data){if(data.res){callPay(data.appId,data.timeStamp,data.nonceStr,data.packag,data.signType,data.paySign);}else{alert("充值失败!");}}})} //调用微信内置浏览器的微信支付 function callPay(appId,timeStamp,nonceStr,packag,signType,paySign) { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } } else { onBridgeReady(appId,timeStamp,nonceStr,packag,signType,paySign); } } //提交微信充值 function onBridgeReady(appId,timeStamp,nonceStr,packag,signType,paySign) { // alert("appId:"+appId+",timeStamp:"+timeStamp+",nonceStr:"+nonceStr+",packag:"+packag+",signType:"+signType+",paySign:"+paySign); WeixinJSBridge.invoke('getBrandWCPayRequest', { "appId" : appId, //公众号名称,由商户传入 "timeStamp" : timeStamp, //时间戳,自1970年以来的秒数 "nonceStr" : nonceStr, //随机串 "package" : packag,//"prepay_id=u802345jgfjsdfgsdg888", "signType" : signType, //微信签名方式: "paySign" : paySign //微信签名 }, function(res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 if (res.err_msg == "get_brand_wcpay_request:ok") { //充值成功后返回页面 window.location.replace("<%=WEBPATH %>/fund/phone_return_url"); } if (res.err_msg == "get_brand_wcpay_request:cancel") { layer.msg("交易取消"); return false; } if (res.err_msg == "get_brand_wcpay_request:fail") { layer.msg("支付失败"); return false; } }); }
效果图如下
阅读全文
0 0
- java-微信公众号充值
- 微信公众号--->java
- Java微信公众号
- Java微信公众号
- 微信公众平台消息接口-java
- 微信公众平台java图文
- java实现微信公众平台
- 微信公众平台开发,java版
- 微信公众平台java开发详解
- JAVA微信公众号开发入门
- Java微信公众号支付
- 微信公众号开发 java版本
- 微信公众号支付Java DEMO
- java接入微信公众平台
- java微信公众号开发
- Java---微信公众号开发
- Java微信公众号开发
- java微信公众平台分享朋友圈
- 解析JSON数据
- C#线程安全
- Java 集合系列06之 Vector源码解析
- 大型网站技术架构演变过程
- 读(Android开发艺术探究)view 的滑动 (一)
- java-微信公众号充值
- OpenCV学习--saturate_cast防止数据溢出
- 鼓励自己
- display:none与visible:hidden的区别
- CSS3
- 使用注解来构造IoC容器
- hdu1174(点到直线的距离)
- 杭电HDU 1004 Let the Balloon Rise AC代码 简单题
- java汉字首字母提取