依赖
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.14</version>
</dependency>
配置类
import com.wechat.pay.java.core.cipher.SignatureResult;
import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.TransactionAmount;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.ReqFundsAccount;
@Configuration
@Setter
@Getter
@ConfigurationProperties("wxmini")
@Slf4j
public class WxMiniConfiguration {
/** 商户号 */
private String mchid;
/** 小程序appid */
private String appid;
/** 支付回调 */
private String notifyUrl;
/** 商户证书序列号 */
private String serialNumber;
/** 商户API私钥路径 */
private String privateKeyPath;
/** 商户APIV3密钥 */
private String payApiV3Key;
private RSAAutoCertificateConfig config;
public WxMiniConfiguration(){
}
private void createConfig(){
try {
File file = new File(this.privateKeyPath);
if (!file.exists()) {//如果配置不存在
try {
String keyPath = "/wxmini_pay_ca/apiclient_key.pem";
//从classespath获取证书
InputStream resourceAsStream = getClass().getResourceAsStream(keyPath);
File dir = new File("/wxmini_pay_ca");
if (!dir.exists()) {
dir.mkdirs();
}
//复制到jar同级目录
FileUtils.copyInputStreamToFile(resourceAsStream,new File(keyPath));
this.privateKeyPath = keyPath;
}catch (Exception e){
log.info("文件不存在");
}
}
// 初始化商户配置
this.config = new RSAAutoCertificateConfig.Builder()
.merchantId(this.mchid)
// 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
.privateKeyFromPath(this.privateKeyPath)
.merchantSerialNumber(this.serialNumber)
.apiV3Key(this.payApiV3Key).build();
log.info("payConfig初始化成功-----------");
}catch (Exception e){
log.error("payConfig初始化失败",e);
}
}
/**
* wx退款api
* @return
*/
@Bean
public RefundService createRefund(){
if (this.config == null){
createConfig();
}
return new RefundService.Builder().config(this.config).build();
}
/**
* 创建订单api
* @return
*/
@Bean
public JsapiService createJsapiService(){
if (this.config == null){
createConfig();
}
return new JsapiService.Builder().config(this.config).build();
}
}
Service层
@Autowired
private JsapiService jsapiService;
@Autowired
private WxMiniConfiguration wxMiniConfiguration;
/**
* 支付
* @param wmOrder 订单编号 //支付金额 单位是元 方法内转换为分
*
*/
private WmAffirmDto pay(WmOrder wmOrder){
Amount amount = new Amount();
Payer payer = new Payer();
amount.setTotal(wmOrder.getActualMoney()
.multiply(new BigDecimal(100)).intValue());// 分为单位
//需要当前支付用户的openid
payer.setOpenid(SecurityUtils.getLoginUser().getWxUser().getOpenid());
PrepayRequest preRequest = new PrepayRequest();
preRequest.setAmount(amount);
preRequest.setAppid(wxMiniConfiguration.getAppid());//小程序id
preRequest.setMchid(wxMiniConfiguration.getMchid());//商户id
preRequest.setDescription("xx");//详情
preRequest.setNotifyUrl(wxMiniConfiguration.getNotifyUrl()); //回调
preRequest.setOutTradeNo(wmOrder.getOrderCode());
preRequest.setPayer(payer);
//创建订单
//新增支付信息
//...
return paySignRSA(wmOrder.getOrderCode(),prepay.getPrepayId());//记录付费
}
/***
* 支付签名计算
* @param code 订单编号
* @param prepayId 支付id
* @return 返回 WmAffirmDto
*/
private WmAffirmDto paySignRSA(String code,String prepayId){
//支付签名计算
String timeStamp = String.valueOf(System.currentTimeMillis());
String paySign = String.format("%s\n%s\n%s\nprepay_id=%s\n",
wxMiniConfiguration.getAppid(),timeStamp,code,prepayId);
SignatureResult sign =
wxMiniConfiguration.getConfig().createSigner().sign(paySign);//计算
String paySignRSA = sign.getSign();
//自己写的实体 自己写个
WmAffirmDto wmAffirmDto = new WmAffirmDto();
wmAffirmDto.setNonceStr(code);
wmAffirmDto.setSignType("RSA");
wmAffirmDto.setTimeStamp(timeStamp);
wmAffirmDto.setPrepay_id(prepayId);
wmAffirmDto.setPaySign(paySignRSA);
return wmAffirmDto;
}
/**
* 支付回调
*
* @param notification
* @return
*/
@Transactional
public ResponseEntity.BodyBuilder parseOrderNotify(HttpServletRequest request, Notification notification) {
try {
//获取body
ByteArrayOutputStream result = new ByteArrayOutputStream();
ServletInputStream inputStream = request.getInputStream();
try {
byte[] buffer = new byte[1024];
for (int length; (length = inputStream.read(buffer)) != -1; ) {
result.write(buffer, 0, length);
}
} catch (IOException e) {
log.error("读取数据流异常:{}", e.toString());
}
log.info("body:" + result.toString("UTF-8"));
String body = result.toString("UTF-8");;
// 签名的验证及解密
// 构建request,传入必要参数
RequestParam requestParam = new RequestParam
.Builder()
.serialNumber(request.getHeader("Wechatpay-Serial"))
.nonce(request.getHeader("Wechatpay-Nonce"))
.signature(request.getHeader("Wechatpay-Signature"))
.signType(request.getHeader("Wechatpay-Signature-Type"))
.timestamp(request.getHeader("Wechatpay-Timestamp"))
.body(body)
.build();
// 从notification中获取解密报文
NotificationParser parser = new NotificationParser(wxMiniConfiguration.getConfig());
Transaction transaction= parser.parse(requestParam, Transaction.class);
String outTradeNo = transaction.getOutTradeNo();
//订单信息处理
//支付成功改为已支付
// 处理成功,返回 200 OK 状态码
return ResponseEntity.status(HttpStatus.SUCCESS);
}catch (Exception e){
log.error("微信支付回调失败",e);
return ResponseEntity.status(HttpStatus.ERROR);
}
}