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

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

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

二、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("\r\n");  
            }  
            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{width: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; width: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();
        }
    }
%>





posted on 2017-09-28 18:06  爱上码  阅读(863)  评论(0编辑  收藏  举报