微信小程序支付一整套

**

小程序代码

const APP_ID = '****************'; //输入小程序appid  
const APP_SECRET = '********************'; //输入小程序app_secret  
var OPEN_ID = '' //储存获取到openid  
var SESSION_KEY = '' //储存获取到session_key  
wxPay() {
    var that = this;
    wx.login({
      success: function(res) {
        wx.request({
          //获取openid接口  
          url: 'https://api.weixin.qq.com/sns/jscode2session',
          data: {
            appid: APP_ID,
            secret: APP_SECRET,
            js_code: res.code,
            grant_type: 'authorization_code'
          },
          method: 'GET',
          success: function(res) {
            OPEN_ID = res.data.openid; //获取到的openid  
            SESSION_KEY = res.data.session_key; //获取到session_key  
            wx.request({
              url: BASE_URL + 'qrOrder/WXSmallProceduresPay',
              data: {
                openid: OPEN_ID,
                session_key: SESSION_KEY,
                mobile: ‘10086’,//手机号
                commodityId: ‘1’,//商品id
                commodityType:‘2’,//商品类型
              },
              success(res) {
                wx.requestPayment({
                  'timeStamp': res.data.timeStamp,
                  'nonceStr': res.data.nonceStr,
                  'package': res.data.package,
                  'signType': 'MD5',
                  'paySign': res.data.paySign,
                  'success': function(res) {
                      wx.navigateTo({
                        url: 'msg_success',
                      })
                  },
                  'fail': function(res) {
                    wx.navigateTo({
                      url: 'msg_fail',
                    })
                  },
                  'complete': function(res) {}
                })
              }
            })
          }
        })
      }
    })
  }

java代码(暂时写在Controller里 - -)

/**
 * 微信小程序支付
 */
@RequestMapping(value = "WXSmallProceduresPay")
@ResponseBody
@CrossOrigin
public  Map<String,String> WXSmallProceduresPay(@RequestParam Map<String, Object> params, HttpServletRequest request){

    String mobile=(String) params.get("mobile");
    String commodityId=(String) params.get("commodityId");
    String commodityType=(String) params.get("commodityType");


 
    QrOrder qrOrderL=new QrOrder();


        //获取订单信息
        qrOrderL=qrOrderService.insertPrepayOrder(mobile,commodityId,commodityType);
        Boolean b=qrOrderService.findOrderByUserIsBuy(qrOrderL);
        if (b){
            Map<String,String> map=new HashMap<>();
            map.put("isBuy","true");
            return  map;
        }
    //小程序ID appid
    String APPID = WXPayConstants.SmallAPPID;
    //商户ID mch_id
    String MERID = WXPayConstants.MERID;
    //密钥
    String SIGNKEY =WXPayConstants.SIGNKEY;
    //appAPPSECRET
    String APPSECRET=WXPayConstants.SmallAPPSECRET;
    //获取ip地址
    String spbill_create_ip = GetAddressByIp.getIpAddress(request);
    //获取openId
    String openId=(String) params.get("openid");
 
    //支付方式
    String tradeType = "JSAPI";
    //虽然官方文档不是必须参数,但是不送有时候会验签失败
    String MD5 = "MD5";
    //商品主题
    String body = "图书";
    //金额转化为分为单位 微信支付以分为单位
    BigDecimal fen=new BigDecimal("100");

    String finalmoneys="";
   
        BigDecimal finalmoney=qrOrderL.getTransactionAmount().multiply(fen).setScale(0);
        finalmoneys=finalmoney.toString();
        
    

    int randomNum  = (int) (Math.random() * 1999+5000);
    //我要获取当前的日期
    Date date = new Date();
    //设置要获取到什么样的时间
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //获取String类型的时间
    String Time = sdf.format(date);
    String out_trade_no = qrOrderService.generatorOrderNo();
    //随机数
    String nonce_str=WXPayUtil.generateNonceStr();
    //获取回调地址
    SignLetion ss = SignLetion.getInstance();
    String notify_url= ss.getUrl();
    if (notify_url==null || notify_url==""){
        QrSystemConstantConfigure qsc= qrSystemConstantConfigureService.findConfigList();
        notify_url=qsc.getSysParam9();
        ss.setUrl(notify_url);
    }
    //签名数据
    Map<String, String> map=new HashMap<>();
    map.put("appid",APPID);
    map.put("body",body);
    map.put("mch_id",MERID);
    map.put("nonce_str",nonce_str);
    map.put("notify_url",notify_url);
    map.put("out_trade_no",out_trade_no);
    map.put("sign_type","MD5");
    map.put("spbill_create_ip",spbill_create_ip);
    map.put("total_fee",finalmoneys);
    map.put("trade_type",tradeType);
    map.put("openid",openId);
    String sign="";
    try {
        sign =WXPayUtil.generateSignature(map,SIGNKEY);// "把sb.toString()做MD5操作并且toUpperCase()一下,至于怎么MD5,百度一下或者看官方文档";
    }catch (Exception e){
        logger.error("获取sign签名失败");
    }
    map.put("sign",sign);
    logger.info(map.toString());
    //封装xml报文
    String xml="";
    try {
        xml=WXPayUtil.mapToXml(map);
    }catch (Exception e){
        logger.error("xml"+xml);
    }
    String URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信统一下单接口
    String res= httpRequestutil.sendPost(URL,xml);
    Map<String,String> XTM;
    String  prepay_id=null;

    try {
        XTM=WXPayUtil.xmlToMap(res);
        System.out.println("统一下单接口"+XTM);
        prepay_id=XTM.get("prepay_id");
    }catch (Exception e){
        logger.error(prepay_id+"prepay_id",e);
    }
    Map<String,String> map1=new HashMap<>();
    map1.put("appId",APPID);
    map1.put("timeStamp",String.valueOf(WXPayUtil.getCurrentTimestamp()));
    map1.put("nonceStr",WXPayUtil.generateNonceStr());
    map1.put("signType","MD5");
    map1.put("package", "prepay_id=".concat(prepay_id));
    String paySign="";
    try {
        paySign=WXPayUtil.generateSignature(map1,SIGNKEY);
    }catch (Exception e){
        logger.error("paySign:"+paySign, e);
    }
    map1.put("paySign",paySign);
    map1.put("prepay_id", prepay_id);


    Date date1=new Date();
    String time=sdf.format(date1);
 
        qrOrderL.setNumber(out_trade_no);
        qrOrderL.setCreateTime(sdf.format(new Date()));
        qrOrderL.setState("0");
        qrOrderL.setIp(GetAddressByIp.getIpAddress(request));
        qrOrderL.setCreateTime(time);
        qrOrderL.setTerminal(String.valueOf(params.get("terminal")));
        qrOrderL.setTransactionMode("微信");
        qrOrderService.insertOrder(qrOrderL);
    return map1;
}

(一)微信支付工具类

package com.github.pig.admin.common.util;

import com.github.pig.admin.common.util.WXPayConstants.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.ByteArrayOutputStream;
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 String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final Random RANDOM = new SecureRandom();

    /**
     * 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) {

            throw ex;
        }

    }

    /**
     * 将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;
    }


    /**
     * 生成带有 sign 的 XML 格式字符串
     *
     * @param data Map类型数据
     * @param key API密钥
     * @return 含有sign字段的XML
     */
    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字段的XML
     */
    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);
    }

    /**
     * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。
     *
     * @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);
    }

    /**
     * 判断签名是否正确,必须包含sign字段,否则返回false。
     *
     * @param data Map类型数据
     * @param key API密钥
     * @param signType 签名方式
     * @return 签名是否正确
     * @throws Exception
     */
    public static boolean isSignatureValid(Map<String, String> 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 String generateSignature(final Map<String, String> data, String key) throws Exception {
        return generateSignature(data, key, SignType.MD5);
    }

    /**
     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
     *
     * @param data 待签名数据
     * @param key API密钥
     * @param signType 签名方式
     * @return 签名
     */
    public static String generateSignature(final Map<String, String> data, String key, SignType signType) throws Exception {
        Set<String> 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 String generateNonceStr() {
        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 String MD5(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 String HMACSHA256(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 Logger getLogger() {
        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();
    }

    /** auth:wtao *
     * InputStream流转换成String字符串 *
     * @param inStream InputStream流 *
     * @param encoding 编码格式 *
     * @return String字符串
     */
    public static String inputStream2String(InputStream inStream, String encoding){
        String result = null;
        ByteArrayOutputStream outStream = null;
        try {
            if(inStream != null){
            outStream = new ByteArrayOutputStream();
            byte[] tempBytes = new byte[1024];
            int count = 0;
            while((count = inStream.read(tempBytes)) != -1){
                outStream.write(tempBytes, 0, count);
            }
            tempBytes = null;
            outStream.flush();
            result = new String(outStream.toByteArray(), encoding);
            outStream.close();
        }
        } catch (Exception e) {
            result = null;
        }
        return result;
    }
}

(二)微信支付工具类

package com.github.pig.admin.common.util;


import sun.net.www.http.HttpClient;

/**
 * 常量
 */
public class WXPayConstants {

    public enum SignType {
        MD5, HMACSHA256
    }


    public static final String APPID = "***";
    //小程序id
    public static final String SmallAPPID = "***";




    public static final String MERID = "***";

    public static final String SIGNKEY ="***";

    public static final String APPSECRET="****";

    public static final String SmallAPPSECRET="***";

    public static final String DOMAIN_API = "api.mch.weixin.qq.com";
    public static final String DOMAIN_API2 = "api2.mch.weixin.qq.com";
    public static final String DOMAIN_APIHK = "apihk.mch.weixin.qq.com";
    public static final String DOMAIN_APIUS = "apius.mch.weixin.qq.com";


    public static final String FAIL     = "FAIL";
    public static final String SUCCESS  = "SUCCESS";
    public static final String HMACSHA256 = "HMAC-SHA256";
    public static final String MD5 = "MD5";

    public static final String FIELD_SIGN = "sign";
    public static final String FIELD_SIGN_TYPE = "sign_type";

    public static final String WXPAYSDK_VERSION = "WXPaySDK/3.0.9";
    public static final String USER_AGENT = WXPAYSDK_VERSION +
            " (" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version") +
            ") Java/" + System.getProperty("java.version") + " HttpClient/" + HttpClient.class.getPackage().getImplementationVersion();

    public static final String MICROPAY_URL_SUFFIX     = "/pay/micropay";
    public static final String UNIFIEDORDER_URL_SUFFIX = "/pay/unifiedorder";
    public static final String ORDERQUERY_URL_SUFFIX   = "/pay/orderquery";
    public static final String REVERSE_URL_SUFFIX      = "/secapi/pay/reverse";
    public static final String CLOSEORDER_URL_SUFFIX   = "/pay/closeorder";
    public static final String REFUND_URL_SUFFIX       = "/secapi/pay/refund";
    public static final String REFUNDQUERY_URL_SUFFIX  = "/pay/refundquery";
    public static final String DOWNLOADBILL_URL_SUFFIX = "/pay/downloadbill";
    public static final String REPORT_URL_SUFFIX       = "/payitil/report";
    public static final String SHORTURL_URL_SUFFIX     = "/tools/shorturl";
    public static final String AUTHCODETOOPENID_URL_SUFFIX = "/tools/authcodetoopenid";

    // sandbox
    public static final String SANDBOX_MICROPAY_URL_SUFFIX     = "/sandboxnew/pay/micropay";
    public static final String SANDBOX_UNIFIEDORDER_URL_SUFFIX = "/sandboxnew/pay/unifiedorder";
    public static final String SANDBOX_ORDERQUERY_URL_SUFFIX   = "/sandboxnew/pay/orderquery";
    public static final String SANDBOX_REVERSE_URL_SUFFIX      = "/sandboxnew/secapi/pay/reverse";
    public static final String SANDBOX_CLOSEORDER_URL_SUFFIX   = "/sandboxnew/pay/closeorder";
    public static final String SANDBOX_REFUND_URL_SUFFIX       = "/sandboxnew/secapi/pay/refund";
    public static final String SANDBOX_REFUNDQUERY_URL_SUFFIX  = "/sandboxnew/pay/refundquery";
    public static final String SANDBOX_DOWNLOADBILL_URL_SUFFIX = "/sandboxnew/pay/downloadbill";
    public static final String SANDBOX_REPORT_URL_SUFFIX       = "/sandboxnew/payitil/report";
    public static final String SANDBOX_SHORTURL_URL_SUFFIX     = "/sandboxnew/tools/shorturl";
    public static final String SANDBOX_AUTHCODETOOPENID_URL_SUFFIX = "/sandboxnew/tools/authcodetoopenid";

}

一整套都到这里为止了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值