E企盈营销工具技术服务商 热线:4006-838-530

微信被投诉,小程序微信退款退款信息回调解密

E企盈直播平台营销卖货系统

一、微信支付(简单贴一下)/发起微信支付/publicMapwechatPay(Stringopenid,HttpServletRequestrequest,StringoutTradeNo,IntegertotalFee){//生成的随机32位字符串Stringnonce_str=RandomString.generateRandomString(32,RandomString.POSSIBLE_CHARS);//商品金额单位分将原来的金额100元-分Integertotal_fee=(totalFee);//商品名称StringpackageName=”杭家订单:”+outTradeNo;//获取客户端的ip地址Stringspbill_create_ip=getIpAddress(request);//生成商户订单号Stringout_trade_no=outTradeNo;//组装参数,用户生成统一下单接口的签名MapString,StringpackageParams=newHashMapString,String();packageParams.put(“appid”,weChatConfig.appId);packageParams.put(“mch_id”,weChatConfig.mchId);packageParams.put(“nonce_str”,nonce_str);packageParams.put(“body”,packageName);packageParams.put(“out_trade_no”,out_trade_no);//商户订单号packageParams.put(“total_fee”,String.valueOf(total_fee));//支付金额,这边需要转成字符串类型,否则后面的签名会失败packageParams.put(“spbill_create_ip”,spbill_create_ip);packageParams.put(“notify_url”,weChatConfig.notifyUrl);//支付成功后的回调地址packageParams.put(“trade_type”,weChatConfig.tradetype);//支付方式packageParams.put(“openid”,openid);Stringprestr=PayUtil.createLinkString(packageParams);//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串//MD5运算生成签名,这里是第一次签名,用于调用统一下单接口Stringmysign=PayUtil.sign(prestr,weChatConfig.key,”utf-8″).toUpperCase();//拼接统一下单接口使用的xml数据,要将上一步生成的签名一起拼接进去Stringxml=”xml”+”appid”+weChatConfig.appId+”/appid”+”body![CDATA[“+packageName+”]]/body”+”mch_id”+weChatConfig.mchId+”/mch_id”+”nonce_str”+nonce_str+”/nonce_str”+”notify_url”+weChatConfig.notifyUrl+”/notify_url”+”openid”+openid+”/openid”+”out_trade_no”+out_trade_no+”/out_trade_no”+”spbill_create_ip”+spbill_create_ip+”/spbill_create_ip”+”total_fee”+total_fee+”/total_fee”+”trade_type”+weChatConfig.tradetype+”/trade_type”+”sign”+mysign+”/sign”+”/xml”;//调用统一下单接口,并接受返回的结果Stringresult=PayUtil.httpRequest(weChatConfig.payUrl,”POST”,xml);System.out.println(“调试模式返回XML数据:”+result);//将解析结果存储在HashMap中Mapmap=PayUtil.doXMLParse(result);Stringreturn_code=(String)map.get(“return_code”);//返回状态码Stringreturn_msg=(String)map.get(“return_msg”);//返回状态信息//返回给移动端需要的参数MapString,Objectresponse=newHashMap();if(“SUCCESS”.equals(return_code)){//业务结果Stringprepay_id=(String)map.get(“prepay_id”);//返回的预付单信息Stringsign=(String)map.get(“sign”);//微信返回的签名值response.put(“sign”,sign);response.put(“signType”,weChatConfig.signtype);response.put(“nonceStr”,nonce_str);response.put(“package”,”prepay_id=”+prepay_id);LongtimeStamp=System.currentTimeMillis()/1000;response.put(“timeStamp”,timeStamp+””);//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误StringstringSignTemp=”appId=”+weChatConfig.appId+”&nonceStr=”+nonce_str+”&package=prepay_id=”+prepay_id+”&signType=”+weChatConfig.signtype+”&timeStamp=”+timeStamp;//再次签名,这个签名用于小程序端调用wx.requesetPayment方法StringpaySign=PayUtil.sign(stringSignTemp,weChatConfig.key,”utf-8″).toUpperCase();log.info(“=======================第二次签名:”+paySign+”=====================”);response.put(“paySign”,paySign);response.put(“totalFee”,total_fee);/业务代码/}else{thrownewBaseException(ResultEnum.WECHAT_PAY_ERROR,return_msg);}response.put(“appid”,weChatConfig.appId);returnresponse;}/支付回调/@Override@TransactionalpublicStringwechatPayCallBack(HttpServletRequestrequest,HttpServletResponseresponse){try{Stringline=null;BufferedReaderbr=newBufferedReader(newInputStreamReader((ServletInputStream)request.getInputStream()));StringBuildersb=newStringBuilder();while((line=br.readLine())!=null){sb.append(line);}br.close();//sb为微信返回的xmlStringnotityXml=sb.toString();StringresXml=””;log.info(“接收到的报文:”+notityXml);Mapmap=PayUtil.doXMLParse(notityXml);StringreturnCode=(String)map.get(“return_code”);if(“SUCCESS”.equals(returnCode)){//验证签名是否正确MapString,StringvalidParams=PayUtil.paraFilter(map);//回调验签时需要去除sign和空值参数StringvalidStr=PayUtil.createLinkString(validParams);//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串Stringsign=PayUtil.sign(validStr,weChatConfig.key,”utf-8″).toUpperCase();//拼装生成服务器端验证的签名//根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等if(sign.equals(map.get(“sign”))){log.info(“sign==sigin签名通过”);/此处添加自己的业务逻辑代码start/StringoutTradeNo=(String)map.get(“out_trade_no”);StringtransactionId=(String)map.get(“transaction_id”);Stringip=getIpAddress(request);//支付回调处理Booleancheck=orderService.wechatPayCallBack(outTradeNo,transactionId,ip);if(check){//通知微信服务器已经支付成功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[FAIL]]/return_msg”+”/xml”;}/此处添加自己的业务逻辑代码end/}}else{resXml=”xml”+”return_code![CDATA[FAIL]]/return_code”+”return_msg![CDATA[报文为空]]/return_msg”+”/xml”;}log.info(resXml);log.info(“微信支付回调数据结束”);BufferedOutputStreamout=newBufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();returnresXml;}catch(Exceptione){returnnull;}}二、微信退款1.主要代码:/微信退款/@OverridepublicMapString,StringwechatRefund(intrefundMoney,inttotalMoney,Stringout_trade_no){//生成的随机32位字符串Stringnonce_str=RandomString.generateRandomString(32,RandomString.POSSIBLE_CHARS);Stringout_refund_no=SnowflakeIdWorker.getId();//商户退款单号//签名算法SortedMapObject,ObjectparamMap=newTreeMapObject,Object();paramMap.put(“appid”,weChatConfig.appId);paramMap.put(“mch_id”,weChatConfig.mchId);paramMap.put(“nonce_str”,nonce_str);paramMap.put(“out_trade_no”,out_trade_no);paramMap.put(“out_refund_no”,out_refund_no);paramMap.put(“total_fee”,String.valueOf(totalMoney));paramMap.put(“refund_fee”,String.valueOf(refundMoney));paramMap.put(“notify_url”,weChatConfig.refundNotifyUrl);Stringsign=PayUtil.createSign(weChatConfig.key,paramMap);//获取最终待发送的数据StringrequestXml=”xml”+”appid”+weChatConfig.appId+”/appid”+”mch_id”+weChatConfig.mchId+”/mch_id”+”nonce_str”+nonce_str+”/nonce_str”+”out_trade_no”+out_trade_no+”/out_trade_no”+”out_refund_no”+out_refund_no+”/out_refund_no”+”total_fee”+String.valueOf(totalMoney)+”/total_fee”+”refund_fee”+String.valueOf(refundMoney)+”/refund_fee”+”notify_url”+weChatConfig.refundNotifyUrl+”/notify_url”+”sign”+sign+”/sign”+”/xml”;//定义本函数返回值:MapString,StringreturnMap=newHashMap();try{//建立连接并发送数据Stringresult=PayUtil.WeixinSendPostToRefund(weChatConfig.refundUrl,requestXml,weChatConfig.mchId);//解析返回的xmlMapString,StringresultMap=PayUtil.doXMLParse(result);//退款返回标志码Stringreturn_code=resultMap.get(“return_code”).toString();Stringresult_code=resultMap.get(“result_code”).toString();if(“SUCCESS”.equals(return_code)&&”SUCCESS”.equals(result_code)){//code…returnMap.put(“status”,”success”);returnMap.put(“msg”,”发起微信退款成功”);returnMap.put(“transactionId”,resultMap.get(“transaction_id”));returnMap.put(“outTradeNo”,resultMap.get(“out_trade_no”));returnMap.put(“outRefundNo”,resultMap.get(“out_refund_no”));returnreturnMap;}elseif(return_code.equals(“SUCCESS”)&&result_code.equals(“FAIL”)){returnMap.put(“status”,”fail”);returnMap.put(“msg”,”微信原路返款失败!”);returnreturnMap;}else{returnMap.put(“status”,”fail”);returnMap.put(“msg”,”微信原路返款失败!”);returnreturnMap;}}catch(Exceptione){e.printStackTrace();returnMap.put(“status”,”fail”);returnMap.put(“msg”,e.getMessage());returnreturnMap;}}2.证书使用微信退款是需要证书的,怎么获取证书,微信支付文档比任何人说得都详细/微信退款–向微信端发送post请求/publicstaticStringWeixinSendPostToRefund(Stringurl,StringxmlObj,Stringmch_id)throwsException{ClassPathResourceclassPathResource=newClassPathResource(“apiclient_cert.p12”);//证书路径(此处我用的相对路径,你也可以考虑安全性,放在项目外)InputStreaminstream=classPathResource.getInputStream();KeyStorekeyStore=KeyStore.getInstance(“PKCS12”);try{keyStore.load(instream,mch_id.toCharArray());}catch(Exceptione){e.printStackTrace();}finally{instream.close();}SSLContextsslcontext=SSLContexts.custom().loadKeyMaterial(keyStore,mch_id.toCharArray()).build();SSLConnectionSocketFactorysslsf=newSSLConnectionSocketFactory(sslcontext,newString[]{“TLSv1″},null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);CloseableHttpClienthttpclient=HttpClients.custom().setSSLSocketFactory(sslsf).build();Stringresult=””;try{HttpPosthttpPost=newHttpPost(url);HttpEntityxmlData=newStringEntity((String)xmlObj,”text/xml”,”iso-8859-1″);httpPost.setEntity(xmlData);CloseableHttpResponseresponse=httpclient.execute(httpPost);try{HttpEntityentity=response.getEntity();result=EntityUtils.toString(entity,”UTF-8″);System.out.println(response.getStatusLine());EntityUtils.consume(entity);}finally{response.close();}}finally{httpclient.close();}//去除空格returnresult.replaceAll(“”,””);}3.代码中引用的方法生成随机字符串:你可以用微信提供的javaSDK,其中有这个,而且map转xml和xml转map等都有商户订单号:我用的SnowflakeIdWorker,这个随你,只要唯一就行了sign签名:/微信退款–sign签名/publicstaticStringcreateSign(StringsecretKey,SortedMapObject,Objectparameters){StringBuffersb=newStringBuffer();SetMap.EntryObject,Objectes=parameters.entrySet();IteratorMap.EntryObject,Objectit=es.iterator();while(it.hasNext()){Map.EntryObject,Objectentry=(Map.EntryObject,Object)it.next();Stringk=(String)entry.getKey();Objectv=entry.getValue();if(null!=v&&!””.equals(v)&&!”sign”.equals(k)&&!”key”.equals(k)){sb.append(k+”=”+v+”&”);}}sb.append(“key=”+secretKey);Stringsign=MD5Utils.MD5(sb.toString()).toUpperCase();parameters.put(“sign”,sign);returnsign;}三、微信退款回调首先不用多说,在外网地址上开放一个接口1.主要代码/微信退款回调/@Override@Transactional(rollbackFor=Exception.class)publicStringwechatRefundCallback(HttpServletRequestrequest,HttpServletResponseresponse){log.info(“微信回调开始啦!!!!”);try{BufferedReaderbr=newBufferedReader(newInputStreamReader((ServletInputStream)request.getInputStream()));Stringline=null;StringBuildersb=newStringBuilder();while((line=br.readLine())!=null){sb.append(line);}br.close();//sb为微信返回的xmlMapresultMap=PayUtil.doXMLParse(sb.toString());if(“SUCCESS”.equals(resultMap.get(“return_code”))){//通信成功Stringreq_info=String.valueOf(resultMap.get(“req_info”));StringresultXml=AESUtil.decryptData(req_info,weChatConfig.key);MapString,ObjectreqInfoMap=PayUtil.doXMLParse(resultXml);//code….StringresultStr=”xmlreturn_code![CDATA[SUCCESS]]/return_codereturn_msg![CDATA[OK]]/return_msg/xml”;returnresultStr;}}catch(Exceptione){e.printStackTrace();}thrownewRuntimeException(“微信回调失败”);}2.解密方法AESUtilimportjavax.crypto.Cipher;importjavax.crypto.spec.SecretKeySpec;publicclassAESUtil{/密钥算法/privatestaticfinalStringALGORITHM=”AES”;/加解密算法/工作模式/填充方式/privatestaticfinalStringALGORITHM_MODE_PADDING=”AES/ECB/PKCS5Padding”;/AES加密/publicstaticStringencryptData(Stringdata,Stringpassword)throwsException{//创建密码器Ciphercipher=Cipher.getInstance(ALGORITHM_MODE_PADDING);SecretKeySpeckey=newSecretKeySpec(MD5Utils.MD5(password).toLowerCase().getBytes(),ALGORITHM);//初始化cipher.init(Cipher.ENCRYPT_MODE,key);returnBase64Util.encode(cipher.doFinal(data.getBytes()));}/AES解密/publicstaticStringdecryptData(Stringbase64Data,Stringpassword)throwsException{Ciphercipher=Cipher.getInstance(ALGORITHM_MODE_PADDING);SecretKeySpeckey=newSecretKeySpec(MD5Utils.MD5(password).toLowerCase().getBytes(),ALGORITHM);cipher.init(Cipher.DECRYPT_MODE,key);byte[]decode=Base64Util.decode(base64Data);byte[]doFinal=cipher.doFinal(decode);returnnewString(doFinal,”utf-8″);}}Base64Utilimportjava.util.Base64;publicclassBase64Util{/解码/publicstaticbyte[]decode(StringencodedText){finalBase64.Decoderdecoder=Base64.getDecoder();returndecoder.decode(encodedText);}/编码/publicstaticStringencode(byte[]data){finalBase64.Encoderencoder=Base64.getEncoder();returnencoder.encodeToString(data);}}MD5Utils/普通MD5/publicstaticStringMD5(Stringinput){MessageDigestmd5=null;try{md5=MessageDigest.getInstance(“MD5″);}catch(NoSuchAlgorithmExceptione){return”checkjdk”;}catch(Exceptione){e.printStackTrace();return””;}char[]charArray=input.toCharArray();byte[]byteArray=newbyte[charArray.length];for(inti=0;icharArray.length;i++){byteArray[i]=(byte)charArray[i];}byte[]md5Bytes=md5.digest(byteArray);StringBufferhexValue=newStringBuffer();for(inti=0;imd5Bytes.length;i++){intval=((int)md5Bytes[i])&0xff;if(val16){hexValue.append(“0”);}hexValue.append(Integer.toHexString(val));}returnhexValue.toString();}ps:很多教程说要替换jre的两个jar包,我这里没照这一步,在AES解密的时候SecretKeySpeckey=newSecretKeySpec(MD5Utils.MD5(password).toLowerCase().getBytes(),ALGORITHM);这步将商户key加密串转成小写了,这样就解决了”JAVA运行环境默认不允许256位密钥的AES加解密””的问题有啥不懂得,或者我贴的代码有啥缺漏的,可以留言参考:

赞(0) 打赏
未经允许不得转载:E企盈小程序开发-热线:4006-838-530 » 微信被投诉,小程序微信退款退款信息回调解密
分享到: 更多 (0)
E企盈小程序直播营销卖货系统
E企盈直播平台营销卖货系统

评论 抢沙发

E企盈小程序开发

联系我们联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏