1、前端
支付金额
¥{{money}}
微信支付
推荐使用微信支付
确认支付
2、后端
package com.jbossjf.bootproject.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jbossjf.bootproject.common.*;
import com.jbossjf.bootproject.model.OrderInfo;
import com.jbossjf.bootproject.model.OrderReturnInfo;
import com.jbossjf.bootproject.model.SignInfo;
import com.thoughtworks.xstream.XStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
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.core.env.Environment;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@RestController
public class WeixinController {
private final Logger L = LoggerFactory.getLogger(WeixinController.class);
HelpUtils _HelpUtils = new HelpUtils();
@Autowired
private HttpServletRequest request;
@Autowired
private Environment env;
// @Autowired
// private HttpServletResponse responses;
@RequestMapping("/wxPay")
public String wxPay(String openid) {
try {
} catch (Exception ex) {
L.debug(ex.getMessage());
L.info(ex.getMessage());
L.error(ex.getMessage());
}
return null;
}
@RequestMapping("/GetOpenID")
public String GetOpenID() {
try {
String desc = request.getParameter("desc");
JSONArray jsonArray = JSONArray.parseArray(desc);
String appid = _HelpUtils.GetJsonArrayValue(jsonArray, "appid");
String secret = _HelpUtils.GetJsonArrayValue(jsonArray, "secret");
String code = _HelpUtils.GetJsonArrayValue(jsonArray, "code");
// String code = request.getParameter("code");
HttpGet httpGet = new HttpGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code");
//设置请求器的配置
HttpClient httpClient = HttpClients.createDefault();
HttpResponse res = httpClient.execute(httpGet);
HttpEntity entity = res.getEntity();
String result = EntityUtils.toString(entity, "UTF-8");
// response.getWriter().append(result);
} catch (Exception e) {
}
return "";
}
// @RequestMapping("/WeiXinSign")
@CrossOrigin
@ResponseBody
@RequestMapping(value = "/API/WeiXinSign", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Map WeiXinSign(@RequestBody JSONObject jsonParam) {
Map map = new HashMap<>(1);
try {
String appid = jsonParam.getString("appid");
String prepay_id = jsonParam.getString("prepay_id");
SignInfo signInfo = new SignInfo();
signInfo.setAppId(appid);
long time = System.currentTimeMillis() / 1000;
signInfo.setTimeStamp(String.valueOf(time));
signInfo.setNonceStr(RandomStringGenerator.getRandomStringByLength(32));
signInfo.setRepay_id("prepay_id=" + prepay_id);
signInfo.setSignType("MD5");
//生成签名
String sign = Signature.getSign(signInfo);
map.put("timeStamp", signInfo.getTimeStamp());
map.put("nonceStr", signInfo.getNonceStr());
map.put("package", signInfo.getRepay_id());
map.put("signType", signInfo.getSignType());
map.put("paySign", sign);
return map;
} catch (Exception e) {
// TODO Auto-generated catch block
map.remove("prepay_id");
map.put("prepay_id", e.getMessage());
e.printStackTrace();
L.error("-------", e);
}
return map;
}
// @RequestMapping("/WeiXinPayResult")
@CrossOrigin
@ResponseBody
@RequestMapping(value = "/API/WeiXinPayResult", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Map WeiXinPayResult() {
try {
// TODO Auto-generated method stub
//response.getWriter().append("Served at: ").append(request.getContextPath());
String reqParams = StreamUtil.read(request.getInputStream());
L.info("-------支付结果:" + reqParams);
StringBuffer sb = new StringBuffer("SUCCESS OK ");
//return sb.toString();
// JSONObject json = new JSONObject();
// json.put("pay_result", sb.toString());
Map map = new HashMap<>(1);
map.put("pay_result", sb.toString());
return map;
//return json.toString();
} catch (Exception ex) {
}
return null;
}
// @RequestMapping("/WeixinXiadan")
@CrossOrigin
@ResponseBody
@RequestMapping(value = "/API/WeixinXiadan", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public Map WeixinXiadan(@RequestBody JSONObject jsonParam) {
Map map = new HashMap<>(1);
try {
String appid = jsonParam.getString("appid");
String openid = jsonParam.getString("openid");
String formcode = jsonParam.getString("formcode");
String money = jsonParam.getString("money");
String productDesc = jsonParam.getString("productDesc");
int money_fen = HelpUtils.changeY2F(Double.parseDouble(money));
//String openid = request.getParameter("openid");
OrderInfo order = new OrderInfo();
order.setAppid(appid);
order.setMch_id(Configure.getMch_id()); //商户号
order.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));//随机字符串
// String newbody=new String(productDesc.getBytes("ISO-8859-1"),"UTF-8");//以utf-8编码放入paymentPo,微信支付要求字符编码统一采用UTF-8字符编码
order.setBody(productDesc);//商品描述s
order.setOut_trade_no(formcode);//商户系统内部订单号
// L.info(formcode);
order.setTotal_fee(money_fen);//订单总金额,单位为分
//order.setSpbill_create_ip("127.0.0.1");//调用微信支付API的机器IP
String keyValue = env.getProperty("server.ip");
order.setNotify_url("https://" + keyValue + "/API/WeiXinPayResult");//异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
order.setTrade_type("JSAPI");//交易类型 小程序取值如下:JSAPI
order.setOpenid(openid);
order.setSign_type("MD5");
//生成签名
String sign = Signature.getSign(order);
order.setSign(sign);
//https://api.mch.weixin.qq.com/pay/unifiedorder
//String body = new String(order.toString().getBytes("ISO8859-1"),"UTF-8");
String result = HttpRequest.sendPost("https://api.mch.weixin.qq.com/pay/unifiedorder", order);
System.out.println(result);
L.info("---------下单返回:" + result);
XStream xStream = new XStream();
xStream.alias("xml", OrderReturnInfo.class);
OrderReturnInfo returnInfo = (OrderReturnInfo) xStream.fromXML(result);
// JSONObject json = new JSONObject();
// json.put("prepay_id", returnInfo.getPrepay_id());//微信生成的预支付会话标识,用于后续接口调用中使用,该值有效期为2小时
// //response.getWriter().append(json.toJSONString());
// return json.toString();
map.put("prepay_id", returnInfo.getPrepay_id());
return map;
} catch (Exception e) {
map.remove("prepay_id");
map.put("prepay_id", e.getMessage());
e.printStackTrace();
L.error("-------", e);
}
return map;
}
@RequestMapping("/WeixinSearchOrder")
public Map WeixinSearchOrder() {
try {
} catch (Exception ex) {
}
return null;
}
@RequestMapping("/GetTestInfo")
public Map GetTestInfo() {
Map map = new HashMap<>(1);
try {
map.put("status","test_sucess");
} catch (Exception ex) {
map.put("status","test_error");
}
return map;
}
}
package com.jbossjf.bootproject.common;
public class Configure {
public static String getFile_url() {
return file_url;
}
public static void setFile_url(String file_url) {
Configure.file_url = file_url;
}
public static String getFile_path() {
return file_path;
}
public static void setFile_path(String file_path) {
Configure.file_path = file_path;
}
//上传文件
private static String file_url = "http://localhost:8066";
private static String file_path = "d:/upload/cover";
public static String getImg_path() {
return img_path;
}
public static void setImg_path(String img_path) {
Configure.img_path = img_path;
}
private static String img_path = "d:/upload/image";
//小程序ID
private static String appID = "5555555";//"你的小程序id";
private static String secret = "66666";//"你的小程序的secret";
//商户号
private static String mch_id = "333";//"你的商户号";
private static String key = "55555555";//"你的商户的api秘钥";
//
public static String getSecret() {
return secret;
}
public static void setSecret(String secret) {
Configure.secret = secret;
}
public static String getKey() {
return key;
}
public static void setKey(String key) {
Configure.key = key;
}
public static String getAppID() {
return appID;
}
public static void setAppID(String appID) {
Configure.appID = appID;
}
public static String getMch_id() {
return mch_id;
}
public static void setMch_id(String mch_id) {
Configure.mch_id = mch_id;
}
}
package com.jbossjf.bootproject.common;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 签名
* @author zuoliangzhu
*
*/
public class Signature {
private static final Logger L = LoggerFactory.getLogger(Signature.class);
/**
* 签名算法
* @param o 要参与签名的数据对象
* @return 签名
* @throws IllegalAccessException
*/
public static String getSign(Object o) throws IllegalAccessException {
ArrayList list = new ArrayList();
Class cls = o.getClass();
Field[] fields = cls.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
if (f.get(o) != null && f.get(o) != "") {
String name = f.getName();
XStreamAlias anno = f.getAnnotation(XStreamAlias.class);
if(anno != null)
name = anno.value();
list.add(name + "=" + f.get(o) + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
result += "key=" + Configure.getKey();
System.out.println("签名数据:"+result);
result = MD5.MD5Encode(result).toUpperCase();
return result;
}
public static String getSign(Map map){
ArrayList list = new ArrayList();
for(Map.Entry entry:map.entrySet()){
if(entry.getValue()!=""){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
result += "key=" + Configure.getKey();
//Util.log("Sign Before MD5:" + result);
result = MD5.MD5Encode(result).toUpperCase();
//Util.log("Sign Result:" + result);
return result;
}
}
package com.jbossjf.bootproject.common;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
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.HttpClients;
import org.apache.http.util.EntityUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
public class HttpRequest {
//连接超时时间,默认10秒
private static final int socketTimeout = 10000;
//传输超时时间,默认30秒
private static final int connectTimeout = 30000;
/**
* post请求
* @throws IOException
* @throws ClientProtocolException
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
* @throws KeyManagementException
* @throws UnrecoverableKeyException
*/
public static String sendPost(String url, Object xmlObj) throws ClientProtocolException, IOException, UnrecoverableKeyException, KeyManagementException, KeyStoreException, NoSuchAlgorithmException {
HttpPost httpPost = new HttpPost(url);
//解决XStream对出现双下划线的bug
XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
xStreamForRequestPostData.alias("xml", xmlObj.getClass());
//将要提交给API的数据对象转换成XML格式数据Post给API
String postDataXML = xStreamForRequestPostData.toXML(xmlObj);
//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(postEntity);
//设置请求器的配置
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
httpPost.setConfig(requestConfig);
HttpClient httpClient = HttpClients.createDefault();
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, "UTF-8");
return result;
}
/**
* 自定义证书管理器,信任所有证书
* @author pc
*
*/
public static class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
}
}
package com.jbossjf.bootproject.common;
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[] 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()));
} catch (Exception e) {
e.printStackTrace();
}
return resultString;
}
}
package com.jbossjf.bootproject.common;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class StreamUtil {
public static String read(InputStream is){
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[512];
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
return new String(baos.toByteArray(), 0, baos.size(), "utf-8");
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
}
package com.jbossjf.bootproject.common;
import java.util.Random;
/**
* 随机字符串生成
* @author zuoliangzhu
*
*/
public class RandomStringGenerator {
/**
* 获取一定长度的随机字符串
* @param length 指定字符串长度
* @return 一定长度的字符串
*/
public static String getRandomStringByLength(int 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();
}
}