微信支付开发h5调用
2015-06-11 16:05
666 查看
这两天做微信支付开发。碰到大坑。纠结死我了。好不容做完。
后台java:直接上代码:注意区分前后端的变量大小写。。。
以上代码获取openid需要根据网页授权来获取。这里就不多讲了。主要讲讲获取prepayid和生成h5页面所需参数,
这里面比较麻烦的就是签名的获取
查看方法SignUtil.getPayCustomSign(signMap,WebConfig.get("pay.key"))
代码如下
其中CommonUtil.FormatBizQueryParaMap是用来做字典排序的。有参考了网上的例子。就没单独做。
其中MD5SignUtil.sign(bizString,key)方法如下
发送请求到微信获取prepayid代码如下
xml转json方法Xml2JsonUtil.xml2JSON(is);。摘自网络
服务端基本这么多
前端被微信和我自己挖了大坑,整整搞了两天,擦
先是看的微信文档jssdk文档(开始埋坑。。)
页面引入js
加入
嗯。配置好了。如果传入jsconfig的参数。。。
然后看到jssdk里面有发送一个微信支付请求?
嗯加进去
然后发布,执行调试。。尼玛。怎么样都支付不了。一会儿报订单信息错误、一会儿报签名错误。。。找了N多资料均不对
后来想啊。大不了用商户平台提供的文档写接口什么的。于是加入了代码
发布调试。。。还是不对。。两个按钮pay()和pay2()均不对。pay方法还是一会儿订单信息错误一会儿签名错误。pay2()方法则一直报签名错误。。。尼玛。吧经历放后台签名。。怎么改都不行。签名明明对的啊。可以获取prepayid的。为毛封装h5参数时就出错了呢。。。折腾啊。。。搞了N久。。就尼玛不对。。。后来一个小错误pay方法js报错了。。结果pay2方法确可以执行了。。。吧pay的js报错去了之后pay2又不能用了。。我擦。。哥有预感。。难道两种方式冲突了??于是我把config和pay方法删除了再试试。。。尼玛果然可以了。不能加入config和pay。。。果然可以了。。。我擦。折腾的。。微信啃爹啊。第一种方式无法用有没有,误导人啊。。。正确结果就是商品平台的文档使用方法js如下:
至此。终于把微信支付搞定了。留着博客。防止后人走弯路(config里面不能加入chooseWXPay方法。。切记)
后台java:直接上代码:注意区分前后端的变量大小写。。。
@RequestMapping(value="/index") publicModelindex(@RequestParam(value="openid",required=true)Stringopenid,Modelmodel,HttpServletRequestrequest)throwsException{ logger.info("************openid***********为:"+openid); //获取prepayid Map<String,String>map=newHashMap<String,String>(); WeiXinConfigwcf=weiXinBaseService.getWeiXinConfig(); StringnonceStr=UUID.randomUUID().toString().substring(0,32); oauthService.shareFactory(request); Stringappid=wcf.getAppid(); longtimestamp=System.currentTimeMillis()/1000; map.put("appid",appid); map.put("mch_id",WebConfig.get("pay.mch_id")); map.put("nonce_str",nonceStr); map.put("body",WebConfig.get("pay.body")); map.put("out_trade_no",payWxUtil.orderNum()); map.put("total_fee",WebConfig.get("pay.price")); map.put("spbill_create_ip",request.getRemoteAddr()); map.put("notify_url",WebConfig.get("hostAddress")+request.getContextPath()+"/babyShow/payInfo/info"); map.put("trade_type","JSAPI"); map.put("openid",openid); StringpaySign=SignUtil.getPayCustomSign(map,WebConfig.get("pay.key")); map.put("sign",paySign); Stringxml=CommonUtil.ArrayToXml(map); Stringprepayid=payWxUtil.getPrepayid(xml); logger.info("prepareid*****************************="+prepayid); //封装h5页面调用参数 Map<String,String>signMap=newHashMap<String,String>(); signMap.put("appId",appid); logger.info("appId="+appid); signMap.put("timeStamp",timestamp+""); logger.info("timeStamp="+timestamp); signMap.put("package","prepay_id="+prepayid); logger.info("package="+"prepay_id="+prepayid); signMap.put("signType","MD5"); logger.info("singType="+"MD5"); signMap.put("nonceStr",nonceStr); logger.info("nonceStr="+nonceStr); model.addAttribute("paytimestamp",timestamp); model.addAttribute("paypackage","prepay_id="+prepayid); model.addAttribute("paynonceStr",nonceStr); model.addAttribute("paysignType","MD5"); StringpaySign2=SignUtil.getPayCustomSign(signMap,WebConfig.get("pay.key")); model.addAttribute("paySign",paySign2); logger.info("paySign="+paySign2); returnmodel; }
以上代码获取openid需要根据网页授权来获取。这里就不多讲了。主要讲讲获取prepayid和生成h5页面所需参数,
这里面比较麻烦的就是签名的获取
查看方法SignUtil.getPayCustomSign(signMap,WebConfig.get("pay.key"))
代码如下
/** *获取支付所需签名 *@paramticket *@paramtimeStamp *@paramcard_id *@paramcode *@return *@throwsException */ publicstaticStringgetPayCustomSign(Map<String,String>bizObj,Stringkey)throwsException{ StringbizString=CommonUtil.FormatBizQueryParaMap(bizObj, false); logger.info(bizString); returnMD5SignUtil.sign(bizString,key); }
其中CommonUtil.FormatBizQueryParaMap是用来做字典排序的。有参考了网上的例子。就没单独做。
publicstaticStringFormatBizQueryParaMap(Map<String,String>paraMap, booleanurlencode)throwsException{ Stringbuff=""; try{ List<Map.Entry<String,String>>infoIds=newArrayList<Map.Entry<String,String>>( paraMap.entrySet()); Collections.sort(infoIds, newComparator<Map.Entry<String,String>>(){ publicintcompare(Map.Entry<String,String>o1, Map.Entry<String,String>o2){ return(o1.getKey()).toString().compareTo( o2.getKey()); } }); for(inti=0;i<infoIds.size();i++){ Map.Entry<String,String>item=infoIds.get(i); //System.out.println(item.getKey()); if(item.getKey()!=""){ Stringkey=item.getKey(); Stringval=item.getValue(); if(urlencode){ val=URLEncoder.encode(val,"utf-8"); } buff+=key+"="+val+"&"; } } if(buff.isEmpty()==false){ buff=buff.substring(0,buff.length()-1); } }catch(Exceptione){ thrownewException(e.getMessage()); } returnbuff; }
其中MD5SignUtil.sign(bizString,key)方法如下
publicstaticStringsign(Stringcontent,Stringkey) throwsException{ StringsignStr=""; signStr=content+"&key="+key; returnMD5Util.MD5(signStr).toUpperCase(); }
其中MD5Util.MD5(signStr)方法如下
publicfinalstaticStringMD5(Strings){ charhexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; try{ byte[]btInput=s.getBytes(); MessageDigestmdInst=MessageDigest.getInstance("MD5"); mdInst.update(btInput); byte[]md=mdInst.digest(); intj=md.length; charstr[]=newchar[j*2]; intk=0; for(inti=0;i<j;i++){ bytebyte0=md[i]; str[k++]=hexDigits[byte0>>>4&0xf]; str[k++]=hexDigits[byte0&0xf]; } returnnewString(str); }catch(Exceptione){ e.printStackTrace(); returnnull; } }
CommonUtil.ArrayToXml(map)方法如下
publicstaticStringArrayToXml(Map<String,String>arr){ Stringxml="<xml>"; Iterator<Entry<String,String>>iter=arr.entrySet().iterator(); while(iter.hasNext()){ Entry<String,String>entry=iter.next(); Stringkey=entry.getKey(); Stringval=entry.getValue(); if(IsNumeric(val)){ xml+="<"+key+">"+val+"</"+key+">"; }else xml+="<"+key+"><![CDATA["+val+"]]></"+key+">"; } xml+="</xml>"; returnxml; }
publicstaticbooleanIsNumeric(Stringstr){ if(str.matches("\\d*")){ returntrue; }else{ returnfalse; } }
发送请求到微信获取prepayid代码如下
publicstaticStringURL="https://api.mch.weixin.qq.com/pay/unifiedorder";
@SuppressWarnings("deprecation")
publicJSONObjectgetPrepayJson(Stringxml){
HttpClienthttpClient=newHttpClient(newHttpClientParams(),newSimpleHttpConnectionManager(true));
InputStreamis=null;
PostMethodmethod=null;
try{
Stringurl=URL;
method=HttpClientUtils.postMethod(url);
method.setRequestBody(xml);
httpClient.executeMethod(method);
//读取响应
is=method.getResponseBodyAsStream();
JSONObjecto=Xml2JsonUtil.xml2JSON(is);
returno;
}catch(Exceptione){
e.printStackTrace();
}finally{
if(method!=null){
method.releaseConnection();
}
if(is!=null){
try{
is.close();
}catch(IOExceptione1){
e1.printStackTrace();
}
}
}
returnnull;
}
publicStringgetPrepayid(Stringxml){
try{
JSONObjectjo=getPrepayJson(xml);
JSONObjectelement=jo.getJSONObject("xml");
Stringprepayid=((JSONArray)element.get("prepay_id")).get(0).toString();
returnprepayid;
}catch(Exceptione){
e.printStackTrace();
}
returnnull;
}
publicStringorderNum(){
Stringchars="0123456789";
Stringorder=System.currentTimeMillis()+"";
Stringres="";
for(inti=0;i<19;i++){
Randomrd=newRandom();
res+=chars.charAt(rd.nextInt(chars.length()-1));
}
order+=res;
returnorder;
}
xml转json方法Xml2JsonUtil.xml2JSON(is);。摘自网络
/**
*转换一个xml格式的字符串到json格式
*
*@paramxml
*xml格式的字符串
*@return成功返回json格式的字符串;失败反回null
*/
@SuppressWarnings("unchecked")
publicstaticJSONObjectxml2JSON(InputStreamis){
JSONObjectobj=newJSONObject();
try{
SAXReadersb=newSAXReader();
Documentdoc=sb.read(is);
Elementroot=doc.getRootElement();
obj.put(root.getName(),iterateElement(root));
returnobj;
}catch(Exceptione){
log.error("传入XML后转换JSON出现错误=====Xml2JsonUtil-->xml2JSON============>>",e);
returnnull;
}
}
/**
*一个迭代方法
*
*@paramelement
*:org.jdom.Element
*@returnjava.util.Map实例
*/
@SuppressWarnings("unchecked")
privatestaticMapiterateElement(Elementelement){
Listjiedian=element.elements();
Elementet=null;
Mapobj=newHashMap();
Listlist=null;
for(inti=0;i<jiedian.size();i++){
list=newLinkedList();
et=(Element)jiedian.get(i);
if(et.getTextTrim().equals("")){
if(et.elements().size()==0)
continue;
if(obj.containsKey(et.getName())){
list=(List)obj.get(et.getName());
}
list.add(iterateElement(et));
obj.put(et.getName(),list);
}else{
if(obj.containsKey(et.getName())){
list=(List)obj.get(et.getName());
}
list.add(et.getTextTrim());
obj.put(et.getName(),list);
}
}
returnobj;
}
服务端基本这么多
前端被微信和我自己挖了大坑,整整搞了两天,擦
先是看的微信文档jssdk文档(开始埋坑。。)
页面引入js
加入
wx.config({
debug:false,//开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId:'${appid}',//必填,公众号的唯一标识
timestamp:'${timestamp}',//必填,生成签名的时间戳
nonceStr:'${nonceStr}',//必填,生成签名的随机串
signature:'${signature}',//必填,签名,见附录1
jsApiList:[
'chooseWXPay'
]//必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
嗯。配置好了。如果传入jsconfig的参数。。。
然后看到jssdk里面有发送一个微信支付请求?
嗯加进去
functionpay(){
wx.chooseWXPay({
timestamp:${paytimestamp},//支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr:'${paynonceStr}',//支付签名随机串,不长于32位
package:'${paypackage}',//统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType:'${paysignType}',//签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign:'${paySign}',//支付签名
success:function(res){
alert("支付成功");
//支付成功后的回调函数
}
});
}
然后发布,执行调试。。尼玛。怎么样都支付不了。一会儿报订单信息错误、一会儿报签名错误。。。找了N多资料均不对
后来想啊。大不了用商户平台提供的文档写接口什么的。于是加入了代码
functiononBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest',{
"appId":"${appid}",//公众号名称,由商户传入
"timeStamp":"${paytimestamp}",//时间戳,自1970年以来的秒数
"nonceStr":"${paynonceStr}",//随机串
"package":"${paypackage}",
"signType":"${paysignType}",//微信签名方式:
"paySign":"${paySign}"//微信签名
},
function(res){
alert(res.err_msg);//使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返
}
);
}
functionpay2(){
if(typeofWeixinJSBridge=="undefined"){
if(document.addEventListener){
document.addEventListener('WeixinJSBridgeReady',onBridgeReady,false);
}elseif(document.attachEvent){
document.attachEvent('WeixinJSBridgeReady',onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady',onBridgeReady);
}
}else{
onBridgeReady();
}
}
发布调试。。。还是不对。。两个按钮pay()和pay2()均不对。pay方法还是一会儿订单信息错误一会儿签名错误。pay2()方法则一直报签名错误。。。尼玛。吧经历放后台签名。。怎么改都不行。签名明明对的啊。可以获取prepayid的。为毛封装h5参数时就出错了呢。。。折腾啊。。。搞了N久。。就尼玛不对。。。后来一个小错误pay方法js报错了。。结果pay2方法确可以执行了。。。吧pay的js报错去了之后pay2又不能用了。。我擦。。哥有预感。。难道两种方式冲突了??于是我把config和pay方法删除了再试试。。。尼玛果然可以了。不能加入config和pay。。。果然可以了。。。我擦。折腾的。。微信啃爹啊。第一种方式无法用有没有,误导人啊。。。正确结果就是商品平台的文档使用方法js如下:
functiononBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest',{
"appId":"${appid}",//公众号名称,由商户传入
"timeStamp":"${paytimestamp}",//时间戳,自1970年以来的秒数
"nonceStr":"${paynonceStr}",//随机串
"package":"${paypackage}",
"signType":"${paysignType}",//微信签名方式:
"paySign":"${paySign}"//微信签名
},
function(res){
alert(res.err_msg);//使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返
}
);
}
functionpay(){
if(typeofWeixinJSBridge=="undefined"){
if(document.addEventListener){
document.addEventListener('WeixinJSBridgeReady',onBridgeReady,false);
}elseif(document.attachEvent){
document.attachEvent('WeixinJSBridgeReady',onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady',onBridgeReady);
}
}else{
onBridgeReady();
}
}
至此。终于把微信支付搞定了。留着博客。防止后人走弯路(config里面不能加入chooseWXPay方法。。切记)
相关文章推荐
- 唯购:开通微信商城,费用全免!
- 微信支付的常见问题,invalide code
- 微信小视频 SD卡位置
- 微信 和 支付宝 公众服务号开发者文档
- 微信公众平台分享
- 微信扫码登录网页实现原理
- 微信公众平台开发(一) 配置接口
- Android-通过SlidingMenu高仿微信6.2最新版手势滑动返回(二)
- 微信公众平台Js API实现微信分享
- c#微信开发
- 用c#开发微信 (16) 微活动 2 刮刮卡
- Android微信图片浏览框架设计
- iOS判断手机上是否安装微信或qq等应用
- 公众号支付-场景介绍(转自官方文档)
- 基于安卓的c/s模式的聊天小程序
- DIY一个局域网聊天的小程序-油聊
- 使用Tkinter编写一个简单的提醒小程序
- 奇葩念头:微信能取代WP应用吗
- 微信公众号开发第1篇---注册微信公众帐号
- 微信开放平台-管理中心-应用删除