zoukankan      html  css  js  c++  java
  • 微信公众号H5支付

    微信支付说明
    1.统一下单接口
    统一支付接口:
      url: https://api.mch.weixin.qq.com/pay/unifiedorder
      目的:通过此接口来创建预支付订单,获取订单支付需要的prepay_id
      过程:
        1.对所有的支付中使用到的参数以字典序排序,然后使用商户的key进行MD5加密,获得加密字符串sign,
        2.然后将sign加入以上信息中将其转化为xml,调用统一下单接口,获取prepay_id。
      代码说明:
        
       

    1.构建支付参数
    //
    写购买商品的详情 JSONObject object = new JSONObject(); JSONArray array = new JSONArray(); JSONObject object1 = new JSONObject(); object1.put("goods_id","购买商品id"); object1.put("goods_name","购买商品名称"); object1.put("quantity","购买商品数量"); object1.put("price","商品单价"); array.add(object1); object.put("goods_detail",array); //构建统一下单需要的参数 Map<String,String> map = new HashMap<>(); map.put('appid',"支付的微信公众号的appid"); map.put("mch_id","支付的商户号"); map.put("device_info","设备编号"); map.put("sign_type","加密类型,一般使用MD5"); map.put("body","商品描述"); map.put("out_trade_no","商户订单号"); map.put("total_url","购买总金额"); map.put("notify_url","支付成功后微信的回掉地址,地址不许带参数"); map.put("trade_type","交易类型"); map.put("nonce_str","随机字符串"); map.put("detail","商品详情"); map.put("openid","支付人的openid"); map.put("spbill_create_ip","支付人ip地址");


    //将统一下单参数进行字典序排序,进行签名
    
    /**
    * 微信支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3).
    *
    * @param params 参数信息
    * @param signType 签名类型,如果为空,则默认为MD5
    * @param signKey 签名Key
    * @param ignoreSignType 签名时,是否忽略signType
    * @return 签名字符串
    */
    public static String createSign(Map<String, String> params, String signType, String signKey, boolean ignoreSignType) {
      SortedMap<String, String> sortedMap = new TreeMap<>(params);
    
      StringBuilder toSign = new StringBuilder();
      for (String key : sortedMap.keySet()) {
        String value = params.get(key);
        boolean shouldSign = false;
        if (ignoreSignType && "sign_type".equals(key)) {
          shouldSign = false;
        } else if (StringUtils.isNotEmpty(value)
          && !Lists.newArrayList("sign", "key", "xmlString", "xmlDoc", "couponList").contains(key)) {
           shouldSign = true;
        }
    
      if (shouldSign) {
        toSign.append(key).append("=").append(value).append("&");
      }
     }
    
      toSign.append("key=").append(signKey);
      if ("HMAC_SHA256".equals(signType)) {
        return createHmacSha256Sign(toSign.toString(), signKey);
      } else {
        return DigestUtils.md5Hex(toSign.toString()).toUpperCase();
      }
    }
    
    //将上一步得到的签名加入上一个支付参数中,转为xml请求统一支付下单接口,获取订单支付需要的prepay_id
    map.put("sign","上一步得到的签名");
    //将map转为xml
    public static String map2XmlString(Map<String, String> map) {
      String xmlResult = "";
    
      StringBuffer sb = new StringBuffer();
      sb.append("<xml>");
      for (String key : map.keySet()) {
        String value = "<![CDATA[" + map.get(key) + "]]>";
        sb.append("<" + key + ">" + value + "</" + key + ">"); 
      }
      sb.append("</xml>");
      xmlResult = sb.toString();
      return xmlResult;
    }
    //进行网络请求
    
    public static String httpPostWithXml(String xml, String url){
      StringBuffer stringBuffer = new StringBuffer();
      HttpPost post = null;
      try {
        HttpClient httpClient = new DefaultHttpClient();
    
    // 设置超时时间
    //httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 2000);
    //httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 2000);
    
        post = new HttpPost(url);
    // 构造消息头
        post.setHeader("Content-type", "application/json; charset=utf-8");
        post.setHeader("Connection", "Close");
    
    
    // 构建消息实体
        StringEntity entity = new StringEntity(xml,"UTF-8");
        entity.setContentEncoding("UTF-8");
    // 发送Json格式的数据请求
        entity.setContentType("application/json");
        post.setEntity(entity);
    
        HttpResponse response = httpClient.execute(post);
    // 检验返回码
        int statusCode = response.getStatusLine().getStatusCode();
        if(statusCode != HttpStatus.SC_OK){
          LogUtil.info("请求出错: "+statusCode);
        }else{
          InputStream inputStream = response.getEntity().getContent();
          BufferedReader br = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
    
          String str= "";
          while((str = br.readLine()) != null){
            stringBuffer .append(str );
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
      return stringBuffer.toString();
    }
    //得到了prepay_id,获取支付的签名
    Map<String,String> map = new HashMap<>();
    map.put('appId',"支付的微信公众号的appid");
    map.put("signType","加密类型");
    map.put("nonceStr","随机字符串");
    map.put("package","固定格式: prepay_id=上一步获得的prepay_id");
    map.put("timeStamp","当前时间戳");
    //将上面的参数使用商户key进行签名,得到paysign,将paySign加入上面的参数之中,发给h5页面调起支付。
    map.put(paySign,"得到的签名");
    
    //h5页面调起支付
    WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
        "appId":rs.appId, //公众号名称,由商户传入
        "timeStamp":rs.timeStamp, //时间戳,自1970年以来的秒数
        "nonceStr":rs.nonceStr, //随机串
        "package":rs.package,
        "signType":"MD5", //微信签名方式:
        "paySign":rs.paySign //微信签名
      },
      function(res){
        if(res.err_msg == "get_brand_wcpay_request:ok" ) {
          //支付成功
        }else if(res.err_msg =="get_brand_wcpay_request:fail"){
          //支付失败
        }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
          //取消支付
        }else {
          //其他情况
        }
      }
    );
  • 相关阅读:
    DataGrip中执行ORACL语句块进行代码测试
    ORACLE存储过程中使用SELECT INOT语句避免NO_DATA_FOUND的方法
    Pandas和numpy如何显示全部数据
    qrcodejs2+html2canvas生产二维码海报vue
    SQL多表查询
    行者app定位不准的问题分析
    Gdb printer打印STL
    Linux中的文件和目录结构详解
    Linux 文件的路径以及管理
    linux创建ftp服务
  • 原文地址:https://www.cnblogs.com/jack1995/p/9198235.html
Copyright © 2011-2022 走看看