这里使用的是Binary Wang 所写的开源项目 weixin-java-pay
github Home · Wechat-Group/WxJava Wiki · GitHub
1、导入maven文件
<!--微信支付-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-pay-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
2、application.yml配置(对应的信息自行去获取,微信支付不需要使用p12证书)
wx:
pay:
appId: wxxxxxxxxxxxxx #微信公众号或者小程序等的appid
mchId: xxxxxxxxx #微信支付商户号
mchKey: xxxxxxxxxxxxxx #微信支付商户密钥
subAppId: #服务商模式下的子商户公众账号ID
subMchId: #服务商模式下的子商户号
keyPath: classpath:/apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
3、WxPayConfiguration配置
将 com.github.binarywang.wxpay.service.WxPayService 作为Bean注入到项目中
/**
* @author Binary Wang
*/
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
@AllArgsConstructor
@Slf4j
public class WxPayConfiguration {
private WxPayProperties properties;
@SneakyThrows
@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.getMchKey()));
payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}
4、WxPayProperties配置
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* wxpay pay properties.
*
* @author Binary Wang
*/
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties {
/**
* 设置微信公众号或者小程序等的appid
*/
private String appId;
/**
* 微信支付商户号
*/
private String mchId;
/**
* 微信支付商户密钥
*/
private String mchKey;
/**
* 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除
*/
private String subAppId;
/**
* 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除
*/
private String subMchId;
/**
* apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
*/
private String keyPath;
}
5、IWxPayService(统一下单)
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import java.math.BigDecimal;
/**
* @author jiavDad
*/
public interface IWxPayService {
WxPayAppOrderResult createDefault(String tradeNo, BigDecimal price, Integer type, String body, Long userId);
}
使用方法:
@Autowired
private IWxPayService wxPayService;
WxPayAppOrderResult wxPayAppOrderResult = wxPayService.createDefault("自己定义的订单号", "金额", "类型", body, "用户id");
(当前支付类型是app,返回类型为WxPayAppOrderResult ,如果是其他支付就用其他类型的)
6、WxPayServiceImpl
/**
* @author jiavDad
*/
@Service
@Slf4j
public class WxPayServiceImpl implements IWxPayService {
@Autowired
private WxPayService wxService;
@Value("${wxPay.callbackPath:/}")
private String wxPayPath;
@Override
public WxPayAppOrderResult createDefault(String tradeNo, BigDecimal price, Integer type, String body, Long userId) {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
//签名类型
orderRequest.setSignType(WxPayConstants.SignType.MD5);
//终端IP
orderRequest.setSpbillCreateIp(PayUtil.getIp());
//商品描述 例如: 腾讯充值中心-QQ会员充值
orderRequest.setBody(body);
//商户订单号 商户系统内部的订单号,32个字符内、可包含字母
orderRequest.setOutTradeNo(tradeNo);
//回调地址
// orderRequest.setNotifyUrl(wxPayPath + tradeNo + "/" + type);
// Integer type = memberRewardByUserReq.getType().equals(1) ? IWxPayService.Type.REWARDPOST : IWxPayService.Type.REWARDCOMMENT;
orderRequest.setNotifyUrl(wxPayPath + tradeNo + "/" + type + "/" + userId);
//支付类型
orderRequest.setTradeType("APP"); //如果你不是app支付就填其他的
// orderRequest.setOpenid(openId); //app支付不需要openId
orderRequest.setTotalFee(price.multiply(new BigDecimal(100)).intValue());
log.error("支付请求参数:[{}]", orderRequest);
try {
log.error("生成订单参数:[{}]", orderRequest);
WxPayAppOrderResult wxPayAppOrderResult = wxService.createOrder(orderRequest);
return wxPayAppOrderResult;
} catch (WxPayException e) {
log.error("微信支付失败!原因:{}", e.getMessage());
}
throw new RuntimeException("微信支付失败!");
}
}
7、设置支付回调接口的路径 application.yml
wxPay:
callbackPath: http://localhost:8080/api/wxPay/notify/order/
8、WxPayController
import com.github.binarywang.wxpay.exception.WxPayException;
import com.mdframework.module.wxpay.IWxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* @author jiavDad
*/
@Validated
@RestController
@RequestMapping("/wxPay")
@Slf4j
@Api(description = "微信支付", tags = "微信支付")
public class WxPayController {
@Autowired
private IWxPayService wxPayService;
/**
* @param xmlData
* @param type 类型
* @return
* @throws WxPayException
*/
@PostMapping("/notify/order/{tradeNo}/{type}/{userId}")
@ResponseBody
@ApiOperation(value = "微信支付回调", notes = "微信支付回调")
public String parseOrderNotifyResult(@RequestBody String xmlData, @PathVariable String tradeNo, @PathVariable Integer type, @PathVariable Long userId) throws WxPayException {
return wxPayService.parseOrderNotifyResult(xmlData, tradeNo, type, userId);
}
}
9、IWxPayService
public interface IWxPayService {
String parseOrderNotifyResult(String xmlData, String tradeNo, Integer type, Long userId);
}
10、WxPayServiceImpl
/**
* @author jiavDad
*/
@Service
@Slf4j
public class WxPayServiceImpl implements IWxPayService {
@Autowired
private WxPayService wxService;
@Autowired
private IAdviceService adviceService;
@Value("${wxPay.callbackPath:/}")
private String wxPayPath;
@SneakyThrows
@Override
@Transactional(rollbackFor = Exception.class)
public String parseOrderNotifyResult(String xmlData, String tradeNo, Integer type, Long userId) {
log.info("手机微信支付回调,xml:[{}],tradeNo:[{}],type:[{}],userId:[{}]", xmlData, tradeNo, type, userId);
WxPayOrderNotifyResult notifyResult = wxService.parseOrderNotifyResult(xmlData);
notifyResult.checkResult(wxService, "MD5", true);
String openid = notifyResult.getOpenid();
String transactionId = notifyResult.getTransactionId();
MemberInfo memberInfo = memberInfoService.getById(userId);
AssertHelper.isTrue(Objects.isNull(memberInfo));
/**
/业务逻辑
**/
return WxPayNotifyResponse.success("成功");
}
}
}
11、支付返回结果:wxPayAppOrderResult
可以自行测试返回来的签名是否正确
地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
注意:app端支付前一定要按照下面的地址配好相应的东西,不然肯定会支付失败!!!!!!
APP端开发步骤https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5