微信支付——沙箱调试环境getsignkey方法秘钥获取及常见问题说明

微信支付——沙箱调试环境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)

这里需要用到沙箱秘钥来替换签名中的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

需要引入

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 param = new HashMap();

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 param1 = new HashMap();

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 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

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 parameters){

StringBuffer sb = new StringBuffer();

sb.append("");

Set es = parameters.keySet();

List list=new ArrayList(es);

Object[] ary =list.toArray();

Arrays.sort(ary);

list=Arrays.asList(ary);

Iterator 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+">"+"");

}else {

sb.append("<"+key+">"+val+"");

}

}

sb.append("");

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

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("");

}

}

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" };

}

这个在进入支付操作页面的时候就会进行支付回调,所以不用进行扫码支付操作!!!

相关推荐

邸郃遗址
365bet亚洲版体育在线

邸郃遗址

⌛ 10-18 👁️ 5274