微信支付
来源:互联网 发布:果蔬清洗机有用吗 知乎 编辑:程序博客网 时间:2024/06/05 09:06
package com.hzbuvi.pay.wechat.controller;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.hzbuvi.pay.wechat.utils.HttpRequest;import com.hzbuvi.pay.wechat.utils.PayCommonUtil;import com.hzbuvi.pay.wechat.utils.WechatUtils;import com.hzbuvi.pay.wechat.utils.XmlUtils;import com.hzbuvi.util.basic.ValueUtil;import com.hzbuvi.util.date.DateUtil;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.*;/** * Created by SJQ on 2017/2/17. */@RestController@RequestMapping("/wechat")public class WechatPay{ private static final Logger log = LoggerFactory.getLogger(WechatPay.class); private static String APPID = "wx29983132bd04dca9";//AppID(应用ID) private static String MCHID= "1435678702"; private static String KEY= "eidiwoeid483"; //32位API密钥 private static String BODY= "order pay";// private static String BODY= "订单支付"; private static String out_trade_no= DateUtil.toString(new Date(),"yyyyMMddHHmmss"); private static String product_id= DateUtil.toString(new Date(),"yyyyMMddHHmmss")+1; private static String notify_url= "http://88.88.88.211:8095/backUrl/wechatPay"; //回调地址。测试回调必须保证外网能访问到此地址 @RequestMapping(value = "/pay",method = RequestMethod.GET) public String pay(@RequestParam Map<String,String> params){ JSONObject retJson = new JSONObject(); try { String jsonStr = ValueUtil.toJson(params); JSONObject requestObj = JSON.parseObject(jsonStr);// String out_trade_no = requestObj.getString("out_trade_no");// String order_price = requestObj.getString("order_price"); // 正式上线的时候价格根据订单id查询 String order_price = "1"; // 价格 注意:价格的单位是分 SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>(); //商户信息 packageParams.put("appid", APPID); //公众账号ID packageParams.put("mch_id", MCHID); //商户号 packageParams.put("nonce_str", WechatUtils.getNonce_str()); //随机字符串 packageParams.put("body",new String(BODY.getBytes("utf-8")) ); //商品描述 eg:腾讯充值中心-QQ会员充值 packageParams.put("trade_type", "NATIVE"); //交易类型 JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里 packageParams.put("spbill_create_ip", "123.12.12.123"); //终端IP eg:123.12.12.123 packageParams.put("notify_url", notify_url); //通知地址 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 packageParams.put("out_trade_no", out_trade_no); //商户订单号 packageParams.put("total_fee", order_price); //标价金额 订单总金额,单位为分,详见支付金额 //MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口 packageParams.put("product_id", product_id); //商品ID trade_type=NATIVE时(即扫码支付),此参数必传。此参数为二维码中包含的商品ID,商户自行定义。 Calendar nowTime = Calendar.getInstance(); packageParams.put("time_start", DateUtil.toString( //交易起始时间 订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。 nowTime.getTime(), "yyyyMMddHHmmss"));// packageParams.put("time_expire", DateUtil.toString( //交易结束时间 订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。// nowTime.getTime(), "yyyyMMddHHmmss")); //生成签名字符串 String sign = PayCommonUtil.createSign("UTF-8", packageParams, KEY); packageParams.put("sign", sign); //签名 String requestXML = PayCommonUtil.getRequestXml(packageParams); log.info("支付请求:" + requestXML); long startTime=System.currentTimeMillis(); String resXml = HttpRequest.post( "https://api.mch.weixin.qq.com/pay/unifiedorder", requestXML); log.info("请求结果:" + resXml); long endTime=System.currentTimeMillis(); Integer execute_time = (int) ((endTime-startTime)/1000); SortedMap map = XmlUtils.parseXmlStr(resXml); Boolean validateCallback = PayCommonUtil.isTenpaySign("utf-8",map,KEY); log.info("验证返回签名结果:" + validateCallback); if (!validateCallback){ return ValueUtil.toError("999","回掉签名验证失败"); } JSONObject reportParams = new JSONObject(); reportParams.put("url", "https://api.mch.weixin.qq.com/pay/unifiedorder"); reportParams.put("execute_time", execute_time); reportParams.put("return_code", map.get("return_code").toString()); reportParams.put("return_msg", map.get("return_msg").toString()); reportParams.put("result_code", map.get("result_code").toString()); if (map.get("err_code") != null) { reportParams.put("err_code", map.get("err_code").toString()); reportParams.put("err_code_des", map.get("err_code_des").toString()); } reportParams.put("out_trade_no", out_trade_no); //交易保障// report(reportParams.toString()); if (map.get("return_code").toString().equals("SUCCESS") && map.get("result_code").toString().equals("SUCCESS")) { String urlCode = (String) map.get("code_url"); //微信二维码短链接 retJson.put("code", 0); retJson.put("message", "下单成功."); retJson.put("data", urlCode); } else { retJson.put("code", 1); retJson.put("message", map.get("err_code_des").toString()); retJson.put("data", ""); } return retJson.toString(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return null; }}
package com.hzbuvi.pay.wechat.utils;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.apache.http.ProtocolException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.net.ssl.HttpsURLConnection;import java.io.*;import java.net.ConnectException;import java.net.MalformedURLException;import java.net.URL;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.text.SimpleDateFormat;import java.util.*;/** * Created by SJQ on 2017/2/17. */public class PayCommonUtil { public static Logger log = LoggerFactory.getLogger(PayCommonUtil.class); /** * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 * @return boolean */ public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) { 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(!"sign".equals(k) && null != v && !"".equals(v)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + API_KEY); //算出摘要 String mysign = MD5.MD5Encode(sb.toString()).toLowerCase(); String tenpaySign = ((String)packageParams.get("sign")).toLowerCase(); //System.out.println(tenpaySign + " " + mysign); return tenpaySign.equals(mysign); }/** * @author * @date 2016-4-22 * @Description:sign签名 * @param characterEncoding * 编码格式 * @params parameters * 请求参数 * @return */ public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) { 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 = ""; try { v = (String) entry.getValue(); } catch (Exception e) { // TODO: handle exception v = entry.getValue() + ""; } if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + API_KEY); System.out.println("ASCII字典序排序::::"+sb.toString()); String sign = MD5.MD5Encode(sb.toString()).toUpperCase(); return sign; } /** * @author * @date 2016-4-22 * @Description:将请求参数转换为xml格式的string * @param parameters * 请求参数 * @return */ public static String getRequestXml(SortedMap<Object, Object> parameters) { StringBuffer sb = new StringBuffer(); sb.append("<xml>"); Set es = parameters.entrySet(); Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); String v = ""; try { v = (String) entry.getValue(); } catch (Exception e) { // TODO: handle exception v = entry.getValue() + ""; } if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) { sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">"); } else { sb.append("<" + k + ">" + v + "</" + k + ">"); } } sb.append("</xml>"); return sb.toString(); } /** * 取出一个指定长度大小的随机正整数. * * @param length * int 设定所取出随机数的长度。length小于11 * @return int 返回生成的随机数。 */ public static int buildRandom(int length) { int num = 1; double random = Math.random(); if (random < 0.1) { random = random + 0.1; } for (int i = 0; i < length; i++) { num = num * 10; } return (int) ((random * num)); } /** * 获取当前时间 yyyyMMddHHmmss * * @return String */ public static String getCurrTime() { Date now = new Date(); SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss"); String s = outFormat.format(now); return s; } public static JSONObject httpsRequestToJsonObject(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; try { StringBuffer buffer = httpsRequest(requestUrl, requestMethod, outputStr); jsonObject = JSON.parseObject(buffer.toString()); } catch (ConnectException ce) { log.error("连接超时:" + ce.getMessage()); } catch (Exception e) { log.error("https请求异常:" + e.getMessage()); } return jsonObject; } private static StringBuffer httpsRequest(String requestUrl, String requestMethod, String output) throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException, MalformedURLException, IOException, ProtocolException, UnsupportedEncodingException { URL url = new URL(requestUrl); HttpsURLConnection connection = (HttpsURLConnection) url .openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setRequestMethod(requestMethod); if (null != output) { OutputStream outputStream = connection.getOutputStream(); outputStream.write(output.getBytes("UTF-8")); outputStream.close(); } // 从输入流读取返回内容 InputStream inputStream = connection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader( inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; StringBuffer buffer = new StringBuffer(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); inputStream.close(); inputStream = null; connection.disconnect(); return buffer; }}
package com.hzbuvi.pay.wechat.utils;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.DocumentHelper;import org.dom4j.Element;import java.util.*;import static javax.swing.text.html.HTML.Tag.BODY;import static javax.swing.text.html.HTML.Tag.HEAD;/** * Created by SJQ on 2017/2/17. */public class XmlUtils { /** * 解析XML字符串 * * @param xml * @return * @throws */ public static SortedMap<String,Object> parseXmlStr(String xml){ SortedMap<String,Object> map = new TreeMap<String, Object>(); try { Document document = DocumentHelper.parseText(xml); Element root = document.getRootElement(); Iterator<Element> it = root.elementIterator(); while (it.hasNext()) { Element element = it.next(); map.put(element.getName(), element.getTextTrim()); } } catch (DocumentException e) { e.printStackTrace(); } return map; }}
package com.hzbuvi.pay.wechat.utils;import java.security.MessageDigest;/** * User: rizenguo * Date: 2014/10/23 * Time: 15:43 */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[] digest) { StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < digest.length; i++) { int val = ((int) digest[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return hexValue.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()));//原文件内容,可能原因是:win2003时系统缺省编码为GBK,win7为utf-8 resultString = byteArrayToHexString(md.digest(resultString.getBytes("utf-8")));//正确的写法 } catch (Exception e) { e.printStackTrace(); } return resultString; }}
package com.hzbuvi.pay.wechat.utils;import java.io.*;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLConnection;import java.util.List;import java.util.Map;/** * Created by SJQ on 2017/2/17. */public class HttpRequest { public static String post(String url,String pama) throws IOException{ URL postUrl = new URL(url); // 打开连接 HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection(); // 设置是否向connection输出,因为这个是post请求,参数要放在 // http正文内,因此需要设为true connection.setDoOutput(true); //设置超时时间 connection.setConnectTimeout(10000); // Read from the connection. Default is true. connection.setDoInput(true); // 默认是 GET方式 connection.setRequestMethod("POST"); // Post 请求不能使用缓存 connection.setUseCaches(false); connection.setInstanceFollowRedirects(true); // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的 // 意思是正文是urlencoded编码过的form参数,下面我们可以看到我们对正文内容使用URLEncoder.encode // 进行编码 connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成, // 要注意的是connection.getOutputStream会隐含的进行connect。 connection.connect(); DataOutputStream out = new DataOutputStream(connection .getOutputStream()); // The URL-encoded contend // 正文,正文内容其实跟get的URL中 '? '后的参数字符串一致 // DataOutputStream.writeBytes将字符串中的16位的unicode字符以8位的字符形式写到流里面 out.writeBytes(pama); out.flush(); out.close(); int status = connection.getResponseCode(); if(status==200){ BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"utf-8")); String line; StringBuffer sb = new StringBuffer(""); while ((line = reader.readLine()) != null){ line = new String(line); sb.append(line); } reader.close(); connection.disconnect(); if(sb.toString().length()>0){ return sb.toString(); } return String.valueOf(status); } return String.valueOf(status); }}
0 0
- 微信、支付宝支付
- 支付宝,微信支付
- 微信支付【支付模式】
- 微信支付Jsapi支付
- 微信支付-刷卡支付
- 微信支付JSAPI支付
- 微信支付 h5 支付
- 支付--微信APP支付
- 微信支付:手机支付
- 支付宝 微信支付
- 支付宝-微信支付
- 微信支付与支付宝支付
- 支付宝支付与微信支付
- 微信支付和支付宝支付
- 微信支付与支付宝支付
- 支付宝支付和微信支付
- 微信支付和支付宝支付
- 支付宝支付接入+微信支付
- linux oracle11g客户端安装笔记
- 卷积神经网络(CNNs / ConvNets) 一
- 自定义滚动条(1)
- RecycleView添加分割线
- Spring @Cacheable注解类内部调用失效问题
- 微信支付
- 携程Android App插件化和动态加载实践
- Struts2---拦截器
- 放在WEB-INF下的jsp文件无法被直接读取
- JavaScript数组
- 自定义滚动条(2)
- how to debug c problem
- web前端表格学习
- python记事