里面有很多逻辑需要大家自己写啊,比如订单获取啊,生成订单啊,变更订单状态,退款啊,等等的,我这里就实现了一个基本的功能,就是拉起支付,支付到账这样的,大家根据需求自己编写就行。我这里提供的基本上都是复制了直接就能用的那种啊,前提是你要有商户号,要生成秘钥证书这些啊
首先需要去注册商户号啊,这个过程比较复杂啊,然后微信平台上有引导的,大家跟着做就行
![](https://i-blog.csdnimg.cn/direct/cf6472b1dcfa4ae8a19f4e09b6d4f4da.png)
![](https://i-blog.csdnimg.cn/direct/56de0cf7096d42c98fa62664a18e89ef.png)
就是这个位置啊,然后需要提交的材料准备好就行,基本上当天就会批下来,费率的话每个行业都是不一样的啊,然后在小程序里关联到商户号就行,
代码编写 只附部分核心程序,他是需要拿着openid去后台获取相应的参数的啊,这里的orderId我直接前端随机了,正常应该写在后端的啊,大家额注意一下。有些参数没明白的,可以去微信平台的文档里看一下啊,都是一一对应的啊,然后我这个也不需要下载什么jdk,maven的话也是springboot那一套啊,没什么特殊的
data: {
phoneNumber: '', // 存储手机号
openid: '', // 用户的 openid
orderId: '', // 订单 ID
paymentData: null, // 存储从后端获取的支付参数
statu:'点击支付',
isButtonDisabled: false // 默认按钮是可点击的
},
generateOrderId: function() {
// 获取当前时间戳
const timestamp = new Date().getTime();
// 生成一个随机数
const randomNum = Math.floor(Math.random() * 100000);
// 拼接时间戳和随机数生成订单号
return timestamp.toString() + randomNum.toString();
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
const orderId = this.generateOrderId();
const openId = wx.getStorageSync('openId')
this.setData({
openid: openId,
orderId: orderId
});
},
// 发起支付函数
startPayment: function () {
const that = this;
// 先从后端获取支付参数
wx.request({
url: url+'api/getPaymentParams',
method: 'POST',
data: {
openid: this.data.openid,
orderId: this.data.orderId
},
success: function (res) {
if (res.data && res.data.success) {
const paymentData = res.data.paymentData;
console.log(res.data.paySign)
// 调用微信支付接口
wx.requestPayment({
timeStamp: paymentData.timeStamp,
nonceStr: paymentData.nonceStr,
package: paymentData.package,
signType: paymentData.signType,
paySign: res.data.paySign,
success: (res) => { // 使用箭头函数
that.setData({
statu: '已支付',
isButtonDisabled: true // 将按钮设置为不可点击
});
console.log('支付成功', res);
wx.request({
url: url + 'api/setOrder?orderId=' + that.data.orderId, //仅为示例,并非真实的接口地址
method: 'GET',
header: { 'content-type': 'application/json' },
success: (res) => {
// 处理成功请求的回调
}
});
// 支付成功后的操作,如跳转页面或其他逻辑
},
fail: (res) => { // 使用箭头函数
console.log('支付失败', res);
// 支付失败后的操作,如提示用户重新支付
}
});
} else {
wx.showToast({
title: '此订单已支付',
icon: 'none'
});
console.error('获取支付参数失败', res);
}
},
fail: function (err) {
wx.showToast({
title: '此订单已支付',
icon: 'none'
});
console.error('请求支付参数失败', err);
}
});
},
Java:服务器端
private static final String APPID = "";
private static final String APPSECRET = "";
private static final String MCHID="";//商户号
private static final String NOTIFYURL="";//回执地址
private static final String MCHKEY="";//秘钥
@PostMapping("/getPaymentParams")
public @ResponseBody Map<String, Object> getPaymentParams(@RequestBody Map<String, String> request) {
String openid = request.get("openid");
String orderId = request.get("orderId");
String money="1";//目前模拟数据,后续需要通过支付金额表或者是通过第三方获取支付金额,通过OPENID去user表找到手机号,然后通过手机号查询金额表
// 创建统一下单请求参数
Map<String, String> params = new HashMap<>();
params.put("appid", APPID);
params.put("mch_id",MCHID );
params.put("nonce_str", WXPayUtil.generateNonceStr());
params.put("body", "订单支付");
params.put("out_trade_no", orderId);
params.put("total_fee", money); // 单位为分
params.put("spbill_create_ip", "127.0.0.1");
params.put("notify_url", NOTIFYURL);
params.put("trade_type", "JSAPI");
params.put("openid", openid);
try {
String sign = WXPayUtil.generateSignature(params, MCHKEY);
params.put("sign", sign);
String xml = WXPayUtil.mapToXml(params);
String response = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
Map<String, String> result = WXPayUtil.xmlToMap(response);
if ("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("result_code"))) {
String prepayId = result.get("prepay_id");
Map<String, String> payMap = new HashMap<>();
payMap.put("appId", APPID);
payMap.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
payMap.put("nonceStr", WXPayUtil.generateNonceStr());
payMap.put("package", "prepay_id=" + prepayId);
payMap.put("signType", "MD5");
String paySign = WXPayUtil.generateSignature(payMap, MCHKEY);
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("success", true);
responseMap.put("paymentData", payMap);
responseMap.put("paySign", paySign);
Order order=new Order();
order.setOrderId(orderId);
order.setOpenId(openid);
order.setPayTime(new Date());
order.setMoney(money);
orderService.add(order);
return responseMap;
} else {
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("success", false);
responseMap.put("errMsg", result.get("err_code_des"));
return responseMap;
}
} catch (Exception e) {
e.printStackTrace();
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("success", false);
responseMap.put("errMsg", e.getMessage());
return responseMap;
}
}
util类,用来生成随机字符串,加密,验证签名等作用的
public class WXPayUtil {
public static String generateNonceStr() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
}
public static String generateSignature(Map<String, String> data, String key) throws Exception {
// 1. Sort the parameters in dictionary order
Map<String, String> sortedData = new TreeMap<>(data);
// 2. Concatenate the parameters as per the format: key1=value1&key2=value2...
String stringA = sortedData.entrySet().stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(Collectors.joining("&"));
// 3. Append the key
String stringSignTemp = stringA + "&key=" + key;
// 4. Sign the concatenated string using MD5
return MD5(stringSignTemp).toUpperCase();
}
public static String mapToXml(Map<String, String> data) {
StringBuilder xml = new StringBuilder();
xml.append("<xml>");
for (Map.Entry<String, String> entry : data.entrySet()) {
xml.append("<").append(entry.getKey()).append(">");
xml.append(entry.getValue());
xml.append("</").append(entry.getKey()).append(">");
}
xml.append("</xml>");
return xml.toString();
}
public static Map<String, String> xmlToMap(String strXML) throws Exception {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new StringReader(strXML));
Element root = doc.getRootElement();
List<Element> children = root.getChildren();
Map<String, String> data = new HashMap<>();
for (Element child : children) {
data.put(child.getName(), child.getTextNormalize());
}
return data;
}
private static String MD5(String data) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte b : array) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
/**
* 验证签名
* @param data 通知数据
* @param key 密钥
* @return 签名是否有效
* @throws Exception
*/
public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {
if (!data.containsKey("sign")) {
return false;
}
String sign = data.get("sign");
return generateSignature(data, key).equals(sign);
}
}