微信支付

1、準備基本配置信息(即在微信支付平臺申請的APP_ID、APP_SECRET、PARTNER、PARTNER_KEY)php

//微信支付標識
public   static final   String APP_ID="xxxxx";
//微信支付密鑰
public   static final   String APP_SECRET="xxxxxx";
//商戶號支付密鑰
public  static  final  String PARTNER_KEY="xxxxx";
//商戶號
public  static  final  String PARTNER="xxxx";

2、調用微信支付平臺中的統一下單API,進行下單處理(參數簽名、生成支付ID等信息給客戶端),參數說明參照,官網說明html

3、如何在服務端進行下單操做:java

1.構建微信支付服務器簽名支付請求請求類node

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;



/*
 '微信支付服務器簽名支付請求請求類
 '============================================================================
 'api說明:
 'init(app_id, app_secret, partner_key, app_key);
 '初始化函數,默認給一些參數賦值,如cmdno,date等。
 'setKey(key_)'設置商戶密鑰
 'getLasterrCode(),獲取最後錯誤號
 'GetToken();獲取Token
 'getTokenReal();Token過時後實時獲取Token
 'createMd5Sign(signParams);生成Md5簽名
 'genPackage(packageParams);獲取package包
 'createSHA1Sign(signParams);建立簽名SHA1
 'sendPrepay(packageParams);提交預支付
 'getDebugInfo(),獲取debug信息
 '============================================================================
 '*/
public class RequestHandler {
	/** Token獲取網關地址地址 */
	private String tokenUrl;
	/** 預支付網關url地址 */
	private String gateUrl;
	/** 查詢支付通知網關URL */
	private String notifyUrl;
	/** 商戶參數 */
	private String appid;
	private String appkey;
	private String partnerkey;
	private String appsecret;
	private String key;
	/** 請求的參數 */
	private SortedMap parameters;
	/** Token */
	private String Token;
	private String charset;
	/** debug信息 */
	private String debugInfo;
	private String last_errcode;

	private HttpServletRequest request;

	private HttpServletResponse response;

	/**
	 * 初始構造函數。
	 * 
	 * @return
	 */
	public RequestHandler(HttpServletRequest request,
			HttpServletResponse response) {
		this.last_errcode = "0";
		this.request = request;
		this.response = response;
		//this.charset = "GBK";
		this.charset = "UTF-8";
		this.parameters = new TreeMap();
		// 驗證notify支付訂單網關
		notifyUrl = "https://gw.tenpay.com/gateway/simpleverifynotifyid.xml";
		
	}

	/**
	 * 初始化函數。
	 */
	public void init(String app_id, String app_secret,	String partner_key) {
		this.last_errcode = "0";
		this.Token = "token_";
		this.debugInfo = "";
		this.appid = app_id;
		this.partnerkey = partner_key;
		this.appsecret = app_secret;
		this.key = partner_key;
	}

	public void init() {
	}

	/**
	 * 獲取最後錯誤號
	 */
	public String getLasterrCode() {
		return last_errcode;
	}

	/**
	 *獲取入口地址,不包含參數值
	 */
	public String getGateUrl() {
		return gateUrl;
	}

	/**
	 * 獲取參數值
	 * 
	 * @param parameter
	 *            參數名稱
	 * @return String
	 */
	public String getParameter(String parameter) {
		String s = (String) this.parameters.get(parameter);
		return (null == s) ? "" : s;
	}

	
	 //設置密鑰
	
	public void setKey(String key) {
		this.partnerkey = key;
	}
	//設置微信密鑰
	public void  setAppKey(String key){
		this.appkey = key;
	}
	
	// 特殊字符處理
	public String UrlEncode(String src) throws UnsupportedEncodingException {
		return URLEncoder.encode(src, this.charset).replace("+", "%20");
	}

	// 獲取package的簽名包
	public String genPackage(SortedMap<String, String> packageParams,String partnerkey)
			throws UnsupportedEncodingException {
		String sign = createSign(packageParams,partnerkey);

		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();
			sb.append(k + "=" + UrlEncode(v) + "&");
		}

		// 去掉最後一個&
		String packageValue = sb.append("sign=" + sign).toString();
//		System.out.println("UrlEncode後 packageValue=" + packageValue);
		return packageValue;
	}

	/**
	 * 建立md5摘要,規則是:按參數名稱a-z排序,遇到空值的參數不參加簽名。
	 */
	public   String createSign(SortedMap<String, String> packageParams,String partnerkey) {
		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 (null != v && !"".equals(v) && !"sign".equals(k)&& !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + partnerkey);
		System.out.println("md5 sb:" + sb+"key="+this.getKey());
		String sign = MD5Util.MD5Encode(sb.toString(), this.charset)
				.toUpperCase();
		System.out.println("packge簽名:" + sign);
		return sign;

	}
	/**
	 * 建立package簽名
	 */
	public boolean createMd5Sign(String signParams) {
		StringBuffer sb = new StringBuffer();
		Set es = this.parameters.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 + "&");
			}
		}

		// 算出摘要
		String enc = TenpayUtil.getCharacterEncoding(this.request,
				this.response);
		String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();

		String tenpaySign = this.getParameter("sign").toLowerCase();

		// debug信息
		this.setDebugInfo(sb.toString() + " => sign:" + sign + " tenpaySign:"
				+ tenpaySign);

		return tenpaySign.equals(sign);
	}

	

    //輸出XML
	   public String parseXML() {
		   StringBuffer sb = new StringBuffer();
	       sb.append("<xml>");
	       Set es = this.parameters.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(null != v && !"".equals(v) && !"appkey".equals(k)) {
					
					sb.append("<" + k +">" + getParameter(k) + "</" + k + ">\n");
				}
			}
	       sb.append("</xml>");
			return sb.toString();
		}

	/**
	 * 設置debug信息
	 */
	protected void setDebugInfo(String debugInfo) {
		this.debugInfo = debugInfo;
	}
	public void setPartnerkey(String partnerkey) {
		this.partnerkey = partnerkey;
	}
	public String getDebugInfo() {
		return debugInfo;
	}
	public String getKey() {
		return partnerkey;
	}

}

2.構建微信支付簽名參數git

private String weiPaySignParams(String imei, String reqIP, RequestHandler reqHandler, String remoteAddr, String orderNo, ThirdOrderInfoObj thirdOrderObj, WeUserModel weUserModel, String goodsOrderToken) {
        String result = "";
        try {

            //接收財付統統知的URL 即訂單支付完成回調地址
            String notify_url = SysUtil.readPro("weiPayV3.callback.path");
            //金額轉化爲分爲單位
            String finalmoney = (int)(thirdOrderObj.getPayprice()*100)+"";

            WeiPayObj weiPayObj =  new WeiPayObj(orderNo,notify_url,orderNo,finalmoney,remoteAddr,"商品購買") ;
            WeiPayObj resultWeiPayObj = WeiPaySignUtils.weiPaySign(weiPayObj,reqHandler);
            int addResult = OrderUtils.createOrder(imei,reqIP,"weiPay", orderNo, "", resultWeiPayObj.getFinalSign(),thirdOrderObj,weUserModel,goodsOrderToken);
            if(addResult>0){
                result = OrderUtils.printJson(1, "上報成功", WeiPayConfig.APP_ID, WeiPayConfig.PARTNER, "Sign=WXPay", resultWeiPayObj.getNonceStr(), resultWeiPayObj.getTimestamp(), resultWeiPayObj.getPrepayId(), resultWeiPayObj.getFinalSign(), orderNo, "", thirdOrderObj.getOrdernum());
            }else{
                result = "{\"status\":0,\"errorCode\":\"5004\",\"message\":\"訂單入庫失敗\"}";
            }


        } catch (Exception e) {
            log.error("", e);
            e.printStackTrace();
            result = "{\"status\":0,\"errorCode\":\"5003\",\"message\":\"簽名過程失敗\"}";
        }
        return result;
    }

3.構建微信支付參數實體類WeiPayObj apache

public class WeiPayObj {
    private String orderNum;
    private String notifyUrl; //回調地址
    private String orderNo;    //訂單號
    private String finalMoney; //金額
    private String remoteAddr;   //Ip 默認 127.0.0.1
    private String nonceStr;  //隨機串
    private String timestamp; //時間戳
    private String prepayId;    //預付單ID
    private String finalSign;   //簽名結果
    private String attach;   //訂單描述
    // 省略 set get方法
}

4.構建微信支付簽名工具類api

import com.tenpay.util.WXUtil;
import com.weipayv3.utils.RequestHandler;
import com.weipayv3.utils.Sha1Util;
import com.weipayv3.utils.WeiPayConfig;
import com.weipayv3.utils.WxOrderUtil;

import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 微信支付V3版簽名
 */
public class WeiPaySignUtils {

    public static WeiPayObj weiPaySign(WeiPayObj weiPayObj,RequestHandler reqHandler){
        String appid = WeiPayConfig.APP_ID;
        //應用對應的憑證
        String appsecret = WeiPayConfig.APP_SECRET;
        //商戶號對應的密鑰
        String partnerkey = WeiPayConfig.PARTNER_KEY;
        //商戶號
        String partner = WeiPayConfig.PARTNER;
        //隨機串
        String noncestr = getNonceStr();
        String body = weiPayObj.getOrderNum();
        String attach = weiPayObj.getAttach();
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("attach", attach);
        //商品
        packageParams.put("body", body);

        packageParams.put("mch_id", partner);
        //隨機串
        packageParams.put("nonce_str", noncestr);
        //回調地址
        packageParams.put("notify_url", weiPayObj.getNotifyUrl());
        //商品訂單號
        packageParams.put("out_trade_no", weiPayObj.getOrderNo());
        //這裏寫的金額爲1 分到時修改
        packageParams.put("total_fee", weiPayObj.getFinalMoney());
        packageParams.put("trade_type", "APP");
        //請求地址
        packageParams.put("spbill_create_ip", weiPayObj.getRemoteAddr());

        reqHandler.init(appid, appsecret, partnerkey);
        //預付單簽名
        String sign = reqHandler.createSign(packageParams,partnerkey);

        String xml = "<xml>" +
                "<appid>" + appid + "</appid>" +
                "<mch_id>" + partner + "</mch_id>" +
                "<nonce_str>" + noncestr + "</nonce_str>" +
                "<sign>" + sign + "</sign>" +
                "<body><![CDATA[" + body + "]]></body>" +
                "<attach>" + attach + "</attach>" +
                "<out_trade_no>" + weiPayObj.getOrderNo() + "</out_trade_no>" +
                "<total_fee>" + weiPayObj.getFinalMoney() + "</total_fee>" +
                "<spbill_create_ip>" + weiPayObj.getRemoteAddr() + "</spbill_create_ip>" +
                "<notify_url>" + weiPayObj.getNotifyUrl() + "</notify_url>" +
                "<trade_type>APP</trade_type>" +
                "</xml>";

        //預付單
        String prepay_id = WxOrderUtil.getPrepayId(xml);

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appid", appid);
        finalpackage.put("noncestr", noncestr);
        finalpackage.put("package", "Sign=WXPay");
        finalpackage.put("partnerid", partner);
        finalpackage.put("prepayid", prepay_id);
        finalpackage.put("timestamp", timestamp);
        //簽名
        String finalsign = reqHandler.createSign(finalpackage,partnerkey);
        weiPayObj.setPrepayId(prepay_id);
        weiPayObj.setTimestamp(timestamp);
        weiPayObj.setNonceStr(noncestr);
        weiPayObj.setFinalSign(finalsign);
        return weiPayObj;
    }

	public String getNonceStr() {
		Random random = new Random();
		return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), "GBK");
	}


}

4.構建參數簽名工具類服務器

/*
'============================================================================
'api說明:
'createSHA1Sign建立簽名SHA1
'getSha1()Sha1簽名
'============================================================================
'*/
public class Sha1Util {

	public static String getNonceStr() {
		Random random = new Random();
		return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), "UTF-8");
	}
	public static String getTimeStamp() {
		return String.valueOf(System.currentTimeMillis() / 1000);
	}
	
   //建立簽名SHA1
	public static String createSHA1Sign(SortedMap<String, String> signParams) throws Exception {
		StringBuffer sb = new StringBuffer();
		Set es = signParams.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();
			sb.append(k + "=" + v + "&");
			//要採用URLENCODER的原始值!
		}
		String params = sb.substring(0, sb.lastIndexOf("&"));
//		System.out.println("sha1以前:" + params);
//		System.out.println("SHA1簽名爲:"+getSha1(params));
		return getSha1(params);
	}
	//Sha1簽名
	public static String getSha1(String str) {
		if (str == null || str.length() == 0) {
			return null;
		}
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'a', 'b', 'c', 'd', 'e', 'f' };

		try {
			MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
			mdTemp.update(str.getBytes("UTF-8"));

			byte[] md = mdTemp.digest();
			int j = md.length;
			char buf[] = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
				buf[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(buf);
		} catch (Exception e) {
			return null;
		}
	}
}

5.構建微信支付生成預付單工具類微信

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付訂單工具類
 * @author binshangwen
 * @date 2016-12-14
 */
public class WxOrderUtil{

	/**
	 * 訂單預支付ID
	 */
	public static String getPrepayId(String xml) {
		String prepay_id="";
		String unifiedorder = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		// 建立HttpClientBuilder
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
		// HttpClient
		CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
		HttpPost httpPost = new HttpPost(unifiedorder);
		StringEntity entity;
		try {
			entity = new StringEntity(xml, "utf-8");
			httpPost.setEntity(entity);
			HttpResponse httpResponse;
			// post請求
			httpResponse = closeableHttpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			if (httpEntity != null) {
				// 打印響應內容
				String result = EntityUtils.toString(httpEntity, "UTF-8");
				System.out.println(result);
				// 過濾
				result = result.replaceAll("<![CDATA[|]]>", "");
				prepay_id = Jsoup.parse(result).select("prepay_id").html();
				if (prepay_id != null)
					return prepay_id;
			}
			// 釋放資源
			closeableHttpClient.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return prepay_id;
	}

	/**
	 * 訂單查詢
	 * @param xml
	 * @return
     */
	public static Map<String, String> reqOrderquery(String xml){
		// 建立HttpClientBuilder
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
		// HttpClient
		CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
		HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/pay/orderquery");
		System.out.println(xml);
		StringEntity entity;
		Map<String, String> map = null;
		try {
			entity = new StringEntity(xml, "utf-8");
			httpPost.setEntity(entity);

			HttpResponse httpResponse;
			// post請求
			httpResponse = closeableHttpClient.execute(httpPost);

			// getEntity()
			HttpEntity httpEntity = httpResponse.getEntity();
			if (httpEntity != null) {
				// 打印響應內容
				String result = EntityUtils.toString(httpEntity, "UTF-8");
				System.out.println(result);
				// 過濾
				result = result.replaceAll("<![CDATA[|]]>", "");
				System.out.println(result);
				Document doc= Jsoup.parse(result);
				map = mapPutData(doc);
			}
			// 釋放資源
			closeableHttpClient.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}

	/**
	 *構造訂單查詢返回結果
	 * @param doc
	 * @return
     */
	public static Map<String, String> mapPutData(Document doc){
		Map<String, String> map = new HashMap<String, String>();
		String appid="",mch_id="",sign="",result_code="",err_code="",err_code_des="",
				trade_type="",trade_state="",total_fee="",transaction_id="",out_trade_no="",trade_state_desc="",return_code="",return_msg="";
		if(doc!=null){
			return_code=doc.select("return_code").html();
			return_msg=doc.select("return_msg").html();
			appid=doc.select("appid").html();
			mch_id=doc.select("mch_id").html();
			sign=doc.select("sign").html();
			result_code=doc.select("result_code").html();
			err_code=doc.select("err_code").html();
			err_code_des=doc.select("err_code_des").html();
			trade_type=doc.select("trade_type").html();
			trade_state=doc.select("trade_state").html();
			total_fee=doc.select("total_fee").html();
			transaction_id=doc.select("transaction_id").html();
			out_trade_no =doc.select("out_trade_no").html();
			trade_state_desc =doc.select("trade_state_desc").html();
		}
		map.put("return_code",return_code);
		map.put("return_msg",return_msg);
		map.put("appid",appid);
		map.put("mch_id",mch_id);
		map.put("sign",sign);
		map.put("result_code",result_code);
		map.put("err_code",err_code);
		map.put("err_code_des",err_code_des);
		map.put("trade_type",trade_type);
		map.put("trade_state",trade_state);
		map.put("total_fee",total_fee);
		map.put("transaction_id",transaction_id);
		map.put("out_trade_no",out_trade_no);
		map.put("trade_state_desc",trade_state_desc);
		return map;
	}



}
相關文章
相關標籤/搜索