App里做微信支付的前提是有在微信开放平台注册账号,然后在微信商户平台成为商家,并且在开放平台里绑定商户id
一:设置密钥
在账户中心-API安全-API密钥 里设置下API密钥。
二:写配置文件
配置文件WeixinPayConfig .java
public class WeixinPayConfig {
/**
* 微信开放平台分配的应用ID
*
*/
public static String APP_ID = "应用ID";
/**
* API密钥
*/
public static String KEY="9022C9F9347F970A9CE87BB2A3B7543A";
/**
* 回调地址
*/
public static String CALLBACK_URL = "外网可以访问的不需要参数的接口地址";
/**
* 商户id
*/
public static String MERCHANT_ID= "商户id";
}
三:微信支付
/**
*
* 生成微信支付接口所需的签名
* @param paramMap
* @return
*/
private static String buildWXPaySign(String paramStr) {
Object params[]=paramStr.split("&");
Arrays.sort(params);
int length=params.length;
String signStr="";
if (params != null &&length>0) {
StringBuilder sb=new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(params[i]+"&");
}
sb.append("key="+WeixinPayConfig.KEY);
signStr=MD5Helper.encrypt(sb.toString());
}
return signStr;
}
//生成随机字符串
private static String createNonceStr() {
return UUID.randomUUID().toString().replace("-", "");
}
/**
* 元转换成分
* @param amount
* @return
*/
public static String getMoney(String amount) {
if(amount==null){
return "";
}
// 金额转化为分为单位
// 处理包含, ¥ 或者$的金额
String currency = amount.replaceAll("\\$|\\¥|\\,", "");
int index = currency.indexOf(".");
int length = currency.length();
Long amLong = 0l;
if(index == -1){
amLong = Long.valueOf(currency+"00");
}else if(length - index >= 3){
amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));
}else if(length - index == 2){
amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);
}else{
amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");
}
return amLong.toString();
}
/**
* 微信支付
* @param token
* @param amount
* @param request
* @param response
* @throws UnsupportedEncodingException
*/
@RequestMapping(value = "/recharge.json")
@AuthorizationApi
public void recharge(@CurrentToken Token token,String amount,HttpServletRequest request,HttpServletResponse response) throws Exception{
if(StringUtil.isBlank(amount)) {
apiData(request, response, ReqJson.error(BusinessError.AMOUNT_IS_NULL));
return;
}
if(!ToolUtils.isNumeric(amount)) {
apiData(request, response, ReqJson.error(BusinessError.AMOUNT_IS_ILLEGAL));
return;
}else {
double number=Double.parseDouble(amount);
if(number<0.01||number>10000) {
apiData(request, response, ReqJson.error(BusinessError.EXCEEDING_THE_QUOTA));
return;
}
}
String accessToken=token.getAccessToken();
String body= "测试钱包充值";
String subject="钱包充值";
String tradeNo=generateOrderNo(token.getUserId());
String goodsType="0";
String tradeStaue="1";
String userId=token.getUserId();
String ip="123.12.12.123";
String params="access_token="+accessToken;
tradeBiz.save(new TradeLog(Double.parseDouble(amount), body, subject, tradeNo, goodsType,tradeStaue,userId,"recharge"));
String requestUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
String paramStr="attach="+URLEncoder.encode(params,"utf-8")+"&sign_type=MD5&body="+body+"&appid="+WeixinPayConfig.APP_ID+"&mch_id="+WeixinPayConfig.MERCHANT_ID+"&nonce_str="+createNonceStr()+
"&out_trade_no="+tradeNo+"&total_fee="+getMoney(amount)+"&spbill_create_ip="+ip+"¬ify_url="+basePath+WeixinPayConfig.CALLBACK_URL+"&trade_type="+"APP";
String sign=buildWXPaySign(paramStr);
paramStr=paramStr+"&sign="+sign;
String result = HttpUtil.sendPost(requestUrl,XMLUtil.stringToxml(paramStr));
apiData(request, response, ReqJson.ok(result));
return;
}
/**
* 生成订单id
* @param userId
* @return
*/
private String generateOrderNo(String userId) {
String orderNo="";
String date=DateUtil.formatDate(new Date(), "yyMMddHHmmss");
int hashCode=userId.hashCode();
orderNo=(date+hashCode).replace("-", "");
return orderNo;
}
四:微信支付回调
/**
* 校验签名
* @param map
* @param sign
* @return
*/
private static boolean checkSign(Map map,String sign){
boolean flag=false;
if(map==null||map.size()==0) {
return flag;
}
Object params[]=new Object[map.size()];
int i=0;
for(String key:map.keySet()) {
params[i]=key+"="+map.get(key);
i++;
}
Arrays.sort(params);
int length=params.length;
String signStr="";
if (params != null &&length>0) {
StringBuilder sb=new StringBuilder(length);
for (int j = 0; j < length; j++) {
sb.append(params[j]+"&");
}
sb.append("key="+WeixinPayConfig.KEY);
signStr=MD5Helper.encrypt(sb.toString());
}
if(sign.equals(signStr)) {
flag=true;
}
return flag;
}
private static Map getParamMap(String params){
if(StringUtil.isBlank(params)) {
return null;
}
Map paramMap=new HashMap<>();
String param[]=null;
if(params.contains("&")) {
String paramArray[]=params.split("&");
for (int i = 0; i < paramArray.length; i++) {
param=paramArray[i].split("=");
paramMap.put(param[0], param[1]);
}
}else {
param=params.split("=");
paramMap.put(param[0], param[1]);
}
System.out.println(paramMap.toString());
return paramMap;
}
/**
* 微信支付回调
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value = "/getWeixinPayNotify.json")
public void getWeixinPayNotify(HttpServletRequest request,HttpServletResponse response) throws Exception {
logger.info("********进入回调*******"+request.getMethod());
TradeLog temp=null;
Map map = XMLUtil.xml2Map(request);
String sign=map.get("sign").toString();
map.remove("sign");
boolean flag = checkSign(map, sign);
if (flag) {
String resultCode=map.get("result_code");
String outTradeNo = map.get("out_trade_no");
String params=URLDecoder.decode(map.get("attach"), "utf-8");
Map attachMap=getParamMap(params);
if(attachMap==null||attachMap.size()==0) {
apiData(request, response, ReqJson.error(CommonError.PARAMS_IMPERFECT));
return;
}
String access_token=(String) attachMap.get("access_token");
if (StringUtil.isBlank(access_token)) {
apiData(request, response, ReqJson.error(CommonError.PARAMS_IMPERFECT));
return;
}
// 校验token
Token token = tokenBiz.checkToken(access_token, response);
// 参数access_token不合法
if (token == null) {
ReqDataUtil.apiData(request, response, ReqJson.error(SysReqJsonStatus.PARAMETERS_ACCESS_TOKEN_INVALID));
return;
}
String userId = token.getUserId();
temp = tradeBiz.get(new TradeLog(null, outTradeNo));
if (temp == null) {
apiData(request, response, ReqJson.error(CommonError.PARAMS_IMPERFECT));
return;
}
if (temp != null && !temp.getUserId().equals(userId)) {
apiData(request, response, ReqJson.error(CommonError.PARAMS_IMPERFECT));
return;
}
if (resultCode.equals("SUCCESS")&&temp.getTradeState().equals("1")) { // 交易支付成功的执行相关业务逻辑
if (temp != null) {
}
} else if (resultCode.equals("FAIL")) { // 未付款交易超时关闭,或支付完成后全额退款,执行相关业务逻辑
}
}else {
logger.info("********签名不正确*******");
}
String str = "return_code=SUCCESS&return_msg=OK";
response.getWriter().write(XMLUtil.stringToxml(str));
return;
}
工具类XMLUtil.java
/**
* 将请求的xml转成map
* @param request
* @return
* @throws IOException
*/
public static Map xml2Map(HttpServletRequest request) throws IOException {
Map map = new HashMap();
SAXReader reader = new SAXReader();
InputStream is = null;
Document doc = null;
try {
is = request.getInputStream();
doc = reader.read(is);
Element root = doc.getRootElement();
List list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} finally {
is.close();
}
return map;
}
/**
* 将字符串转成xml
* @param params
* @return
*/
public static String stringToxml(String params) {
try {
String paramArray[] = params.split("&");
String param[] = null;
String xml = "";
for (int i = 0; i < paramArray.length; i++) {
param = paramArray[i].split("=");
xml += "<" + param[0] + ">";
xml += param[1];
xml += "" + param[0] + ">";
}
xml += " ";
return xml;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}