微信小程序之支付二

微信小程序支付模式二

支付流程

小程序支付模式一是用户直接支付。支付模式二是商户生成收费二维码,客户扫码支付。微信支付的官方文档
在这里插入图片描述

小程序代码

//eid 是运单号,这是早期做的一个物流项目。
  wxpay: function (eid) {
    var that = this;
 // openid 是不变的值,设计表的时候可以将openid设为属性字段。 
    let openid = wx.getStorageSync("openid");
 //wx.request:可以在app.js里写一个全局的wx.request,后续统一调用,这部分代码比较早。
    wx.request({
      url: 'https://hcwl.hcgyl.com.cn/hcwl/wxpay/Hddwxpay',
      data: {
        openid: openid,
        eid: eid
      },
      method: 'GET',
      //返回一个二维码
      success: function (res) {
        let img = res.data;
        // console.log("二维码图片数据:"+img);
        if (img.length !='' && img !=null) {
          console.log("图片不为空")
          img = img.replace(/[\r\n]/g, '');
          // 后端加了就不需要加
          //var img2 = "data:image/jpg;base64,"+img
          //图片
          that.setData({
            base64ImgUrl: img
          })
        } else {
          wx.hideLoading();
          console.log("二维码生成失败!!")
          }
      }
    })
  }

java后台

@RequestMapping("/***wxpay")
   public void Hddwxpay(@Param("openid") String openid,@Param("eid") String eid, HttpServletRequest request, HttpServletResponse response) throws Exception {
       String appid = PayConfigUtil.appid2;  // appid
       String appsecret = PayConfigUtil.appsecret2; // appsecret
       String mch_id = PayConfigUtil.MCH_ID; // 商业号
       String key = PayConfigUtil.API_KEY; // key 微信的API key
       String currTime = PayCommonUtil.getCurrTime();  //获取当前时间
       String strTime = currTime.substring(8, currTime.length());
       String strRandom = PayCommonUtil.buildRandom(4) + "";    //取出一个指定长度大小的随机正整数
       String nonce_str = strTime + strRandom;
       String order_price = total_fee; // 价格   注意:价格的单位是分
       String out_trade_no = mid; // 订单号
       String spbill_create_ip =  request.getRemoteAddr(); //获取发起电脑 ip
       //回调接口
       String notify_url = "https://*.ahhz.net/*/wxpay/notify";
       String trade_type = "NATIVE";
       SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
       packageParams.put("appid", appid);
       packageParams.put("mch_id", mch_id);  // 商户号
       packageParams.put("nonce_str", nonce_str);  //随机时间
       packageParams.put("body", body);  //商品名称(这里没有)
       packageParams.put("out_trade_no", out_trade_no);  //订单号
       packageParams.put("total_fee", order_price); // 金额
       packageParams.put("spbill_create_ip", spbill_create_ip);
       packageParams.put("notify_url", notify_url);  // 回调查询路径
       packageParams.put("trade_type", trade_type); 
       String sign = PayCommonUtil.createSign("UTF-8", packageParams,key); //签名(1)
       packageParams.put("sign", sign);
       System.out.println("第二个数据:sign=" + sign);
       String requestXML = PayCommonUtil.getRequestXml(packageParams);
       System.out.println(requestXML);
       String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);
       System.out.println(resXml);
       Map map = XMLUtil.doXMLParse(resXml);
       String urlCode = (String) map.get("code_url");
       String dataImg2 = "";
       if(urlCode!=null&&urlCode!=""){
           System.out.println("支付请求链接:"+urlCode);//把这个地址转成二维码在前端显示
           byte[] qrCodeImage = QRCodeGenerator.getQRCodeImage(urlCode, 360, 360);
           BASE64Encoder encoder = new BASE64Encoder();
           String dataImg = encoder.encode(qrCodeImage);
           dataImg2= "data:image/png;base64,"+dataImg;
       }
       Writer out = response.getWriter();
       out.write(dataImg2);
       out.flush();
   }

支付类PayCommonUtil

验证签名
签名
获取随机数
将请求参数转换为xml格式的string

import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedMap;

 public class  PayCommonUtil {
 /**
  * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
  * @return boolean
  */
 public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
     StringBuffer sb = new StringBuffer();
     Set es = packageParams.entrySet();
     Iterator it = es.iterator();
     while(it.hasNext()) {
         Map.Entry entry = (Map.Entry)it.next();
         String k = (String)entry.getKey();
         String v = (String)entry.getValue();
         if(!"sign".equals(k) && null != v && !"".equals(v)) {
             sb.append(k + "=" + v + "&");
         }
     }

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

     //算出摘要
     String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();
     String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();

     //System.out.println(tenpaySign + "    " + mysign);
     return tenpaySign.equals(mysign);
 }

 /**
  * @author
  * @date 2016-4-22
  * @Description:sign签名
  * @param characterEncoding
  *            编码格式
  *            请求参数
  * @return
  */
 public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
     StringBuffer sb = new StringBuffer();
     Set es = packageParams.entrySet();
     Iterator it = es.iterator();
     while (it.hasNext()) {
         Map.Entry entry = (Map.Entry) it.next();
         String k = (String) entry.getKey();
         String v = (String) entry.getValue();
         if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
             sb.append(k + "=" + v + "&");
         }
     }
     sb.append("key=" + API_KEY);
     String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
     return sign;
 }

 /**
  * @author
  * @date 2016-4-22
  * @Description:将请求参数转换为xml格式的string
  * @param parameters
  *            请求参数
  * @return
  */
 public static String getRequestXml(SortedMap<Object, Object> parameters) {
     StringBuffer sb = new StringBuffer();
     sb.append("<xml>");
     Set es = parameters.entrySet();
     Iterator it = es.iterator();
     while (it.hasNext()) {
         Map.Entry entry = (Map.Entry) it.next();
         String k = (String) entry.getKey();
         String v = (String) entry.getValue();
         if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
             sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
         } else {
             sb.append("<" + k + ">" + v + "</" + k + ">");
         }
     }
     sb.append("</xml>");
     return sb.toString();
 }

 /**
  * 取出一个指定长度大小的随机正整数.
  *
  * @param length
  *            int 设定所取出随机数的长度。length小于11
  * @return int 返回生成的随机数。
  */
 public static int buildRandom(int length) {
     int num = 1;
     double random = Math.random();
     if (random < 0.1) {
         random = random + 0.1;
     }
     for (int i = 0; i < length; i++) {
         num = num * 10;
     }
     return (int) ((random * num));
 }

 /**
  * 获取当前时间 yyyyMMddHHmmss
  *
  * @return String
  */
 public static String getCurrTime() {
     Date now = new Date();
     SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
     String s = outFormat.format(now);
     return s;
 }
}

MD5Util

import java.security.MessageDigest;

    public class MD5Util {
        private static String byteArrayToHexString(byte b[]) {
            StringBuffer resultSb = new StringBuffer();
            for (int i = 0; i < b.length; i++)
                resultSb.append(byteToHexString(b[i]));
    
            return resultSb.toString();
        }
    
        private static String byteToHexString(byte b) {
            int n = b;
            if (n < 0)
                n += 256;
            int d1 = n / 16;
            int d2 = n % 16;
            return hexDigits[d1] + hexDigits[d2];
        }
    
        public static String MD5Encode(String origin, String charsetname) {
            String resultString = null;
            try {
                resultString = new String(origin);
                MessageDigest md = MessageDigest.getInstance("MD5");
                if (charsetname == null || "".equals(charsetname))
                    resultString = byteArrayToHexString(md.digest(resultString
                            .getBytes()));
                else
                    resultString = byteArrayToHexString(md.digest(resultString
                            .getBytes(charsetname)));
            } catch (Exception exception) {
            }
            return resultString;
        }
    
        private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    }

HttpUtil

import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.net.URL;
  import java.net.URLConnection;

public class HttpUtil {
  //private static final Log logger = Logs.get();
  private final static int CONNECT_TIMEOUT = 5000; // in milliseconds
  private final static String DEFAULT_ENCODING = "UTF-8";
  public static String postData(String urlStr, String data){
      return postData(urlStr, data, null);
  }
  public static String postData(String urlStr, String data, String contentType){
      BufferedReader reader = null;
      try {
          URL url = new URL(urlStr);
          URLConnection conn = url.openConnection();
          conn.setDoOutput(true);
          conn.setConnectTimeout(CONNECT_TIMEOUT);
          conn.setReadTimeout(CONNECT_TIMEOUT);
          if(contentType != null)
              conn.setRequestProperty("content-type", contentType);
          OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
          if(data == null)
              data = "";
          writer.write(data);
          writer.flush();
          writer.close();
          reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
          StringBuilder sb = new StringBuilder();
          String line = null;
          while ((line = reader.readLine()) != null) {
              sb.append(line);
              sb.append("\r\n");
          }
          return sb.toString();
      } catch (IOException e) {
          //logger.error("Error connecting to " + urlStr + ": " + e.getMessage());
      } finally {
          try {
              if (reader != null)
                  reader.close();
          } catch (IOException e) {
          }
      }
      return null;
  }
}

XMLUTIL

import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import org.jdom.Document;
    import org.jdom.Element;
    import org.jdom.JDOMException;
    import org.jdom.input.SAXBuilder;

public class XMLUtil {
    /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
     * @param strxml
     * @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();
    }
}

支付回调

这一块我做的不行,就是无法做到支付成功自动反馈!推荐去这里看看!

/*
    * 支付回调
    * */
    @RequestMapping("/notify")
    public void wxpayNotify(HttpServletRequest request,HttpServletResponse response)throws Exception{
        //读取参数
        InputStream inputStream ;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s ;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null){
            sb.append(s);
        }
        in.close();
        inputStream.close();

        //解析xml成map
        Map<String, String> m = new HashMap<String, String>();
        try {
            m = XMLUtil.doXMLParse(sb.toString());
        } catch (JDOMException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //过滤空 设置 TreeMap
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        Iterator it = m.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = m.get(parameter);

            String v = "";
            if(null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        // 账号信息
        String key = PayConfigUtil.API_KEY; //key

        //判断签名是否正确
        if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,key)) {
            String resXml = "";
            if("SUCCESS".equals((String)packageParams.get("result_code"))){
                // 这里是支付成功
                //执行自己的业务逻辑
                request.getSession().setAttribute("_PAY_RESULT", "OK");
                //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            }
            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } else{
            System.out.println("通知签名验证失败");
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值