1、获取商户号merchantId
账户中心->商户信息->微信支付商户号
3、获取商户证书序列号merchantSerialNumber
账户中心->API安全->API证书管理
5、获取appID
产品中心->AppID账号管理
Java接入微信支付APIV3(Native)_java native微信支付-CSDN博客
com.github.wechatpay-apiv3
wechatpay-java
0.2.5
cn.hutool
hutool-all
5.8.16
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.RequestParam;
import com.wechat.pay.java.service.partnerpayments.nativepay.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 lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
/**
* Native 支付工具类 获取支付地址、解析支付数据
*/
@Slf4j
public class PayUtils {
//商户号
public static String merchantId = "16***";
//商户API私钥路径 服务器里的路径
public static String privateKeyPath = "/home/jx****rvice/apiclient_key.pem";
//商户证书序列号
public static String merchantSerialNumber = "*******";
//商户APIV3密钥
public static String apiV3key = "iK8fl7*3";
public static String appId = "wx0*****7e";
// 使用自动更新平台证书的RSA配置
public static Config config = new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId) // 商户号
.privateKeyFromPath(privateKeyPath) // API证书地址(此处的路径自己调试一下,能找到就行)
.merchantSerialNumber(merchantSerialNumber) // API证书序列号
.apiV3Key(apiV3key) // API密匙
.build();
// 初始化 解析器 NotificationParser
public static NotificationParser parser = new NotificationParser((NotificationConfig) config);
/**
* 获取支付地址 设置回调路径
*
* @param total 【总金额】 订单总金额,单位为分
* @param desc 商品描述
* @param notifyUrl 回调地址(必须是http) 如:"http://*7.*2.***.2**:8081/pay/notifyNative"
* @return
* @Param orderNo 自己后端的唯一订单号
*/
public static String nativePayAddr(Integer total, String desc, String notifyUrl, String orderNo, String attach) {
// 构建service
NativePayService service = new NativePayService.Builder().config(config).build();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(total); // 【总金额】 订单总金额,单位为分。
request.setAmount(amount);
request.setAppid(appId); // 应用ID
request.setMchid(merchantId); // 商户号
request.setDescription(desc); // 商品描述
request.setNotifyUrl(notifyUrl); // 支付成功的回调地址
request.setAttach(attach);
// 生成模拟系统内部订单号(yyyyMMddHHmmssSSS)
request.setOutTradeNo(orderNo); // 自己后端的唯一订单号,此处使用时间模拟
// 调用下单方法,得到应答
try {
// 发送请求
PrepayResponse response = service.prepay(request);
// 使用微信扫描 code_url 对应的二维码,即可体验Native支付
System.out.println(response.getCodeUrl());
// 将支付地址返回
return response.getCodeUrl();
} catch (Exception e) {
System.out.println("获取支付的url失败:" + e.getMessage());
return e.getMessage();
}
}
/**
* 解析器 解密微信给的数据
*
* @param request
* @return
*/
public Transaction parser(HttpServletRequest request) {
try {
// 获取请求体原内容(此时获取的数据是加密的)
BufferedReader reader = request.getReader();
StringBuilder requestBody = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
requestBody.append(line);
}
// 获取请求携带的数据,构造参数
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(request.getHeader("Wechatpay-Serial")) // 微信支付平台证书的序列号
.nonce(request.getHeader("Wechatpay-Nonce")) // 签名中的随机数
.signature(request.getHeader("Wechatpay-Signature")) // 应答的微信支付签名
.timestamp(request.getHeader("Wechatpay-Timestamp")) // 签名中的时间戳
.body(requestBody.toString()) // 请求体内容(原始内容,不要解析)
.build();
// 解析为Transaction对象(解密数据)
Transaction transaction = parser.parse(requestParam, Transaction.class);
//解密完成后的数据
return transaction;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
swagger-ui 、ipUtil工具类 、@Slf4j 哪里报红删哪里
实体类、支付记录表 自己设计吧 记得把支付日志表给我一份
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jxn.mapper.PayLogMapper;
import com.jxn.pojo.PayLog;
import com.jxn.utils.IpUtils;
import com.jxn.utils.PayUtils;
import com.jxn.utils.Result;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.DynamicParameter;
import io.swagger.annotations.DynamicParameters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* @author szl
* @date 2023/11/2 0002 10:30
*/
@Slf4j
@Api(tags = "支付")
@RestController
@CrossOrigin
@RequestMapping("/pay")
public class WechatPayController {
@Autowired
PayLogMapper payLogMapper;
/**
* Native支付下单,获取支付地址
*
* @param
* @return 支付地址,前端用于生成支付二维码
*/
@ApiOperation(value = "预支付,获取支付地址", response = Result.class)
@DynamicParameters(name = "data", properties = {
@DynamicParameter(name = "total", value = "页码", example = "1", required = true),
@DynamicParameter(name = "userId", value = "条数", example = "10", required = true),
})
@PostMapping("/getNativePayAddr")
public String nativePayAddr(HttpServletRequest request, @RequestBody JSONObject data) {
//String ipAddr = IpUtils.getIpAddr(request);
Integer total = data.getInteger("total");
String userId = data.getString("userId");
JSONObject attach = new JSONObject();
attach.put("userId", userId);
//attach.put("ipAddr", ipAddr);
String notifyUrl = "http://4*.*2.1*2.2**:8081/pay/notifyNative";
String orderNo = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN);
//调用支付工具类,获取支付的url(也就是二维码)
String payAddr = PayUtils.nativePayAddr(total, "测试xxx商品简述", notifyUrl, orderNo, attach.toString());
return payAddr;
}
@ApiOperation(value = "成功支付的回调", response = Result.class)
@PostMapping("/notifyNative")
public void notifyNative(HttpServletRequest request, HttpServletResponse response) throws IOException {
//String ipAddr = IpUtils.getIpAddr(request);
//log.info("ipaddr:" + ipAddr);
String a = "{\"transaction_id\":\"1217752501201407033233368018\",\"amount\":{ \"payer_total\":100, \"total\":100, \"currency\":\"CNY\", \"payer_currency\":\"CNY\"},\"mchid\":\"1230000109\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CMC\",\"promotion_detail\":[ { \"amount\":100, \"wechatpay_contribute\":0, \"coupon_id\":\"109519\", \"scope\":\"GLOBAL\", \"merchant_contribute\":0, \"name\":\"单品惠-6\", \"other_contribute\":0, \"currency\":\"CNY\", \"stock_id\":\"931386\", \"goods_detail\":[ { \"goods_remark\":\"商品备注信息\", \"quantity\":1, \"discount_amount\":1, \"goods_id\":\"M1006\", \"unit_price\":100 }, { \"goods_remark\":\"商品备注信息\", \"quantity\":1, \"discount_amount\":1, \"goods_id\":\"M1006\", \"unit_price\":100 } ] }, { \"amount\":100, \"wechatpay_contribute\":0, \"coupon_id\":\"109519\", \"scope\":\"GLOBAL\", \"merchant_contribute\":0, \"name\":\"单品惠-6\", \"other_contribute\":0, \"currency\":\"CNY\", \"stock_id\":\"931386\", \"goods_detail\":[ { \"goods_remark\":\"商品备注信息\", \"quantity\":1, \"discount_amount\":1, \"goods_id\":\"M1006\", \"unit_price\":100 }, { \"goods_remark\":\"商品备注信息\", \"quantity\":1, \"discount_amount\":1, \"goods_id\":\"M1006\", \"unit_price\":100 } ] }],\"success_time\":\"2018-06-08T10:34:56+08:00\",\"payer\":{ \"openid\":\"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o\"},\"out_trade_no\":\"1217752501201407033233368018\",\"AppID\":\"wxd678efh567hg6787\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"MICROPAY\",\"attach\":\"自定义数据\",\"scene_info\":{ \"device_id\":\"013467007045764\"}\n}";
Transaction transaction = JSON.parseObject(a, Transaction.class);
//Transaction transaction = new PayUtils().parser(request);
log.info("解析后的数据:" + transaction.toString());
// 获取支付单号
log.info("支付成功,回调信息:{}", transaction);
// 打印其中的"微信支付单号"字段,可用于查单操作
log.info("微信支付单号:{}", transaction.getTransactionId());
//解密完成后的数据
PayLog payLog = new PayLog();
payLog.setPayStatus(transaction.getTradeStateDesc());
payLog.setCreateTime(transaction.getSuccessTime());
payLog.setTotal(transaction.getAmount().getTotal());
payLog.setTransactionId(transaction.getTransactionId());//微信支付系统生成的订单号
payLog.setOrderNo(transaction.getOutTradeNo());//自己系统的订单号
payLog.setPayType(transaction.getTradeType().toString());//支付类型
if ("SUCCESS".equals(transaction.getTradeState().toString())) {
payLog.setPayStatus("1");//交易状态
} else {
payLog.setPayStatus("0");//交易状态
}
payLog.setOpenid(transaction.getPayer().getSubOpenid() + transaction.getPayer().getSpOpenid());//支付人信息 包含openid
String goodsName = transaction.getPromotionDetail().get(0).getName();
payLog.setReturnData(transaction.toString());
log.info("插入支付日志:{}", payLog.toString());
payLogMapper.insert(payLog);
}
}
这是官方的地址 微信回调给到你的数据 解析后存到自己 的支付记录表
支付通知 - Native支付 | 微信支付商户文档中心
1、拿到支付的url,搜索在线生成二维码,粘贴url 生成二维码
2、扫码支付后,触发回调,解析Transaction,取有用的数据,存到日志表
回调时 Transaction transaction 取得是demo数据,记得注释掉
有问题评论 在线答复。记得 支付日志表设计完 给我一份
饭在锅里,钱在抽屉里,工具类在这里,具体使用在那里,配置类在开发者文档里,我出去办点事