审计记录

src/org/theyeasy/weixin/service/impl/WxPayServiceImpl.java 8.6 KB
zxt@theyeasy.com committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
package org.theyeasy.weixin.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
import java.util.Random;

import javax.annotation.PostConstruct;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import javax.servlet.jsp.jstl.core.Config;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.theyeasy.weixin.service.WxPayService;
import org.theyeasy.weixin.util.MD5Util;
import org.theyeasy.weixin.util.WxMessageUtil;

import com.sun.org.apache.xerces.internal.parsers.XMLParser;
import com.w1hd.zzhnc.config.WxPayConfig;
import com.w1hd.zzhnc.vo.Vo_msg;

@Service
public class WxPayServiceImpl implements WxPayService{
	@Autowired 
	WxPayConfig config;
	
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	
	private String mch_appid = "";
	private String mchid = "";
	private String key = "";
	private String cert_file="";
	private String spbill_create_ip="";
	 
	
	@PostConstruct
    public void init() {
		mch_appid = config.getMchappid();
		mchid = config.getMchid();
		key = config.getKey();
		cert_file = config.getCertFile();
		spbill_create_ip = config.getIp();
	}
	
	@Override
	public Vo_msg payMoney(String partner_trade_no, String openid, int amount, String desc) {
		Vo_msg msg = new Vo_msg(-1,null,"未知错误");
		try {					
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			FileInputStream instream = new FileInputStream(new File(cert_file));
			try {
				keyStore.load(instream, mchid.toCharArray());
			} finally {
				instream.close();
			}

			String nonce_str = getRandomString(30);
			String sign = getSign(nonce_str, partner_trade_no, openid, "NO_CHECK", amount, desc, spbill_create_ip);
			System.out.println("sign=" + sign);
			
			//构造xml参数
			StringBuffer sb = new StringBuffer();
			sb.append("<xml>\n");
			sb.append("<mch_appid>").append(mch_appid).append("</mch_appid>").append("\n");
			sb.append("<mchid>").append(mchid).append("</mchid>").append("\n");
			sb.append("<nonce_str>").append(nonce_str).append("</nonce_str>").append("\n");
			sb.append("<partner_trade_no>").append(partner_trade_no).append("</partner_trade_no>").append("\n");
			sb.append("<openid>").append(openid).append("</openid>").append("\n");
			sb.append("<check_name>").append("NO_CHECK").append("</check_name>").append("\n");
			sb.append("<amount>").append(amount).append("</amount>").append("\n");
			sb.append("<desc>").append(desc).append("</desc>").append("\n");
			sb.append("<spbill_create_ip>").append(spbill_create_ip).append("</spbill_create_ip>").append("\n");
			sb.append("<sign>").append(sign).append("</sign>").append("\n");
			sb.append("</xml>");
			String param = sb.toString();
			System.out.println(param);
			String uri = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
			// Trust own CA and all self-signed certs
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray()).build();
			// Allow TLSv1 protocol only
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			try {
				HttpPost httppost = new HttpPost(uri);
				httppost.setEntity(new StringEntity(param, Charset.forName("UTF-8")));
				
				httppost.setHeader("Content-Type","text/xml");  
				httppost.setHeader("charset","utf-8");  
	             		       
				CloseableHttpResponse response = httpclient.execute(httppost);
				try {
					HttpEntity entity = response.getEntity();

					System.out.println("----------------------------------------");
					System.out.println(response.getStatusLine());
					if (entity != null) {
						System.out.println("Response content length: " + entity.getContentLength());
						BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
						StringBuffer sb2 = new StringBuffer();
						String text;
						while ((text = bufferedReader.readLine()) != null) {
							sb2.append(text);
						}
						log.info(sb2.toString());
						Map<String, String> requestMap = WxMessageUtil.parseXml(sb2.toString());
			        	String code = requestMap.get("return_code");
			        	String resultCode = requestMap.get("result_code");
			        	if(code.equals("SUCCESS")&&resultCode.equals("SUCCESS")) //成功
			        	{
			        		String payment_no = requestMap.get("payment_no");
			        		msg = new Vo_msg(0, null, payment_no);
			        	}
			        	else {
			        		String errmsg = requestMap.get("err_code_des");
			        		msg = new Vo_msg(-1,null,errmsg);
			        		log.info("企业付款到零钱失败:" + errmsg);
						}			        
					}
					EntityUtils.consume(entity);
				} finally {
					response.close();
				}
			} finally {
				httpclient.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
			msg = new Vo_msg(-1, null, "系统处理失败!");
		}
		return msg;
	}

	
	/**
	 * 获取签名sign
	 * @param nonce_str  随机字符串,最长32位
	 * @param partner_trade_no  订单号
	 * @param openid   粉丝的openid
	 * @param check_name  是否实名验证
	 * @param amount   金额(单位:分)
	 * @param desc  付款描述
	 * @param spbill_create_ip  调用api的ip
	 * @return
	 */
	private String getSign(String nonce_str,String partner_trade_no, String openid, String check_name, int amount, String desc, String spbill_create_ip) {

		String[] array = new String[9];
		array[0] = "mch_appid=" + mch_appid;
		array[1] = "mchid=" + mchid;
		array[2] = "nonce_str=" + nonce_str;
		array[3] = "partner_trade_no=" + partner_trade_no;
		array[4] = "openid=" + openid;
		array[5] = "check_name=" + check_name;
		array[6] = "amount=" + amount;
		array[7] = "desc=" + desc;
		array[8] = "spbill_create_ip=" + spbill_create_ip;

		StringBuffer sb = new StringBuffer();
		// 字符串排序
		Arrays.sort(array);
		for (int i = 0; i <array.length; i++) {
			sb.append(array[i]).append("&");
		}

		sb.append("key=" + key);
		String signTemp = sb.toString();
		System.out.println(signTemp);
		String sign = MD5Util.getMD5(signTemp);

		return sign;
	}

	

	/**
	 * 生成签名数据_HmacSHA1加密(用以验证微信服务端发过来的签名),对getSignStr的结果进行加密
	 * 
	 * @param data
	 *            待加密的数据
	 * @param key
	 *            加密使用的key
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 */
	public static String hash_hmac(String signStr, String key) {
		try {
			byte[] keyBytes = key.getBytes();
			// 根据给定的字节数组构造一个密钥。
			SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");
			Mac mac = Mac.getInstance("HmacSHA256");
			mac.init(signingKey);

			byte[] rawHmac = mac.doFinal(signStr.getBytes());

			String hexBytes = byte2hex(rawHmac).toUpperCase();
			return hexBytes;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "error";
	}

	/**
	 * byte To Hex
	 * @param b
	 * @return
	 */
	public static String byte2hex(final byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			// 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式。
			stmp = (java.lang.Integer.toHexString(b[n] & 0xFF));
			if (stmp.length() == 1) {
				hs = hs + "0" + stmp;
			} else {
				hs = hs + stmp;
			}
		}
		return hs;
	}
	 
	
	/**
	 * 构造指定长的随机字符串
	 * @param length
	 * @return 指定长度的随机字符串
	 */
	public static String getRandomString(int length) { // length表示生成字符串的长度
		String base = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}
}