IJPay接入微信支付和支付宝支付

IJPay框架支付Demo

引入pom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<dependency>
<!-- 微信支付 -->
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-WxPay</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 支付宝支付 -->
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-AliPay</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 核心包,必须引入! -->
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-Core</artifactId>
<version>2.7.0</version>
</dependency>

自定义实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@SuperBuilder
public class PayWayInfoEntity implements Serializable {

private static final long serialVersionUID = 493664191798244071L;

/**
* 微信应用编号
*/
private String appId;

/**
* appSecret 是 appId 对应的接口密码,(服务商模式)就是服务商的 appSecret
* 如果是支付宝支付就是支付宝的公钥
*/
private String appSecret;

/**
* API 密钥,微信商户后台配置
* 如果是支付宝支付就是支付宝的私钥
*/
private String partnerKey;

/**
* apiclient_cert.p12 证书绝对路径,在服务商微信商户后台下载
*/
private String certPath;

/**
* 外网访问项目的域名,支付通知、回调中会使用
*/
private String doMain;

/**
* 微信支付商户号
*/
private String mchId;

/**
* 是否是服务商模式
*/
private Boolean isServer;

/**
* 子商户号的应用编号(服务商模式)
*/
private String subAppId;

/**
* 子商户号(服务商模式)
*/
private String subMchId;

/**
* 支付描述信息
*/
private String body;

/**
* 支付方式类型 1微信支付
*/
private Integer type;
}

微信支付

公用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* 获取支付参数
*
* @param request
* @param tradeType 支付方式
* @param totalFee 金额
* @param openId 用户openId
* @param orderNumber 订单号
* @param payWayInfoEntity 配置信息
* @return
*/
private Map<String, String> getWexinResult(HttpServletRequest request, String tradeType, String totalFee, String openId, String orderNumber, PayWayInfoEntity payWayInfoEntity) {
String ip = IpKit.getRealIp(request);
if (StrUtil.isBlank(ip)) {
ip = "127.0.0.1";
}
UnifiedOrderModel unifiedOrderModel = UnifiedOrderModel
.builder()
.appid(payWayInfoEntity.getAppId())
.mch_id(payWayInfoEntity.getMchId())
.nonce_str(WxPayKit.generateStr())
.body(payWayInfoEntity.getBody())
.out_trade_no(orderNumber)
.total_fee(totalFee)
.spbill_create_ip(ip)
.notify_url(payWayInfoEntity.getDoMain() + OtherTypeKey.WEIXIN_PAY_NOTIFY_URL)
.trade_type(tradeType)
.build();
if(openId != null){
unifiedOrderModel.setOpenid(openId);
}

// 服务商模式独有
if (payWayInfoEntity.getIsServer()) {
unifiedOrderModel.setSub_mch_id(payWayInfoEntity.getSubMchId());
unifiedOrderModel.setSub_appid(payWayInfoEntity.getSubAppId());
}
Map<String, String> params = unifiedOrderModel.createSign(payWayInfoEntity.getPartnerKey(), SignType.HMACSHA256);
log.info(params);
String xmlResult = WxPayApi.pushOrder(false, params);
log.info(xmlResult);
return WxPayKit.xmlToMap(xmlResult);
}

private ResponseResult<String> resultJudge(Map<String, String> result) {
String returnCode = result.get("return_code");
String returnMsg = result.get("return_msg");
String errCodeDes = result.get("err_code_des");
if (!WxPayKit.codeIsOk(returnCode)) {
return ResponseResult.error(returnMsg);
}
String resultCode = result.get("result_code");
if (!WxPayKit.codeIsOk(resultCode)) {
return ResponseResult.error(errCodeDes);
}
return null;
}

APP支付

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 微信APP支付
*
* @param totalFee 金额(单位是分)
* @param orderNumber 订单号
* @return
*/
public ResponseResult<String> appPay(HttpServletRequest request, String totalFee, String orderNumber) {
// 缓存中获取微信支付信息
String data = rs.opsForValue().get(RedisKey.PAY_WEIXIN_PAY_PARAM);
if (data == null) {
return ResponseResult.error(ResponseCode.SERVER_ERROR);
}
PayWayInfoEntity payWayInfoEntity = JSONObject.parseObject(data, PayWayInfoEntity.class);
Map<String, String> result = getWexinResult(request, TradeType.APP.getTradeType(), totalFee, null, orderNumber, payWayInfoEntity);
log.info(result);
ResponseResult<String> returnMsg = resultJudge(result);
if (returnMsg != null) {
return returnMsg;
}
// 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
String prepayId = result.get("prepay_id");
Map<String, String> packageParams = WxPayKit.appPrepayIdCreateSign(payWayInfoEntity.getAppId(), payWayInfoEntity.getMchId(), prepayId,
payWayInfoEntity.getPartnerKey(), SignType.HMACSHA256);
String jsonStr = JSON.toJSONString(packageParams);
log.info("返回apk的参数:" + jsonStr);
return ResponseResult.success(jsonStr);
}

h5支付

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 微信h5支付
*
* @param totalFee 金额(单位是分)
* @param orderNumber 订单号
* @return
*/
public ResponseResult<String> h5Pay(HttpServletRequest request, String totalFee, String orderNumber) {
String data = rs.opsForValue().get(RedisKey.PAY_WEIXIN_PAY_PARAM);
if (data == null) {
return ResponseResult.error(ResponseCode.SERVER_ERROR);
}
PayWayInfoEntity payWayInfoEntity = JSONObject.parseObject(data, PayWayInfoEntity.class);
Map<String, String> result = getWexinResult(request, TradeType.MWEB.getTradeType(), totalFee, null, orderNumber, payWayInfoEntity);
log.info(result);
ResponseResult<String> returnMsg = resultJudge(result);
if (returnMsg != null) {
return returnMsg;
}
String webUrl = result.get("mweb_url");
return ResponseResult.success(webUrl);
}

小程序支付

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 微信小程序支付
*
* @param totalFee 金额
* @param openId 用户opendId
* @param orderNumber 订单号
* @return
*/
public ResponseResult<String> miniAppPay(HttpServletRequest request, String totalFee, String openId, String orderNumber) {
String data = rs.opsForValue().get(RedisKey.PAY_WEIXIN_PAY_PARAM);
if (data == null) {
return ResponseResult.error(ResponseCode.SERVER_ERROR);
}
PayWayInfoEntity payWayInfoEntity = JSONObject.parseObject(data, PayWayInfoEntity.class);
Map<String, String> result = getWexinResult(request, TradeType.JSAPI.getTradeType(), totalFee, openId, orderNumber, payWayInfoEntity);
log.info(result);
ResponseResult<String> returnMsg = resultJudge(result);
if (returnMsg != null) {
return returnMsg;
}
// 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
String prepayId = result.get("prepay_id");
Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(payWayInfoEntity.getAppId(), prepayId,
payWayInfoEntity.getPartnerKey(), SignType.HMACSHA256);
String jsonStr = JSON.toJSONString(packageParams);
log.info("小程序支付的参数:" + jsonStr);
return ResponseResult.success(jsonStr);
}

回调验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 异步通知
*/
@RequestMapping(value = "/payNotify", method = {RequestMethod.POST, RequestMethod.GET})
public String payNotify(HttpServletRequest request) {
String xmlMsg = HttpKit.readData(request);
log.info("支付通知=" + xmlMsg);
Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);

String returnCode = params.get("return_code");

if (WxPayKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey(), SignType.HMACSHA256)) {
if (WxPayKit.codeIsOk(returnCode)) {
Map<String, String> xml = new HashMap<String, String>(2);
xml.put("return_code", "SUCCESS");
xml.put("return_msg", "OK");
return WxPayKit.toXml(xml);
}
}
return null;
}

支付宝支付

公用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void setConfig(PayWayInfoEntity payWayInfoEntity) {
AliPayApiConfig aliPayApiConfig;
try {
aliPayApiConfig = AliPayApiConfigKit.getApiConfig(payWayInfoEntity.getAppId());
} catch (Exception e) {
aliPayApiConfig = AliPayApiConfig.builder()
.setAppId(payWayInfoEntity.getAppId())
.setAliPayPublicKey(payWayInfoEntity.getAppSecret())
.setCharset(OtherTypeKey.ALIPAY_CHARSET)
.setPrivateKey(payWayInfoEntity.getPartnerKey())
.setServiceUrl(payWayInfoEntity.getDoMain())
.setSignType(OtherTypeKey.ALIPAY_SIGN_TYPE)
// 普通公钥方式
.build();
}
AliPayApiConfigKit.setThreadLocalAliPayApiConfig(aliPayApiConfig);
}

APP支付

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* app支付
* @param money 金额
* @param orderNumber 订单号
* @return
*/
public ResponseResult<String> appPay(String money, String orderNumber) {
String data = rs.opsForValue().get(RedisKey.PAY_ALIPAY_PAY_PARAM);
if (data == null) {
return ResponseResult.error(ResponseCode.SERVER_ERROR);
}
PayWayInfoEntity payWayInfoEntity = JSONObject.parseObject(data, PayWayInfoEntity.class);
setConfig(payWayInfoEntity);
try {
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody(payWayInfoEntity.getBody());
model.setSubject(payWayInfoEntity.getBody());
// 商户网站唯一订单号
model.setOutTradeNo(orderNumber);
// 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:5m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m
model.setTimeoutExpress("30m");
// 订单总金额,单位为元,精确到小数点后两位
model.setTotalAmount(money);
String orderInfo = AliPayApi.appPayToResponse(model, payWayInfoEntity.getDoMain() + OtherTypeKey.ALIPAY_NOTIFY_URL).getBody();
log.info("支付宝支付参数 {}", orderInfo);
return ResponseResult.success(orderInfo);
} catch (AlipayApiException e) {
e.printStackTrace();
}
return ResponseResult.error(ResponseCode.ERROR);
}

回调验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RequestMapping(value = "/notify_url")
public String certNotifyUrl(HttpServletRequest request) {
try {
// 获取支付宝POST过来反馈信息
Map<String, String> params = AliPayApi.toMap(request);

for (Map.Entry<String, String> entry : params.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}

boolean verifyResult = AlipaySignature.rsaCertCheckV1(params, aliPayBean.getAliPayCertPath(), "UTF-8", "RSA2");

if (verifyResult) {
System.out.println("certNotifyUrl 验证成功succcess");
return "success";
} else {
System.out.println("certNotifyUrl 验证失败");
return "failure";
}
} catch (AlipayApiException e) {
e.printStackTrace();
return "failure";
}
}

相关文章

微信支付和微信退款