zoukankan      html  css  js  c++  java
  • 微信扫码支付

    前些日子做的微信扫码支付,现在都有点忘了怎么做的了,赶紧记录一下。。

    首先先看比较好的案例,帮了我好多好多,太感谢无私奉献的人们了,我选择的模式二开发

    一、场景:公司需要在网站上进行微信支付。

    二、API:使用微信开放平台的接入微信支付


    -扫码支付。微信支付开发者平台链接

    三、实现:

          一是:按照微信扫码支付规则生成二维码信息.

      二是:微信没有提供生成二维码图片的接口。需要我们自己把二维码信息生成到二维码图片中。

    1、首先我们要获取微信后台的必要的信息。

    public class Configure {
        // 每次自己Post数据给API的时候都要用这个key来对所有字段进行签名,生成的签名会放在Sign这个字段,API收到Post数据的时候也会用同样的签名算法对Post过来的数据进行签名和验证
        // 收到API的返回的时候也要用这个key来对返回的数据算下签名,跟API的Sign数据进行比较,如果值不一致,有可能数据被第三方给篡改

        public static String key = "";
        
        //微信分配的公众号ID(开通公众号之后可以获取到)
        public static String appID = "";
        
        public static String appsecret = "";

        //微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
        public static String mchID = "";

        //HTTPS证书的本地路径
        public static String certLocalPath = "D:/wx/apiclient_cert.p12";

        //HTTPS证书密码,默认密码等于商户号MCHID
        public static String certPassword = "";

        /**
         * 功能描述: 获取客户端IP
         *
         * @author yanzy  2016-1-18 下午08:19:45
         *
         * @param request
         * @return
         */
        public static String getClientIp(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();
            }
            return ip;
        }
        
        //随机字符串
        public static String getNonceStr() {
            String currTime = PayCommonUtil.getCurrTime();  
            String strTime = currTime.substring(8, currTime.length());  
            String strRandom = PayCommonUtil.buildRandom(4) + "";
            String nonce_st = strTime + strRandom;  
            return nonce_st;
        }

        //1)扫码支付API
        public static String PAY_API = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        //2)退款API
        public static String REFUND_API = "https://api.mch.weixin.qq.com/secapi/pay/refund";

        //3)退款查询API
        public static String REFUND_QUERY_API = "https://api.mch.weixin.qq.com/pay/refundquery";
        
        //4)查询订单状态
        public static String PAY_QUERY_API = "https://api.mch.weixin.qq.com/pay/orderquery";
        
        public static String notify_url = BlockAttribute.host+"/payment/weixin/weixin_notify.jsp";

        public static String HttpsRequestClassName = "com.tencent.common.HttpsRequest";
     
    }
    还有各种工具类:HttpUtil

    public class HttpUtil {
        private final static int CONNECT_TIMEOUT = 5000; // in milliseconds  
        private final static String DEFAULT_ENCODING = "UTF-8";  
          
        public static String postData(String urlStr, String data){  
            return postData(urlStr, data, null);  
        }  
          
        public static String postData(String urlStr, String data, String contentType){  
            BufferedReader reader = null;  
            try {  
                URL url = new URL(urlStr);  
                URLConnection conn = url.openConnection();  
                conn.setDoOutput(true);  
                conn.setConnectTimeout(CONNECT_TIMEOUT);  
                conn.setReadTimeout(CONNECT_TIMEOUT);  
                if(contentType != null)  
                    conn.setRequestProperty("content-type", contentType);  
                OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);  
                if(data == null)  
                    data = "";  
                writer.write(data);   
                writer.flush();  
                writer.close();    
     
                reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));  
                StringBuilder sb = new StringBuilder();  
                String line = null;  
                while ((line = reader.readLine()) != null) {  
                    sb.append(line);  
                    sb.append(" ");  
                }  
                return sb.toString();  
            } catch (IOException e) {
                LogUtil.writeLog("Error connecting to " + urlStr + ": " + e.getMessage());  
            } finally {  
                try {  
                    if (reader != null)  
                        reader.close();  
                } catch (IOException e) {  
                }  
            }  
            return null;  
        }  
        
        /**
         * 自定义SSL双向证书验证
         *  
         * @param url
         * @param mchId
         * @param arrayToXml
         * @return
         * @throws Exception
         */  
        public static String clientCustomSSLCall(String url,String mchId, String arrayToXml) throws Exception {  
            String jsonStr = null;
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            // System.out.println("capath:=" + cAPath);  
            FileInputStream instream = new FileInputStream(new File(Configure.certLocalPath));  
            try {  
                keyStore.load(instream, mchId.toCharArray());  
            } finally {  
                instream.close();  
            }  
            // Trust own CA and all self-signed certs  
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();  
            // Allow TLSv1 protocol only  
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);  
            CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();  
            try {  
                HttpPost httpPost = new HttpPost(url);  
                httpPost.setEntity(new StringEntity(arrayToXml, "UTF-8"));  
                CloseableHttpResponse response = httpclient.execute(httpPost);  
     
                jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");  
                response.close();  
            } finally {  
                httpclient.close();  
            }  
            return jsonStr;  
        }  
        

    MD5工具类

    public class MD5 {
        private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
                "8", "9", "a", "b", "c", "d", "e", "f"};

        /**
         * 转换字节数组为16进制字串
         * @param b 字节数组
         * @return 16进制字串
         */
        public static String byteArrayToHexString(byte[] b) {
            StringBuilder resultSb = new StringBuilder();
            for (byte aB : b) {
                resultSb.append(byteToHexString(aB));
            }
            return resultSb.toString();
        }

        /**
         * 转换byte到16进制
         * @param b 要转换的byte
         * @return 16进制格式
         */
        private static String byteToHexString(byte b) {
            int n = b;
            if (n < 0) {
                n = 256 + n;
            }
            int d1 = n / 16;
            int d2 = n % 16;
            return hexDigits[d1] + hexDigits[d2];
        }

        /**
         * MD5编码
         * @param origin 原始字符串
         * @return 经过MD5加密之后的结果
         */
        public static String MD5Encode(String origin, String charsetname) {  
            String resultString = null;  
            try {  
                resultString = new String(origin);  
                MessageDigest md = MessageDigest.getInstance("MD5");  
                if (charsetname == null || "".equals(charsetname))  
                    resultString = byteArrayToHexString(md.digest(resultString  
                            .getBytes()));  
                else  
                    resultString = byteArrayToHexString(md.digest(resultString  
                            .getBytes(charsetname)));  
            } catch (Exception exception) {  
            }  
            return resultString;  
        }  

    }

    PayCommonUtil 工具类

    @SuppressWarnings({"rawtypes"})
    public class PayCommonUtil {
        /**
         * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
         * @return boolean
         */  
        public static boolean isTenpaySign(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(!"sign".equals(k) && null != v && !"".equals(v)) {  
                    sb.append(k + "=" + v + "&");  
                }  
            }  
            sb.append("key=" + API_KEY);  
            //算出摘要  
            String mysign = MD5.MD5Encode(sb.toString(), characterEncoding).toLowerCase();  
            String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();  
            return tenpaySign.equals(mysign);  
        }  
     
        /**
         * @Description:sign签名
         * @param characterEncoding
         * @param parameters
         * @return
         */  
        public static String createSign(String characterEncoding, SortedMap<String, String> parameters, String API_KEY) {  
            StringBuffer sb = new StringBuffer();  
            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 (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {  
                    sb.append(k + "=" + v + "&");  
                }  
            }  
            sb.append("key=" + API_KEY);  
            String sign = MD5.MD5Encode(sb.toString(), characterEncoding).toUpperCase();  
            return sign;  
        }  
     
        /**
         * @author
         * @date 2016-4-22
         * @Description:将请求参数转换为xml格式的string
         * @param parameters
         * 请求参数
         * @return
         */  
        public static String getRequestXml(SortedMap<String, String> 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();  
        }  
     
        /**
         * 取出一个指定长度大小的随机正整数.
         * @param length
         *  int 设定所取出随机数的长度。length小于11
         * @return int 返回生成的随机数。
         */  
        public static int buildRandom(int length) {  
            int num = 1;  
            double random = Math.random();  
            if (random < 0.1) {  
                random = random + 0.1;  
            }  
            for (int i = 0; i < length; i++) {  
                num = num * 10;  
            }  
            return (int) ((random * num));  
        }  
     
        /**
         * 获取当前时间 yyyyMMddHHmmss
         * @return String
         */  
        public static String getCurrTime() {  
            Date now = new Date();  
            SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");  
            String s = outFormat.format(now);  
            return s;  
        }  
     
        public static String getCurrTimeS() {
            Date now = new Date();
            SimpleDateFormat outFormat = new SimpleDateFormat("yyyy"+"年"+"MM"+"月"+"dd"+"日    "+"HH"+"时"+"mm"+"分"+"ss"+"秒");
            String s = outFormat.format(now);
            return s;
            
    }
    }  

    XMLUtil  工具类

    @SuppressWarnings({"unchecked"})
    public class XMLUtil {
        /**
         * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
         * @param strxml
         * @return
         * @throws JDOMException
         * @throws IOException
         */  
        public static Map<String, Object> doXMLParse(String strxml) throws JDOMException, IOException {  
            strxml = strxml.replaceFirst("encoding=".*"", "encoding="UTF-8"");  
     
            if(null == strxml || "".equals(strxml)) {  
                return null;  
            }  
              
            Map<String, Object> m = new HashMap<String, Object>();
              
            InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));  
            SAXBuilder builder = new SAXBuilder();  
            Document doc = builder.build(in);  
            Element root = doc.getRootElement();  
            List<Element> list = root.getChildren();  
            Iterator<Element> it = list.iterator();  
            while(it.hasNext()) {  
                Element e = (Element) it.next();  
                String k = e.getName();  
                String v = "";  
                List<Element> children = e.getChildren();  
                if(children.isEmpty()) {  
                    v = e.getTextNormalize();  
                } else {  
                    v = XMLUtil.getChildrenText(children);  
                }  
                  
                m.put(k, v);  
            }  
              
            //关闭流  
            in.close();  
              
            return m;  
        }  
          
        /**
         * 获取子结点的xml
         * @param children
         * @return String
         */  
        public static String getChildrenText(List<Element> children) {  
            StringBuffer sb = new StringBuffer();  
            if(!children.isEmpty()) {  
                 Iterator<Element> it = children.iterator();  
                while(it.hasNext()) {  
                    Element e = (Element) it.next();  
                    String name = e.getName();  
                    String value = e.getTextNormalize();  
                    List<Element> list = e.getChildren();  
                    sb.append("<" + name + ">");  
                    if(!list.isEmpty()) {  
                        sb.append(XMLUtil.getChildrenText(list));  
                    }  
                    sb.append(value);  
                    sb.append("</" + name + ">");  
                }  
            }  
              
            return sb.toString();  
        }  
          

    以上是需要用到的工具类,下面我们就要开始调用了

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ page import="com.cn.service.face.payment.weixinpay.*"%>
    <%@ page import="java.util.*"%>
    <%@ page import="java.lang.*"%>
    <%@ page import="com.cn.service.environment.*" %>
    <%@ page import="com.cn.dto.entity.ordermanage.*"%>
    <%@ page import="com.cn.service.face.order.commodity.*"%>
    <%@ page import="com.cn.service.face.payment.weixinpay.*"%>
    <%@ page import="com.cn.service.system.tools.*"%>
    <%
            ///////////////////////微信扫码支付接口      请求参数/////////////////////////////
            String orderno = request.getParameter("orderno");
            OrderManyPayFace orderManyPayFace=EnvironmentBean.getInstance().getBeanByBeanClass(OrderManyPayFace.class);
            UserOrder uo = orderManyPayFace.getUserOrder(orderno);
            double money=orderManyPayFace.getPayMoney(orderno);
            int transport=uo.getTransportCosts()!=null?uo.getTransportCosts().intValue():0;
            orderno=orderManyPayFace.getPayOrderno(orderno);
            money=money+transport;
            String txnAmt =Double.valueOf(money*100).intValue()+"";
            String body=uo.getOrderName();
        
            SortedMap<String,String> parameters = new TreeMap<String,String>();
            parameters.put("body", body);                          //商品描述              
            parameters.put("out_trade_no", orderno);            //商户订单号    
            parameters.put("total_fee", txnAmt);                 //交易金额,单位分,不要带小数点          
            parameters.put("trade_type", "NATIVE");             //交易类型 ,
            parameters.put("product_id", orderno);              //商品ID
            
            WinxinpayServiceFace winxinpay=EnvironmentBean.getInstance().getBeanByBeanClass(WinxinpayServiceFace.class);
            String sHtmlText = winxinpay.trade_create_by_weixinpay(parameters,request);
            String qrcode=ZxingEncode.createQRCode(200, 200, request, sHtmlText);

    %>
    <script type="text/javascript" src="js/jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="js/qrcode.js"></script>
    <style>
    *{ margin:0px; padding:0px;}
    .wrapper{1000px; margin:20px auto;border:1px solid #ccc;}
    .orderdetail{ background:#f2f2f2; height:60px; line-height:60px; color:#333333; padding-left:20px; padding-right:20px;}
    .orderdetail span{ display:block;}
    .ordernum{ float:left;}
    .ordermoney{ float:right;}
    .logo{ padding:20px;}
    .pay_method{margin:20px; position:relative; height:400px;}
    .pay_method ul{ position:absolute;left:0px;top:0px;background:#fff; z-index:1;}
    .pay_method ul li{ float:left; list-style:none; border:1px solid #ccc;border-bottom:none; height:30px; line-height:30px; padding-left:20px; padding-right:20px;}
    .num_pay{border:1px solid #ccc;position:absolute;left:0px;top:29px; 960px; height:360px;}
    .logowx{margin-top:20px;margin-left:20px;}
    .erweima{ margin:0px auto; text-align:center;}
    .erweima span{ display:block; margin-bottom:10px;}
    </style>
    <body>
    <div class="wrapper">
        <div class="logo"><img src="images/pay/logo.png" width="61" height="26" /></div>
        <div class="orderdetail">
            <span class="ordernum">订单编号: <%=orderno%></span>
            <span class="ordermoney">应付金额:&yen;<%=money%></span>
        </div>
        <div class="pay_method">
            <ul>
                <li>微信支付</li>
            </ul>
            <div style="clear:both;"></div>
            <div class="num_pay">
                <img src="images/pay/WePayLogo.png" width="120" height="32" class="logowx" />
                <div class="erweima">
                   <!--  <span id="qrcode"></span> -->
                    <img src="<%=qrcode%>"/>
                    <span><img src="images/pay/des.png" width="180" height="60"/></span>
                </div>
            </div>
        </div>
    </div>
    </body>
    <script type="text/javascript">
        //这是查询订单
        var t1;
        var sum=0;
        var out_trade_no="<%=orderno%>";
        var paymentId="<%=uo.getPaymentId()%>";
        t1=setInterval("ajaxstatus()", 5000);
        function ajaxstatus() {
            sum++;
            if(sum>600){ window.clearInterval(t1);return false;}
            if(sum>180){
                m=sum % 10;
                if(m!=0){return false;}
            }
            if (out_trade_no != null) {
                $.ajax({
                 type:"post",
                 url:"/PaymentFgAction!weixinQuery.action",
                 dataType:"json",
                 data: {"orderno":out_trade_no,"paymentId":paymentId},
                 success: function (data) {
                     if (data== "1") {
                         window.location.href = "http://www.hiersun-ido.com/account/listUserOrder.html";
                         //<a href="http://www.hiersun-ido.com/account/listUserOrder.html">返回个人中心</a>
                     }
                 },
                     error: function(XMLHttpRequest, textStatus, errorThrown) {
                     alert("请求订单状态出错");
                 }
                 });
             }
         }
    </script>

    /**
         * 构造微信扫码支付跳转接口
         * @param sParaTemp 请求参数集合
         * @return 表单提交HTML信息
         * @throws IOException
         * @throws JDOMException
         */
        public static String trade_create_by_weixinpay(SortedMap<String, String> parameters,HttpServletRequest request) throws JDOMException, IOException {
            //增加基本配置
            parameters.put("appid", Configure.appID);
            parameters.put("mch_id", Configure.mchID);
            parameters.put("nonce_str",Configure.getNonceStr());
            parameters.put("spbill_create_ip", Configure.getClientIp(request));
            parameters.put("notify_url", Configure.notify_url);
            String sign = PayCommonUtil.createSign("UTF-8", parameters,Configure.key);  
            parameters.put("sign", sign);
            String requestXML = PayCommonUtil.getRequestXml(parameters);  
            String resXml = HttpUtil.postData(Configure.PAY_API, requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            String urlCode = (String) map.get("code_url");
            return urlCode;
        }

    /**
         * 微信扫码支付交易状态查询
         * @throws IOException
         * @throws JDOMException
         */
        public String weixinQuery(String orderno) throws JDOMException, IOException {
            
            SortedMap<String,String> parameters = new TreeMap<String,String>();
            //查询交易需要的参数
            parameters.put("appid", Configure.appID);
            parameters.put("mch_id", Configure.mchID);
            parameters.put("out_trade_no", orderno);            //商户订单号
            parameters.put("nonce_str",Configure.getNonceStr());
            String sign = PayCommonUtil.createSign("UTF-8", parameters,Configure.key);  
            parameters.put("sign", sign);
            String requestXML = PayCommonUtil.getRequestXml(parameters);  
            
            String resXml = HttpUtil.postData(Configure.PAY_QUERY_API, requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            String trade_state  = (String) map.get("trade_state");
            return trade_state ;
        }
        
        /**
         * 构造微信扫码申请退款接口
         * @param sParaTemp 请求参数集合
         * @return 表单提交HTML信息
         * @throws Exception
         */
        public static String trade_create_by_weixinrefund(SortedMap<String, String> parameters)  {
            String result_code=null;
            //增加基本配置
            try {
            parameters.put("appid", Configure.appID);
            parameters.put("mch_id", Configure.mchID);
            parameters.put("nonce_str",Configure.getNonceStr());
            String sign = PayCommonUtil.createSign("UTF-8", parameters,Configure.key);  
            parameters.put("sign", sign);
            String requestXML = PayCommonUtil.getRequestXml(parameters);  
            String resXml;
                resXml = HttpUtil.clientCustomSSLCall(Configure.REFUND_API, Configure.mchID,requestXML);
            //String resXml = HttpUtil.postData(Configure.REFUND_API, requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            result_code = (String) map.get("result_code");
            String err_code_des=(String)map.get("err_code_des");
            String refund_id=(String)map.get("refund_id");
            if("SUCCESS".equals(result_code)){
                return refund_id;
            }else{
                return err_code_des;
            }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return "申请退款失败";
            }  
        }

    生成二维码的工具类

    import java.io.*;
    import java.util.*;
    import java.awt.*;
    import java.awt.image.*;
    import javax.imageio.*;
    import javax.servlet.http.*;
    import com.google.zxing.*;
    import com.google.zxing.common.*;
    import com.cn.service.system.common.*;
    import com.google.zxing.qrcode.decoder.*;

    @SuppressWarnings({ "rawtypes","unchecked","unused"})
    public class ZxingEncode {

        public ZxingEncode() {
            super();
        }
        
        /**
         * 生成二维码,并返回二维码图片路径,文件名自动生成
         * content:二维码内容
         */
        public static String createQRCode(int width,int height,HttpServletRequest request,String content) {
            String attachPath="";
            try {
                attachPath=AttachFile.getImagePath(request,BlockAttribute.twoDimensionCode);
                /*String projectName=AttachFile.getProjectName(attachPath);
                
                String temp_attachPath=attachPath;
                String mob_attachPath=attachPath;
                attachPath=attachPath.replaceAll(projectName, "OhdManage.war");
                temp_attachPath=temp_attachPath.replaceAll(projectName, "OhdStudio.war");    同步文件夹:一个文件同时存储在二个项目下
                mob_attachPath=mob_attachPath.replaceAll(projectName, "OhdMobile.war");      同步文件夹:一个文件同时存储在二个项目下
                */
                attachPath=AttachFile.createAttachDir(attachPath);
                /*temp_attachPath=AttachFile.createAttachDir(temp_attachPath);
                mob_attachPath=AttachFile.createAttachDir(mob_attachPath);*/
                
                String fileName=AttachFile.createFileName("png");
                attachPath=attachPath+FileTool.getFileSystemSeparator()+fileName;
                /*temp_attachPath=temp_attachPath+FileTool.getFileSystemSeparator()+fileName;
                mob_attachPath=mob_attachPath+FileTool.getFileSystemSeparator()+fileName;*/
                
                ZxingEncode qrcodeEncoder=new ZxingEncode();
                qrcodeEncoder.encoderQRCode(content, attachPath,width,height);
                /*qrcodeEncoder.encoderQRCode(content, temp_attachPath,width,height);
                qrcodeEncoder.encoderQRCode(content, mob_attachPath,width,height);
                
                attachPath=attachPath.substring(attachPath.indexOf("userfiles"));*/
            }
            catch(Exception err) {
                err.printStackTrace();
            }
            return AttachFile.getWebAttachPath(attachPath);
        }
        
        /**
         * 生成二维码,并返回二维码图片路径,需要传入文件名
         * content:二维码内容
         */
        public static String createQRCode(int width,int height,HttpServletRequest request,String content,String fileName) {
            String attachPath="";
            try {
                attachPath=AttachFile.getImagePath(request,BlockAttribute.twoDimensionCode);
                /*String projectName=AttachFile.getProjectName(attachPath);
                
                String temp_attachPath=attachPath;
                String mob_attachPath=attachPath;
                attachPath=attachPath.replaceAll(projectName, "OhdManage.war");
                temp_attachPath=temp_attachPath.replaceAll(projectName, "OhdStudio.war");    同步文件夹:一个文件同时存储在二个项目下
                mob_attachPath=mob_attachPath.replaceAll(projectName, "OhdMobile.war");      同步文件夹:一个文件同时存储在二个项目下 */
                
                attachPath=AttachFile.createAttachDir(attachPath);
                /*temp_attachPath=AttachFile.createAttachDir(temp_attachPath);
                mob_attachPath=AttachFile.createAttachDir(mob_attachPath);*/
                
                fileName=fileName+".png";
                attachPath=attachPath+FileTool.getFileSystemSeparator()+fileName;
                /*temp_attachPath=temp_attachPath+FileTool.getFileSystemSeparator()+fileName;
                mob_attachPath=mob_attachPath+FileTool.getFileSystemSeparator()+fileName;*/
                
                ZxingEncode qrcodeEncoder=new ZxingEncode();
                qrcodeEncoder.encoderQRCode(content, attachPath,width,height);
                /*qrcodeEncoder.encoderQRCode(content, temp_attachPath,width,height);
                qrcodeEncoder.encoderQRCode(content, mob_attachPath,width,height);
                
                attachPath=attachPath.substring(attachPath.indexOf("userfiles"));*/
            }
            catch(Exception err) {
                err.printStackTrace();
            }
            return AttachFile.getWebAttachPath(attachPath);
        }
        
        /**  
         * 生成二维码(QRCode)图片  
         * 用微信扫描GBK编码的中文二维码时出现乱码,用UTF-8编码时微信可正常识别 。
         * 并且MultiFormatWriter.encode()时若传入hints参数来指定UTF-8编码中文时,微信压根就不识别所生成的二维码。
         * 所以这里使用的是这种方式new String(content.getBytes("UTF-8"), "ISO-8859-1")。
         * 生成的二维码图片默认背景为白色,前景为黑色,但是在加入logo图像后会导致logo也变为黑白色,至于是什么原因还没有仔细去读它的源码 。
         * 所以这里对其第一个参数黑色将ZXing默认的前景色0xFF000000稍微改了一下0xFF000001,最终效果也是白色背景黑色前景的二维码,且logo颜色保持原有。
         */
        public void encoderQRCode(String content,String imgPath,int width,int height) {
            try {
                 MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
                 Map hints = new HashMap<EncodeHintType, String>();
                 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);  
                 //hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
                 BitMatrix bitMatrix = multiFormatWriter.encode(new String(content.getBytes("UTF-8"),"ISO-8859-1"), BarcodeFormat.QR_CODE, width, height,hints);
                 File file = new File(imgPath);
                 MatrixToImageWriter.writeToFile(bitMatrix, "png", file);
            }
            catch(Exception err) {
                err.printStackTrace();
            }
        }
        
        /**
         * 暂不支持加入头象
         * 为其二维码添加头象
         * 1)生成二维码的纠错级别建议采用最高等级H,这样可以增加二维码的正确识别能力(我测试过,不设置级别时,二维码工具无法读取生成的二维码图片)
         * 2)头像大小最好不要超过二维码本身大小的1/5,而且只能放在正中间部位,这是由于二维码本身结构造成的(你就把它理解成图片水印吧)
         * 3)在仿照腾讯微信在二维码四周增加装饰框,那么一定要在装饰框和二维码之间留出白边,这是为了二维码可被识别
         */
        public void overlapImage(String imagePath, String logoPath) throws IOException {
            BufferedImage image = ImageIO.read(new File(imagePath));  
            int logoWidth = image.getWidth()/5;   //设置logo图片宽度为二维码图片的五分之一  
            int logoHeight = image.getHeight()/5; //设置logo图片高度为二维码图片的五分之一  
            int logoX = (image.getWidth()-logoWidth)/2;   //设置logo图片的位置,这里令其居中  
            int logoY = (image.getHeight()-logoHeight)/2; //设置logo图片的位置,这里令其居中  
            Graphics2D graphics = image.createGraphics();  
            graphics.drawImage(ImageIO.read(new File(logoPath)), logoX, logoY, logoWidth, logoHeight, null);  
            graphics.dispose();  
            ImageIO.write(image, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath));
        }
        
        private static final class MatrixToImageWriter {
            
            private static final int BLACK = 0xFF000000;
            private static final int WHITE = 0xFFFFFFFF;

            private MatrixToImageWriter() {
            }

            public static BufferedImage toBufferedImage(BitMatrix matrix) {
                int width = matrix.getWidth();
                int height = matrix.getHeight();
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                for (int x = 0; x < width; x++) {
                    for (int y = 0; y < height; y++) {
                        image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
                    }
                }
                return image;
            }

            public static void writeToFile(BitMatrix matrix, String format,File file) throws IOException {
                BufferedImage image = toBufferedImage(matrix);
                if (!ImageIO.write(image, format, file)) {
                    throw new IOException("Could not write an image of format "    + format + " to " + file);
                }
            }
            
            public static void writeToStream(BitMatrix matrix, String format,OutputStream stream) throws IOException {
                BufferedImage image = toBufferedImage(matrix);
                if (!ImageIO.write(image, format, stream)) {
                    throw new IOException("Could not write an image of format " + format);
                }
            }
        }
        
        public static void main(String[] args) {
            String imgPath = "D:/Michael_QRCode.png";
            ZxingEncode qrcodeEncoder=new ZxingEncode();
            qrcodeEncoder.encoderQRCode("http://192.168.12.33:8080/fdsfsafj-fkdsfks343243.html", imgPath,120,120);
        }
    }

    附件的保存与删除
    附件只保存在OhdFileMage项目下,图片二维码的工具类

    public class AttachFile {

        public AttachFile() {
        }
                
        /**
         * 保存附件,返回文件路径,type=0保 存的是文件,type=1保存的是图片
         * clsPath:文件的分类文件夹名
         * 附件只保存在OhdFileMage项目下
         */
        public static String saveAttach(byte[] content,String extenName,int type,HttpServletRequest request,String clsPath) throws Exception {
            String attachPath="";
            try {
                if(type==0) {
                    attachPath=getAttachPath(request,clsPath);
                }
                else if(type==1) {
                    attachPath=getImagePath(request,clsPath);
                }
                //String projectName=getProjectName(attachPath);
                /*String temp_attachPath=attachPath;
                String mob_attachPath=attachPath;*/
                //attachPath=attachPath.replaceAll(projectName, "OhdFileMage.war");
                /*temp_attachPath=temp_attachPath.replaceAll(projectName, "OhdStudio.war");    同步文件夹:一个文件同时存储在二个项目下
                mob_attachPath=mob_attachPath.replaceAll(projectName, "OhdMobile.war");      同步文件夹:一个文件同时存储在二个项目下 */
                
                attachPath=createAttachDir(attachPath);
                /*temp_attachPath=createAttachDir(temp_attachPath);
                mob_attachPath=createAttachDir(mob_attachPath);*/
                
                String fileName=createFileName(extenName);
                attachPath=attachPath+FileTool.getFileSystemSeparator()+fileName;
                /*temp_attachPath=temp_attachPath+FileTool.getFileSystemSeparator()+fileName;
                mob_attachPath=mob_attachPath+FileTool.getFileSystemSeparator()+fileName;*/
                
                FileTool.writeFile(attachPath, content);
                /*FileTool.writeFile(temp_attachPath, content);
                FileTool.writeFile(mob_attachPath, content);*/
            }
            catch(Exception err) {
                throw err;
            }
            return getWebAttachPath(attachPath);
        }
        
        /**
         * 设置图片路径
         */
        public static String getWebAttachPath(String attachPath) {
            return "IdoFileMage/"+attachPath.substring(attachPath.indexOf("userfiles"));
        }
        
        /**
         * 返回项目名称
         */
        public static String getProjectName(String attachPath) throws Exception {
            String projectName=null;
            if(attachPath.indexOf("IdoManage.war")>=0) {
                projectName="IdoManage.war";
            }
            else if(attachPath.indexOf("IdoStudio.war")>=0) {
                projectName="IdoStudio.war";
            }
            else if(attachPath.indexOf("IdoMobile.war")>=0) {
                projectName="IdoMobile.war";
            }
            return projectName;
        }
        
        /**
         * 按年月日创建文件夹
         */
        public static String createAttachDir(String attachPath) throws Exception {
            attachPath=attachPath+FileTool.getFileSystemSeparator()+DateTool.getYear();
            createAttachPath(attachPath);
            attachPath=attachPath+FileTool.getFileSystemSeparator()+(DateTool.getMonth()+1);
            createAttachPath(attachPath);
            /*attachPath=attachPath+FileTool.getFileSystemSeparator()+DateTool.getDay();    //文件夹只需要到月,到日产生太多的文件夹。
            createAttachPath(attachPath);*/
            return attachPath;
        }
        
        /**
         * 删除文件
         */
        public static boolean deleteAttach(String attachPath) throws Exception {
            boolean deleteAttach=false;
            if(FileTool.isFileExist(attachPath)) {
                FileTool.deleteFile(attachPath);
                deleteAttach=true;
            }
            return deleteAttach;
        }
        
        /**
         * 创建指定的文件夹
         */
        private static void createAttachPath(String attachPath) throws Exception {
            if(!FileTool.isFileExist(attachPath)) {
                FileTool.createDir(attachPath);
            }
        }
        
        /**
         * 创建文件名
         */
        public static String createFileName(String extenName) {
            String filename=DateTool.dateToTimeString()+getRandom()+"."+extenName;
            return filename;
        }
        
        /**
         * 获取web项目路径
         * 注:附件只存在OhdFileMage.war项目下
         */
        public static String getWebPath(HttpServletRequest request) throws Exception {
            String attachPath=request.getSession().getServletContext().getRealPath("/");
            String projectName=getProjectName(attachPath);
            attachPath=attachPath.replaceAll(projectName, "IdoFileMage.war");
            return attachPath;
        }
        
        /**
         * 获取附件的保存路径
         * clsPath:文件的分类文件夹名
         */
        public static String getAttachPath(HttpServletRequest request,String clsPath) throws Exception {
            String attachPath=getWebPath(request);
            attachPath=attachPath+FileTool.getFileSystemSeparator()+"userfiles"+FileTool.getFileSystemSeparator()+"files"+FileTool.getFileSystemSeparator()+clsPath;
            createAttachPath(attachPath);
            return attachPath;
        }
        
        /**
         * 获取附件的保存路径
         * clsPath:文件的分类文件夹名
         */
        public static String getImagePath(HttpServletRequest request,String clsPath) throws Exception {
            String attachPath=getWebPath(request);
            attachPath=attachPath+FileTool.getFileSystemSeparator()+"userfiles"+FileTool.getFileSystemSeparator()+"images"+FileTool.getFileSystemSeparator()+clsPath;
            createAttachPath(attachPath);
            return attachPath;
        }
        
        /**
         * 生成一个1到1000的随机数
         */
        public static int getRandom() {
            Random rd = new Random();
            return (1+rd.nextInt(1000));
        }
    }


    支付成功后的回调接口

    <%
    /* *
     功能:微信服务器异步通知页面
     日期:2017-05-16
     
     * */
    %>
    <%@ page language="java" contentType="text/html; charset=GBK" pageEncoding="GBK"%>
    <%@ page import="java.text.*"%>
    <%@ page import="java.util.*"%>
    <%@ page import="java.io.*"%>
    <%@ page import="java.lang.*"%>
    <%@ page import="com.cn.service.error.*" %>
    <%@ page import="com.cn.service.environment.*" %>
    <%@ page import="com.cn.service.face.payment.weixinpay.util.*"%>
    <%@ page import="com.cn.service.face.order.commodity.*"%>
    <%@ page import="com.cn.dto.entity.ordermanage.*"%>
    <%@ page import="com.cn.service.face.order.*"%>
    <%
        String paymentno=null;
        String out_trade_no=null;
        try{
            //读取参数  
            InputStream inputStream;  
            StringBuffer sb = new StringBuffer();  
            inputStream = request.getInputStream();  
            String s;  
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));  
            while ((s = in.readLine()) != null){  
                sb.append(s);  
            }  
            in.close();
            inputStream.close();
              //解析xml成map  
            Map<String, Object> m = new HashMap<String, Object>();
            m = XMLUtil.doXMLParse(sb.toString());
            
          //过滤空 设置 TreeMap  
            SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
            Iterator it = m.keySet().iterator();
            while (it.hasNext()) {
                String parameter = (String) it.next();
                String parameterValue =(String) m.get(parameter);
                String v = "";
                if(null != parameterValue) {
                    v = parameterValue.trim();  
                }  
                packageParams.put(parameter, v);  
            }  
             // 账号信息  
            String key = Configure.key; // key
          //判断签名是否正确  
          if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,key)) {
              String resXml = "";
              if("SUCCESS".equals((String)packageParams.get("result_code"))) {
                  //获取微信支付的通知返回参数,可参考技术文档中页面跳转异步通知参数列表(以下仅供参考)
                  String mch_id = (String)packageParams.get("mch_id");  
                  String is_subscribe = (String)packageParams.get("is_subscribe");  
                  out_trade_no = (String)packageParams.get("out_trade_no");
                  String total_fee = (String)packageParams.get("total_fee");
                  String transaction_id = (String)packageParams.get("transaction_id");
                  String time_end = (String)packageParams.get("time_end");
                  
                  OrderPayRefundLogFace orderPayRefundLogFace=EnvironmentBean.getInstance().getBeanByBeanClass(OrderPayRefundLogFace.class);
                    orderPayRefundLogFace.saveOrderPayLog(out_trade_no, "微信", packageParams.toString(), "");
                  
                  //执行自己的业务逻辑
                  UserOrderFace userOrderFace= EnvironmentBean.getInstance().getBeanByBeanClass(UserOrderFace.class);
                  UserOrder uo = userOrderFace.findUserOrder(out_trade_no);
                  String money=String.valueOf(Double.valueOf(uo.getMoney().doubleValue()*100).intValue());
                  if(money.equals(total_fee.trim())) {
                        userOrderFace.flushOrderStateSequence(out_trade_no,transaction_id,time_end);
                          //out.println("支付成功");
                          //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.  
                          resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
                              + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                  }
                  else {
                      out.println("假通知");  
                  }
              }
              else {  
                  out.println("支付失败,错误信息:" + packageParams.get("err_code"));  
                  resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
                          + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
              }  
              out.println(resXml);  
          }
          else{  
              out.println("通知签名验证失败");
          }  
        }
        catch(Exception ex) {
            out.println("通知签名验证失败");  
            ex.printStackTrace();
            try {
                OrderPayRefundLogFace orderPayRefundLogFace=EnvironmentBean.getInstance().getBeanByBeanClass(OrderPayRefundLogFace.class);
                orderPayRefundLogFace.saveOrderPayLog(out_trade_no, "微信", "", ExceptionOut.writeException(ex));
            }
            catch(Exception error) {
                error.printStackTrace();
            }
        }
    %>

    退款的

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ page import="java.util.*"%>
    <%@ page import="java.lang.*"%>
    <%@ page import="com.cn.service.error.*" %>
    <%@ page import="com.cn.service.environment.*" %>
    <%@ page import="com.cn.service.system.tools.*" %>
    <%@ page import="com.cn.dto.entity.ordermanage.*"%>
    <%@ page import="com.cn.service.face.order.commodity.*"%>
    <%@ page import="com.cn.service.face.payment.weixinpay.*"%>
    <%@ page import="com.cn.service.face.payment.weixinpay.util.*"%>
    <%
        String transaction_id="";   //微信流水号(订单号)
        try {
            ///////////////////////微信扫码支付接口      请求参数/////////////////////////////
            String orderno = request.getParameter("orderno");
            /* type:1-定金,type:2-尾款 */
            String type=request.getParameter("type");
            
            String txnAmt="";           //正式的金额
            String serviceOrderno="";   //退款批次号
            String refundMoney="";      //退款金额
            int refundMoneyInt=0;
            
            UserOrderFace userOrderFace=EnvironmentBean.getInstance().getBeanByBeanClass(UserOrderFace.class);
            UserOrder uo = userOrderFace.findUserOrder(orderno);
            UserAfterSaleFace userAfterSaleFace=EnvironmentBean.getInstance().getBeanByBeanClass(UserAfterSaleFace.class);
            AfterSaleService afterSaleService=userAfterSaleFace.getAfterSaleServic(uo.getServiceOrderno());
            refundMoneyInt=afterSaleService.getRefundMoney()!=null?afterSaleService.getRefundMoney().intValue()*100:afterSaleService.getMoney().intValue()*100;
            refundMoney=refundMoneyInt+"";
            serviceOrderno=CodeCreator.createCodeNum12(1)[0];
            if("0".equals(uo.getPayType())) {      //全款支付退款
                transaction_id=uo.getTradeNo();       
                txnAmt =Double.valueOf(uo.getMoney().doubleValue()*100).intValue()+"";
            }
            else if("1".equals(uo.getPayType())) { //定金支付
                OrderManyPayFace orderManyPayFace=EnvironmentBean.getInstance().getBeanByBeanClass(OrderManyPayFace.class);
                OrderManyPay orderManyPay1=orderManyPayFace.getOrderManyPay(orderno+"1");
                OrderManyPay orderManyPay2=orderManyPayFace.getOrderManyPay(orderno+"2");
                if("1".equals(type.trim())) {        //定金退款
                    transaction_id=orderManyPay1.getTradeNo();
                    txnAmt=Double.valueOf(orderManyPay1.getPaidMoney().doubleValue()*100).intValue()+"";
                    orderno=orderManyPay1.getPayOrderno();
                    if(refundMoneyInt>(orderManyPay1.getPaidMoney().intValue()*100)) {
                        refundMoney=orderManyPay1.getPaidMoney().intValue()*100+"";
                    }
                }
                else if("2".equals(type.trim())) {   //尾款退款
                    transaction_id=orderManyPay2.getTradeNo();
                    txnAmt=Double.valueOf(orderManyPay2.getPaidMoney().doubleValue()*100).intValue()+"";
                    orderno=orderManyPay2.getPayOrderno();
                    int toal=orderManyPay1.getPaidMoney().intValue()*100+orderManyPay2.getPaidMoney().intValue()*100;
                    if(refundMoneyInt>=toal) {                //退款金额不能多支付金额
                        refundMoney=orderManyPay2.getPaidMoney().intValue()*100+"";
                    }
                    else if(refundMoneyInt<toal && refundMoneyInt>(orderManyPay1.getPaidMoney().intValue()*100)) {
                        refundMoney=refundMoneyInt-(orderManyPay1.getPaidMoney().intValue()*100)+"";
                    }
                    else if(refundMoneyInt<=(orderManyPay1.getPaidMoney().intValue()*100)) {
                        refundMoney="0";
                    }
                }
            }
            SortedMap<String,String> parameters = new TreeMap<String,String>();
            parameters.put("transaction_id", transaction_id);             //微信订单号    
            parameters.put("out_refund_no", serviceOrderno);              //商户退款单号
            parameters.put("total_fee", txnAmt);                              //交易金额,单位分,不要带小数点          
            parameters.put("refund_fee", refundMoney);                    //退款金额
            parameters.put("appid", Configure.appID);
            parameters.put("mch_id", Configure.mchID);
            parameters.put("nonce_str",Configure.getNonceStr());
            parameters.put("refund_account","REFUND_SOURCE_RECHARGE_FUNDS");
            String sign = PayCommonUtil.createSign("UTF-8", parameters,Configure.key);  
            parameters.put("sign", sign);
            String requestXML = PayCommonUtil.getRequestXml(parameters);
            String resXml = HttpUtil.clientCustomSSLCall(Configure.REFUND_API, Configure.mchID,requestXML);
            Map map = XMLUtil.doXMLParse(resXml);
            
            String result_code =(String)map.get("result_code");
            String err_code_des=(String)map.get("err_code_des");
            String refund_id=(String)map.get("refund_id");
            
            OrderPayRefundLogFace orderPayRefundLogFace=EnvironmentBean.getInstance().getBeanByBeanClass(OrderPayRefundLogFace.class);
            orderPayRefundLogFace.saveOrderRefundLog(transaction_id, "微信", parameters.toString()+resXml, "");
            
            if("SUCCESS".equals(result_code)) {
                userAfterSaleFace.flushOrderStateSequence(transaction_id,refund_id);
                userOrderFace.saveBatchNoSingle(orderno, serviceOrderno);     //保存退款批次号
                response.sendRedirect("/IdoManage/UserOtoOrderAction!queryUserOrder.action");
            }
            else{
                out.println(err_code_des);
            }
        }
        catch(Exception err) {
            err.printStackTrace();
            try {
                OrderPayRefundLogFace orderPayRefundLogFace=EnvironmentBean.getInstance().getBeanByBeanClass(OrderPayRefundLogFace.class);
                orderPayRefundLogFace.saveOrderRefundLog(transaction_id, "微信","", ExceptionOut.writeException(err));
            }
            catch(Exception error) {
                error.printStackTrace();
            }
        }
    %>





  • 相关阅读:
    Intouch 制作自定义登录弹窗
    ifix vba 读取计算机中的txt文件,截取字符串显示
    intouch 开发源程序加密方法
    语音报警系统说明
    ifix历史数据(H04/H08/H24)转换为CSV文件导出
    ifix 自动化(Automation)错误弹窗的解决方案
    云平台制作(二)-平台展示
    knudson hypothesis 二次突变假说
    纯合子,杂合子,杂合性缺失
    zero-base coordinate 和one-base coordinate
  • 原文地址:https://www.cnblogs.com/xiaoxiaojuan/p/7607900.html
Copyright © 2011-2022 走看看