2022-07-26:微信支付

微信支付接口

方法1>>>>>>>>>>>>>>>>>>>>

public Map UnifiedOrder(String prepayId)throws Exception {

String appid =wxParameter.getAppid();

        Date time =new Date();

        String timeStamp = String.valueOf(time.getTime() /1000);

        String SYMBOLS ="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

        Random RANDOM =new SecureRandom();

        char[] nonceChars =new char[32];

        for (int index =0; index < nonceChars.length; ++index) {

nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));

        }

String nonce =new String(nonceChars);

        String signType ="MD5";

        Map map =new HashMap<>();

        map.put("appId", appid);

        map.put("timeStamp", timeStamp);

        map.put("nonceStr", nonce);

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

        map.put("signType", signType);

        String paySign = WXPayUtil.generateSignature(map, wxParameter.getApikey());

        map.put("paySign", paySign);

        return map;

    }

方法二>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    public String getprepay_id(BigDecimal price, String str, String openid, String notify_url)throws Exception {

String appid =wxParameter.getAppid();

        String mch_id =wxParameter.getMchid();

        String SYMBOLS ="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

        Random RANDOM =new SecureRandom();

        char[] nonceChars =new char[32];

        for (int index =0; index < nonceChars.length; ++index) {

nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));

        }

String nonce_str =new String(nonceChars);//随机字符串

        String body ="充值";

        String out_trade_no = str;//商品订单号

        String total_fee = price.stripTrailingZeros().toPlainString();

        String spbill_create_ip ="127.0.0.1";

        String trade_type ="JSAPI";

//        String notify_url = wxParameter.getDomain() + "/api/back/payment";

//        notify_url= "https://www.yixiaodui.cn/api/back/payment";

//        notify_url= "http://frp.pooke.net/xiadan/back/twoPay";

        Map map =new HashMap<>();

        map.put("appid", appid);

        map.put("mch_id", mch_id);

        map.put("nonce_str", nonce_str);

        map.put("body", body);

        map.put("out_trade_no", out_trade_no);

        map.put("total_fee", total_fee);

        map.put("spbill_create_ip", spbill_create_ip);

        map.put("trade_type", trade_type);

        map.put("notify_url", notify_url);

        map.put("attach",这个参数是商品附加信息,需要可以传递value)

        map.put("openid", openid);

        String sign = WXPayUtil.generateSignature(map, wxParameter.getApikey());

        map.put("sign", sign);

        // 获取公众号prepay_id的链接

        String prepayIdUrl ="https://api.mch.weixin.qq.com/pay/unifiedorder";

        String xml = WXPayUtil.mapToXml(map);

        String post =doPost(prepayIdUrl, xml);

        Map stringMap = WXPayUtil.xmlToMap(post);

        // 如果请求成功

        if (null != post) {

try {

return stringMap.get("prepay_id");

            }catch (JSONException e) {

}

}else {

System.out.println("未获取到prepay_id");

        }

return null;

    }



>>>>>>>>>>>>>>>use>>>>>>>>>>>>>>>>>>>>>>>

调用方法1,*************

price:需要支付的价格;       str 随机字符串(订单号) ; ----随机字符串不重复,可以用时间戳拼接随机数

openid:商户openid;           notify_url:支付回调地址.

String prepayId = getprepay_id(price,    str,    user.getOpen_id(),    "https://cocoondance.hnbjx.net.cn/order_room/back/pay");

调用方法2,获得传递给前端的map

Map map = UnifiedOrder(prepayId);

接下来,可以在数据库中插入一个未支付的订单号,然后在回调中修改支付状态!!!


支付回调接口

@RequestMapping("back/pay")

@ResponseBody

    public StringbackPay(HttpServletRequest request, HttpServletResponse response)throws Exception {

BufferedReader br =new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));

        String line =null;

        StringBuilder sb =new StringBuilder();

        while ((line = br.readLine()) !=null) {

sb.append(line);

        }

br.close();

        //sb为微信返回的xml

        String notityXml = sb.toString();

        String resXml ="";

        //转为map

        Map map = WXPayUtil.xmlToMap(notityXml);

        String returnCode = map.get("return_code");

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

if (WXPayUtil.isSignatureValid(WXPayUtil.mapToXml(map), wxParameter.getApikey())) {

    //              回调,处理订单需要的逻辑这里直接在service中处理了

****************************************************

                order_roomService.backpay(map);

**************************************************88

                resXml ="<xml>" +""

                        +"<return_msg><![CDATA[OK]]></return_msg>" +"</xml> ";

            }

}else {

resXml ="<xml>" +""

                    +"<return_msg><![CDATA[报文为空]]></return_msg>" +"</xml> ";

        }

BufferedOutputStream out =new BufferedOutputStream(response.getOutputStream());

        out.write(resXml.getBytes());

        out.flush();

        out.close();

        return resXml;

    }








使用到的工具类1

import com.ijpay.core.enums.SignType;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import javax.crypto.Mac;

import javax.crypto.spec.SecretKeySpec;

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.security.MessageDigest;

import java.security.SecureRandom;

import java.util.*;

public class WXPayUtil {

private static final StringSYMBOLS ="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    private static final RandomRANDOM =new SecureRandom();

    /**

    * XML格式字符串转换为Map

*

    * @param strXML XML字符串

    * @return XML数据转换后的Map

    * @throws Exception

*/

    public static MapxmlToMap(String strXML)throws Exception {

try {

Map data =new HashMap();

            DocumentBuilder documentBuilder = com.bjx.sdk.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;

        }

}

/**

    * 将Map转换为XML格式的字符串

    *

    * @param data Map类型数据

    * @return XML格式的字符串

    * @throws Exception

*/

    public static StringmapToXml(Map 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;

    }

/**

    * 将Map转换为XML格式的字符串

    *

    * @param data Map类型数据

    * @return XML格式的字符串

    * @throws Exception

*/

    public static StringmapToXml2(Map 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;

    }

/**

    * 生成带有 sign 的 XML 格式字符串

    *

    * @param data Map类型数据

    * @param key  API密钥

    * @return 含有sign字段的XML

*/

    public static StringgenerateSignedXml(final Map data, String key)throws Exception {

return generateSignedXml(data, key, SignType.MD5);

    }

/**

    * 生成带有 sign 的 XML 格式字符串

    *

    * @param data    Map类型数据

    * @param key      API密钥

    * @param signType 签名类型

    * @return 含有sign字段的XML

*/

    public static StringgenerateSignedXml(final Map 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 data =xmlToMap(xmlStr);

        if (!data.containsKey(WXPayConstants.FIELD_SIGN)) {

return false;

        }

String sign = data.get(WXPayConstants.FIELD_SIGN);

        return generateSignature(data, key).equals(sign);

    }

/**

    * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。

    *

    * @param data Map类型数据

    * @param key  API密钥

    * @return 签名是否正确

    * @throws Exception

*/

    public static boolean isSignatureValid(Map data, String key)throws Exception {

return isSignatureValid(data, key, SignType.MD5);

    }

/**

    * 判断签名是否正确,必须包含sign字段,否则返回false。

    *

    * @param data    Map类型数据

    * @param key      API密钥

    * @param signType 签名方式

    * @return 签名是否正确

    * @throws Exception

*/

    public static boolean isSignatureValid(Map data, String key, SignType signType)throws Exception {

if (!data.containsKey(WXPayConstants.FIELD_SIGN)) {

return false;

        }

String sign = data.get(WXPayConstants.FIELD_SIGN);

        return generateSignature(data, key, signType).equals(sign);

    }

/**

    * 生成签名

    *

    * @param data 待签名数据

    * @param key  API密钥

    * @return 签名

    */

    public static StringgenerateSignature(final Map data, String key)throws Exception {

return generateSignature(data, key, SignType.MD5);

    }

/**

    * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。

    *

    * @param data    待签名数据

    * @param key      API密钥

    * @param signType 签名方式

    * @return 签名

    */

    public static StringgenerateSignature(final Map data, String key, SignType signType)throws Exception {

Set keySet = data.keySet();

        String[] keyArray = keySet.toArray(new String[keySet.size()]);

        Arrays.sort(keyArray);

        StringBuilder sb =new StringBuilder();

        for (String k : keyArray) {

if (k.equals(WXPayConstants.FIELD_SIGN)) {

continue;

            }

if (data.get(k).trim().length() >0)// 参数值为空,则不参与签名

            {

sb.append(k).append("=").append(data.get(k).trim()).append("&");

            }

}

sb.append("key=").append(key);

        if (SignType.MD5.equals(signType)) {

return MD5(sb.toString()).toUpperCase();

        }else if (SignType.HMACSHA256.equals(signType)) {

return HMACSHA256(sb.toString(), key);

        }else {

throw new Exception(String.format("Invalid sign_type: %s", signType));

        }

}

/**

    * 获取随机字符串 Nonce Str

*

    * @return String 随机字符串

    */

    public static StringgenerateNonceStr() {

char[] nonceChars =new char[32];

        for (int index =0; index < nonceChars.length; ++index) {

nonceChars[index] =SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));

        }

return new String(nonceChars);

    }

/**

    * 生成 MD5

*

    * @param data 待处理数据

    * @return MD5结果

    */

    public static StringMD5(String data)throws Exception {

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

    }

/**

    * 生成 HMACSHA256

*

    * @param data 待处理数据

    * @param key  密钥

    * @return 加密结果

    * @throws Exception

*/

    public static StringHMACSHA256(String data, String key)throws Exception {

Mac sha256_HMAC = Mac.getInstance("HmacSHA256");

        SecretKeySpec secret_key =new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");

        sha256_HMAC.init(secret_key);

        byte[] array = sha256_HMAC.doFinal(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();

    }

/**

    * 日志

    *

    * @return

    */

    public static LoggergetLogger() {

Logger logger = LoggerFactory.getLogger("wxpay java sdk");

        return logger;

    }

/**

    * 获取当前时间戳,单位秒

    *

    * @return

    */

    public static long getCurrentTimestamp() {

return System.currentTimeMillis() /1000;

    }

/**

    * 获取当前时间戳,单位毫秒

    *

    * @return

    */

    public static long getCurrentTimestampMs() {

return System.currentTimeMillis();

    }

}


工具类2


import lombok.Data;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

@Data

@Component

public class WxParameter {

@Value("${wx.miniapp.appid}")

private StringAppid;

    @Value("${wx.miniapp.appsecret}")

private StringAppsecret;

    @Value("${wx.mchid}")

private Stringmchid;

    @Value("${wx.apikey}")

private Stringapikey;

}









    

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容