content: /*
   * 微信公众平台(JAVA) SDK
   *
   * Copyright (c) 2014, Ansitech Network Technology Co.,Ltd All rights reserved.
   * 
   * http://www.weixin4j.org/
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.weixin4j.model.pay;
  
  import org.weixin4j.util.SignUtil;
  import java.util.HashMap;
  import java.util.Map;
  import org.apache.commons.codec.digest.DigestUtils;
  import org.weixin4j.Configuration;
  import org.weixin4j.util.MapUtil;
  
  /**
   * JS API 微信支付
   *
   * @author yangqisheng
   * @since 0.0.1
   */
  public class WXPay {
  
      private final String appId;             //公众号Id
      private final String timestamp;         //支付签名时间戳
      private final String nonceStr;          //支付签名随机串
      private final String packages;          //订单详情扩展字符串
      private final String signType = "MD5";  //签名方式，默认为'SHA1'，使用新版支付需传入'MD5'
      private final String paySign;           //支付签名
      private final String signature;         //jsapi授权签名
  
      /**
       * chooseWXPay
       *
       * @param appId 公众号Id
       * @param jsapi_ticket jsapi验证票据
       * @param prepay_id 预下单Id
       * @param url 发起请求的url地址
       * @param paternerKey 商户密钥
       */
      public WXPay(String appId, String jsapi_ticket, String prepay_id, String url, String paternerKey) {
          this.appId = appId;
          this.timestamp = System.currentTimeMillis() / 1000 + "";
          this.nonceStr = java.util.UUID.randomUUID().toString().substring(0, 15);
          //生成订单详情扩展字符串
          this.packages = "prepay_id=" + prepay_id;
          //生成jsapi授权签名
          this.signature = SignUtil.getSignature(jsapi_ticket, this.nonceStr, this.timestamp, url);
  
          //对提交的参数进行签名
          Map<String, String> paySignMap = new HashMap<String, String>();
          paySignMap.put("appId", this.appId);
          paySignMap.put("timeStamp", timestamp);
          paySignMap.put("nonceStr", this.nonceStr);
          paySignMap.put("package", this.packages);
          paySignMap.put("signType", this.signType);
  
          //生成支付签名
          this.paySign = SignUtil.getSign(paySignMap, paternerKey);
      }
  
      /**
       * 生成package单详情扩展字符串
       *
       * package 生成方法：
       *
       * 由于package中携带了生成订单的详细信息， 因此在微信将对package里面的内容进行鉴权，
       * 确定package携带的信息是真实、有效、合理的。 因此，这里将定义生成package字符 串的方法。
       *
       * 1.对所有传入参数按照字段名的ASCII码从小到大排序（字典序）后，
       * 使用URL键值对的格式（即key1=value1&key2=value2…）拼接成字符串string1， 注意：值为空的参数不参与签名；
       *
       * 2.在string1最后拼接上key=paternerKey得到stringSignTemp字符串，
       * 并对stringSignTemp进行md5运算，再将得到的字符串所有字符转换为大写， 得到sign值signValue。
       *
       * 3.对传入参数中所有键值对的value进行urlencode转码后重新拼接成字符串string2。
       * 对于JS前端程序，一定要使用函数encodeURIComponent进行urlencode编码
       * （注意！进行urlencode时要将空格转化为%20而不是+）。
       *
       * 4.将sign=signValue拼接到string2后面得到最终的package字符串。
       *
       * @param M 参数详情对象
       * @param paternerKey 商户密钥
       * @return 返回订单详情package
       */
      private static String getPackage(Map<String, String> M, String paternerKey) {
          //1.1 将packages参数进行字典序排序
          Map<String, String> sortParams = MapUtil.sortAsc(M);
          //1.2 使用URL键值对的格式
          String string1 = MapUtil.mapJoin(sortParams, false);
          //2.1 接上key=paternerKey
          String stringSignTemp = string1 + "&key=" + paternerKey;
          //2.2 MD5加密
          String sign = DigestUtils.md5Hex(stringSignTemp).toUpperCase();
          if (Configuration.isDebug()) {
              System.out.println("sign = " + sign);
          }
          //3 对传入参数中所有键值对的value进行urlencode转码
          String string2 = MapUtil.mapJoin(sortParams, true);
          if (Configuration.isDebug()) {
              System.out.println("string2 = " + string2);
          }
          //4 将sign=signValue拼接到string2后面得到最终的package字符串。
          return string2 + "&sign=" + sign;
      }
  
      public String getTimeStamp() {
          return timestamp;
      }
  
      public String getNonceStr() {
          return nonceStr;
      }
  
      public String getPackage() {
          return packages;
      }
  
      public String getPaySign() {
          return paySign;
      }
  
      public String getSignature() {
          return signature;
      }
  
      public String getAppId() {
          return appId;
      }
  
      public String getSignType() {
          return signType;
      }
  
  }
  