新增:微信Native支付

This commit is contained in:
gxwebsoft
2024-05-11 19:11:16 +08:00
parent 8ea313d7c8
commit a0a090dc6d
9 changed files with 229 additions and 19 deletions

View File

@@ -51,6 +51,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
"/api/parseToken/*",
"/api/login-alipay/*",
"/api/wx-login/loginByMpWxPhone",
"/api/system/wx-native-pay/**",
"/api/wxWorkQrConnect",
"/api/sys/user-plan-log/wx-pay/**",
"/api/wx-official/**",

View File

@@ -1,9 +1,11 @@
package com.gxwebsoft.common.system.controller;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Company;
import com.gxwebsoft.common.system.entity.OrderInfo;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.CompanyService;
import com.gxwebsoft.common.system.service.OrderInfoService;
@@ -21,6 +23,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@@ -75,13 +78,30 @@ public class OrderController extends BaseController {
public ApiResult<?> save(@RequestBody Order order) {
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser == null) {
return fail("请先登录");
}
// 微信openid(必填)
if(StrUtil.isBlank(loginUser.getOpenid())){
return fail("微信openid(必填)");
}
// 商品描述(必填)
if(StrUtil.isBlank(order.getComments())){
return fail("商品描述(必填)");
}
// 微信支付(商品金额不能为0)
if(order.getPayType().equals(1)){
if (order.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
return fail("商品金额不能为0");
}
}
// 订单信息
long timeMillis = System.currentTimeMillis();
long orderNo = IdUtil.getSnowflakeNextId();
if (loginUser != null) {
order.setUserId(loginUser.getUserId());
order.setOpenid(loginUser.getOpenid());
}
order.setOrderNo(Long.toString(orderNo));
order.setUserId(loginUser.getUserId());
order.setOpenid(loginUser.getOpenid());
order.setRealName(loginUser.getRealName());
order.setStartTime(timeMillis / 1000);
order.setAddTime(timeMillis / 1000);

View File

@@ -253,9 +253,14 @@ public class WxLoginController extends BaseController {
@PostMapping("/getWxOpenId")
public ApiResult<?> getWxOpenId(@RequestBody UserParam userParam) {
final User loginUser = getLoginUser();
if(loginUser.getUsername().equals("www")){
return fail("游客");
if(loginUser == null){
return fail("请先登录");
}
// 已存在直接返回
if(StrUtil.isNotBlank(loginUser.getOpenid())){
return success(loginUser);
}
// 请求微信接口获取openid
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session";
final HashMap<String, Object> map = new HashMap<>();
final JSONObject setting = settingService.getBySettingKey("mp-weixin");
@@ -266,13 +271,16 @@ public class WxLoginController extends BaseController {
map.put("js_code",userParam.getCode());
map.put("grant_type","authorization_code");
final String response = HttpUtil.get(apiUrl,map);
System.out.println("response = " + response);
final JSONObject jsonObject = JSONObject.parseObject(response);
final String openid = jsonObject.getString("openid");
jsonObject.getString("session_key");
jsonObject.getString("unionid");
System.out.println("openid = " + openid);
System.out.println("loginUser = " + loginUser);
String openid = jsonObject.getString("openid");
String sessionKey = jsonObject.getString("session_key");
String unionid = jsonObject.getString("unionid");
// 保存openID
if(loginUser.getOpenid() == null || StrUtil.isBlank(loginUser.getOpenid())){
loginUser.setOpenid(openid);
loginUser.setUnionid(unionid);
userService.updateById(loginUser);
}
return success("获取成功",jsonObject);
}

View File

@@ -0,0 +1,132 @@
package com.gxwebsoft.common.system.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Order;
import com.gxwebsoft.common.system.entity.Setting;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.param.SettingParam;
import com.gxwebsoft.common.system.service.OrderService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RSANotificationConfig;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Map;
import static com.gxwebsoft.common.core.constants.OrderConstants.PAY_STATUS_NO_PAY;
import static com.gxwebsoft.common.core.constants.OrderConstants.PAY_STATUS_SUCCESS;
@Api(tags = "微信Native支付接口")
@RestController
@RequestMapping("/api/system/wx-native-pay")
public class WxNativePayController extends BaseController {
/** 商户号 */
public static String merchantId = "1246610101";
/** 商户API私钥路径 */
public static String privateKeyPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_key.pem";
// public static String privateKeyPath = "/Users/gxwebsoft/cert/1246610101_20240511_cert/apiclient_cert.pem";
/** 商户证书序列号 */
public static String merchantSerialNumber = "48749613B40AA8F1D768583FC352358E13EB5AF0";
/** 商户APIV3密钥 */
public static String apiV3Key = "zGufUcqa7ovgxRL0kF5OlPr482EZwtn9";
// 公众号的AppID
public static String appId = "wx541db955e7a62709";
private final Config wxPayConfig;
@Resource
private OrderService orderService;
@Resource
private ConfigProperties config;
public WxNativePayController() {
File file = new File(privateKeyPath);
if (file.exists()) {
this.wxPayConfig =
new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3Key)
.build();
}else {
System.out.println("无法访问文件");
this.wxPayConfig = null ;
}
}
@ApiOperation("生成付款码")
@PostMapping("/codeUrl")
public ApiResult<?> getCodeUrl(@RequestBody Order order) {
order.setMoney(new BigDecimal(0.01));
order.setOrderNo(CommonUtil.createOrderNo());
// 使用自动更新平台证书的RSA配置
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
// 构建service
NativePayService service = new NativePayService.Builder().config(wxPayConfig).build();
// request.setXxx(val)设置所需参数具体参数可见Request定义
PrepayRequest request = new PrepayRequest();
// 计算金额
BigDecimal decimal = order.getMoney();
final BigDecimal multiply = decimal.multiply(new BigDecimal(100));
// 将 BigDecimal 转换为 Integer
Integer money = multiply.intValue();
Amount amount = new Amount();
amount.setTotal(money);
request.setAmount(amount);
request.setAppid(appId);
request.setMchid(merchantId);
request.setDescription("网宿软件企业版-1年授权");
request.setNotifyUrl("https://server.gxwebsoft.com/api/system/wx-native-pay/notify/10150");
request.setOutTradeNo(order.getOrderNo());
// 调用下单方法,得到应答
PrepayResponse response = service.prepay(request);
// 使用微信扫描 code_url 对应的二维码即可体验Native支付
// System.out.println(response.getCodeUrl());
// 生成指定url对应的二维码到文件宽和高都是300像素
// QrCodeUtil.generate(response.getCodeUrl(), 300, 300, FileUtil.file("/Users/gxwebsoft/Documents/uploads/wx-native-qrcode.jpg"));
return success("生成付款码",response.getCodeUrl());
}
@ApiModelProperty("异步通知")
@PostMapping("/notify/{tenantId}")
public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) {
System.out.println("异步通知*************** = ");
System.out.println("request header = " + header);
System.out.println("request body = " + body);
System.out.println("tenantId = " + tenantId);
// 获取支付配置信息用于解密
final SettingParam param = new SettingParam();
param.setSettingKey("payment");
param.setTenantId(tenantId);
final String uploadPath = config.getUploadPath(); // 服务器本地路径
return "fail";
}
}

View File

@@ -52,7 +52,7 @@ import static com.gxwebsoft.common.core.constants.OrderConstants.PAY_STATUS_SUCC
*/
@Api(tags = "会员特权购买记录表管理")
@RestController
@RequestMapping("/api/love/user-plan-log")
@RequestMapping("/api/system/notify")
public class WxPayNotifyController extends BaseController {
@Resource
private OrderService orderService;

View File

@@ -237,11 +237,9 @@ public class User implements UserDetails {
private Integer dealerId;
@ApiModelProperty("微信openid")
@TableField(exist = false)
private String openid;
@ApiModelProperty("微信unionid")
@TableField(exist = false)
private String unionid;
@ApiModelProperty("ico文件")

View File

@@ -96,7 +96,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
final String appId = mpWx.getString("appId");
final String mchId = payment.getMchId();
final String openid = order.getOpenid(); // openid
final String notifyUrl = config.getServerUrl() + "/love/user-plan-log/wx-pay/notify/" + order.getTenantId(); // 异步通知地址
final String notifyUrl = config.getServerUrl() + "/system/notify/" + order.getTenantId(); // 异步通知地址
final String privateKey = uploadPath.concat("file").concat(payment.getApiclientKey()); // 秘钥证书
final String apiclientCert = uploadPath.concat("file").concat(payment.getApiclientCert());
final String merchantSerialNumber = payment.getMerchantSerialNumber(); // 证书序列号
@@ -127,9 +127,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
request.setAmount(amount);
request.setAppid(appId);
request.setMchid(mchId);
OrderInfo desc = order.getOrderInfoList().get(0);
request.setDescription(desc.getSiteName().concat(desc.getFieldName()).concat(desc.getDateTime()));
request.setDescription(order.getComments());
request.setNotifyUrl(notifyUrl);
request.setOutTradeNo(order.getOrderNo());
request.setAttach(order.getTenantId().toString());