首页 > 代码库 > java实现微信支付之扫码支付

java实现微信支付之扫码支付

本文直接从代码调用微信扫码支付讲起。账号配置,参数生成等请参考官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1

微信扫码支付。简单来说,就是你把微信支付需要的信息,生成到二维码图片中。通过微信扫一扫,发起支付。我们需要做的就是二件事:

一是:按照微信扫码支付规则生成二维码信息.

二是:微信没有提供生成二维码图片的接口。需要我们自己把二维码信息生成到二维码图片中。

1.模式选择:

微信扫码支付,有两种模式,文档中有介绍。第二种模式,微信接口会返回二维码信息给我们。而第一种模式则需要我们自己去生成二维码信息。会有些麻烦。尤其 是参数大小写,还有签名的问题,容易出错。总的来说第二种模式比第一种模式简单。所有我采用的是第二种模式,比较通用。京东与携程亦用的是第二种模式。

2.调用统一下单接口获取带有二维码信息的url:(模式二)

模式二的微信扫码支付,需要先调用微信的统一下单接口,生成预交易单。(参数传递与接收都是XML 数据格式。)

正确调用后,会返回含有交易标示ID,和二维码链接的URL。

 

3.实现扫码支付(模式二)

 

  private static String APPID = "";  

  private static String MCHID= "";
  private static String KEY= "";
  private static String APPSECRET= "";
  private static String body= "";
  private static String notify_url= "";    //回调地址。测试回调必须保证外网能访问到此地址

  /**  * 统一下单接口 * 微信二维码支付 * @param params * @return */ public String weixin_pay(String out_trade_no,String product_id) { JSONObject retJson = new JSONObject(); try { String currTime = PayCommonUtil.getCurrTime(); String strTime = currTime.substring(8, currTime.length()); String strRandom = PayCommonUtil.buildRandom(4) + ""; String nonce_str = strTime + strRandom;      //生成随机字符串 JSONObject requestObj = JSONObject.fromObject(params); // 正式上线的时候价格根据订单id查询 String order_price = "1"; // 价格 注意:价格的单位是分 SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>(); packageParams.put("appid", APPID); packageParams.put("mch_id", MCHID); 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", "用户端ip"); packageParams.put("notify_url", notify_url); packageParams.put("trade_type", "NATIVE"); packageParams.put("product_id", product_id); Calendar nowTime = Calendar.getInstance(); packageParams.put("time_start", DateFormatUtil.formatDate( nowTime.getTime(), "yyyyMMddHHmmss")); nowTime.add(Calendar.MINUTE, requestObj.getInt("expire_time")); packageParams.put("time_expire", DateFormatUtil.formatDate( nowTime.getTime(), "yyyyMMddHHmmss")); String sign = PayCommonUtil.createSign("UTF-8", packageParams, KEY); packageParams.put("sign", sign);        //加密 String requestXML = PayCommonUtil.getRequestXml(packageParams); logger.info("支付请求:" + requestXML); long startTime=System.currentTimeMillis(); String resXml = HttpRequest.postData( "https://api.mch.weixin.qq.com/pay/unifiedorder", requestXML); long endTime=System.currentTimeMillis(); Integer execute_time = (int) ((endTime-startTime)/1000); logger.info("支付结果:" + resXml); Map map = XMLUtil.doXMLParse(resXml); JSONObject reportParams = new JSONObject(); reportParams.put("url", "https://api.mch.weixin.qq.com/pay/unifiedorder"); reportParams.put("execute_time", execute_time); reportParams.put("return_code", map.get("return_code").toString()); reportParams.put("return_msg", map.get("return_msg").toString()); reportParams.put("result_code", map.get("result_code").toString()); if (map.get("err_code") != null) { reportParams.put("err_code", map.get("err_code").toString()); reportParams.put("err_code_des", map.get("err_code_des").toString()); } reportParams.put("out_trade_no", out_trade_no); //交易保障 report(reportParams.toString()); if (map.get("return_code").toString().equals("SUCCESS") && map.get("result_code").toString().equals("SUCCESS")) { String urlCode = (String) map.get("code_url");          //微信二维码短链接 retJson.put("code", 0); retJson.put("message", "下单成功."); retJson.put("data", urlCode); } else { retJson.put("code", 1); retJson.put("message", map.get("err_code_des").toString()); retJson.put("data", ""); } return retJson.toString(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } }

 

 

4.支付工具类

public class PayCommonUtil {        public static Logger log = LoggerFactory.getLogger(PayCommonUtil.class);        /**     * 是否签名正确,规则是:按参数名称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 = MD5.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     *            编码格式     * @param parameters     *            请求参数     * @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 = "";            try {                v = (String) entry.getValue();            } catch (Exception e) {                // TODO: handle exception                v = entry.getValue() + "";            }                         if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {                  sb.append(k + "=" + v + "&");              }          }          sb.append("key=" + API_KEY);          String sign = MD5.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 = "";            try {                v = (String) entry.getValue();            } catch (Exception e) {                // TODO: handle exception                v = 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;      }              public static JSONObject httpsRequestToJsonObject(String requestUrl,            String requestMethod, String outputStr) {        JSONObject jsonObject = null;        try {            StringBuffer buffer = httpsRequest(requestUrl, requestMethod,                    outputStr);            jsonObject = JSONObject.fromObject(buffer.toString());        } catch (ConnectException ce) {            log.error("连接超时:" + ce.getMessage());        } catch (Exception e) {            log.error("https请求异常:" + e.getMessage());        }        return jsonObject;    }    private static StringBuffer httpsRequest(String requestUrl,            String requestMethod, String output)            throws NoSuchAlgorithmException, NoSuchProviderException,            KeyManagementException, MalformedURLException, IOException,            ProtocolException, UnsupportedEncodingException {        URL url = new URL(requestUrl);        HttpsURLConnection connection = (HttpsURLConnection) url                .openConnection();        connection.setDoOutput(true);        connection.setDoInput(true);        connection.setUseCaches(false);        connection.setRequestMethod(requestMethod);        if (null != output) {            OutputStream outputStream = connection.getOutputStream();            outputStream.write(output.getBytes("UTF-8"));            outputStream.close();        }        // 从输入流读取返回内容        InputStream inputStream = connection.getInputStream();        InputStreamReader inputStreamReader = new InputStreamReader(                inputStream, "utf-8");        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);        String str = null;        StringBuffer buffer = new StringBuffer();        while ((str = bufferedReader.readLine()) != null) {            buffer.append(str);        }        bufferedReader.close();        inputStreamReader.close();        inputStream.close();        inputStream = null;        connection.disconnect();        return buffer;    }}

 

java实现微信支付之扫码支付