微信開發之微信支付(商戶平臺提供的方式)

愛吃素的灰太狼發表於2016-09-11

注意的是
1、支付方法的路徑必須在支付授權目錄中設定的路徑下邊 否則報錯
2、用於生成預支付id的簽名引數必須和提交到微信的商品引數一致否則報錯。
3、簽名的問題:在使用商戶平臺提供的支付方式支付的時候只需要兩個簽名 得到預支付id需要的簽名 和 支付時使用的簽名, 如果使用公眾平臺提供的jssdk當中的支付方式需要三種簽名 驗證支付需要的簽名、 得到預支付id需要的簽名、 支付時使用的簽名

微信支付的流程:
得到簽名—>得到預支付id—>得到預支付id—>得到支付簽名—->支付

// 準備字串獲得
    public static String create_nonce_str() {
        String uuid = UUID.randomUUID().toString();
        uuid = uuid.replace("-", "");
        if (uuid.length() > 32) {
            uuid = uuid.substring(0, 32);
        }
        return uuid;
    }
/**
     * 微信簽名 建立md5摘要,規則是:按引數名稱a-z排序,遇到空值的引數不參加簽名。
     */
    public static String createSign(SortedMap<String, String> packageParams) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();// 所有參與傳參的引數按照accsii排序(升序)
        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 + "&");
            }
        }
        String Key = WinxinFinalValue.API_SECRET;
        sb.append("key=" + Key);

        System.out.println("md5 sb:" + sb);
        String sign = MD5Utils.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
        System.out.println("packge簽名:" + sign);
        return sign;
    }
package com.team.weixin.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.team.weixin.model.Pay;
import com.team.weixin.model.ReceiveXmlEntity;
public class SerializeXmlUtil {
    /**
     * @description 將xml字串轉換成map
     * @param xml
     * @return Map
     */
    /**
     * 解析微信xml訊息
     * 
     * @param strXml
     * @return
     */
    public static Pay getMsgEntity(String strXml) {
        System.out.println("99999999999999999999999999999");
        System.out.println(strXml);
        System.out.println("99999999999999999999999999999");

        Pay msg = null;
        try {
            if (strXml.length() <= 0 || strXml == null)
                return null;

            // 將字串轉化為XML文件物件
            Document document = DocumentHelper.parseText(strXml);
            // 獲得文件的根節點
            Element root = document.getRootElement();
            // 遍歷根節點下所有子節點
            Iterator<?> iter = root.elementIterator();

            // 遍歷所有結點
            msg = new Pay();
            // 利用反射機制,呼叫set方法
            // 獲取該實體的元型別
            System.out.println("在這裡");
            Class<?> c = Class.forName("com.team.weixin.model.Pay");
            System.out.println("在這裡55");
            msg = (Pay) c.newInstance();// 建立這個實體的物件

            while (iter.hasNext()) {
                Element ele = (Element) iter.next();
                // 獲取set方法中的引數欄位(實體類的屬性)
                Field field = c.getDeclaredField(ele.getName());
                // 獲取set方法,field.getType())獲取它的引數資料型別


                String first = ele.getName().substring(0, 1).toUpperCase();
                String rest = ele.getName().substring(1, ele.getName().length());
                String newStr = new StringBuffer(first).append(rest).toString();
                System.out.println("set" +newStr+","+field.getType());


                Method method = c.getDeclaredMethod("set" +newStr, field.getType());
                method.invoke(msg, ele.getText());


                // 呼叫set方法

            }
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println("xml 格式異常: " + strXml);
            e.printStackTrace();
        }
        return msg;
    }

}
// 得到prepay_id
    public static String getPayNo(String url, String xmlParam) {
        DefaultHttpClient client = new DefaultHttpClient();
        HttpPost httpost = new HttpPost(url);
        client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
        String prepay_id = "";
        String nustr = "";
        try {
            httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
            HttpResponse response = client.execute(httpost);
            String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
            Map<String, Object> dataMap = new HashMap<String, Object>();

            System.out.println(jsonStr);

            prepay_id = SerializeXmlUtil.getMsgEntity(jsonStr.toString()).getPrepay_id();
            nustr = SerializeXmlUtil.getMsgEntity(jsonStr.toString()).getNonce_str();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return prepay_id + "," + nustr;
    }
// 呼叫預支付訂單
    public static WeixinUnifiedOrder getUnifiedOrder(WeixinUnifiedOrder order, String openid)
            throws UnknownHostException {

        openid = "oJBwTwTjJTp4BNHlJC38c4Xczjjk";
        String nonce_str = WeixinUtil.create_nonce_str();
        String notify_url = "www.shujb.com" + "/weixingroup/weixin/paySuccess";
        String spbill_create_ip = InetAddress.getLocalHost().getHostAddress().toString();// 獲得本機IP


        order.setAppid("appid 由商戶提供");

        order.setMch_id("商戶id(商戶平臺提供) 由商戶提供");
        order.setNonce_str(nonce_str);
        order.setNotify_url(notify_url);
        order.setSpbill_create_ip(spbill_create_ip);
        order.setTrade_type("JSAPI");

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", order.getAppid());
        packageParams.put("mch_id", order.getMch_id());
        packageParams.put("device_info", "WEB");
        packageParams.put("nonce_str", order.getNonce_str());

        packageParams.put("body", order.getBody());
        packageParams.put("out_trade_no", order.getOut_trade_no());
        packageParams.put("total_fee", order.getTotal_fee());
        packageParams.put("spbill_create_ip", order.getSpbill_create_ip());
        packageParams.put("notify_url", order.getNotify_url());
        packageParams.put("trade_type", order.getTrade_type());
        /* packageParams.put("attach", order.getAttach()); */
        packageParams.put("openid", openid);

        String sign = createSign(packageParams);// 建立用於獲得預支付id的簽名

        String xml = "<xml>" + "<appid>" + order.getAppid() + "</appid>" + "<mch_id>" + order.getMch_id() + "</mch_id>"
                + "<device_info><![CDATA[WEB]]></device_info>" + "<nonce_str>" + order.getNonce_str() + "</nonce_str>"
                + "<sign><![CDATA[" + sign + "]]></sign>" + "<body>" + order.getBody() + "</body>" + "<out_trade_no>"
                + order.getOut_trade_no() + "</out_trade_no>" + "<total_fee>" + order.getTotal_fee() + "</total_fee>"
                + "<spbill_create_ip>" + order.getSpbill_create_ip() + "</spbill_create_ip>" + "<notify_url>"
                + order.getNotify_url() + "</notify_url>" + "<trade_type>" + order.getTrade_type() + "</trade_type>" +
                /* "<attach>" + order.getAttach() + "</attach>"+ */
                "<openid>" + openid + "</openid>" + "</xml>";

        System.out.println(xml);

        // 得到prepay_id
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        String prepay_id = "";
        try {
            String[] pi = getPayNo(createOrderURL, xml).split(",");
            prepay_id = pi[0];
            order.setPrepay_id(prepay_id);
            if (prepay_id.equals("")) {
                System.out.println("統一支付介面獲取預支付訂單出錯");
            }
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return order;
    }
這裡是controller中的呼叫統一下單介面
//支付模組
    //支付
    @RequestMapping("/to_pay")
    public String to_pay(@RequestParam("money") String money , HttpServletRequest request,HttpSession seeion,Model model){
    //獲得訂單號
        //獲得
        WeixinUnifiedOrder order = new WeixinUnifiedOrder();

        order.setAttach("附加資料,在查詢API和支付通知中原樣返回,該欄位主要用於商戶攜帶訂單的自定義資料");//附加訊息
        order.setTotal_fee("1");//金額
        order.setBody("羅輯思維-圖書");//
        order.setOut_trade_no(primaryKeyFactory.generatePrimaryKey()+"");

        try {
            order = WeixinUtil.getUnifiedOrder(order, seeion.getAttribute("openid")+"");

            //生成支付簽名
            String timestamp = WeixinUtil.create_timestamp();
            String nonceStr =WeixinUtil.create_nonce_str();
            String prepay_id = "prepay_id="+order.getPrepay_id();

            //建立支付用的資料
            SortedMap<String, String> finalpackage = new TreeMap<String, String>();
            finalpackage.put("appId", WinxinFinalValue.AppID);  
            finalpackage.put("timeStamp", timestamp);  
            finalpackage.put("nonceStr", nonceStr);  
            finalpackage.put("package", prepay_id);  
            finalpackage.put("signType", "MD5");

            String paySign =  WeixinUtil.createSign(finalpackage);//建立支付用的簽名

            PayReg payReg = new PayReg();
            payReg.setAppid(WinxinFinalValue.AppID);
            payReg.setTimeStamp(timestamp);
            payReg.setNonceStr(nonceStr);
            payReg.setPackages("prepay_id="+order.getPrepay_id());
            payReg.setSignType("MD5");
            payReg.setSign(paySign);


            model.addAttribute("obj",payReg);
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }



        return "/dataTreasure/pay";
    }

相關文章