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

本文详述了微信小程序支付后台的Java实现过程,包括前端获取openId和订单号传递给后台,后台签名并调用微信统一下单接口,解析微信返回的XML字符串并二次签名,最后将支付信息返回给前端。主要涉及的类有HttpRequest和WXPayUtil,提供了关键代码片段和注意事项。
摘要由CSDN通过智能技术生成

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

前言:

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

支付流程:

1.小程序前端获取微信 openId 以及订单号 传给后台

2,后台根据 openId 和订单号进行签名 post 微信统一下单接口

3.后台获取微信返回的xml字符串 解析 二次签名以后返回给前端

4.前端调起支付微信支付 API

先看支付函数:

//获取支付信息

@EngineFunction("getPayInformation")

public static Map 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 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 resultMap = new TreeMap<>(

new Comparator() {

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

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.URL;

import java.net.URLConnection;

import java.util.List;

import java.util.Map;

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> 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 org.w3c.dom.NodeList;

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 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("");

// sb2.append("");

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 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;

}

}

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值