封装常用工具类CommonUtils和WXpayUtils(10-11)

从微信开发者文档获取部分代码 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1
1、CommonUtils包含方法 md5,uuid等
        //生成 uuid, 即用来标识一笔单,也用做 nonce_str
        public static String generateUUID() {
            return UUID.randomUUID().toString().replaceAll("-", "")
                    .substring(0, 32);
        }
​
        //MD5工具类
        public static String MD5(String data)  {
            try {
                java.security.MessageDigest md = MessageDigest.getInstance("MD5");
                byte[] array = md.digest(data.getBytes("UTF-8"));
                StringBuilder sb = new StringBuilder();
                for (byte item : array) {
                    sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
                }
                return sb.toString().toUpperCase();
            } catch (Exception exception) {
            }
            return null;
​
        }
​
2、WXPayUtil包含方法 xmlToMap,mapToXml,createSign,isCorrectPaySign

 

​package net.gaven.video.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;


/**
 * @program: video
 * @description: 微信支付的工具类
 *               xml----map
 *               map----xml
 *                 生成签名
 *
 *
 *
 * @author: Mr.lee
 * @create: 2020-02-25 21:42
 **/
public class WXPayUtil {
    /**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            } catch (Exception ex) {
                // do nothing
            }
            return data;
        } catch (Exception ex) {
            WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
            throw ex;
        }

    }
    /**
     * 日志
     * @return
     */
    public static Logger getLogger() {
        org.slf4j.Logger logger = LoggerFactory.getLogger("wxpay java sdk");
        return logger;
    }

    /**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key: data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
        try {
            writer.close();
        }
        catch (Exception ex) {
        }
        return output;
    }

  /**
     * 生成签名
     * stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
     * stringSignTemp=stringA+"&key=192006250b4c09247ec02edce69f6a2d" //注:key为商户平台设置的密钥key
     *
     * sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" //注:MD5签名方式
     * @param sortedMap  传入的对象信息
     * @param key        传入的密钥
     * @return
     */

    public static String createSign(SortedMap<String,String> sortedMap, String key){

        StringBuilder sb=new StringBuilder();

        Set<Map.Entry<String, String>> entries = sortedMap.entrySet();
        Iterator<Map.Entry<String, String>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, String> next = iterator.next();
            if (null!=next.getValue()&&""!=next.getValue()&&"key"!=next.getKey()&&"singn"!=next.getKey()){
                /**
                 * 所有条件都满足才进行拼接
                 * 空属性不进行签名  (wx文档)
                 */
                sb.append(next.getKey()+"="+next.getValue()+"&");
            }



        }
        //拼接密钥
        sb.append("key=").append(key);
        String stmpKey = sb.toString();
        String sign = CommonUtils.MD5(stmpKey).toUpperCase();
        return sign;


    }

 /**
     * 校验sign  与生成sign步骤相同,只是把传来的sign与计算的sign进行比较
     * @param sortedMap
     * @param key
     * @return
     */
    public static boolean isCreateSign(SortedMap<String,String> sortedMap,String key){




        String sign = createSign(sortedMap, key);
        String beCheckedSign = sortedMap.get("sign");
        return beCheckedSign.equals(sign);


    }




}

https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=4_3

信支付下单API接口和签名开发

下单接口开发和微信支付签名生成开发,并设置微信回调地址(用于用户微信支付成功后,通知我们服务器完成更新订单状态)

1、统一下单参数需要微信签名,签名规则如下
            文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3
            签名生成的通用步骤如下:
​
            第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
​
            第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
​
            参数
                SortedMap<String, String> params = new TreeMap<>();  
                params.put("appid", wxPayConfig.getAppId());  //公众账号ID  
                params.put("mch_id", wxPayConfig.getMchId());  //商户号    
                params.put("nonce_str", CommonUtil.generateNonceStr());  //随机字符串    
                params.put("body", videoOrder.getVideoTitle());  // 商品描述    
                params.put("out_trade_no", videoOrder.getOutTradeNo()); //商户订单号,商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一
                params.put("total_fee", videoOrder.getTotalFee().toString());  //标价金额   分
                params.put("spbill_create_ip", videoOrder.getIp());  
                params.put("notify_url", wxPayConfig.getDomain()+wxPayConfig.getCallbackUrl()); //通知地址    
                params.put("trade_type", "NATIVE");  //交易类型 JSAPI 公众号支付 NATIVE 扫码支付 APP APP支付
                
                //生成签名
                String sign = WXPayUtil.createSign(params, wxPayConfig.getKey());
                params.put("sign", sign); 
                //参数转xml
                String requestXMl = WXPayUtil.mapToXml(params);
​
                生成签名后,通过工具去校验
                https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=20_1
​
        2、测试地址:localhost:8081/api/v1/order/add?video_id=2
​
​
        3、课程测试签名结果
            
            sign: 85118C91DFCB052FB02AC183BF3D57D2
​
            <?xml version="1.0" encoding="UTF-8" standalone="no"?>
            <xml>
            <appid>wx5beac15ca207cdd40c</appid>
            <body>高级教程666</body>
            <mch_id>1503808832</mch_id>
            <nonce_str>b11446ae6fc14ddb89c9bc5fa291dc43</nonce_str>
            <notify_url>16web.tunnel.qydev.com/pub/api/v1/wechat/order/callback1</notify_url>
            <out_trade_no>2a273e4b9f8c453380a08c7930fc3b6b</out_trade_no>
            <sign>85118C91DFCB052FB02AC183BF3D57D2</sign>
            <spbill_create_ip>0:0:0:0:0:0:0:1</spbill_create_ip>
            <total_fee>500</total_fee>
            <trade_type>NATIVE</trade_type>
            </xml>

调用微信统一下单接口实战

调用微信统一下单接口实战,发送post请求,并获取响应转成map,获取交易会话的二维码链接code_url

1、配置统一下单接口
        2、发送请求验证
            微信统一下单响应
                <xml><return_code><![CDATA[SUCCESS]]></return_code>
                <return_msg><![CDATA[OK]]></return_msg>
                <appid><![CDATA[wx5beac15ca207c40c]]></appid>
                <mch_id><![CDATA[1503809911]]></mch_id>
                <nonce_str><![CDATA[Go5gDC2CYL5HvizG]]></nonce_str>
                <sign><![CDATA[BC62592B9A94F5C914FAAD93ADE7662B]]></sign>
                <result_code><![CDATA[SUCCESS]]></result_code>
                <prepay_id><![CDATA[wx262207318328044f75c9ebec2216783076]]></prepay_id>
                <trade_type><![CDATA[NATIVE]]></trade_type>
                <code_url><![CDATA[weixin://wxpay/bizpayurl?pr=hFq9fX6]]></code_url>
                </xml>
        3、获取code_url
​
            遇到问题,根据错误码解决
            https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智达教育‍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值