1.Todaynow,微信小程序的支付顺利完成。不要慌,先说几个我在做支付之前解决的问题:1、我们公司有自己的App,App可以微信登录,所以做小程序的要求是和App的用户打通。简而言之,App的手机号绑定了一个微信号,如果小程序用该微信号授权,可以直接拿到他在App绑定的手机号。这就会用到UnionID来区分用户的唯一性;具体的调用方法就不多说了,大家看微信的官方连接就可以接下来
支付start2.微信小程序的支付分为四步:一、获取openId二、统一下单(服务端先调用一下微信的后台,获取到一个最重要的值“prepay_id”)三、拿到服务端返回的六个参数掉起微信并支付(5个参数+sign)四、支付回调
第一步:获取openId3.微信调用openId的官方文档注:因为openId是用来区分用户的唯一性的,不会轻易改变,所以我把它存到了数据库,不用每次都调用微信接口
第二步:统一下单4.统一下单官方文档把所有必填的参数都填上(非必填的根据自己的需要填写,这里有个注意的地方就是openId是必填的)代码如下:
publicMapString,ObjectpreOrder(Orderorder){MapString,Stringparams=newHashMapString,String();params.put("appid","小程序的appID");params.put("mch_id","商户号");params.put("nonce_str",WXPayUtil.generateNonceStr());//随机字符串params.put("body","yly-"+StringUtils.subString(order.getGoodsName(),0,20));//商品描述params.put("out_trade_no",order.getPayRequestId());//商户订单号//微信的金额要转成分params.put("total_fee",String.valueOf(AmountUtils.mul2Int(Double.valueOf(order.getTrxAmount()),100,0)));params.put("spbill_create_ip",order.getRequestIP());//终端IP//回调地址params.put("notify_url","回调地址");//交易类型,小程序取值如下:JSAPIparams.put("trade_type","JSAPI");//openID,必传params.put("openid",order.getOpenId());//过滤参数值为空的参数MapString,StringsPara=WXPayCore.paraFilter(params);//把数组所有元素,按照“参数=参数值”的模式用“”字符拼接成字符串并且拼接上key//StringmySign=WXPayCore.sha256Sign(sPara,WXPayConstants.SECRET_KEY);StringmySign=WXPayCore.md5Sign(sPara,WXPayConstants.MERCHANT_NO_SECRET);//签名params.put("sign",mySign);try{StringparamsXml=WXPayUtil.mapToXml(params);LOG.info("paramsXmlis{"+paramsXml+"}");Stringresult=HttpUtils.post(WXPayConstants.UNIFIED_ORDER_URL,paramsXml,Constants.CHARSET_UTF8);LOG.info("resultis{"+result+"}");MapString,ObjectresultMap=XmlUtils.Dom2Map(result);LOG.info("resultMapis{"+resultMap+"}");returnresultMap;}catch(Exceptione){e.printStackTrace();}returnnull;}5.用到的工具类放到最后按照微信要求的方式一步一步来,我遇到一个坑,那就是接口的调用结果报签名错误首先检查自己的参数是否传错或者有误,可以用微信官方给的校验工具进行校验,微信官方签名效验如果检验不通过,那就检查自己的参数。但是呢,我调用了官方的效验工具,效验是通过的,一模一样,当时的我一脸懵逼,微信bug???经过一系列排查,才发现是我的秘钥错了,我之前就是用的小程序的appSecret而不是商户的api秘钥,这里的秘钥必须和上面商户号是匹配的,否则会一直报错,换成商户秘钥,立马能够支付成功!!!
第三步:返给前端5个参数+sign,调起支付6.小程序调起支付Api官方文档代码如下:`publicMapString,Stringpay(Orderorder){MapString,Stringparams=newHashMapString,String();//小程序IDparams.put(“appId”,“小程序的appID”);//时间戳params.put(“timeStamp”,String.valueOf(WXPayUtil.getCurrentTimestamp()));//随机字符串params.put(“nonceStr”,WXPayUtil.generateNonceStr());//数据包params.put(“package”,“prepay_id=”+“统一下单返回的prepay_id”);//签名方式params.put(“signType”,WXPayConstants.MD5);
MapString,StringsPara=WXPayCore.paraFilter(params);//StringmySign=WXPayCore.sha256Sign(sPara,WXPayConstants.SECRET_KEY);StringpaySign=WXPayCore.md5Sign(sPara,"商户号的秘钥");params.put("paySign",paySign);LOG.info("返给前端调起微信支付的参数为:{"+params+"}");returnparams;}`7.调起支付需要的参数如下图:*这个有个问题需要注意一下:调起支付是不需要appId这个参数的,但是签名的时候这个参数是必填的而且统一下单的时候也需要这个参数,是小写的"appid";这次是驼峰的大写"appId";这个一定要注意,要不然会报"支付验证签名失败"
第四步:支付回调8.支付回调官方文档回调没什么可说的,就是修改订单状态以及各种逻辑处理,根据自己的实际业务来写回调,但是需要注意以下两点:下面是用到的工具类:
/***获取随机字符串NonceStr**@returnString随机字符串*/publicstaticStringgenerateNonceStr(){returnUUID.randomUUID().toString().replaceAll("-","").substring(0,32);}/***除去数组中的空值和签名参数**@paramsArray*签名参数组*@return去掉空值与签名参数后的新签名参数组*/publicstaticMapString,StringparaFilter(MapString,StringsArray){MapString,Stringresult=newHashMapString,String();if(sArray==null||sArray.size()=0){returnresult;}for(Stringkey:sArray.keySet()){Stringvalue=sArray.get(key);if(value==null||value.equals("")||key.equalsIgnoreCase("sign")){continue;}result.put(key,value);}returnresult;}/***将Map转换为XML格式的字符串**@paramdata*Map类型数据*@returnXML格式的字符串*@throwsException*/publicstaticStringmapToXml(MapString,Stringdata)throwsException{DocumentBuilderFactorydocumentBuilderFactory=DocumentBuilderFactory.newInstance();DocumentBuilderdocumentBuilder=documentBuilderFactory.newDocumentBuilder();org.w3c.dom.Documentdocument=documentBuilder.newDocument();org.w3c.dom.Elementroot=document.createElement("xml");document.appendChild(root);for(Stringkey:data.keySet()){Stringvalue=data.get(key);if(value==null){value="";}value=value.trim();org.w3c.dom.Elementfiled=document.createElement(key);filed.appendChild(document.createTextNode(value));root.appendChild(filed);}TransformerFactorytf=TransformerFactory.newInstance();Transformertransformer=tf.newTransformer();DOMSourcesource=newDOMSource(document);transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");transformer.setOutputProperty(OutputKeys.INDENT,"yes");StringWriterwriter=newStringWriter();StreamResultresult=newStreamResult(writer);transformer.transform(source,result);Stringoutput=writer.getBuffer().toString();//.replaceAll("|r",//"");try{writer.close();}catch(Exceptionex){}returnoutput;}/***xml数据转map*@paramxml*@return*@throwsDocumentException*@authorBanWei*/@SuppressWarnings("rawtypes")publicstaticMapString,ObjectDom2Map(Stringxml)throwsDocumentException{MapString,Objectmap=newHashMapString,Object();Documentdoc=DocumentHelper.parseText(xml);if(doc==null)returnmap;Elementroot=doc.getRootElement();for(Iteratoriterator=root.elementIterator();iterator.hasNext();){Elemente=(Element)iterator.next();Listlist=e.elements();if(list.size()0){map.put(e.getName(),Dom2Map(e));}elsemap.put(e.getName(),e.getText());}returnmap;}/***获取当前时间戳,单位秒**@return*/publicstaticlonggetCurrentTimestamp(){returnSystem.currentTimeMillis()/1000;}/***把数组所有元素字典排序,并按照“参数=参数值”的模式用“amp;”字符拼接成字符串**@paramparams*需要排序并参与字符拼接的参数组*@return拼接后字符串*/publicstaticStringcreateLinkString(MapString,Stringparams){ListStringkeys=newArrayListString(params.keySet());Collections.sort(keys);Stringprestr="";for(inti=0;ikeys.size();i++){Stringkey=keys.get(i);Stringvalue=params.get(key);prestr=prestr+key+"="+value+"";}returnprestr;}/***生成MD5**@paramdata*待处理数据*@returnMD5结果*@throwsException*/publicstaticStringMD5(Stringdata)throwsException{java.security.MessageDigestmd=MessageDigest.getInstance("MD5");byte[]array=md.digest(data.getBytes("UTF-8"));StringBuildersb=newStringBuilder();for(byteitem:array){sb.append(Integer.toHexString((item0xFF)|0x100).substring(1,3));}returnsb.toString().toUpperCase();}/***发送post请求*@paramreqUrl*@paramcontent*@paramcharset*@return*@throwsIOException*/publicstaticStringpost(StringreqUrl,Stringcontent,Stringcharset)throwsIOException{URLurl=newURL(reqUrl);HttpURLConnectioncon=(HttpURLConnection)url.openConnection();con.setDoInput(true);con.setDoOutput(true);con.setAllowUserInteraction(false);con.setUseCaches(false);con.setRequestMethod("POST");con.setConnectTimeout(30000);//连接超时单位毫秒con.setDoOutput(true);//是否输入参数con.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset="+charset);//con.setRequestProperty("Content-Type","text/plain;charset="+//charset);DataOutputStreamdataOutput=newDataOutputStream(con.getOutputStream());byte[]bytes=content.toString().getBytes(charset);dataOutput.write(bytes);//输入参数dataOutput.flush();dataOutput.close();BufferedReaderbin=newBufferedReader(newInputStreamReader(con.getInputStream(),charset),SIZE);StringBuilderresult=newStringBuilder();while(true){Stringline=bin.readLine();if(line==null){break;}else{result.append(line);}}bin.close();returnresult.toString();}9.到这里,小程序微信支付就大功告成了,是不是很简单呀我也是第一次写博客,有写的不对的地方欢迎指导,我也不吝赐教大家如果有什么别的问题:可以加我的QQ:2454424223我一定知无不言,言无不尽!!!













