微信支付——沙箱調試環境getsignkey方法秘鑰獲取及常見問題說明


 

官方文檔 :https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=23_1

 

微信支付PC二維碼支付:https://www.cnblogs.com/pxblog/p/10542917.html

 

公眾號支付:https://www.cnblogs.com/pxblog/p/12815705.html

 

 

在做沙箱測試的時候,微信支付里面的金額固定的,其他金額是無效的。需要按照文檔來輸入。金額必須是(1.01)

 

<xml>
  <return_code><![CDATA[FAIL]]></return_code>
  <return_msg><![CDATA[沙箱支付金額(1)無效,請檢查需要驗收的case]]></return_msg>
</xml>

 

 

 

這里需要用到沙箱秘鑰來替換簽名中的key,同樣驗簽的時候也是同樣用沙箱秘鑰獲取簽名,沙箱秘鑰的獲取方法

 

微信支付仿真測試系統(后簡稱仿真系統)的簡化原理圖。仿真系統的API協議與正式API完全相同(API接口文檔)。商戶開發者只需將正式API的調用URL增加一層sandboxnew路徑,即可對接到仿真系統。

例如,付款碼支付URL:https://api.mch.weixin.qq.com/pay/micropay

變更為:https://api.mch.weixin.qq.com/sandboxnew/pay/micropay。

仿真系統與生產環境完全獨立,包括存儲層。商戶在仿真系統所做的所有交易(如下單、支付、查詢)均為無資金流的假數據,即:用戶無需真實扣款,商戶也不會有資金入賬。代金券同理,沙箱環境中無需商戶真實制券與發券,亦不會出現真實扣券情況。驗收仿真測試系統的API驗簽密鑰需從API獲取:

 

支付的接口地址改為:

https://api2.mch.weixin.qq.com/sandboxnew/pay/unifiedorder

 

 

 

<xml>
  <return_code><![CDATA[FAIL]]></return_code>
  <return_msg><![CDATA[沙箱驗證簽名失敗,請確認沙箱簽名key是否正確(通過getsignkey調用生成)]]></return_msg>
</xml>

 

 

 

需要引入

commons-lang-2.4.jar、jdom-1.1.3.jar

 

getSignKeyUtils.java 工具類

 

package com.jetcms.weixinpay;

import org.apache.commons.lang.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.util.*;

public class getSignKeyUtils {


    /**
     *  獲取微信支付沙箱API驗簽密鑰 (調用該方法生成)
     * @param nonce_str 隨機字符串 生成方法:RandomStringUtils.random(10, N62_CHARS);
     * @param mchId  正式的商戶號
     * @param apiKey  正式的密鑰
     * @return
     */
    public static String getSignKey(String nonce_str,String mchId,String apiKey) {
        Map<String, String> param = new HashMap<String, String>();
        param.put("mch_id", mchId);//需要真實商戶號
        param.put("nonce_str", nonce_str);//隨機字符
        String sign = createSign(param, apiKey);//通過SDK生成簽名其中API_KEY為商戶對應的真實密鑰
        param.put("sign", sign);
        String xml = assembParamToXml(param);//將map轉換為xml格式
        String url = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey";//沙箱密鑰獲取api
        Map<String, String> param1 = new HashMap<String, String>();
        String resXml = post(url, xml);
        try {
            if (StringUtils.isNotBlank(resXml)) {
                param1 = parseXMLToMap(resXml);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String key = param1.get("sandbox_signkey");
        return key;
    }


    /**
     * 微信支付簽名sign
     * @param param
     * @param key
     * @return
     */
    @SuppressWarnings("unchecked")
    public static String createSign(Map<String, String> param,String key){
        //簽名步驟一:按字典排序參數
        List list=new ArrayList(param.keySet());
        Object[] ary =list.toArray();
        Arrays.sort(ary);
        list=Arrays.asList(ary);
        String str="";
        for(int i=0;i<list.size();i++){
            str+=list.get(i)+"="+param.get(list.get(i)+"")+"&";
        }
        //簽名步驟二:加上key
        str+="key="+key;
        //步驟三:加密並大寫
        str= MD5Encode(str,"utf-8").toUpperCase();
        return str;
    }

    /**
     * 將需要傳遞給微信的參數轉成xml格式
     * @param parameters
     * @return
     */
    public static String assembParamToXml(Map<String,String> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set<String> es = parameters.keySet();
        List<Object> list=new ArrayList<Object>(es);
        Object[] ary =list.toArray();
        Arrays.sort(ary);
        list=Arrays.asList(ary);
        Iterator<Object> it = list.iterator();
        while(it.hasNext()) {
            String key =  (String) it.next();
            String val=(String) parameters.get(key);
            if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {
                sb.append("<"+key+">"+"<![CDATA["+val+"]]></"+key+">");
            }else {
                sb.append("<"+key+">"+val+"</"+key+">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    public static String post(String urlStr,String xmlInfo) {
        String line1 = "";
        try {
            URL url = new URL(urlStr);
            URLConnection con = url.openConnection();
            con.setDoOutput(true);
            con.setRequestProperty("Cache-Control", "no-cache");
            con.setRequestProperty("Content-Type", "text/xml");

            OutputStreamWriter out = new OutputStreamWriter(con
                    .getOutputStream());
            out.write(new String(xmlInfo.getBytes("utf-8")));
            out.flush();
            out.close();
            BufferedReader br = new BufferedReader(new InputStreamReader(con
                    .getInputStream()));
            String line = "";
            for (line = br.readLine(); line != null; line = br.readLine()) {
                line1+=line;
            }
            return new String(line1.getBytes(),"utf-8");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 解析xml,返回第一級元素鍵值對。如果第一級元素有子節點,則此節點的值是子節點的xml數據。
     * @param strxml
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static Map parseXMLToMap(String strxml) throws JDOMException, IOException {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
        if(null == strxml || "".equals(strxml)) {
            return null;
        }
        Map m = new HashMap();
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while(it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if(children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v =getChildrenText(children);
            }
            m.put(k, v);
        }
        //關閉流
        in.close();
        return m;
    }

    /**
     * 62個字母和數字,含大小寫
     */
    public static final char[] N62_CHARS = {'0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
            'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
            'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
            'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
            'x', 'y', 'z'};


    public static String MD5Encode(String origin,String charsetName){
        String resultString=null;
        try{
            resultString=new String(origin);
            MessageDigest md=MessageDigest.getInstance("MD5");
            if(StringUtils.isBlank(charsetName)){
                resultString=byteArrayToHexString(md.digest(resultString.getBytes()));
            }else{
                resultString=byteArrayToHexString(md.digest(resultString.getBytes(charsetName)));
            }
        }catch(Exception e){

        }
        return resultString;
    }

    public static String byteArrayToHexString(byte b[]){
        StringBuffer resultSb=new StringBuffer();
        for(int i=0;i<b.length;i++){
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }


    /**
     * 獲取子結點的xml
     * @param children
     * @return String
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if(!children.isEmpty()) {
            Iterator it = children.iterator();
            while(it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if(!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        return sb.toString();
    }

    public static String byteToHexString(byte b){
        int n=b;
        if(n<0){
            n+=256;
        }
        int d1=n/16;
        int d2=n%16;
        return hexDigits[d1]+hexDigits[d2];
    }

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

 

 

 這個在進入支付操作頁面的時候就會進行支付回調,所以不用進行掃碼支付操作!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM