2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 微信公众号支付流程解读及支付签名验证方法

微信公众号支付流程解读及支付签名验证方法

时间:2023-06-14 14:50:19

相关推荐

微信公众号支付流程解读及支付签名验证方法

微信公众号支付大致分为以下几步:

1.获取openID:微信公众号支付一个重要的参数就是openID,此步骤可以查阅相关文档

2.获取支付相关参数:appid:公众账号ID,mch_id:商户号,nonce_str:随机字符串,sign_type:签名类型,out_trade_no:商户订单号,total_fee:标价金额(交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数),spbill_create_ip:终端IP,notify_url:通知地址,trade_type:交易类型,openid:用户标识,sign:签名

TreeMap paramMap = new TreeMap();

paramMap.put("appid", PaymentConst.WECHAT_APPID);//公众账号ID

paramMap.put("mch_id", PaymentConst.WECHAT_MCHID);//商户号

paramMap.put("nonce_str", Util.getRandomString(30, null));//随机字符串

paramMap.put("sign_type", PaymentConst.WECHAT_SIGNTYPE);//签名类型

//paramMap.put("body", "爱检查医疗套餐支付");//商品描述

paramMap.put("body", "Melical Fee");//商品描述

paramMap.put("out_trade_no", orderMain.getNumber());//商户订单号

//交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数。

paramMap.put("total_fee", (int)(orderMain.getTotalamount()*100));//标价金额

paramMap.put("spbill_create_ip", Util.getIpAddr(request));//终端IP

paramMap.put("notify_url", weChatNotifyUrl);//通知地址

paramMap.put("trade_type", PaymentConst.WECHAT_TRADETYPE_JSAPI);//交易类型

paramMap.put("openid", openid);//用户标识

paramMap.put("sign",Signature.createSign("UTF-8", paramMap));//签名

3.签名算法:

public static String createSign(String characterEncoding,SortedMap<String,Object> parameters){

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

Object v = entry.getValue();

if(null != v && !"".equals(v)

&& !"sign".equals(k) && !"key".equals(k)) {

sb.append(k + "=" + v + "&");

}

}

sb.append("key=" + PaymentConst.WECHAT_KEY);

System.out.println("签名:"+sb.toString());

String sign =MD5.GetMD5Code(sb.toString()).toUpperCase();

return sign;

}

4.请求:

String response = HttpClientUtil.post(PaymentConst.wechatPayUrl,new String( XMLUtils.simpleMapToXml(paramMap).getBytes(), "UTF-8"));

5.XMLUtils.simpleMapToXml 方法:

public static String simpleMapToXml(Map<String, Object> map){

StringBuilder xmlString = new StringBuilder();

xmlString.append("<?xml version='1.0' encoding='UTF-8'?>").append(RT);

xmlString.append("<xml>").append(RT);

for (Map.Entry<String, Object> entry : map.entrySet()){

String key = entry.getKey();

xmlString.append("<" + key + ">" + entry.getValue() + "</" + key + ">").append(RT);

}

xmlString.append("</xml>").append(RT);

return xmlString.toString();

}

6.返回预支付结果,二次签名

System.out.println("预支付返回结果:"+response);

Map<String, String> resultParams = getWechatXmlToMap(response);

if (PaymentConst.WECHAT_STATUSCODE_FAIL.equals(resultParams.get("return_code"))){

throw new MessageException(resultParams.get("return_msg"));

}else{

if (PaymentConst.WECHAT_STATUSCODE_FAIL.equals(resultParams.get("result_code"))){

throw new MessageException(resultParams.get("return_msg"));

}else{

String prepay_id = resultParams.get("prepay_id");

TreeMap paramMap1 = new TreeMap();

paramMap1.put("appId", paramMap.get("appid"));//公众账号ID

String s = String.valueOf(Util.getSecond());

paramMap1.put("timeStamp", s);

paramMap1.put("nonceStr", Util.getRandomString(30, null));

paramMap1.put("package", "prepay_id="+prepay_id);//签名类型

paramMap1.put("signType", paramMap.get("sign_type"));//签名类型

paramMap1.put("sign1",Signature.createSign("UTF-8", paramMap1));//签名

LOGGER.info("最终签名:"+paramMap1.get("sign1"));

//生成前台支付需要的数据

Map<String, Object> map = new HashMap<String, Object>();

map.put("appId", paramMap.get("appid"));

String s1 = String.valueOf(Util.getSecond());

map.put("timeStamp", s1);

map.put("nonceStr", Util.getRandomString(30, null));

map.put("package", "prepay_id="+prepay_id);

map.put("signType", paramMap.get("sign_type"));

map.put("paySign", paramMap1.get("sign1"));

System.out.println("tttttttttttttttttttttttttttttt9999999999999tttttttttttttttttttttttttttttttttttttt");

result.setT(map);

}

}

7./**

* @Title:getWechatXmlToMap

* @Description:微信返回xml结果转为Map

* @param result

* @return

* @throws Exception Map<String,String> 返回类型

*/

private Map<String, String> getWechatXmlToMap(String result) throws Exception{

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = factory.newSAXParser();

XMLHandler xmlHandler = new XMLHandler();

parser.parse(new ByteArrayInputStream(result.getBytes("UTF-8")), xmlHandler);

return xmlHandler.getParams();

}

8.授权成功回调方法

/**

* @Title:weixinPayBack

* @Description:支付回调(微信支付)

* @param request

* @return String 返回类型

*/

@RequestMapping(value="/weiXinPayNotify")

public String weixinPayBack(HttpServletRequest request){

try {

InputStream inStream = request.getInputStream();

ByteArrayOutputStream outSteam = new ByteArrayOutputStream();

byte[] buffer = new byte[1024];

int len = 0;

while ((len = inStream.read(buffer)) != -1) {

outSteam.write(buffer, 0, len);

}

outSteam.close();

inStream.close();

String resultStr = new String(outSteam.toByteArray(),"utf-8");

System.out.println("微信支付的回调:"+resultStr);

Map<String, String> resultMap = getWechatXmlToMap(resultStr);

String return_code = resultMap.get("return_code");

if("SUCCESS".equals(return_code)){

//检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改

if(!Signature.checkIsSignValidFromResponseString(resultStr)){

throw new MessageException("微信回调参数签名不合法");

}

String result_code = resultMap.get("result_code");

if("SUCCESS".equals(result_code)){

//支付成功的业务逻辑

//通知微信.异步确认成功.必写.不然微信会一直通知后台.八次之后就认为交易失败了.

return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

}

}

} catch (Exception e) {

LOGGER.error(e.getMessage() ,e);

}

return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>";

}

9.签名错误测试方法:

https://pay./wiki/doc/api/native.php?chapter=20_1

填入如下参数

点击生成签名:出现如下xml

复制xml:

重新选择xml校验方式

生成签名出现下面的提示,校验通过,说明签名正确

其他签名错误情况检查参数是否正确

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。