加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

微信小程序 支付后台java实现实例

发布时间:2020-12-14 20:16:59 所属栏目:资源 来源:网络整理
导读:微信小程序 支付后台java实现实例 前言: 前些天使用 LeanCloud 云引擎写了个小程序的支付相关 以前只做过 APP 支付 这次在小程序支付爬了两天的坑 把代码也分享出来 支付流程: 1.小程序前端获取微信 openId 以及订单号 传给后台2,后台根据 openId 和订单号

微信小程序 支付后台java实现实例

前言:

前些天使用 LeanCloud 云引擎写了个小程序的支付相关 以前只做过 APP 支付 这次在小程序支付爬了两天的坑 把代码也分享出来

支付流程:

1.小程序前端获取微信 openId 以及订单号 传给后台 2,后台根据 openId 和订单号进行签名 post 微信统一下单接口 3.后台获取微信返回的xml字符串 解析 二次签名以后返回给前端 4.前端调起支付微信支付 API

先看支付函数:

getPayInformation( @EngineFunctionParam("orderId") String orderId ) throws AVException,UnsupportedEncodingException,DocumentException { Map reqMap = new TreeMap( new Comparator() { public int compare(String obj1,String obj2) { // 升序排序 return obj1.compareTo(obj2); } }); if (AVUser.getCurrentUser() != null) { String authDataJson = JSONArray.toJSONString(AVUser.getCurrentUser().get("authData")); JSONObject jsonObject = JSON.parSEObject(authDataJson); jsonObject.get("lc_weapp"); JSONObject j2 = JSON.parSEObject(jsonObject.get("lc_weapp").toString()); String openId = (String) j2.get("openid");
  AVQuery<Order> query = AVObject.getQuery(Order.class);
  Order order = query.get(orderId);
  reqMap.put("appid",System.getenv("appid"));
  reqMap.put("mch_id",System.getenv("mch_id"));
  reqMap.put("nonce_str",WXPayUtil.getNonce_str());
  reqMap.put("body",new String(order.getDishesList().toString().getBytes("UTF-8")));
  reqMap.put("openid",openId);
  reqMap.put("out_trade_no",order.getObjectId());
  reqMap.put("total_fee",1); //订单总金额,单位为分
  reqMap.put("spbill_create_ip","192.168.0.1"); //用户端ip
  reqMap.put("notify_url",System.getenv("notify_url")); //通知地址
  reqMap.put("trade_type",System.getenv("trade_type")); //trade_type=JSAPI时(即公众号支付),此参数必传,此参数为微信用户在商户对应appid下的唯一标识
  String reqStr = WXPayUtil.map2Xml(reqMap);
  String resultXml = HttpRequest.sendPost(reqStr);
  System.out.println("微信请求返回:" + resultXml);
  //解析微信返回串 如果状态成功 则返回给前端
  if (WXPayUtil.getReturnCode(resultXml) != null && WXPayUtil.getReturnCode(resultXml).equals("SUCCESS")) {
    //成功
    Map<String,Object> resultMap = new TreeMap<>(
        new Comparator<String>() {
          public int compare(String obj1,String obj2) {
            // 升序排序
            return obj1.compareTo(obj2);
          }
        });
    resultMap.put("appId",System.getenv("appid"));
    resultMap.put("nonceStr",WXPayUtil.getNonceStr(resultXml));//解析随机字符串
    resultMap.put("package","prepay_id=" + WXPayUtil.getPrepayId(resultXml));
    resultMap.put("signType","MD5");
    resultMap.put("timeStamp",String.valueOf((System.currentTimeMillis() / 1000)));//时间戳
    String paySign = WXPayUtil.getSign(resultMap);
    resultMap.put("paySign",paySign);
    return resultMap;
  } else {
    throw new AVException(999,"微信请求支付失败");
  }
} else {
  throw new AVException(98,"当前未登录用户");
}

}

其中appid和mch_id可以用系统常量

PS:这里注意一个坑

二次签名的时候使用 appId nonceStr package signType timeStamp 这五个key生成签名(这里无视微信官方文档 以及注意 appId 的大小写)

前端调起API支付时 按照官方文档就可以

网络请求类:

HttpRequest

public class HttpRequest {
/**

  • 向指定URL发送GET方法的请求
  • @param url 发送请求的URL
  • @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
  • @return URL 所代表远程资源的响应结果
    /
    public static String sendGet(String url,String param) {
    String result = "";
    BufferedReader in = null;
    try {
    String urlNameString = url + "?" + param;
    URL realUrl = new URL(urlNameString);
    // 打开和URL之间的连接
    URLConnection connection = realUrl.openConnection();
    // 设置通用的请求属性
    connection.setRequestProperty("accept","
    /*");
    connection.setRequestProperty("connection","Keep-Alive");
    connection.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
    // 建立实际的连接
    connection.connect();
    // 获取所有响应头字段
    Map<String,List> map = connection.getHeaderFields();
    // 遍历所有的响应头字段
    for (String key : map.keySet()) {
    System.out.println(key + "--->" + map.get(key));
    }
    // 定义 BufferedReader输入流来读取URL的响应
    in = new BufferedReader(new InputStreamReader(
    connection.getInputStream()));
    String line;
    while ((line = in.readLine()) != null) {
    result += line;
    }
    } catch (Exception e) {
    System.out.println("发送GET请求出现异常!" + e);
    e.printStackTrace();
    }
    // 使用finally块来关闭输入流
    finally {
    try {
    if (in != null) {
    in.close();
    }
    } catch (Exception e2) {
    e2.printStackTrace();
    }
    }
    return result;
    }

/**

  • 向指定 URL 发送POST方法的请求
  • @param url 发送请求的 URL
  • @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
  • @return 所代表远程资源的响应结果
    /
    public static String sendPost(String param) {
    PrintWriter out = null;
    BufferedReader in = null;
    String result = "";
    try {
    URL realUrl = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder");
    // 打开和URL之间的连接
    URLConnection conn = realUrl.openConnection();
    // 设置通用的请求属性
    conn.setRequestProperty("accept","
    /*");
    conn.setRequestProperty("connection","Keep-Alive");
    conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
    // conn.setRequestProperty("Pragma:","no-cache");
    // conn.setRequestProperty("Cache-Control","no-cache");
    // conn.setRequestProperty("Content-Type","text/xml;charset=utf-8");
    // 发送POST请求必须设置如下两行
    conn.setDoOutput(true);
    conn.setDoInput(true);
    // 获取URLConnection对象对应的输出流
    out = new PrintWriter(conn.getOutputStream());
    // 发送请求参数
    out.print(param);
    // flush输出流的缓冲
    out.flush();
    // 定义BufferedReader输入流来读取URL的响应
    in = new BufferedReader(
    new InputStreamReader(conn.getInputStream()));
    String line;
    while ((line = in.readLine()) != null) {
    result += line;
    }
    } catch (Exception e) {
    System.out.println("发送 POST 请求出现异常!" + e);
    e.printStackTrace();
    }
    //使用finally块来关闭输出流、输入流
    finally {
    try {
    if (out != null) {
    out.close();
    }
    if (in != null) {
    in.close();
    }
    } catch (IOException ex) {
    ex.printStackTrace();
    }
    }
    return result;
    }
    }

XML解析工具类

WXPayUtil

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Random;

public class WXPayUtil {

//生成随机字符串
public static String getNonce_str() {
String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 15; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}

//map转xml 加上签名信息
public static String map2Xml(Map<String,Object> map) throws UnsupportedEncodingException {
StringBuffer sb = new StringBuffer();
StringBuilder sb2 = new StringBuilder();
sb2.append("");
for (String key : map.keySet()) {
sb.append(key);
sb.append('=');
sb.append(map.get(key));
sb.append('&');
// sb2是用来做请求的xml参数
sb2.append("<" + key + ">");
// sb2.append("<![CDATA[" + map.get(key) + "]]>");
sb2.append(map.get(key));
sb2.append("</" + key + ">");
}
sb.append(System.getenv("signKey"));
String sign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
sb2.append("");
sb2.append(sign);
sb2.append("
");
sb2.append("
");
return sb2.toString();
}

//解析微信返回return_code SUCCESS或FILE
//根据微信返回resultXml再次生成签名
public static String getSign(Map<String,Object> map) {
StringBuffer sb = new StringBuffer();
for (String key : map.keySet()) {
sb.append(key);
sb.append('=');
sb.append(map.get(key));
sb.append('&');
}
sb.append(System.getenv("signKey"));
System.out.println("第二次签名内容:" + sb);
System.out.println("第二次签名SING:" + MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase());
return MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
}

//解析微信返回return_code SUCCESS或FILE
public static String getReturnCode(String resultXml) {
String nonceStr;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = dbf.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
org.w3c.dom.Document doc = builder.parse(inputStream); //
// 下面开始读取
org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
NodeList nl = root.getElementsByTagName("return_code");
org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
org.w3c.dom.Node nd = el.getFirstChild();
nonceStr = nd.getNodeValue();
return nonceStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

//解析微信返回return_msg
public static String getReturn_msg(String resultXml) {
String nonceStr;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = dbf.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
org.w3c.dom.Document doc = builder.parse(inputStream); //
// 下面开始读取
org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
NodeList nl = root.getElementsByTagName("return_msg");
org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
org.w3c.dom.Node nd = el.getFirstChild();
nonceStr = nd.getNodeValue();
return nonceStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

//解析微信返回appid
public static String getAppId(String resultXml) {
String nonceStr;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = dbf.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
org.w3c.dom.Document doc = builder.parse(inputStream); //
// 下面开始读取
org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
NodeList nl = root.getElementsByTagName("appid");
org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
org.w3c.dom.Node nd = el.getFirstChild();
nonceStr = nd.getNodeValue();
return nonceStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

//解析微信返回mch_id
public static String getMchId(String resultXml) {
String nonceStr;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = dbf.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
org.w3c.dom.Document doc = builder.parse(inputStream); //
// 下面开始读取
org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
NodeList nl = root.getElementsByTagName("mch_id");
org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
org.w3c.dom.Node nd = el.getFirstChild();
nonceStr = nd.getNodeValue();
return nonceStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

//解析微信返回nonce_str
public static String getNonceStr(String resultXml) {
String nonceStr;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = dbf.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
org.w3c.dom.Document doc = builder.parse(inputStream); //
// 下面开始读取
org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
NodeList nl = root.getElementsByTagName("nonce_str");
org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
org.w3c.dom.Node nd = el.getFirstChild();
nonceStr = nd.getNodeValue();
return nonceStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

//解析微信返回prepay_id
public static String getPrepayId(String resultXml) {
String nonceStr;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = dbf.newDocumentBuilder();
InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
org.w3c.dom.Document doc = builder.parse(inputStream); //
// 下面开始读取
org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
NodeList nl = root.getElementsByTagName("prepay_id");
org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
org.w3c.dom.Node nd = el.getFirstChild();
nonceStr = nd.getNodeValue();
return nonceStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读