天天看點

微信公衆号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 {
      //其他情況
    }
  }
);