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;

}









    

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容