Java集成微信小程序支付和退款

微信支付文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter1_1_1.shtml

微信退款文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml

1、微信小程序支付

前提

在进行对接微信支付之前,我们首先需要将以下几点准备好:

  • 申请APPID
  • 申请商户号
  • 小程序开通微信支付,绑定已经申请好的商户号。登录小程序后台(mp.weixin.qq.com)。点击左侧导航栏的微信支付,在页面中进行开通。(开通申请要求小程序已发布上线)
注意事项
  • appid必须为最后拉起收银台的小程序appid;
  • mch_id为和appid成对绑定的支付商户号,收款资金会进入该商户号;
  • trade_type请填写JSAPI;
  • openid为appid对应的用户标识,即使用wx.login接口获得的openid。

本文主要记录后端步骤,前端步骤无非就是获取后端数据然后调用提供的API进行支付,大家可自行查看官方文档。

1. 支付业务流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JNr92RdW-1683010524685)(E:\PRD\Images\image-20230502113439837.png)]

2. 导入依赖
implementation group: 'com.github.wechatpay-apiv3', name: 'wechatpay-apache-httpclient', version: '0.4.7'
implementation group: 'com.github.wxpay',name: 'wxpay-sdk',version: '0.0.3'
3. 编写相关工具类
解析Xml工具类
/**
 * @author zzw
 * @description TODO 解析xml工具类
 * @date 2023-04-28 14:02
 */
public class XMLUtil {
   
     

	/**  
     * 瑙f瀽xml,杩斿洖绗竴绾у厓绱犻敭鍊煎銆傚鏋滅锟�?绾у厓绱犳湁瀛愯妭鐐癸紝鍒欐鑺傜偣鐨勶拷?锟芥槸瀛愯妭鐐圭殑xml鏁版嵁锟�?  
     * @param strxml  
     * @author Lyp
     * @return  
     * @throws JDOMException  
     * @throws IOException  
     */    
    public static Map doXMLParse(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 = XMLUtil.getChildrenText(children);    
            }    

            m.put(k, v);    
        }    

        //鍏抽棴锟�?    
        in.close();    

        return m;    
    }    
    
    /**  
     * 鑾峰彇瀛愮粨鐐圭殑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(XMLUtil.getChildrenText(list));    
                }    
                sb.append(value);    
                sb.append("</" + name + ">");    
            }    
        }    

        return sb.toString();    
    }
}  

微信支付工具类

/**
 * @author zzw
 * @description TODO 微信支付工具类
 * @date 2023-04-28 14:02
 */
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>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.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.getTagName());
                }
            }
            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;
        }

	}
   
   /**
     * ??ap?????ML?????????
     * @param data Map??????
     * @return XML?????????
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
   
   
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
        org.w3c.dom.Document document = documentBuilder.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;
    }
    
    /**
     * ?????? sign ?? XML ????????
     * @param data Map??????
     * @param key API???
     * @return ???sign?????ML
     */
    public static String generateSignedXml(final Map<String, String> data, String key) throws Exception {
   
   
        return generateSignedXml(data, key, SignType.MD5);
    }

    /**
     * ?????? sign ?? XML ????????
     * @param data Map??????
     * @param key API???
     * @param signType ??????
     * @return ???sign?????ML
     */
    public static String generateSignedXml(final Map<String, String> data, String key, SignType signType) throws Exception {
   
   
        String sign = generateSignature(data, key, signType);
        data.put(WXPayConstants.FIELD_SIGN, sign);
        return mapToXml(data);
    }

    /**
     * ????????????
     *
     * @param xmlStr XML??????
     * @param key API???
     * @return ?????????
     * @throws Exception
     */
    public static boolean isSignatureValid(String xmlStr, String key) throws Exception {
   
   
        Map<String, String> data = xmlToMap(xmlStr);
        if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) {
   
   
            return false;
        }
        String sign = data.get(WXPayConstants.FIELD_SIGN);
        return generateSignature(data, key).equals(sign);
    }

    /**
     * ????????????????????ign???????????alse?????D5?????
     *
     * @param data Map??????
     * @param key API???
     * @return ?????????
     * @throws Exception
     */
    public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {
   
   
        return isSignatureValid(data, key, SignType.MD5);
    }

    /**
     * ????????????????????ign???????????alse??
     *
     * @param data Map??????
     * @param key API???
     * @param signType ??????
     * @return ?????????
     * @throws Exception
     */
    public static boolean isSignatureValid(
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值