订单接口修改

This commit is contained in:
Cool 2024-09-04 23:27:31 +08:00
parent fccdb9c8ed
commit ab8a2f0714
15 changed files with 15 additions and 776 deletions

24
pom.xml
View File

@ -62,30 +62,6 @@
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>1.2.83</version> <version>1.2.83</version>
</dependency> </dependency>
<!--微信支付-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.8</version>
</dependency>
<!-- 引入jar包-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.14</version>
</dependency>
<!-- 微信支付API -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>4.1.0</version>
</dependency>
<dependency> <dependency>
<groupId>commons-lang</groupId> <groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>

View File

@ -1,47 +0,0 @@
package com.bigdata.wxappserver.config;
import com.bigdata.wxappserver.properties.WeChatProperties;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created with IntelliJ IDEA.
*
* @Author: Cool
* @Date: 2024/09/03/22:19
* @Description:
*/
@Configuration
@ConditionalOnClass(WxPayService.class)
public class MyWxPayConfig {
@Autowired
private WeChatProperties properties;
@Bean
@ConditionalOnMissingBean
public WxPayService wxService() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
payConfig.setMchKey(StringUtils.trimToNull(this.properties.getSecret()));
payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiV3Key()));
payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyFilePath()));
payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getWeChatPayCertFilePath()));
// payConfig.setPrivateKeyPath();
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}

View File

@ -22,7 +22,7 @@ public class OrderController {
OrderService orderService; OrderService orderService;
@RequestMapping("addOrUpdate") @RequestMapping("addOrUpdate")
public JSONObject addOrUpdate(@RequestBody JSONObject jsonObject){ public Result addOrUpdate(@RequestBody JSONObject jsonObject){
return orderService.addOrUpdate(jsonObject); return orderService.addOrUpdate(jsonObject);
} }
@ -41,15 +41,4 @@ public class OrderController {
return orderService.delete(id); return orderService.delete(id);
} }
/**
* 订单支付
*
* @param
* @return
*/
@PutMapping("/payment")
public Result payment(@RequestBody JSONObject jsonObject) throws Exception {
return orderService.payment(jsonObject);
}
} }

View File

@ -1,118 +0,0 @@
package com.bigdata.wxappserver.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bigdata.wxappserver.properties.WeChatProperties;
import com.bigdata.wxappserver.service.OrderService;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
/**
* 支付回调相关接口
*/
@RestController
@RequestMapping("/notify")
@Slf4j
public class PayNotifyController {
@Autowired
private OrderService orderService;
@Autowired
private WeChatProperties weChatProperties;
/**
* 支付成功回调
*
* @param request
*/
@RequestMapping("/paySuccess")
public void paySuccessNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
//读取数据
String body = readData(request);
log.info("支付成功回调:{}", body);
//数据解密
String plainText = decryptData(body);
log.info("解密后的文本:{}", plainText);
JSONObject jsonObject = JSON.parseObject(plainText);
String outTradeNo = jsonObject.getString("out_trade_no");//商户平台订单号
String transactionId = jsonObject.getString("transaction_id");//微信支付交易号
log.info("商户平台订单号:{}", outTradeNo);
log.info("微信支付交易号:{}", transactionId);
//业务处理修改订单状态来单提醒
orderService.paySuccess(outTradeNo);
//给微信响应
responseToWeixin(response);
}
/**
* 读取数据
*
* @param request
* @return
* @throws Exception
*/
private String readData(HttpServletRequest request) throws Exception {
BufferedReader reader = request.getReader();
StringBuilder result = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
if (result.length() > 0) {
result.append("\n");
}
result.append(line);
}
return result.toString();
}
/**
* 数据解密
*
* @param body
* @return
* @throws Exception
*/
private String decryptData(String body) throws Exception {
JSONObject resultObject = JSON.parseObject(body);
JSONObject resource = resultObject.getJSONObject("resource");
String ciphertext = resource.getString("ciphertext");
String nonce = resource.getString("nonce");
String associatedData = resource.getString("associated_data");
AesUtil aesUtil = new AesUtil(weChatProperties.getApiV3Key().getBytes(StandardCharsets.UTF_8));
//密文解密
String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
nonce.getBytes(StandardCharsets.UTF_8),
ciphertext);
return plainText;
}
/**
* 给微信响应
*
* @param response
*/
private void responseToWeixin(HttpServletResponse response) throws Exception {
response.setStatus(200);
HashMap<Object, Object> map = new HashMap<>();
map.put("code", "SUCCESS");
map.put("message", "SUCCESS");
response.setHeader("Content-type", ContentType.APPLICATION_JSON.toString());
response.getOutputStream().write(JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8));
response.flushBuffer();
}
}

View File

@ -1,57 +0,0 @@
package com.bigdata.wxappserver.controller;
import com.bigdata.wxappserver.result.Result;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
/**
* Created with IntelliJ IDEA.
*
* @Author: Cool
* @Date: 2024/09/03/22:25
* @Description:
*/
@RestController
@Slf4j
public class TestController {
@Autowired
private WxPayService wxService;
@PostMapping("/unifiedOrder")
public Result unifiedOrder() throws Exception {
String orderCode = UUID.randomUUID().toString().replace("-", "");
WxPayUnifiedOrderV3Request wxPayUnifiedOrderRequest = new WxPayUnifiedOrderV3Request();
wxPayUnifiedOrderRequest.setDescription("商品描述");
wxPayUnifiedOrderRequest.setOutTradeNo(orderCode);
wxPayUnifiedOrderRequest.setNotifyUrl("https://49.233.248.140:8082/order/loadData");
WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
amount.setTotal(100); // 订单总金额单位为分
wxPayUnifiedOrderRequest.setAmount(amount);
WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
payer.setOpenid(UUID.randomUUID().toString().replace("-", "")); // 需要获取用户的OpenID
wxPayUnifiedOrderRequest.setPayer(payer);
wxService.createOrderV3(TradeTypeEnum.JSAPI, wxPayUnifiedOrderRequest);
return Result.success();
}
@PostMapping("/queryOrder")
public Result queryOrder(String outTradeNo) throws Exception {
WxPayOrderQueryResult wxPayOrderQueryResult = wxService.queryOrder(null, outTradeNo);
log.info(wxPayOrderQueryResult.toString());
return Result.success(wxPayOrderQueryResult);
}
}

View File

@ -21,8 +21,8 @@ public class Order extends Base {
private Integer userId; private Integer userId;
private Integer goodsId; private Integer goodsId;
private String orderCode;
private String address; private String address;
private LocalDateTime deliveryTime;
/** /**
* 订单状态 @see * 订单状态 @see

View File

@ -1,22 +0,0 @@
package com.bigdata.wxappserver.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "dx.wechat")
@Data
public class WeChatProperties {
private String appId; //小程序的appid
private String secret; //小程序的秘钥
private String mchId; //商户号
private String mchSerialNo; //商户API证书的证书序列号
private String privateKeyFilePath; //商户私钥文件
private String apiV3Key; //证书解密的密钥
private String weChatPayCertFilePath; //平台证书
private String notifyUrl; //支付成功的回调地址
private String refundNotifyUrl; //退款成功的回调地址
}

View File

@ -10,7 +10,6 @@ import com.bigdata.wxappserver.entity.User;
import com.bigdata.wxappserver.enums.OrderStatusEnum; import com.bigdata.wxappserver.enums.OrderStatusEnum;
import com.bigdata.wxappserver.mapper.OrderMapper; import com.bigdata.wxappserver.mapper.OrderMapper;
import com.bigdata.wxappserver.result.Result; import com.bigdata.wxappserver.result.Result;
import com.bigdata.wxappserver.utils.WeChatPayUtil;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -19,7 +18,6 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -32,8 +30,6 @@ import java.util.stream.Collectors;
*/ */
@Service @Service
public class OrderService extends ServiceImpl<OrderMapper, Order> { public class OrderService extends ServiceImpl<OrderMapper, Order> {
@Autowired
private WeChatPayUtil weChatPayUtil;
@Autowired @Autowired
UserService userService; UserService userService;
@ -41,18 +37,26 @@ public class OrderService extends ServiceImpl<OrderMapper, Order> {
GoodsService goodsService; GoodsService goodsService;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public JSONObject addOrUpdate(JSONObject jsonObject) { public Result addOrUpdate(JSONObject jsonObject) {
Order order = jsonObject.toJavaObject(Order.class); Order order = jsonObject.toJavaObject(Order.class);
if (order == null) { if (order == null) {
return new JSONObject().fluentPut("success", false).fluentPut("message", "参数错误"); return Result.error("参数错误");
} }
if (!StringUtils.hasLength(order.getAddress())) { if (!StringUtils.hasLength(order.getAddress())) {
User user = userService.getById(order.getUserId()); User user = userService.getById(order.getUserId());
order.setAddress(user.getAddress()); order.setAddress(user.getAddress());
} }
// TODO 判空 if (order.getUserId() == null || order.getAddress() == null || order.getNum() == null || order.getGoodsId() == null) {
return Result.error("请携带完整的参数");
}
String orderCode = UUID.randomUUID().toString().replace("-", "");
order.setOrderCode(orderCode);
boolean success = saveOrUpdate(order); boolean success = saveOrUpdate(order);
return new JSONObject().fluentPut("message", "success").fluentPut("success", success); if(success){
return Result.success(orderCode);
}else {
return Result.error("未知错误,请联系管理员!");
}
} }
public JSONObject list(JSONObject jsonObject) { public JSONObject list(JSONObject jsonObject) {
@ -131,39 +135,5 @@ public class OrderService extends ServiceImpl<OrderMapper, Order> {
saveOrUpdate(order); saveOrUpdate(order);
} }
/**
* 订单支付
*
* @param ordersPaymentDTO
* @return
*/
public Result payment(JSONObject ordersPaymentDTO) throws Exception {
// 当前登录用户id
String openId = ordersPaymentDTO.getString("openId");
String orderCode = ordersPaymentDTO.getString("orderCode");
List<User> userList = userService.list();
User user = userList.stream().filter(e -> Objects.equals(e.getOpenId(), openId)).findFirst().orElse(null);
if (user == null) {
return Result.error("查询不到该用户");
}
//调用微信支付接口生成预支付交易单
JSONObject jsonObject = weChatPayUtil.pay(
orderCode, //商户订单号
new BigDecimal(0.01), //支付金额单位
"Test123", //商品描述
user.getOpenId() //微信用户的openid
);
if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
return Result.error("该订单已支付");
}
// OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
// vo.setPackageStr(jsonObject.getString("package"));
//
// return vo;
return Result.success();
}
} }

View File

@ -1,138 +0,0 @@
package com.bigdata.wxappserver.utils;
import okhttp3.HttpUrl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Random;
/**
* Created with IntelliJ IDEA.
*
* @Author: Cool
* @Date: 2024/09/03/20:34
* @Description:
*/
@Component
public class SignV3Util{
//V3主商户ID
private static String merchantId;
//微信商户平台APIv3证书序列号
private static String certificateSerialNo;
//私钥不要把私钥文件暴露在公共场合如上传到Github写在客户端代码等
private static String privateKey;
//配置文件配置好主商户号
@Value("${dx.wechat.mchid}")
public void setMerchantId(String merchantId) {
SignV3Util.merchantId = merchantId;
}
//配置文件配置好序列号
@Value("${dx.wechat.mchSerialNo}")
public void setCertificateSerialNo(String certificateSerialNo) {
SignV3Util.certificateSerialNo = certificateSerialNo;
}
//配置文件配置好私钥
@Value("${dx.wechat.apiV3Key}")
public void setPrivateKey(String privateKey) {
SignV3Util.privateKey = privateKey;
}
/**
* 使用方法
*
* @param method 请求方法
* @param url 请求url
* @param body 请求内容
* @return
*/
public static HashMap<String, String> getSignMap(String method, String url, String body) throws InvalidKeySpecException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException, SignatureException {
String authorization = getSign(method, url, body);
HashMap<String, String> headsMap = new HashMap<>();
headsMap.put("Authorization", authorization);
headsMap.put("Content-Type", "application/json");
headsMap.put("Accept", "application/json");
return headsMap;
}
public static String getSign(String method, String url, String body) throws NoSuchAlgorithmException, SignatureException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException {
return "WECHATPAY2-SHA256-RSA2048 " + getToken(method, HttpUrl.parse(url), body);
}
public static String getToken(String method, HttpUrl url, String body) throws UnsupportedEncodingException, SignatureException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
String nonceStr = nonceString();
long timestamp = System.currentTimeMillis() / 1000;
String message = buildMessage(method, url, timestamp, nonceStr, body);
String signature = sign(message.getBytes("utf-8"));
return "mchid=\"" + merchantId + "\","
+ "nonce_str=\"" + nonceStr + "\","
+ "timestamp=\"" + timestamp + "\","
+ "serial_no=\"" + certificateSerialNo + "\","
+ "signature=\"" + signature + "\"";
}
public static String sign(byte[] message) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(getPKCS8PrivateKey(privateKey));
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}
public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
String canonicalUrl = url.encodedPath();
if (url.encodedQuery() != null) {
canonicalUrl += "?" + url.encodedQuery();
}
return method + "\n"
+ canonicalUrl + "\n"
+ timestamp + "\n"
+ nonceStr + "\n"
+ body + "\n";
}
private static PrivateKey getPKCS8PrivateKey(String strPk) throws NoSuchAlgorithmException, InvalidKeySpecException {
String realPK = strPk.replaceAll("-----END PRIVATE KEY-----", "")
.replaceAll("-----BEGIN PRIVATE KEY-----", "")
.replaceAll("\n", "");
byte[] b1 = Base64.getDecoder().decode(realPK);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
public static String nonceString() {
String currTime = String.format("%d", (long) System.currentTimeMillis() / 1000);
String strTime = currTime.substring(8, currTime.length());
Random random = new Random();
int num = (int) (random.nextDouble() * (1000000 - 100000) + 100000);
String code = String.format("%06d", num);
String nonce_str = currTime.substring(2) + code;
return nonce_str;
}
}

View File

@ -1,233 +0,0 @@
package com.bigdata.wxappserver.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bigdata.wxappserver.properties.WeChatProperties;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.*;
/**
* 微信支付工具类
*/
@Component
public class WeChatPayUtil {
//微信支付下单接口地址
public static final String PAY_API = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//申请退款接口地址
public static final String REFUNDS = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
@Autowired
private WeChatProperties weChatProperties;
/**
* 获取调用微信接口的客户端工具对象
*
* @return
*/
private CloseableHttpClient getClient() {
PrivateKey merchantPrivateKey = null;
try {
//merchantPrivateKey商户API私钥如何加载商户API私钥请看常见问题
merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(new File(weChatProperties.getPrivateKeyFilePath())));
//加载平台证书文件
X509Certificate x509Certificate = PemUtil.loadCertificate(new FileInputStream(new File(weChatProperties.getWeChatPayCertFilePath())));
//wechatPayCertificates微信支付平台证书列表你也可以使用后面章节提到的定时更新平台证书功能而不需要关心平台证书的来龙去脉
List<X509Certificate> wechatPayCertificates = Arrays.asList(x509Certificate);
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(weChatProperties.getMchId(), weChatProperties.getMchSerialNo(), merchantPrivateKey)
.withWechatPay(wechatPayCertificates);
// 通过WechatPayHttpClientBuilder构造的HttpClient会自动的处理签名和验签
CloseableHttpClient httpClient = builder.build();
return httpClient;
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
/**
* 发送post方式请求
*
* @param url
* @param body
* @return
*/
private String post(String url, String body) throws Exception {
CloseableHttpClient httpClient = getClient();
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
httpPost.addHeader("Wechatpay-Serial", weChatProperties.getMchSerialNo());
httpPost.setEntity(new StringEntity(body, "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
String bodyAsString = EntityUtils.toString(response.getEntity());
return bodyAsString;
} finally {
httpClient.close();
response.close();
}
}
/**
* 发送get方式请求
*
* @param url
* @return
*/
private String get(String url) throws Exception {
CloseableHttpClient httpClient = getClient();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
httpGet.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
httpGet.addHeader("Wechatpay-Serial", weChatProperties.getMchSerialNo());
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
String bodyAsString = EntityUtils.toString(response.getEntity());
return bodyAsString;
} finally {
httpClient.close();
response.close();
}
}
/**
* jsapi下单
*
* @param orderNum 商户订单号
* @param total 总金额
* @param description 商品描述
* @param openid 微信用户的openid
* @return
*/
private String jsapi(String orderNum, BigDecimal total, String description, String openid) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("appid", weChatProperties.getAppId());
jsonObject.put("mchid", weChatProperties.getMchId());
jsonObject.put("description", description);
jsonObject.put("out_trade_no", orderNum);
jsonObject.put("nonce_str", UUID.randomUUID().toString());
jsonObject.put("notify_url", weChatProperties.getNotifyUrl());
JSONObject amount = new JSONObject();
amount.put("total", total.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue());
amount.put("currency", "CNY");
jsonObject.put("amount", amount);
JSONObject payer = new JSONObject();
payer.put("openid", openid);
jsonObject.put("payer", payer);
String body = jsonObject.toJSONString();
return post(PAY_API, body);
}
/**
* 小程序支付
*
* @param orderNum 商户订单号
* @param total 金额单位
* @param description 商品描述
* @param openid 微信用户的openid
* @return
*/
public JSONObject pay(String orderNum, BigDecimal total, String description, String openid) throws Exception {
//统一下单生成预支付交易单
String bodyAsString = jsapi(orderNum, total, description, openid);
//解析返回结果
JSONObject jsonObject = JSON.parseObject(bodyAsString);
System.out.println(jsonObject);
String prepayId = jsonObject.getString("prepay_id");
if (prepayId != null) {
String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonceStr = RandomStringUtils.randomNumeric(32);
ArrayList<Object> list = new ArrayList<>();
list.add(weChatProperties.getAppId());
list.add(timeStamp);
list.add(nonceStr);
list.add("prepay_id=" + prepayId);
//二次签名调起支付需要重新签名
StringBuilder stringBuilder = new StringBuilder();
for (Object o : list) {
stringBuilder.append(o).append("\n");
}
String signMessage = stringBuilder.toString();
byte[] message = signMessage.getBytes();
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(PemUtil.loadPrivateKey(new FileInputStream(new File(weChatProperties.getPrivateKeyFilePath()))));
signature.update(message);
String packageSign = Base64.getEncoder().encodeToString(signature.sign());
//构造数据给微信小程序用于调起微信支付
JSONObject jo = new JSONObject();
jo.put("timeStamp", timeStamp);
jo.put("nonceStr", nonceStr);
jo.put("package", "prepay_id=" + prepayId);
jo.put("signType", "RSA");
jo.put("paySign", packageSign);
return jo;
}
return jsonObject;
}
/**
* 申请退款
*
* @param outTradeNo 商户订单号
* @param outRefundNo 商户退款单号
* @param refund 退款金额
* @param total 原订单金额
* @return
*/
public String refund(String outTradeNo, String outRefundNo, BigDecimal refund, BigDecimal total) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("out_trade_no", outTradeNo);
jsonObject.put("out_refund_no", outRefundNo);
JSONObject amount = new JSONObject();
amount.put("refund", refund.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue());
amount.put("total", total.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue());
amount.put("currency", "CNY");
jsonObject.put("amount", amount);
jsonObject.put("notify_url", weChatProperties.getRefundNotifyUrl());
String body = jsonObject.toJSONString();
//调用申请退款接口
return post(REFUNDS, body);
}
}

View File

@ -14,14 +14,4 @@ mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml mapper-locations: classpath*:/mapper/*Mapper.xml
configuration: configuration:
map-underscore-to-camel-case: true map-underscore-to-camel-case: true
dx:
wechat:
appId: wx865aefa5a7115ae0
secret: df0817d59696a6160de2770222d8ec53
mchId: 1684540409
mchSerialNo: 1E860B81D50719F1AA6AB92F00033A222F81C72C
privateKeyFilePath: classpath:template/wechatpay_429733475DFDCEBE2A6135485F984EE337297F4F.pem
apiV3Key: d5a58d44588b42cbbe01daa5cfa4e792
weChatPayCertFilePath: classpath:template/wechatpay_429733475DFDCEBE2A6135485F984EE337297F4F.pem
notifyUrl: https://www.weixin.qq.com/wxpay/pay.php
refundNotifyUrl: https://www.weixin.qq.com/wxpay/pay.php

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDE4z0uWRbfuMPP
m19ZOd3CoKmm20Rdp0EJGsYsItxWk1veEUrtUDGUevrBpAWxSW6ka6YRcs3G6nzK
sAkrOzoFOU1xTH4I0qrspIelXwLZMYKZrdR+G+LNS9gmITrvkBKlZsrWTNOxStv1
0CTeWPr3mBUt3SrUOHPX+eY5JR1XgBau8Y/9hd5fiYuPTCoWQsM+IUIXBrWsaEqI
oDrymtFH8Nupgz55g8qgUX0jxb1yjcuenO7jlonqMySIpZuNrAxla4GnfERG7TAL
36VYJ/f4QWiHpa8lg4azq/FgwegL7nVo2wcDoCcqkIjDvyYxTXtwwn7llFSa44B9
abXQ4Ip3AgMBAAECggEBAMCtwcoB1ajLoJUjcIRZZPR7Vou8OYONks/eK+I1m3v+
agFA2xqzSFIOqCeo5QlC28x8rOCWgVsRT17sN4zfQUCre2ZNfWoVAMDlovnrqVX0
ZeMPgsyHbcWLW9S04IBhdl334rkmJmVy5SACupH+clyrsM5Zivh05qmOHgf+kmB1
dpG8oJ+4gaAg5f8YQ0S3q0jJy/Tr2tZRaTU5S1Gaa3xmfDHBvte6bmmSrjF7V56M
hibEOqvjrgK04P20FtFH7Laug4tq5IMyi6L9XVN2tE06c0epN7+Z7oBEzeTuQ+zU
EwEnNwH7GG+JYjUIrxlQMr6XXNEWv/iDhbXKJd5zvoECgYEA/9AFOlQthPdR0dY3
9N9q41jmrxvF0yep+MFw4+X7sEV+gnLLRATQCnsBF+Br3DHdUU2H8DwtOEYD8V9L
Ks8j7B9ivVcbs4KT6iu3ehrQgX2DvnGov+ZlRpVwWV90CppLzubuX++0L8K/dYfF
OPpm128k18BgwWY+4UvD1BClrU8CgYEAxQgqsEysa9RUcKFcPMMkMUG3SDvB0+q3
vkn4EDZVgUoojQnk54vQ4U6pbF4KTPPHvNF4vrmu5DdhSWBBnHAchdLHO7NXVl7n
cIPOHnakzauiS+jZlokpf4bMIECsQMW+n6c2WfT4mhbciCTo4+oLBu/aZ/tS/fUu
EJyW2+/VllkCgYByexSr2toYJFpgbt7R3l5GahWqjeJFMf32DhPIWbb+Vstb86WV
xhWYax29IrkCbOpfpTPNxhBym5rOHVhVSygHVrBojaAfALPTW0ccBP4ExTf9NX5Q
ivoN0Xja9kXHLO/6IwzQsERSD3SBU4ZmjmERznKNf1GNm4VObAqyT9TlLwKBgQCT
R1OBjQ6lW4Xy2urzkHqRRyoVmHV+TskiOHBwzeyEREajhm3QlraAdCg4lOLmOqNn
BL1Y87tDZBIYoxboNPVdIv1CJwB102L0u9Fq/AycoFskmt1qpQScCsqyoSUhFa8z
7+20uGTL6aLXMZ/UHbI4cTm02CxlIMxaJnKt3EyvoQKBgQCeZwTjaqIQmR3fBrNm
MG0qO652ONVLirzEsfn7DpxPC6+ON3MGuPZxaiSaYwAhQq3dqQ/dpJoxrInPMScH
bebJz33OLTH4+1t4NvNDJkauWwuDI46uZhX+MVfIelNC5j5V+qrd1n614nQe9pJJ
UMlUt8FS3+aqnzvtYMOs6MNO9g==
-----END PRIVATE KEY-----

View File

@ -1,4 +1,3 @@
-----BEGIN CERTIFICATE-----
MIIEFDCCAvygAwIBAgIUQpczR139zr4qYTVIX5hO4zcpf08wDQYJKoZIhvcNAQEL MIIEFDCCAvygAwIBAgIUQpczR139zr4qYTVIX5hO4zcpf08wDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
@ -21,4 +20,3 @@ IRlGr714v8WoudsIwuT7U6t4rws6mekrPrh9tTtDr6xpEuuLaYe0gJrpFM0UbryO
H20I1g2mxzmXl3MuGq8zB+fGQUy+MIO4EoUGIIEM6q7HzcCAPIVn+Qb/MCto56Ne H20I1g2mxzmXl3MuGq8zB+fGQUy+MIO4EoUGIIEM6q7HzcCAPIVn+Qb/MCto56Ne
YPr5a+w7g6u4UZ+sVix2AddlOnqJPBIv/t91sQtFSzew9yztW/r2b1AyUHAsYa0n YPr5a+w7g6u4UZ+sVix2AddlOnqJPBIv/t91sQtFSzew9yztW/r2b1AyUHAsYa0n
76QTS6cjmV/Ee726l9d6tYGhF/NR9lUcXK7hr4JzA9e0zKr0JnAy8Q== 76QTS6cjmV/Ee726l9d6tYGhF/NR9lUcXK7hr4JzA9e0zKr0JnAy8Q==
-----END CERTIFICATE-----

View File

@ -1,19 +1,8 @@
package com.bigdata.wxappserver; package com.bigdata.wxappserver;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.bigdata.wxappserver.utils.SignV3Util;
import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -25,35 +14,5 @@ class WxappServerApplicationTests {
void contextLoads() { void contextLoads() {
} }
@Test
public void test() throws Exception {
CloseableHttpClient httpClient = HttpClients.createDefault();
//处理请求参数
String param = JSON.toJSONString("请求参数");
//获取签名请求头
HashMap<String, String> heads = SignV3Util.getSignMap("POST", "https://api.mch.weixin.qq.com/pay/unifiedorder", param);
//请求微信接口
HttpPost post = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
for (Map.Entry<String, String> entry : heads.entrySet()) {
post.addHeader(entry.getKey(), entry.getValue());
}
// 设置请求参数
StringEntity entity = new StringEntity(JSON.toJSONString("请求参数"), "UTF-8");
post.setEntity(entity);
// 发送POST请求
CloseableHttpResponse response = httpClient.execute(post);
try {
// 获取响应实体
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 打印响应内容
System.out.println("Response content: " + EntityUtils.toString(responseEntity, "UTF-8"));
}
} finally {
response.close();
}
}
} }