1.1.准备好小程序的appid,mch_id和key(注意这里的key是api秘钥,不是小程序秘钥,不是小程序秘钥,不是小程序秘钥)
2.2.java的后台支付代码:小程序的支付是需要获取用户的openid
3.3.直接上代码:
4.controller发起支付的代码如下:
5./***@Description:发起微信支付*@paramopenid*@paramrequest*@author:wcf*@date:2018年7月17日*/@RequestMapping("wxrPay")@ResponseBodypublicMapString,ObjectwxrPay(HttpServletRequestrequest){MapString,ObjectmapnewHashMap();mapwxroutineService.paywxr(request);returnmap;}
6.controlle回调方法的代码如下:
7./***@Description:微信支付*@return*@throwsException*/@RequestMapping("wxNotify")@ResponseBodypublicvoidwxNotify(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{System.out.println("-------------------------------------------------------进入回调");BufferedReaderbrnewBufferedReader(newInputStreamReader((ServletInputStream)request.getInputStream()));Stringlinenull;StringBuildersbnewStringBuilder();while((linebr.readLine())!null){sb.append(line);}br.close();//sb为微信返回的xmlStringnotityXmlsb.toString();StringresXml"";System.out.println("接收到的报文:"+notityXml);MapmapPayUtilrou.doXMLParse(notityXml);StringreturnCode(String)map.get("return_code");if("SUCCESS".equals(returnCode)){//验证签名是否正确MapString,StringvalidParamsPayUtilrou.paraFilter(map);//回调验签时需要去除sign和空值参数StringvalidStrPayUtilrou.createLinkString(validParams);//把数组所有元素,按照“参数参数值”的模式用“”字符拼接成字符串StringsignPayUtilrou.sign(validStr,WxPayConfig.key,"utf-8").toUpperCase();//拼装生成服务器端验证的签名//根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等if(sign.equals(map.get("sign"))){/**此处添加自己的业务逻辑代码start**/StringorderNumber(String)map.get("out_trade_no");//订单号Stringamount(String)map.get("total_fee");//价格IntegertotalPriceInteger.valueOf(amount);//服务器这边记录的是钱的分if(orderNumber.length()20){payService.updateRechargeStatus(orderNumber,totalPrice);}/**此处添加自己的业务逻辑代码end**///通知微信服务器已经支付成功resXml"xml"+"return_code![CDATA[SUCCESS]]/return_code"+"return_msg![CDATA[OK]]/return_msg"+"/xml";}}else{resXml"xml"+"return_code![CDATA[FAIL]]/return_code"+"return_msg![CDATA[报文为空]]/return_msg"+"/xml";}System.out.println(resXml);System.out.println("微信支付回调数据结束");BufferedOutputStreamoutnewBufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();}
8.service代码如下:
9.MapString,Objectpaywxr(HttpServletRequestrequest);
10.serviceImpl代码:
11.@OverridepublicMapString,Objectpaywxr(HttpServletRequestrequest,StringorderId,Stringtemp){try{//生成的随机字符串Stringnonce_strPaytool.getRandomStringByLength(32);//商品名称Stringbody"肉品会";//获取客户端的ip地址Stringspbill_create_ipPayUtil.getRemoteAddrIp(request);//获得终端IPStringopenidrequest.getParameter("openId");floatpriceFloat.parseFloat(temp);intprice1(int)(price*100);Stringpprice1+"";//组装参数,用户生成统一下单接口的签名MapString,StringpackageParamsnewHashMapString,String();packageParams.put("appid",WxPayConfig.appid);packageParams.put("mch_id",WxPayConfig.mch_id);packageParams.put("nonce_str",nonce_str);packageParams.put("body",body);packageParams.put("out_trade_no",orderId);//商户订单号packageParams.put("total_fee",p);//支付金额,这边需要转成字符串类型,否则后面的签名会失败packageParams.put("spbill_create_ip",spbill_create_ip);packageParams.put("notify_url",WxPayConfig.notify_url);//支付成功后的回调地址packageParams.put("trade_type",WxPayConfig.TRADETYPE);//支付方式packageParams.put("openid",openid);StringprestrPayUtilrou.createLinkString(packageParams);//把数组所有元素,按照“参数参数值”的模式用“”字符拼接成字符串//MD5运算生成签名,这里是第一次签名,用于调用统一下单接口StringsignPayUtilrou.sign(prestr,WxPayConfig.key,"utf-8").toUpperCase();//拼接统一下单接口使用的xml数据,要将上一步生成的签名一起拼接进去Stringxml"xml"+"appid"+WxPayConfig.appid+"/appid"+"body![CDATA["+body+"]]/body"+"mch_id"+WxPayConfig.mch_id+"/mch_id"+"nonce_str"+nonce_str+"/nonce_str"+"notify_url"+WxPayConfig.notify_url+"/notify_url"+"openid"+openid+"/openid"+"out_trade_no"+orderId+"/out_trade_no"+"spbill_create_ip"+spbill_create_ip+"/spbill_create_ip"+"total_fee"+p+"/total_fee"+"trade_type"+WxPayConfig.TRADETYPE+"/trade_type"+"sign"+sign+"/sign"+"/xml";System.out.println("调试模式_统一下单接口请求XML数据:"+xml);//调用统一下单接口,并接受返回的结果StringresultPayUtilrou.httpRequest(WxPayConfig.pay_url,"POST",xml);System.out.println("调试模式_统一下单接口返回XML数据:"+result);//将解析结果存储在HashMap中MapmapPayUtilrou.doXMLParse(result);Stringreturn_code(String)map.get("return_code");//返回状态码MapString,ObjectresponsenewHashMapString,Object();//返回给小程序端需要的参数if(return_code.equals("SUCCESS")){Stringprepay_id(String)map.get("prepay_id");//返回的预付单信息response.put("nonceStr",nonce_str);response.put("package","prepay_id"+prepay_id);LongtimeStampSystem.currentTimeMillis()/1000;response.put("timeStamp",timeStamp+"");//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误//拼接签名需要的参数StringstringSignTemp"appId"+WxPayConfig.appid+"nonceStr"+nonce_str+"packageprepay_id"+prepay_id+"signTypeMD5timeStamp"+timeStamp;//再次签名,这个签名用于小程序端调用wx.requesetPayment方法StringpaySignPayUtilrou.sign(stringSignTemp,WxPayConfig.key,"utf-8").toUpperCase();response.put("paySign",paySign);}response.put("appid",WxPayConfig.appid);//写支付前的业务代码returnresponse;}catch(Exceptione){e.printStackTrace();}returnnull;}
12.下面就是用到的一些工具类:
13.生成字符串:
14.publicclassPaytool{/***StringUtils工具类方法*获取一定长度的随机字符串,范围0-9,a-z*@paramlength:指定字符串长度*@return一定长度的随机字符串*/publicstaticStringgetRandomStringByLength(intlength){Stringbase"abcdefghijklmnopqrstuvwxyz0123456789";RandomrandomnewRandom();StringBuffersbnewStringBuffer();for(inti0;ilength;i++){intnumberrandom.nextInt(base.length());sb.append(base.charAt(number));}returnsb.toString();}
15.}
16.其他的一些处理数据的工具类:
17.publicclassPayUtilrou{/***签名字符串*@paramtext需要签名的字符串*@paramkey密钥*@paraminput_charset编码格式*@return签名结果*/publicstaticStringsign(Stringtext,Stringkey,Stringinput_charset){texttext+"key"+key;returnDigestUtils.md5Hex(getContentBytes(text,input_charset));}/***签名字符串*@paramtext需要签名的字符串*@paramsign签名结果*@paramkey密钥*@paraminput_charset编码格式*@return签名结果*/publicstaticbooleanverify(Stringtext,Stringsign,Stringkey,Stringinput_charset){texttext+key;StringmysignDigestUtils.md5Hex(getContentBytes(text,input_charset));if(mysign.equals(sign)){returntrue;}else{returnfalse;}}/***@paramcontent*@paramcharset*@return*@throwsSignatureException*@throwsUnsupportedEncodingException*/publicstaticbyte[]getContentBytes(Stringcontent,Stringcharset){if(charsetnull||"".equals(charset)){returncontent.getBytes();}try{returncontent.getBytes(charset);}catch(UnsupportedEncodingExceptione){thrownewRuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:"+charset);}}privatestaticbooleanisValidChar(charch){if((ch'0'ch'9')||(ch'A'ch'Z')||(ch'a'ch'z'))returntrue;if((ch0x4e00ch0x7fff)||(ch0x8000ch0x952f))returntrue;//简体中文汉字编码returnfalse;}/***除去数组中的空值和签名参数*@paramsArray签名参数组*@return去掉空值与签名参数后的新签名参数组*/publicstaticMapString,StringparaFilter(MapString,StringsArray){MapString,StringresultnewHashMapString,String();if(sArraynull||sArray.size()0){returnresult;}for(Stringkey:sArray.keySet()){StringvaluesArray.get(key);if(valuenull||value.equals("")||key.equalsIgnoreCase("sign")||key.equalsIgnoreCase("sign_type")){continue;}result.put(key,value);}returnresult;}/***把数组所有元素排序,并按照“参数参数值”的模式用“”字符拼接成字符串*@paramparams需要排序并参与字符拼接的参数组*@return拼接后字符串*/publicstaticStringcreateLinkString(MapString,Stringparams){ListStringkeysnewArrayListString(params.keySet());Collections.sort(keys);Stringprestr"";for(inti0;ikeys.size();i++){Stringkeykeys.get(i);Stringvalueparams.get(key);if(ikeys.size()-1){//拼接时,不包括最后一个字符prestrprestr+key+""+value;}else{prestrprestr+key+""+value+"";}}returnprestr;}/****@paramrequestUrl请求地址*@paramrequestMethod请求方法*@paramoutputStr参数*/publicstaticStringhttpRequest(StringrequestUrl,StringrequestMethod,StringoutputStr){//创建SSLContextStringBufferbuffernull;try{URLurlnewURL(requestUrl);HttpURLConnectionconn(HttpURLConnection)url.openConnection();conn.setRequestMethod(requestMethod);conn.setDoOutput(true);conn.setDoInput(true);conn.connect();//往服务器端写内容if(null!outputStr){OutputStreamosconn.getOutputStream();os.write(outputStr.getBytes("utf-8"));os.close();}//读取服务器端返回的内容InputStreamisconn.getInputStream();InputStreamReaderisrnewInputStreamReader(is,"utf-8");BufferedReaderbrnewBufferedReader(isr);buffernewStringBuffer();Stringlinenull;while((linebr.readLine())!null){buffer.append(line);}br.close();}catch(Exceptione){e.printStackTrace();}returnbuffer.toString();}publicstaticStringurlEncodeUTF8(Stringsource){Stringresultsource;try{resultjava.net.URLEncoder.encode(source,"UTF-8");}catch(UnsupportedEncodingExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}returnresult;}/***解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。*@paramstrxml*@return*@throwsJDOMException*@throwsIOException*/publicstaticMapdoXMLParse(Stringstrxml)throwsException{if(nullstrxml||"".equals(strxml)){returnnull;}/*!!!!注意,修复了微信官方反馈的漏洞,更新于2018-10-16*/try{MapString,StringdatanewHashMapString,String();//TODO在这里更换DocumentBuilderFactorydocumentBuilderFactoryDocumentBuilderFactory.newInstance();documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities",false);documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities",false);documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true);documentBuilderFactory.setXIncludeAware(false);documentBuilderFactory.setExpandEntityReferences(false);InputStreamstreamnewByteArrayInputStream(strxml.getBytes("UTF-8"));org.w3c.dom.DocumentdocdocumentBuilderFactory.newDocumentBuilder().parse(stream);doc.getDocumentElement().normalize();NodeListnodeListdoc.getDocumentElement().getChildNodes();for(intidx0;idxnodeList.getLength();++idx){NodenodenodeList.item(idx);if(node.getNodeType()Node.ELEMENT_NODE){org.w3c.dom.Elementelement(org.w3c.dom.Element)node;data.put(element.getNodeName(),element.getTextContent());}}try{stream.close();}catch(Exceptionex){//donothing}returndata;}catch(Exceptionex){throwex;}}/***获取子结点的xml*@paramchildren*@returnString*/publicstaticStringgetChildrenText(Listchildren){StringBuffersbnewStringBuffer();if(!children.isEmpty()){Iteratoritchildren.iterator();while(it.hasNext()){Elemente(Element)it.next();Stringnamee.getName();Stringvaluee.getTextNormalize();Listliste.getChildren();sb.append(""+name+"");if(!list.isEmpty()){sb.append(getChildrenText(list));}sb.append(value);sb.append("/"+name+"");}}returnsb.toString();}publicstaticInputStreamString2Inputstream(Stringstr){returnnewByteArrayInputStream(str.getBytes());}
18.}
19.自己项目的一些配置参数:
20.publicclassWxPayConfig{//小程序appidpublicstaticfinalStringappid"xxxxx";//微信支付的商户idpublicstaticfinalStringmch_id"xxxxx";//微信支付的商户密钥publicstaticfinalStringkey"xxxxx";//支付成功后的服务器回调urlpublicstaticfinalStringnotify_url"http://ip/xx/xx/wxNotify";//签名方式,固定值publicstaticfinalStringSIGNTYPE"MD5";//交易类型,小程序支付的固定值为JSAPIpublicstaticfinalStringTRADETYPE"JSAPI";//微信统一下单接口地址publicstaticfinalStringpay_url"https://api.mch.weixin.qq.com/pay/unifiedorder";
21.}
22.到这里,就可以成功进行小程序支付了!!!
23.参考文章:https://blog.csdn.net/zhourenfei17/article/details/77765585
java实现微信小程序支付功能-微信小程序实现微信支付功能-微信小程序支付代码
浏览量:1776
时间:
来源:No-way
版权声明
即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。
最新资讯
-

即速应用,赋能企业玩转微信小程序智慧经营
作为国内领军的智慧商业经营服务商,即速应用始终秉承“让每个企业都拥有自己的智慧店铺”的愿景,持续赋能更多企业玩转智慧经营。即速应用旗下拥有“小程序搭建工具-即速应用”、“私域流量专家-即客云”等产品,帮助商家打通互联网全生态营销闭环。 -

即客云2.0重磅更新,让微信小程序运营更简单!
即客云作为一款基于企业微信的第三方工具,现从多维度提供超过30种功能,自上线以来,已服务多家企业,受到一致好评。近期,我们根据客户反馈和市场调研正式推出升级版 即客云2.0!更新了私域运营SOP,群日历功能,批量拓客,客户雷达,消息推送,个人欢迎语,帮助企业更好运用企业微信;同时提升了社群运营工作标准化,提升运营效率,帮助企业实现客户增长,玩转私域流量。 -

零代码 + AI 双轮驱动|即速应用解锁人工智能小程序开发新范式
无需代码、无需 AI 算法功底,普通人也能快速搭建智能小程序。即速应用将人工智能与零代码开发深度融合,推出 AI 智能生成能力,用户通过自然语言描述需求,AI 自动生成小程序页面、功能模块与后台配置,覆盖商城、预约、同城、社区团购等全场景。平台内置 AI 智能推荐、智能客服、用户画像分析等能力,一键对接微信生态,打通视频号、企业微信、短信跳转,帮企业快速落地 AI 应用,抢占智慧经营先机,让每家企业都拥有 AI 驱动的智慧店铺。










