1. 程式人生 > >微信小程式支付以及微信退款開發

微信小程式支付以及微信退款開發

最近公司專案急著測試,需要開發微信小程式+微信支付+微信退款,本著這幾天的一些研究,決定記錄一下開發的過程。

本著知識分享的原則,希望對大家有所幫助。

本篇針對的是微信小程式的支付開發,如果有對微信公眾號的支付開發需要的,可以去我的github上看看,有個sell的專案很好的完成了公眾號方面的支付與退款,程式碼很全,用的是最優秀的sdk,肯定對你們學習和工作有幫助,下面貼一下github連結: https://github.com/wenbingshen/springboot

廢話不多說,開始我們的小程式支付開發之旅:

首先呢,開發之前,需要交代的是,有關微信支付的開發需要有自己的商戶號和金鑰,這在微信支付開發文件上面講的很清楚,有過支付開發經驗的對這一點很清楚。

瞭解了上面的情況後咱們就開始著手開發吧!

先編寫一個常量類Constant,將有關的配置常量配在裡面:

public class Constant {

    public static final String DOMAIN = "http://sellbin.natapp1.cc";//配置自己的域名

    public static final String APP_ID = "填寫自己的";

    public static final String APP_SECRET = "填寫自己的";

    public static final String APP_KEY = "填寫自己的";

    
public static final String MCH_ID = "填寫自己的"; //商戶號 public static final String URL_UNIFIED_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder"; public static final String URL_NOTIFY = Constant.DOMAIN + "/wxpay/views/payInfo.jsp"; public static final String TIME_FORMAT = "yyyyMMddHHmmss";
public static final int TIME_EXPIRE = 2; //單位是day }

支付的時候,我們需要利用發起支付的使用者code去微信介面獲取使用者的openid,只有得到了openid才能去申請預付單獲得prepayId,然後去喚起微信支付。

微信支付文件上面也寫的很清楚:

接下來我們編寫PayController類去呼叫微信支付的介面:

package luluteam.wxpay.controller;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import luluteam.wxpay.constant.Constant;
import luluteam.wxpay.entity.PayInfo;
import luluteam.wxpay.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Controller
public class PayController {

    private static Logger log = Logger.getLogger(PayController.class);

    @ResponseBody
    @RequestMapping(value = "/prepay", produces = "text/html;charset=UTF-8")
    public String prePay(String code, ModelMap model, HttpServletRequest request) {

        System.out.println("code:"+code);
        String content = null;
        Map map = new HashMap();
        ObjectMapper mapper = new ObjectMapper();

        boolean result = true;
        String info = "";

        log.error("\n======================================================");
        log.error("code: " + code);

        String openId = getOpenId(code);
        System.out.println("獲取openid啊"+openId);
        if(StringUtils.isBlank(openId)) {
            result = false;
            info = "獲取到openId為空";
        } else {
            openId = openId.replace("\"", "").trim();

            String clientIP = CommonUtil.getClientIp(request);

            log.error("openId: " + openId + ", clientIP: " + clientIP);

            String randomNonceStr = RandomUtils.generateMixString(32);
            String prepayId = unifiedOrder(openId, clientIP, randomNonceStr);

            log.error("prepayId: " + prepayId);

            if(StringUtils.isBlank(prepayId)) {
                result = false;
                info = "出錯了,未獲取到prepayId";
            } else {
                map.put("prepayId", prepayId);
                map.put("nonceStr", randomNonceStr);
            }
        }

        try {
            map.put("result", result);
            map.put("info", info);
            content = mapper.writeValueAsString(map);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return content;
    }


    private String getOpenId(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Constant.APP_ID +
                "&secret=" + Constant.APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";

        HttpUtil httpUtil = new HttpUtil();
        try {

            HttpResult httpResult = httpUtil.doGet(url, null, null);

            if(httpResult.getStatusCode() == 200) {

                JsonParser jsonParser = new JsonParser();
                JsonObject obj = (JsonObject) jsonParser.parse(httpResult.getBody());

                log.error("getOpenId: " + obj.toString());

                if(obj.get("errcode") != null) {
                    log.error("getOpenId returns errcode: " + obj.get("errcode"));
                    return "";
                } else {
                    return obj.get("openid").toString();
                }
                //return httpResult.getBody();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 呼叫統一下單介面
     * @param openId
     */
    private String unifiedOrder(String openId, String clientIP, String randomNonceStr) {

        try {

            String url = Constant.URL_UNIFIED_ORDER;

            PayInfo payInfo = createPayInfo(openId, clientIP, randomNonceStr);
            String md5 = getSign(payInfo);
            payInfo.setSign(md5);

            log.error("md5 value: " + md5);

            String xml = CommonUtil.payInfoToXML(payInfo);
            xml = xml.replace("__", "_").replace("<![CDATA[1]]>", "1");
            //xml = xml.replace("__", "_").replace("<![CDATA[", "").replace("]]>", "");
            log.error(xml);

            StringBuffer buffer = HttpUtil.httpsRequest(url, "POST", xml);
            log.error("unifiedOrder request return body: \n" + buffer.toString());
            Map<String, String> result = CommonUtil.parseXml(buffer.toString());


            String return_code = result.get("return_code");
            if(StringUtils.isNotBlank(return_code) && return_code.equals("SUCCESS")) {

                String return_msg = result.get("return_msg");
                if(StringUtils.isNotBlank(return_msg) && !return_msg.equals("OK")) {
                    //log.error("統一下單錯誤!");
                    return "";
                }

                String prepay_Id = result.get("prepay_id");
                return prepay_Id;

            } else {
                return "";
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }

    private PayInfo createPayInfo(String openId, String clientIP, String randomNonceStr) {

        Date date = new Date();
        String timeStart = TimeUtils.getFormatTime(date, Constant.TIME_FORMAT);
        String timeExpire = TimeUtils.getFormatTime(TimeUtils.addDay(date, Constant.TIME_EXPIRE), Constant.TIME_FORMAT);

        String randomOrderId = CommonUtil.getRandomOrderId();

        PayInfo payInfo = new PayInfo();
        payInfo.setAppid(Constant.APP_ID);
        payInfo.setMch_id(Constant.MCH_ID);
        payInfo.setDevice_info("WEB");
        payInfo.setNonce_str(randomNonceStr);
        payInfo.setSign_type("MD5");  //預設即為MD5
        payInfo.setBody("JSAPI支付測試");
        payInfo.setAttach("支付測試4luluteam");
        payInfo.setOut_trade_no(randomOrderId);
        payInfo.setTotal_fee(1);
        payInfo.setSpbill_create_ip(clientIP);
        payInfo.setTime_start(timeStart);
        payInfo.setTime_expire(timeExpire);
        payInfo.setNotify_url(Constant.URL_NOTIFY);
        payInfo.setTrade_type("JSAPI");
        payInfo.setLimit_pay("no_credit");
        payInfo.setOpenid(openId);

        return payInfo;
    }

    private String getSign(PayInfo payInfo) throws Exception {
        StringBuffer sb = new StringBuffer();
        sb.append("appid=" + payInfo.getAppid())
                .append("&attach=" + payInfo.getAttach())
                .append("&body=" + payInfo.getBody())
                .append("&device_info=" + payInfo.getDevice_info())
                .append("&limit_pay=" + payInfo.getLimit_pay())
                .append("&mch_id=" + payInfo.getMch_id())
                .append("&nonce_str=" + payInfo.getNonce_str())
                .append("&notify_url=" + payInfo.getNotify_url())
                .append("&openid=" + payInfo.getOpenid())
                .append("&out_trade_no=" + payInfo.getOut_trade_no())
                .append("&sign_type=" + payInfo.getSign_type())
                .append("&spbill_create_ip=" + payInfo.getSpbill_create_ip())
                .append("&time_expire=" + payInfo.getTime_expire())
                .append("&time_start=" + payInfo.getTime_start())
                .append("&total_fee=" + payInfo.getTotal_fee())
                .append("&trade_type=" + payInfo.getTrade_type())
                .append("&key=" + Constant.APP_KEY);

        log.error("排序後的拼接引數:" + sb.toString());

        return CommonUtil.getMD5(sb.toString().trim()).toUpperCase();
    }



}

小程式端通過wx.request發起網路請求,通過伺服器發起預支付,獲取prepayId以及其他支付需要簽名的引數後,利用wx.requestPayment發起支付。

// 1. 完成頁面結構、佈局、樣式
// 2. 設計資料結構
// 3. 完成資料繫結
// 4. 設計互動操作事件
// 5. 資料儲存
var app = getApp()   //例項化小程式,從而獲取全域性資料或者使用全域性函式
// console.log(app.globalData)
var MD5Util = require('../../utils/md5.js');

Page({
  // ===== 頁面資料物件 =====
  data: {
    input: '',
    todos: [],
    leftCount: 0,
    allCompleted: false,
    logs: [],
    price: 0.01,
    number: 18820000000,
    deviceNo: 10080925
  },
  
  // ===== 頁面生命週期方法 =====
  onLoad: function () {

  },
  // ===== 事件處理函式 =====
  wxPay: function (e) {
    var code = ''     //傳給伺服器以獲得openId
    var timestamp = String(Date.parse(new Date()))   //時間戳
    var nonceStr = ''   //隨機字串,後臺返回
    var prepayId = ''    //預支付id,後臺返回
    var paySign = ''     //加密字串

    //獲取使用者登入狀態
    wx.login({
      success: function (res) {
        if (res.code) {
          code = res.code
          //發起網路請求,發起的是HTTPS請求,向服務端請求預支付
          wx.request({
            url: 'http://sellbin.natapp1.cc/prepay',
            data: {
              code: res.code
            },
            success: function (res) {
              console.log(res.data);
              if (res.data.result == true) {
                nonceStr = res.data.nonceStr
                prepayId = res.data.prepayId
                // 按照欄位首字母排序組成新字串
                var payDataA = "appId=" + app.globalData.appId + "&nonceStr=" + res.data.nonceStr + "&package=prepay_id=" + res.data.prepayId + "&signType=MD5&timeStamp=" + timestamp;
                var payDataB = payDataA + "&key=" + app.globalData.key;
                // 使用MD5加密演算法計算加密字串
                paySign = MD5Util.MD5(payDataB).toUpperCase();
                // 發起微信支付
                wx.requestPayment({
                  'timeStamp': timestamp,
                  'nonceStr': nonceStr,
                  'package': 'prepay_id=' + prepayId,
                  'signType': 'MD5',
                  'paySign': paySign,
                  'success': function (res) {
                    // 保留當前頁面,跳轉到應用內某個頁面,使用wx.nevigeteBack可以返回原頁面
                    wx.navigateTo({
                      url: '../pay/pay'
                    })
                  },
                  'fail': function (res) {
                    console.log(res.errMsg)
                  }
                })
              } else {
                console.log('請求失敗' + res.data.info)
              }
            }
          })
        } else {
          console.log('獲取使用者登入態失敗!' + res.errMsg)
        }
      }
    });
  },
   formSubmit: function (e) {
    console.log('form發生了submit事件,攜帶資料為:', e.detail.value)
  },
  formReset: function () {
    console.log('form發生了reset事件')
  }
})

接下來,我們貼一下微信退款相關的程式碼RefundController

package luluteam.wxpay.controller;

import luluteam.wxpay.constant.Constant;
import luluteam.wxpay.entity.WxRefundInfoEntity;
import luluteam.wxpay.service.WxRefundInfoService;
import luluteam.wxpay.util.common.PayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.*;

@Controller
public class RefundController extends HttpServlet {

    private static Logger log = Logger.getLogger(PayController.class);

    @Autowired
    private WxRefundInfoService wxRefundInfoService;

    @RequestMapping(params = "refund", method = RequestMethod.POST)
    @Transactional
    public @ResponseBody
    Map<String, Object> refund(String openid, String orderId, HttpServletRequest request) {
        Map<String, Object> result = new HashMap<String, Object>();
        String currTime = PayUtils.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = PayUtils.buildRandom(4) + "";
        String nonceStr = strTime + strRandom;
        String outRefundNo = "[email protected]@" + PayUtils.getTimeStamp();
        String outTradeNo = "";
        String transactionId = "";

        String unionId = openid;
        String appid = Constant.APP_ID;
        String mchid = Constant.MCH_ID;
        String key =  Constant.APP_KEY;//mch_key
//        String key = ResourceUtil.getConfigByName("wx.application.mch_key");
        if (StringUtils.isNotEmpty(orderId)) {
            int total_fee = 1;
            //商戶側傳給微信的訂單號32位
            outTradeNo = "115151sdasdsadsadsadas";
            DecimalFormat df = new DecimalFormat("0.00");
            //String fee = String.valueOf(df.format((float)total_fee/100));
            String fee = String.valueOf(total_fee);
            SortedMap<String, String> packageParams = new TreeMap<String, String>();
            packageParams.put("appid", appid);
            packageParams.put("mch_id", mchid);//微信支付分配的商戶號
            packageParams.put("nonce_str", nonceStr);//隨機字串,不長於32位
            packageParams.put("op_user_id", mchid);//操作員帳號, 預設為商戶號
            //out_refund_no只能含有數字、字母和字元_-|*@
            packageParams.put("out_refund_no", outRefundNo);//商戶系統內部的退款單號,商戶系統內部唯一,同一退款單號多次請求只退一筆
            packageParams.put("out_trade_no", outTradeNo);//商戶側傳給微信的訂單號32位
            packageParams.put("refund_fee", fee);
            packageParams.put("total_fee", fee);
            packageParams.put("transaction_id", transactionId);//微信生成的訂單號,在支付通知中有返回
            String sign = PayUtils.createSign(packageParams, key);

            String refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
            String xmlParam = "<xml>" +
                    "<appid>" + appid + "</appid>" +
                    "<mch_id>" + mchid + "</mch_id>" +
                    "<nonce_str>" + nonceStr + "</nonce_str>" +
                    "<op_user_id>" + mchid + "</op_user_id>" +
                    "<out_refund_no>" + outRefundNo + "</out_refund_no>" +
                    "<out_trade_no>" + outTradeNo + "</out_trade_no>" +
                    "<refund_fee>" + fee + "</refund_fee>" +
                    "<total_fee>" + fee + "</total_fee>" +
                    "<transaction_id>" + transactionId + "</transaction_id>" +
                    "<sign>" + sign + "</sign>" +
                    "</xml>";
            log.info("---------xml返回:" + xmlParam);
            String resultStr = PayUtils.post(refundUrl, xmlParam);
            log.info("---------退款返回:" + resultStr);
            //解析結果
            try {
                Map map = PayUtils.doXMLParse(resultStr);
                String returnCode = map.get("return_code").toString();
                if (returnCode.equals("SUCCESS")) {
                    String resultCode = map.get("result_code").toString();
                    if (resultCode.equals("SUCCESS")) {
                        //儲存退款記錄,可在資料庫建一個退款表記錄
                        WxRefundInfoEntity refundInfoEntity = new WxRefundInfoEntity();
                        refundInfoEntity.setCreateDate(new Date());
                        refundInfoEntity.setAppid(appid);
                        refundInfoEntity.setMchId(mchid);
                        refundInfoEntity.setNonceStr(nonceStr);
                        refundInfoEntity.setSign(sign);
                        refundInfoEntity.setOutRefundNo(outRefundNo);
                        refundInfoEntity.setOutTradeNo(outTradeNo);
                        refundInfoEntity.setTotalFee(total_fee);
                        refundInfoEntity.setRefundFee(total_fee);
                        refundInfoEntity.setUnionid(unionId);
                        wxRefundInfoService.save(refundInfoEntity);
                        result.put("status", "success");
                    } else {
                        result.put("status", "fail");
                    }
                } else {
                    result.put("status", "fail");
                }
            } catch (Exception e) {
                e.printStackTrace();
                result.put("status", "fail");
            }
        }
        return result;
    }
}

支付與退款有關的工具類和實體類一併貼在下面,如果有不清楚的,可以去我的github上面下載原始碼:

https://github.com/wenbingshen/wechatpay

entity包:

package luluteam.wxpay.entity;

import java.io.Serializable;

public class PayInfo implements Serializable {

    private String appid;
    private String mch_id;
    private String device_info; //裝置號,小程式傳"WEB"
    private String nonce_str;
    private String sign;
    private String sign_type;  //簽名型別
    private String body;
    //private String detail;
    private String attach;
    private String out_trade_no;
    private int total_fee;
    private String spbill_create_ip;
    private String time_start;
    private String time_expire;
    private String notify_url;
    private String trade_type; //交易型別,JSAPI
    private String limit_pay;  //指定支付方式,no_credit
    private String openid;

    public String getAppid() {
        return appid;
    }

    public void setAppid(String appid) {
        this.appid = appid;
    }

    public String getMch_id() {
        return mch_id;
    }

    public void setMch_id(String mch_id) {
        this.mch_id = mch_id;
    }

    public String getDevice_info() {
        return device_info;
    }

    public void setDevice_info(String device_info) {
        this.device_info = device_info;
    }

    public String getNonce_str() {
        return nonce_str;
    }

    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getSign_type() {
        return sign_type;
    }

    public void setSign_type(String sign_type) {
        this.sign_type = sign_type;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getAttach() {
        return attach;
    }

    public void setAttach(String attach) {
        this.attach = attach;
    }

    public String getOut_trade_no() {
        return out_trade_no;
    }

    public void setOut_trade_no(String out_trade_no) {
        this.out_trade_no = out_trade_no;
    }

    public int getTotal_fee() {
        return total_fee;
    }

    public void setTotal_fee(int total_fee) {
        this.total_fee = total_fee;
    }

    public String getSpbill_create_ip() {
        return spbill_create_ip;
    }

    public void setSpbill_create_ip(String spbill_create_ip) {
        this.spbill_create_ip = spbill_create_ip;
    }

    public String getTime_start() {
        return time_start;
    }

    public void setTime_start(String time_start) {
        this.time_start = time_start;
    }

    public String getTime_expire() {
        return time_expire;
    }

    public void setTime_expire(String time_expire) {
        this.time_expire = time_expire;
    }

    public String getNotify_url() {
        return notify_url;
    }

    public void setNotify_url(String notify_url) {
        this.notify_url = notify_url;
    }

    public String getTrade_type() {
        return trade_type;
    }

    public void setTrade_type(String trade_type) {
        this.trade_type = trade_type;
    }

    public String getLimit_pay() {
        return limit_pay;
    }

    public void setLimit_pay(String limit_pay) {
        this.limit_pay = limit_pay;
    }

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }
}
WxRefundInfoEntity類,用來退款後向資料新增退款的記錄,方面查賬:
package luluteam.wxpay.entity;

import javax.persistence.Entity;
import java.io.Serializable;
import java.util.Date;

@Entity
public class WxRefundInfoEntity implements Serializable {
    private Date createDate;

    private String appid;

    private String mchId;

    private String nonceStr;

    private String sign;

    private String outRefundNo;

    private String outTradeNo;

    private int totalFee;

    private int refundFee;

    private String unionid;

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public String getAppid() {
        return appid;
    }

    public void setAppid(String appid) {
        this.appid = appid;
    }

    public String getMchId() {
        return mchId;
    }

    public void setMchId(String mchId) {
        this.mchId = mchId;
    }

    public String getNonceStr() {
        return nonceStr;
    }

    public void setNonceStr(String nonceStr) {
        this.nonceStr = nonceStr;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getOutRefundNo() {
        return outRefundNo;
    }

    public void setOutRefundNo(String outRefundNo) {
        this.outRefundNo = outRefundNo;
    }

    public String getOutTradeNo() {
        return outTradeNo;
    }

    public void setOutTradeNo(String outTradeNo) {
        this.outTradeNo = outTradeNo;
    }

    public int getTotalFee() {
        return totalFee;
    }

    public void setTotalFee(int totalFee) {
        this.totalFee = totalFee;
    }

    public int getRefundFee() {
        return refundFee;
    }

    public void setRefundFee(int refundFee) {
        this.refundFee = refundFee;
    }

    public String getUnionid() {
        return unionid;
    }

    public void setUnionid(String unionid) {
        this.unionid = unionid;
    }
}

util包:

package luluteam.wxpay.util.common;

import java.security.MessageDigest;

public class MD5 {
    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
            "8", "9", "a", "b", "c", "d", "e", "f"};

    /**
     * 轉換位元組陣列為16進位制字串
     * @param b 位元組陣列
     * @return 16進位制字串
     */
    public static String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (byte aB : b) {
            resultSb.append(byteToHexString(aB));
        }
        return resultSb.toString();
    }

    /**
     * 轉換byte到16進位制
     * @param b 要轉換的byte
     * @return 16進位制格式
     */
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    /**
     * MD5編碼
     * @param origin 原始字串
     * @return 經過MD5加密之後的結果
     */
    public static String MD5Encode(String origin) {
        String resultString = null;
        try {
            resultString = origin;
            MessageDigest md = MessageDigest.getInstance("MD5");
            resultString = byteArrayToHexString(md.digest(resultString.getBytes("utf-8")));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultString;
    }

}
package luluteam.wxpay.util.common;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import luluteam.wxpay.constant.Constant;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;


@SuppressWarnings("deprecation")
public class PayUtils {
    private static Object Server;
    @SuppressWarnings("deprecation")
    public static DefaultHttpClient httpclient;
    private static SortedMap parameters;

    static {
        httpclient = new DefaultHttpClient();
        // httpclient = (DefaultHttpClient) HttpClientConnectionManager.getSSLInstance(httpclient);
        parameters = new TreeMap();
    }

    public static final String KEY_PATH = "E:/wxzf/cert/apiclient_cert.p12";

    /**
     * 把物件轉換成字串
     *
     * @param obj
     * @retur