一、前期准备
做微信开发首先要申请一个公共账号,申请成功后会以邮件形式发给你一些必要信息,公共账号中有开发文档以及开发中必要信息,以及测试的数据查询。
二、工具类
1.MD5加密工具类
- package com.pay.utils.weixin;
- import java.security.MessageDigest;
- public class MD5Util {
- public final static String MD5(String s) {
- char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- try {
- byte[] btInput = s.getBytes();
- // 获得MD5摘要算法的 MessageDigest 对象
- MessageDigest mdInst = MessageDigest.getInstance("MD5");
- // 使用指定的字节更新摘要
- mdInst.update(btInput);
- // 获得密文
- byte[] md = mdInst.digest();
- // 把密文转换成十六进制的字符串形式
- int j = md.length;
- char str[] = new char[j * 2];
- int k = 0;
- for (int i = 0; i < j; i++) {
- byte byte0 = md[i];
- str[k++] = hexDigits[byte0 >>> 4 & 0xf];
- str[k++] = hexDigits[byte0 & 0xf];
- }
- return new String(str);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- }
2.CommonUtil工具类,用于装换成微信所需XML。以下return new String(xml.toString().getBytes(),"ISO8859-1");将工具类中的utf-8改成iso8859-1,否则微信订单中的中文会出现乱码,改后可以正确显示。
- package com.pay.utils.weixin;
- import java.io.UnsupportedEncodingException;
- import java.net.URLEncoder;
- import java.util.*;
- import java.util.Map.Entry;
- public class CommonUtil {
- public static String CreateNoncestr(int length) {
- String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- String res = "";
- for (int i = 0; i < length; i++) {
- Random rd = new Random();
- res += chars.indexOf(rd.nextInt(chars.length() - 1));
- }
- return res;
- }
- public static String CreateNoncestr() {
- String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- String res = "";
- for (int i = 0; i < 16; i++) {
- Random rd = new Random();
- res += chars.charAt(rd.nextInt(chars.length() - 1));
- }
- return res;
- }
- public static String FormatQueryParaMap(HashMap<String, String> parameters)
- throws SDKRuntimeException {
- String buff = "";
- try {
- List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
- parameters.entrySet());
- Collections.sort(infoIds,
- new Comparator<Map.Entry<String, String>>() {
- public int compare(Map.Entry<String, String> o1,
- Map.Entry<String, String> o2) {
- return (o1.getKey()).toString().compareTo(
- o2.getKey());
- }
- });
- for (int i = 0; i < infoIds.size(); i++) {
- Map.Entry<String, String> item = infoIds.get(i);
- if (item.getKey() != "") {
- buff += item.getKey() + "="
- + URLEncoder.encode(item.getValue(), "utf-8") + "&";
- }
- }
- if (buff.isEmpty() == false) {
- buff = buff.substring(0, buff.length() - 1);
- }
- } catch (Exception e) {
- throw new SDKRuntimeException(e.getMessage());
- }
- return buff;
- }
- public static String FormatBizQueryParaMap(HashMap<String, String> paraMap,
- boolean urlencode) throws SDKRuntimeException {
- String buff = "";
- try {
- List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
- paraMap.entrySet());
- Collections.sort(infoIds,
- new Comparator<Map.Entry<String, String>>() {
- public int compare(Map.Entry<String, String> o1,
- Map.Entry<String, String> o2) {
- return (o1.getKey()).toString().compareTo(
- o2.getKey());
- }
- });
- for (int i = 0; i < infoIds.size(); i++) {
- Map.Entry<String, String> item = infoIds.get(i);
- //System.out.println(item.getKey());
- if (item.getKey() != "") {
- String key = item.getKey();
- String val = item.getValue();
- if (urlencode) {
- val = URLEncoder.encode(val, "utf-8");
- }
- buff += key.toLowerCase() + "=" + val + "&";
- }
- }
- if (buff.isEmpty() == false) {
- buff = buff.substring(0, buff.length() - 1);
- }
- } catch (Exception e) {
- throw new SDKRuntimeException(e.getMessage());
- }
- return buff;
- }
- public static boolean IsNumeric(String str) {
- if (str.matches("\\d *")) {
- return true;
- } else {
- return false;
- }
- }
- public static String ArrayToXml(HashMap<String, String> arr) {
- String xml = "<xml>";
- Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
- while (iter.hasNext()) {
- Entry<String, String> entry = iter.next();
- String key = entry.getKey();
- String val = entry.getValue();
- if (IsNumeric(val)) {
- xml += "<" + key + ">" + val + "</" + key + ">";
- } else
- xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
- }
- xml += "</xml>";
- try {
- return new String(xml.toString().getBytes(),"ISO8859-1");
- } catch (UnsupportedEncodingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return "";
- }
- }
3.ClientCustomSSL工具类,用于生成sign以及创建微信订单
- package com.pay.utils.weixin;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.springframework.util.StringUtils;
- /**
- * This example demonstrates how to create secure connections with a custom SSL
- * context.
- */
- public class ClientCustomSSL {
- public static String GetBizSign(HashMap<String, String> bizObj)
- throws SDKRuntimeException {
- HashMap<String, String> bizParameters = new HashMap<String, String>();
- List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
- bizObj.entrySet());
- System.out.println(infoIds);
- Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
- public int compare(Map.Entry<String, String> o1,
- Map.Entry<String, String> o2) {
- return (o1.getKey()).toString().compareTo(o2.getKey());
- }
- });
- System.out.println("--------------------");
- System.out.println(infoIds);
- for (int i = 0; i < infoIds.size(); i++) {
- Map.Entry<String, String> item = infoIds.get(i);
- if (item.getKey() != "") {
- bizParameters.put(item.getKey().toLowerCase(), item.getValue());
- }
- }
- //bizParameters.put("key", "12345678123456781234567812345671");
- String bizString = CommonUtil.FormatBizQueryParaMap(bizParameters,
- false);
- bizString += "&key=12345678123456781234567812345671";
- System.out.println("***************");
- System.out.println(bizString);
- // return SHA1Util.Sha1(bizString);
- return MD5Util.MD5(bizString);
- }
- /**
- * 微信创建订单
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @return
- * @throws SDKRuntimeException
- */
- public static String CreateNativePackage(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号"); //公众账号Id
- nativeObj.put("mch_id", "见邮件"); //商户号
- nativeObj.put("nonce_str", nonceStr); //随机字符串
- nativeObj.put("body", orderDescribe); //商品描述
- nativeObj.put("attach", "tradeno"); //附加数据
- nativeObj.put("out_trade_no", orderNo); //商户订单号(全局唯一)
- nativeObj.put("total_fee", price); //总金额(单位为分,不能带小数点)
- nativeObj.put("spbill_create_ip","192.168.0.144"); //终端Ip
- nativeObj.put("time_start", timeStart); //交易起始时间
- nativeObj.put("time_expire", timeExpire); //交易结束时间
- nativeObj.put("notify_url", CustomizedPropertyPlaceholderConfigurer.getContextProperty("wxurl")+"/weixin_callback/weixinCallback/init.action"); //回调通知地址
- nativeObj.put("trade_type", "NATIVE"); //交易类型
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- /**
- * 微信订单支付查询
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @return
- * @throws SDKRuntimeException
- */
- public static String SearchNativePackage(String transactionId,String outTradeNo,String nonceStr) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众共账号"); //公众账号Id
- nativeObj.put("mch_id", "见邮件");//商户号
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- if(!StringUtils.isEmpty(transactionId)){
- nativeObj.put("transaction_id", transactionId);
- }
- if(!StringUtils.isEmpty(outTradeNo)){
- nativeObj.put("out_trade_no", outTradeNo);//随机字符串
- }
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- /**
- * 微信退款
- * @param outTradeNo
- * @param outRefundNo
- * @param totalFee
- * @param refundFee
- * @return
- * @throws SDKRuntimeException
- */
- public static String RefundNativePackage(String outTradeNo,String outRefundNo,String totalFee,String refundFee,String nonceStr) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号");//公众账号Id
- nativeObj.put("mch_id", "见邮件");//商户号
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- nativeObj.put("out_trade_no", outTradeNo);//商户订单号(全局唯一)
- nativeObj.put("out_refund_no", outRefundNo);//商户退款单号(全局唯一)
- nativeObj.put("total_fee", totalFee);//总金额(单位为分,不能带小数点)
- nativeObj.put("refund_fee", refundFee);//退款金额(单位为分,不能带小数点)
- nativeObj.put("op_user_id", "邮件");
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- /**
- * 微信待支付
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @return
- * @throws SDKRuntimeException
- */
- public static String CreateJsApiPackage(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire,String openId) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号");//公众账号Id
- nativeObj.put("openid", openId);//公众账号Id
- nativeObj.put("mch_id", "见邮件")//商户号
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- nativeObj.put("body", orderDescribe);//商品描述
- nativeObj.put("attach", "tradeno");//附加数据
- nativeObj.put("out_trade_no", orderNo);//商户订单号(全局唯一)
- nativeObj.put("total_fee", price);//总金额(单位为分,不能带小数点)
- nativeObj.put("spbill_create_ip","192.168.0.144");//终端Ip
- nativeObj.put("time_start", timeStart);//交易起始时间
- nativeObj.put("time_expire", timeExpire)//交易结束时间
- nativeObj.put("notify_url",CustomizedPropertyPlaceholderConfigurer.getContextProperty("wxurl")+"/weixin_callback/weixinCallback/init.action");//通知地址
- nativeObj.put("trade_type", "JSAPI");//交易类型
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- /**
- * 微信关闭订单
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @param openId
- * @return
- * @throws SDKRuntimeException
- */
- public static String CreateCloseOrder(String outTradeNo,String nonceStr) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号");//公众账号Id
- nativeObj.put("mch_id", "见邮件");//商户号
- nativeObj.put("out_trade_no", outTradeNo);//商户订单号(全局唯一)
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- }
4.调用微信支付接口
- package com.pay.controller.weixin;
- import java.io.File;
- import java.io.FileInputStream;
- import java.security.KeyStore;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.List;
- import javax.net.ssl.SSLContext;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import net.sf.json.JSONArray;
- import net.sf.json.JSONObject;
- 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.dom4j.Document;
- import org.dom4j.DocumentHelper;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.http.HttpStatus;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseStatus;
- import org.springframework.web.bind.annotation.RestController;
- import com.pay.bo.PayHist;
- import com.pay.constants.PayHistoryPayStatus;
- import com.pay.constants.PayHistoryPayType;
- import com.pay.service.WeiXinPayService;
- import com.pay.utils.weixin.ClientCustomSSL;
- import com.pay.utils.weixin.CloseWeiXinOrderUtils;
- import com.pay.utils.weixin.CustomizedPropertyPlaceholderConfigurer;
- @RestController
- @RequestMapping("/Pay")
- public class WeiXinPayController {
- @Autowired
- WeiXinPayService weiXinPayService;
- private static long standardTime = 1662652800000L;
- /**
- * 返回生成二维码的url
- * @param request
- * @param response
- * @return
- */
- @RequestMapping(value="/getUrl",method=RequestMethod.POST)
- @ResponseStatus(HttpStatus.OK)
- public Object getUrl(HttpServletResponse response,@RequestBody String body){
- try{
- JSONObject jsonO = JSONObject.fromObject(body);
- PayHist ph = null;
- // List<Map<String,Object>> td = weiXinPayService.getTrade(orderNo);
- Date dt = new Date();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
- String nonceStr = sdf.format(dt).toString();
- Date now = new Date();
- String tradePayNo = jsonO.get("orderNo").toString()+String.format("%10d",standardTime - now.getTime()).substring(0, 10);
- System.out.println("订单标号orderNo======="+jsonO.get("orderNo").toString());
- System.out.println("10位随机数======="+String.format("%10d",standardTime - now.getTime()).substring(0, 10));
- String price = Math.round(Float.valueOf(jsonO.get("price").toString())*100)+"";
- Long timeExpireStrOld = dt.getTime();
- Long timeNew = Long.parseLong(CustomizedPropertyPlaceholderConfigurer.getContextProperty("weixin.send2finish.overtime").toString());
- Long timeExpireNew = timeExpireStrOld+timeNew;
- Date dtTimeExpire = new Date(timeExpireNew);
- SimpleDateFormat dtSdf = new SimpleDateFormat("yyyyMMddHHmmss");
- String timeExpire = dtSdf.format(dtTimeExpire).toString();
- System.out.println("nonceStr=="+nonceStr);
- System.out.println("orderNo=="+jsonO.get("orderNo").toString());
- System.out.println("price=="+price);
- System.out.println("timeStart=="+nonceStr);
- System.out.println("timeExpire=="+timeExpire);
- JSONObject result = (JSONObject) setUrl(nonceStr,"订单",tradePayNo,price,nonceStr,timeExpire);
- if(result.get("status").toString().equals("success")){
- ph = new PayHist();
- ph.setTradePayUrl(result.getString("weixinPayUrl"));//此字段为支付链接,可以此链接生成二维码扫码支付
- ph.setPayTradeNo(jsonO.get("orderNo").toString());
- ph.setTradePayNo(tradePayNo);
- ph.setPayStatus(PayHistoryPayStatus.WECHAT_PAY_STATUS_WAIT);
- ph.setPayType(PayHistoryPayType.WECHAT);
- ph.setAppKey(jsonO.getString("appKey").toString());
- ph.setPayAmount(price);
- result.put("payTradeNo", ph.getPayTradeNo());
- result.put("tradePayNo", ph.getTradePayNo());
- result.put("payStatus", ph.getPayStatus());
- result.put("payType", ph.getPayType());
- }
- return result;
- }catch(Exception e){
- e.printStackTrace();
- JSONObject result = new JSONObject();
- result.put("status","error");
- result.put("msg",e.getMessage());
- // return result.toString();
- }
- return null;
- }
- public Object setUrl(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire) {
- try{
- KeyStore keyStore = KeyStore.getInstance("PKCS12");
- FileInputStream instream = new FileInputStream(new File(微信证书绝对路径));
- try {
- keyStore.load(instream, "商户ID".toCharArray());
- }finally {
- instream.close();
- }
- // Trust own CA and all self-signed certs
- SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,<span style="font-family: Arial, Helvetica, sans-serif;">商户ID</span>.toCharArray()).build();
- // Allow TLSv1 protocol only
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
- sslcontext, new String[] { "TLSv1" }, null,
- SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- CloseableHttpClient httpclient = HttpClients.custom()
- .setSSLSocketFactory(sslsf).build();
- // HttpGet httpget = new
- // HttpGet("https://api.mch.weixin.qq.com/secapi/pay/refund");
- HttpPost httppost = new HttpPost(
- "https://api.mch.weixin.qq.com/pay/unifiedorder");
- String xml = ClientCustomSSL.CreateNativePackage(nonceStr,orderDescribe,orderNo,price,timeStart,timeExpire);
- try {
- StringEntity se = new StringEntity(xml);
- httppost.setEntity(se);
- System.out.println("executing request" + httppost.getRequestLine());
- CloseableHttpResponse responseEntry = httpclient.execute(httppost);
- try {
- HttpEntity entity = responseEntry.getEntity();
- System.out.println("----------------------------------------");
- System.out.println(responseEntry.getStatusLine());
- if (entity != null) {
- System.out.println("Response content length: "
- + entity.getContentLength());
- /* BufferedReader bufferedReader = new BufferedReader(
- new InputStreamReader(entity.getContent()));
- String text;
- while ((text = bufferedReader.readLine()) != null) {
- System.out.println("======="+text);
- }*/
- SAXReader saxReader = new SAXReader();
- Document document = saxReader.read(entity.getContent());
- Element rootElt = document.getRootElement();
- System.out.println("根节点:" + rootElt.getName());
- System.out.println("==="+rootElt.elementText("result_code"));
- System.out.println("==="+rootElt.elementText("return_msg"));
- String resultCode = rootElt.elementText("result_code");
- JSONObject result = new JSONObject();
- Document documentXml =DocumentHelper.parseText(xml);
- Element rootEltXml = documentXml.getRootElement();
- if(resultCode.equals("SUCCESS")){
- System.out.println("=================prepay_id===================="+ rootElt.elementText("prepay_id"));
- System.out.println("=================sign===================="+ rootEltXml.elementText("sign"));
- result.put("weixinPayUrl", rootElt.elementText("code_url"));
- result.put("prepayId", rootElt.elementText("prepay_id"));
- result.put("status","success");
- result.put("msg","success");
- }else{
- result.put("status","false");
- result.put("msg",rootElt.elementText("err_code_des"));
- }
- return result;
- }
- EntityUtils.consume(entity);
- }
- finally {
- responseEntry.close();
- }
- }
- finally {
- httpclient.close();
- }
- return null;
- }catch(Exception e){
- e.printStackTrace();
- JSONObject result = new JSONObject();
- result.put("status","error");
- result.put("msg",e.getMessage());
- return result;
- }
- }
- }
httpclient jar包下载地址:http://download.csdn.net/detail/wangxuewei111/8460181
json jar包现在地址:http://download.csdn.net/detail/wangxuewei111/8460185
一、前期准备
做微信开发首先要申请一个公共账号,申请成功后会以邮件形式发给你一些必要信息,公共账号中有开发文档以及开发中必要信息,以及测试的数据查询。
二、工具类
1.MD5加密工具类
- package com.pay.utils.weixin;
- import java.security.MessageDigest;
- public class MD5Util {
- public final static String MD5(String s) {
- char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- try {
- byte[] btInput = s.getBytes();
- // 获得MD5摘要算法的 MessageDigest 对象
- MessageDigest mdInst = MessageDigest.getInstance("MD5");
- // 使用指定的字节更新摘要
- mdInst.update(btInput);
- // 获得密文
- byte[] md = mdInst.digest();
- // 把密文转换成十六进制的字符串形式
- int j = md.length;
- char str[] = new char[j * 2];
- int k = 0;
- for (int i = 0; i < j; i++) {
- byte byte0 = md[i];
- str[k++] = hexDigits[byte0 >>> 4 & 0xf];
- str[k++] = hexDigits[byte0 & 0xf];
- }
- return new String(str);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
- }
2.CommonUtil工具类,用于装换成微信所需XML。以下return new String(xml.toString().getBytes(),"ISO8859-1");将工具类中的utf-8改成iso8859-1,否则微信订单中的中文会出现乱码,改后可以正确显示。
- package com.pay.utils.weixin;
- import java.io.UnsupportedEncodingException;
- import java.net.URLEncoder;
- import java.util.*;
- import java.util.Map.Entry;
- public class CommonUtil {
- public static String CreateNoncestr(int length) {
- String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- String res = "";
- for (int i = 0; i < length; i++) {
- Random rd = new Random();
- res += chars.indexOf(rd.nextInt(chars.length() - 1));
- }
- return res;
- }
- public static String CreateNoncestr() {
- String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- String res = "";
- for (int i = 0; i < 16; i++) {
- Random rd = new Random();
- res += chars.charAt(rd.nextInt(chars.length() - 1));
- }
- return res;
- }
- public static String FormatQueryParaMap(HashMap<String, String> parameters)
- throws SDKRuntimeException {
- String buff = "";
- try {
- List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
- parameters.entrySet());
- Collections.sort(infoIds,
- new Comparator<Map.Entry<String, String>>() {
- public int compare(Map.Entry<String, String> o1,
- Map.Entry<String, String> o2) {
- return (o1.getKey()).toString().compareTo(
- o2.getKey());
- }
- });
- for (int i = 0; i < infoIds.size(); i++) {
- Map.Entry<String, String> item = infoIds.get(i);
- if (item.getKey() != "") {
- buff += item.getKey() + "="
- + URLEncoder.encode(item.getValue(), "utf-8") + "&";
- }
- }
- if (buff.isEmpty() == false) {
- buff = buff.substring(0, buff.length() - 1);
- }
- } catch (Exception e) {
- throw new SDKRuntimeException(e.getMessage());
- }
- return buff;
- }
- public static String FormatBizQueryParaMap(HashMap<String, String> paraMap,
- boolean urlencode) throws SDKRuntimeException {
- String buff = "";
- try {
- List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
- paraMap.entrySet());
- Collections.sort(infoIds,
- new Comparator<Map.Entry<String, String>>() {
- public int compare(Map.Entry<String, String> o1,
- Map.Entry<String, String> o2) {
- return (o1.getKey()).toString().compareTo(
- o2.getKey());
- }
- });
- for (int i = 0; i < infoIds.size(); i++) {
- Map.Entry<String, String> item = infoIds.get(i);
- //System.out.println(item.getKey());
- if (item.getKey() != "") {
- String key = item.getKey();
- String val = item.getValue();
- if (urlencode) {
- val = URLEncoder.encode(val, "utf-8");
- }
- buff += key.toLowerCase() + "=" + val + "&";
- }
- }
- if (buff.isEmpty() == false) {
- buff = buff.substring(0, buff.length() - 1);
- }
- } catch (Exception e) {
- throw new SDKRuntimeException(e.getMessage());
- }
- return buff;
- }
- public static boolean IsNumeric(String str) {
- if (str.matches("\\d *")) {
- return true;
- } else {
- return false;
- }
- }
- public static String ArrayToXml(HashMap<String, String> arr) {
- String xml = "<xml>";
- Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
- while (iter.hasNext()) {
- Entry<String, String> entry = iter.next();
- String key = entry.getKey();
- String val = entry.getValue();
- if (IsNumeric(val)) {
- xml += "<" + key + ">" + val + "</" + key + ">";
- } else
- xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
- }
- xml += "</xml>";
- try {
- return new String(xml.toString().getBytes(),"ISO8859-1");
- } catch (UnsupportedEncodingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return "";
- }
- }
3.ClientCustomSSL工具类,用于生成sign以及创建微信订单
- package com.pay.utils.weixin;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.springframework.util.StringUtils;
- /**
- * This example demonstrates how to create secure connections with a custom SSL
- * context.
- */
- public class ClientCustomSSL {
- public static String GetBizSign(HashMap<String, String> bizObj)
- throws SDKRuntimeException {
- HashMap<String, String> bizParameters = new HashMap<String, String>();
- List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
- bizObj.entrySet());
- System.out.println(infoIds);
- Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
- public int compare(Map.Entry<String, String> o1,
- Map.Entry<String, String> o2) {
- return (o1.getKey()).toString().compareTo(o2.getKey());
- }
- });
- System.out.println("--------------------");
- System.out.println(infoIds);
- for (int i = 0; i < infoIds.size(); i++) {
- Map.Entry<String, String> item = infoIds.get(i);
- if (item.getKey() != "") {
- bizParameters.put(item.getKey().toLowerCase(), item.getValue());
- }
- }
- //bizParameters.put("key", "12345678123456781234567812345671");
- String bizString = CommonUtil.FormatBizQueryParaMap(bizParameters,
- false);
- bizString += "&key=12345678123456781234567812345671";
- System.out.println("***************");
- System.out.println(bizString);
- // return SHA1Util.Sha1(bizString);
- return MD5Util.MD5(bizString);
- }
- /**
- * 微信创建订单
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @return
- * @throws SDKRuntimeException
- */
- public static String CreateNativePackage(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号"); //公众账号Id
- nativeObj.put("mch_id", "见邮件"); //商户号
- nativeObj.put("nonce_str", nonceStr); //随机字符串
- nativeObj.put("body", orderDescribe); //商品描述
- nativeObj.put("attach", "tradeno"); //附加数据
- nativeObj.put("out_trade_no", orderNo); //商户订单号(全局唯一)
- nativeObj.put("total_fee", price); //总金额(单位为分,不能带小数点)
- nativeObj.put("spbill_create_ip","192.168.0.144"); //终端Ip
- nativeObj.put("time_start", timeStart); //交易起始时间
- nativeObj.put("time_expire", timeExpire); //交易结束时间
- nativeObj.put("notify_url", CustomizedPropertyPlaceholderConfigurer.getContextProperty("wxurl")+"/weixin_callback/weixinCallback/init.action"); //回调通知地址
- nativeObj.put("trade_type", "NATIVE"); //交易类型
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- /**
- * 微信订单支付查询
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @return
- * @throws SDKRuntimeException
- */
- public static String SearchNativePackage(String transactionId,String outTradeNo,String nonceStr) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众共账号"); //公众账号Id
- nativeObj.put("mch_id", "见邮件");//商户号
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- if(!StringUtils.isEmpty(transactionId)){
- nativeObj.put("transaction_id", transactionId);
- }
- if(!StringUtils.isEmpty(outTradeNo)){
- nativeObj.put("out_trade_no", outTradeNo);//随机字符串
- }
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- /**
- * 微信退款
- * @param outTradeNo
- * @param outRefundNo
- * @param totalFee
- * @param refundFee
- * @return
- * @throws SDKRuntimeException
- */
- public static String RefundNativePackage(String outTradeNo,String outRefundNo,String totalFee,String refundFee,String nonceStr) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号");//公众账号Id
- nativeObj.put("mch_id", "见邮件");//商户号
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- nativeObj.put("out_trade_no", outTradeNo);//商户订单号(全局唯一)
- nativeObj.put("out_refund_no", outRefundNo);//商户退款单号(全局唯一)
- nativeObj.put("total_fee", totalFee);//总金额(单位为分,不能带小数点)
- nativeObj.put("refund_fee", refundFee);//退款金额(单位为分,不能带小数点)
- nativeObj.put("op_user_id", "邮件");
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- /**
- * 微信待支付
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @return
- * @throws SDKRuntimeException
- */
- public static String CreateJsApiPackage(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire,String openId) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号");//公众账号Id
- nativeObj.put("openid", openId);//公众账号Id
- nativeObj.put("mch_id", "见邮件")//商户号
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- nativeObj.put("body", orderDescribe);//商品描述
- nativeObj.put("attach", "tradeno");//附加数据
- nativeObj.put("out_trade_no", orderNo);//商户订单号(全局唯一)
- nativeObj.put("total_fee", price);//总金额(单位为分,不能带小数点)
- nativeObj.put("spbill_create_ip","192.168.0.144");//终端Ip
- nativeObj.put("time_start", timeStart);//交易起始时间
- nativeObj.put("time_expire", timeExpire)//交易结束时间
- nativeObj.put("notify_url",CustomizedPropertyPlaceholderConfigurer.getContextProperty("wxurl")+"/weixin_callback/weixinCallback/init.action");//通知地址
- nativeObj.put("trade_type", "JSAPI");//交易类型
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- /**
- * 微信关闭订单
- * @param nonceStr
- * @param orderDescribe
- * @param orderNo
- * @param price
- * @param timeStart
- * @param timeExpire
- * @param openId
- * @return
- * @throws SDKRuntimeException
- */
- public static String CreateCloseOrder(String outTradeNo,String nonceStr) throws SDKRuntimeException {
- HashMap<String, String> nativeObj = new HashMap<String, String>();
- nativeObj.put("appid", "见公众账号");//公众账号Id
- nativeObj.put("mch_id", "见邮件");//商户号
- nativeObj.put("out_trade_no", outTradeNo);//商户订单号(全局唯一)
- nativeObj.put("nonce_str", nonceStr);//随机字符串
- String sign = GetBizSign(nativeObj);
- nativeObj.put("sign", sign.toUpperCase());
- return CommonUtil.ArrayToXml(nativeObj);
- }
- }
4.调用微信支付接口
- package com.pay.controller.weixin;
- import java.io.File;
- import java.io.FileInputStream;
- import java.security.KeyStore;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.List;
- import javax.net.ssl.SSLContext;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import net.sf.json.JSONArray;
- import net.sf.json.JSONObject;
- 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.dom4j.Document;
- import org.dom4j.DocumentHelper;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.http.HttpStatus;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseStatus;
- import org.springframework.web.bind.annotation.RestController;
- import com.pay.bo.PayHist;
- import com.pay.constants.PayHistoryPayStatus;
- import com.pay.constants.PayHistoryPayType;
- import com.pay.service.WeiXinPayService;
- import com.pay.utils.weixin.ClientCustomSSL;
- import com.pay.utils.weixin.CloseWeiXinOrderUtils;
- import com.pay.utils.weixin.CustomizedPropertyPlaceholderConfigurer;
- @RestController
- @RequestMapping("/Pay")
- public class WeiXinPayController {
- @Autowired
- WeiXinPayService weiXinPayService;
- private static long standardTime = 1662652800000L;
- /**
- * 返回生成二维码的url
- * @param request
- * @param response
- * @return
- */
- @RequestMapping(value="/getUrl",method=RequestMethod.POST)
- @ResponseStatus(HttpStatus.OK)
- public Object getUrl(HttpServletResponse response,@RequestBody String body){
- try{
- JSONObject jsonO = JSONObject.fromObject(body);
- PayHist ph = null;
- // List<Map<String,Object>> td = weiXinPayService.getTrade(orderNo);
- Date dt = new Date();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
- String nonceStr = sdf.format(dt).toString();
- Date now = new Date();
- String tradePayNo = jsonO.get("orderNo").toString()+String.format("%10d",standardTime - now.getTime()).substring(0, 10);
- System.out.println("订单标号orderNo======="+jsonO.get("orderNo").toString());
- System.out.println("10位随机数======="+String.format("%10d",standardTime - now.getTime()).substring(0, 10));
- String price = Math.round(Float.valueOf(jsonO.get("price").toString())*100)+"";
- Long timeExpireStrOld = dt.getTime();
- Long timeNew = Long.parseLong(CustomizedPropertyPlaceholderConfigurer.getContextProperty("weixin.send2finish.overtime").toString());
- Long timeExpireNew = timeExpireStrOld+timeNew;
- Date dtTimeExpire = new Date(timeExpireNew);
- SimpleDateFormat dtSdf = new SimpleDateFormat("yyyyMMddHHmmss");
- String timeExpire = dtSdf.format(dtTimeExpire).toString();
- System.out.println("nonceStr=="+nonceStr);
- System.out.println("orderNo=="+jsonO.get("orderNo").toString());
- System.out.println("price=="+price);
- System.out.println("timeStart=="+nonceStr);
- System.out.println("timeExpire=="+timeExpire);
- JSONObject result = (JSONObject) setUrl(nonceStr,"订单",tradePayNo,price,nonceStr,timeExpire);
- if(result.get("status").toString().equals("success")){
- ph = new PayHist();
- ph.setTradePayUrl(result.getString("weixinPayUrl"));//此字段为支付链接,可以此链接生成二维码扫码支付
- ph.setPayTradeNo(jsonO.get("orderNo").toString());
- ph.setTradePayNo(tradePayNo);
- ph.setPayStatus(PayHistoryPayStatus.WECHAT_PAY_STATUS_WAIT);
- ph.setPayType(PayHistoryPayType.WECHAT);
- ph.setAppKey(jsonO.getString("appKey").toString());
- ph.setPayAmount(price);
- result.put("payTradeNo", ph.getPayTradeNo());
- result.put("tradePayNo", ph.getTradePayNo());
- result.put("payStatus", ph.getPayStatus());
- result.put("payType", ph.getPayType());
- }
- return result;
- }catch(Exception e){
- e.printStackTrace();
- JSONObject result = new JSONObject();
- result.put("status","error");
- result.put("msg",e.getMessage());
- // return result.toString();
- }
- return null;
- }
- public Object setUrl(String nonceStr,String orderDescribe,String orderNo,String price,String timeStart,String timeExpire) {
- try{
- KeyStore keyStore = KeyStore.getInstance("PKCS12");
- FileInputStream instream = new FileInputStream(new File(微信证书绝对路径));
- try {
- keyStore.load(instream, "商户ID".toCharArray());
- }finally {
- instream.close();
- }
- // Trust own CA and all self-signed certs
- SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,<span style="font-family: Arial, Helvetica, sans-serif;">商户ID</span>.toCharArray()).build();
- // Allow TLSv1 protocol only
- SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
- sslcontext, new String[] { "TLSv1" }, null,
- SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- CloseableHttpClient httpclient = HttpClients.custom()
- .setSSLSocketFactory(sslsf).build();
- // HttpGet httpget = new
- // HttpGet("https://api.mch.weixin.qq.com/secapi/pay/refund");
- HttpPost httppost = new HttpPost(
- "https://api.mch.weixin.qq.com/pay/unifiedorder");
- String xml = ClientCustomSSL.CreateNativePackage(nonceStr,orderDescribe,orderNo,price,timeStart,timeExpire);
- try {
- StringEntity se = new StringEntity(xml);
- httppost.setEntity(se);
- System.out.println("executing request" + httppost.getRequestLine());
- CloseableHttpResponse responseEntry = httpclient.execute(httppost);
- try {
- HttpEntity entity = responseEntry.getEntity();
- System.out.println("----------------------------------------");
- System.out.println(responseEntry.getStatusLine());
- if (entity != null) {
- System.out.println("Response content length: "
- + entity.getContentLength());
- /* BufferedReader bufferedReader = new BufferedReader(
- new InputStreamReader(entity.getContent()));
- String text;
- while ((text = bufferedReader.readLine()) != null) {
- System.out.println("======="+text);
- }*/
- SAXReader saxReader = new SAXReader();
- Document document = saxReader.read(entity.getContent());
- Element rootElt = document.getRootElement();
- System.out.println("根节点:" + rootElt.getName());
- System.out.println("==="+rootElt.elementText("result_code"));
- System.out.println("==="+rootElt.elementText("return_msg"));
- String resultCode = rootElt.elementText("result_code");
- JSONObject result = new JSONObject();
- Document documentXml =DocumentHelper.parseText(xml);
- Element rootEltXml = documentXml.getRootElement();
- if(resultCode.equals("SUCCESS")){
- System.out.println("=================prepay_id===================="+ rootElt.elementText("prepay_id"));
- System.out.println("=================sign===================="+ rootEltXml.elementText("sign"));
- result.put("weixinPayUrl", rootElt.elementText("code_url"));
- result.put("prepayId", rootElt.elementText("prepay_id"));
- result.put("status","success");
- result.put("msg","success");
- }else{
- result.put("status","false");
- result.put("msg",rootElt.elementText("err_code_des"));
- }
- return result;
- }
- EntityUtils.consume(entity);
- }
- finally {
- responseEntry.close();
- }
- }
- finally {
- httpclient.close();
- }
- return null;
- }catch(Exception e){
- e.printStackTrace();
- JSONObject result = new JSONObject();
- result.put("status","error");
- result.put("msg",e.getMessage());
- return result;
- }
- }
- }
httpclient jar包下载地址:http://download.csdn.net/detail/wangxuewei111/8460181
json jar包现在地址:http://download.csdn.net/detail/wangxuewei111/8460185