Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
T
travel-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
cloud
travel-cloud
Commits
d396743e
提交
d396743e
authored
12月 10, 2024
作者:
hzh
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
微信支付模块集成
上级
b27cce0b
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
768 行增加
和
0 行删除
+768
-0
pom.xml
ruoyi-common/ruoyi-common-bom/pom.xml
+7
-0
pom.xml
ruoyi-common/ruoyi-common-pay/pom.xml
+55
-0
WechatPayConfiguration.java
...org/dromara/common/pay/config/WechatPayConfiguration.java
+61
-0
Amount.java
...y/src/main/java/org/dromara/common/pay/domain/Amount.java
+42
-0
GoodsDetail.java
.../main/java/org/dromara/common/pay/domain/GoodsDetail.java
+47
-0
JsapiNotifyModel.java
.../java/org/dromara/common/pay/domain/JsapiNotifyModel.java
+106
-0
Payer.java
...ay/src/main/java/org/dromara/common/pay/domain/Payer.java
+27
-0
PromotionDetail.java
...n/java/org/dromara/common/pay/domain/PromotionDetail.java
+82
-0
SceneInfo.java
...rc/main/java/org/dromara/common/pay/domain/SceneInfo.java
+27
-0
IWxPayService.java
...in/java/org/dromara/common/pay/service/IWxPayService.java
+49
-0
WxPayServiceImpl.java
...org/dromara/common/pay/service/impl/WxPayServiceImpl.java
+262
-0
org.springframework.boot.autoconfigure.AutoConfiguration.imports
...ingframework.boot.autoconfigure.AutoConfiguration.imports
+2
-0
RemoteOrderServiceImpl.java
.../java/org/dromara/order/dubbo/RemoteOrderServiceImpl.java
+1
-0
没有找到文件。
ruoyi-common/ruoyi-common-bom/pom.xml
浏览文件 @
d396743e
...
...
@@ -271,6 +271,13 @@
<version>
${revision}
</version>
</dependency>
<!-- 支付 -->
<dependency>
<groupId>
org.dromara
</groupId>
<artifactId>
ruoyi-common-pay
</artifactId>
<version>
${revision}
</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
ruoyi-common/ruoyi-common-pay/pom.xml
0 → 100644
浏览文件 @
d396743e
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<parent>
<groupId>
org.dromara
</groupId>
<artifactId>
ruoyi-common
</artifactId>
<version>
${revision}
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
ruoyi-common-pay
</artifactId>
<description>
ruoyi-common-pay 支付接口模块
</description>
<dependencies>
<dependency>
<groupId>
org.dromara
</groupId>
<artifactId>
ruoyi-common-core
</artifactId>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
</dependency>
<dependency>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
<version>
5.8.22
</version>
</dependency>
<dependency>
<groupId>
com.github.javen205
</groupId>
<artifactId>
IJPay-WxPay
</artifactId>
<version>
2.9.9
</version>
</dependency>
<dependency>
<groupId>
com.github.javen205
</groupId>
<artifactId>
IJPay-Core
</artifactId>
<version>
2.9.9
</version>
</dependency>
<dependency>
<groupId>
javax.servlet
</groupId>
<artifactId>
servlet-api
</artifactId>
<version>
2.5
</version>
<scope>
provided
</scope>
</dependency>
</dependencies>
</project>
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/config/WechatPayConfiguration.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
config
;
import
lombok.Getter
;
import
lombok.Setter
;
import
lombok.ToString
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.stereotype.Component
;
/**
* <p>IJPay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
*
* <p>不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。 </p>
*
* <p>IJPay 交流群: 723992875、864988890</p>
*
* <p>Node.js 版: <a href="https://gitee.com/javen205/TNWX">https://gitee.com/javen205/TNWX</a></p>
*
* <p>微信配置 Bean</p>
*
* @author Javen
*/
@Getter
@Setter
@ToString
@Component
@ConfigurationProperties
(
prefix
=
"pay.wechat.v3"
)
public
class
WechatPayConfiguration
{
/**
* 应用编号
*/
private
String
appId
;
/**
* 商户号
*/
private
String
mchId
;
/**
* 商户平台「API安全」中的 APIv3 密钥
*/
private
String
apiKey3
;
/**
* API 证书中的 key.pem
*/
private
String
keyPath
;
/**
* API 证书中的 cert.pem
*/
private
String
certPath
;
/**
* 微信平台证书
*/
private
String
platformCertPath
;
/**
* 应用域名,回调中会使用此参数
*/
private
String
domain
;
/**
* 回调函数的接口路径
*/
private
String
notify
;
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/domain/Amount.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
domain
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors
(
chain
=
true
)
public
class
Amount
implements
Serializable
{
/**
* 订单总金额,单位为分。
*/
private
Integer
total
;
/**
* 用户支付金额,单位为分。
*/
private
Integer
payer_total
;
/**
* CNY:人民币,境内商户号仅支持人民币。
*/
private
String
currency
;
/**
* 用户支付币种
*/
private
String
payer_currency
;
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/domain/GoodsDetail.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
domain
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors
(
chain
=
true
)
public
class
GoodsDetail
implements
Serializable
{
/**
* 商品编码。
*/
private
String
goods_id
;
/**
* 用户购买的数量。
*/
private
Integer
quantity
;
/**
* 商品单价,单位为分。
*/
private
Integer
unit_price
;
/**
* 商品优惠金额。
*/
private
Integer
discount_amount
;
/**
* 商品备注信息。
*/
private
String
goods_remark
;
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/domain/JsapiNotifyModel.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
domain
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* @author hzh
* @date 2024-12-10
* @desc jsapi 回调参数
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors
(
chain
=
true
)
public
class
JsapiNotifyModel
implements
Serializable
{
/**
* 直连商户申请的公众号或移动应用AppID。
*/
private
String
appid
;
/**
* 商户的商户号,由微信支付生成并下发。
*/
private
String
mchid
;
/**
* 商户系统内部订单号,可以是数字、大小写字母_-*的任意组合且在同一个商户号下唯一。
*/
private
String
out_trade_no
;
/**
* 微信支付系统生成的订单号。
*/
private
String
transaction_id
;
/**
* 交易类型,枚举值:
* JSAPI:公众号支付
* NATIVE:扫码支付
* App:App支付
* MICROPAY:付款码支付
* MWEB:H5支付
* FACEPAY:刷脸支付
*/
private
String
trade_type
;
/**
* 交易状态,枚举值:
* SUCCESS:支付成功
* REFUND:转入退款
* NOTPAY:未支付
* CLOSED:已关闭
* REVOKED:已撤销(付款码支付)
* USERPAYING:用户支付中(付款码支付)
* PAYERROR:支付失败(其他原因,如银行返回失败)
*/
private
String
trade_state
;
/**
* 交易状态描述。
*/
private
String
trade_state_desc
;
/**
* 银行类型,采用字符串类型的银行标识。银行标识请参考《银行类型对照表》。
*/
private
String
bank_type
;
/**
* 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段。
*/
private
String
attach
;
/**
* 支付完成时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
*/
private
String
success_time
;
/**
* 银行类型,采用字符串类型的银行标识。银行标识请参考《银行类型对照表》。
*/
private
Payer
payer
;
/**
* 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段。
*/
private
Amount
amount
;
/**
* 支付场景信息描述。
*/
private
SceneInfo
scene_info
;
/**
* 优惠功能,享受优惠时返回该字段
*/
private
PromotionDetail
promotion_detail
;
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/domain/Payer.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
domain
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors
(
chain
=
true
)
public
class
Payer
implements
Serializable
{
/**
* 用户在直连商户AppID下的唯一标识。
*/
private
String
openid
;
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/domain/PromotionDetail.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
domain
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors
(
chain
=
true
)
public
class
PromotionDetail
implements
Serializable
{
/**
* 券ID。
*/
private
String
coupon_id
;
/**
* 优惠名称。
*/
private
String
name
;
/**
* 优惠范围,枚举值:
* GLOBAL:全场代金券
* SINGLE:单品优惠。
*/
private
String
scope
;
/**
* 优惠类型,枚举值:
* CASH:充值型代金券
* NOCASH:免充值型代金券
*/
private
String
type
;
/**
* 优惠券面额。
*/
private
Integer
amount
;
/**
* 活动ID。
*/
private
String
stock_id
;
/**
* 微信出资,单位为分。
*/
private
Integer
wechatpay_contribute
;
/**
* 商户出资,单位为分。
*/
private
Integer
merchant_contribute
;
/**
* 其他出资,单位为分。
*/
private
Integer
other_contribute
;
/**
* CNY:人民币,境内商户号仅支持人民币
*/
private
String
currency
;
/**
* 单品列表信息
*/
private
GoodsDetail
goods_detail
;
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/domain/SceneInfo.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
domain
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* @author hzh
* @date 2024-12-10
**/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors
(
chain
=
true
)
public
class
SceneInfo
implements
Serializable
{
/**
* 终端设备号(门店号或收银设备ID)。
*/
private
String
device_id
;
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/service/IWxPayService.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
service
;
import
com.ijpay.wxpay.model.v3.UnifiedOrderModel
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
/**
* @author wenhe
*/
public
interface
IWxPayService
{
/**
* 微信支付小程序支付
*
* @param model model
* @return 支付结果
* @throws Exception
*/
String
jsapi
(
UnifiedOrderModel
model
)
throws
Exception
;
/**
* 微信支付查询
* @param outTradeNo 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* @return 支付结果
*/
JsapiNotifyModel
query
(
String
outTradeNo
);
/**
* 自动获取证书
*
* @param serialNumber serialNumber
* @return 是否成功
* @throws Exception 异常
*/
boolean
autoUpdateOrGetCertificate
(
String
serialNumber
)
throws
Exception
;
/**
* 支付回调
*
* @param timestamp 时间搓
* @param nonce nonce
* @param serialNo 唯一序列号
* @param signature 签名
* @param result 支付通知密文
* @return 支付通知明文
*/
JsapiNotifyModel
notify
(
String
timestamp
,
String
nonce
,
String
serialNo
,
String
signature
,
String
result
);
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/service/impl/WxPayServiceImpl.java
0 → 100644
浏览文件 @
d396743e
package
org
.
dromara
.
common
.
pay
.
service
.
impl
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.date.DatePattern
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.io.file.FileWriter
;
import
cn.hutool.core.text.CharSequenceUtil
;
import
cn.hutool.http.HttpStatus
;
import
cn.hutool.json.JSONObject
;
import
cn.hutool.json.JSONUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.ijpay.core.IJPayHttpResponse
;
import
com.ijpay.core.constant.IJPayConstants
;
import
com.ijpay.core.enums.RequestMethodEnum
;
import
com.ijpay.core.kit.AesUtil
;
import
com.ijpay.core.kit.PayKit
;
import
com.ijpay.core.kit.WxPayKit
;
import
com.ijpay.core.utils.DateTimeZoneUtil
;
import
com.ijpay.wxpay.WxPayApi
;
import
com.ijpay.wxpay.enums.WxDomainEnum
;
import
com.ijpay.wxpay.enums.v3.BasePayApiEnum
;
import
com.ijpay.wxpay.enums.v3.OtherApiEnum
;
import
com.ijpay.wxpay.model.v3.Certificate
;
import
com.ijpay.wxpay.model.v3.CertificateInfo
;
import
com.ijpay.wxpay.model.v3.EncryptCertificate
;
import
com.ijpay.wxpay.model.v3.UnifiedOrderModel
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.dromara.common.pay.config.WechatPayConfiguration
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.service.IWxPayService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.io.File
;
import
java.nio.charset.StandardCharsets
;
import
java.security.cert.X509Certificate
;
import
java.util.*
;
/**
* @author hzh
* @date 2024-12-10
**/
@Service
@Slf4j
public
class
WxPayServiceImpl
implements
IWxPayService
{
@Autowired
private
WechatPayConfiguration
config
;
/**
* 商户 API 证书序列号
*/
private
String
serialNo
;
/**
* 获取证书序列号
*
* @return 证书序列号
*/
private
String
getSerialNumber
()
{
if
(
StringUtils
.
isEmpty
(
serialNo
))
{
// 获取证书序列号
X509Certificate
certificate
=
PayKit
.
getCertificate
(
config
.
getCertPath
());
if
(
null
!=
certificate
)
{
serialNo
=
certificate
.
getSerialNumber
().
toString
(
16
).
toUpperCase
();
// 提前两天检查证书是否有效
boolean
isValid
=
PayKit
.
checkCertificateIsValid
(
certificate
,
config
.
getMchId
(),
-
2
);
log
.
info
(
"证书是否可用 {} 证书有效期为 {}"
,
isValid
,
DateUtil
.
format
(
certificate
.
getNotAfter
(),
DatePattern
.
NORM_DATETIME_PATTERN
));
}
}
return
serialNo
;
}
@Override
public
String
jsapi
(
UnifiedOrderModel
unifiedOrderModel
)
throws
Exception
{
log
.
info
(
"统一下单参数 {}"
,
JSONUtil
.
toJsonStr
(
unifiedOrderModel
));
IJPayHttpResponse
response
=
WxPayApi
.
v3
(
RequestMethodEnum
.
POST
,
WxDomainEnum
.
CHINA
.
toString
(),
BasePayApiEnum
.
JS_API_PAY
.
toString
(),
config
.
getMchId
(),
getSerialNumber
(),
null
,
config
.
getKeyPath
(),
JSONUtil
.
toJsonStr
(
unifiedOrderModel
));
log
.
info
(
"微信小程序统一下单响应 {}"
,
response
);
// 根据证书序列号查询对应的证书来验证签名结果
boolean
verifySignature
=
WxPayKit
.
verifySignature
(
response
,
config
.
getPlatformCertPath
());
log
.
info
(
"verifySignature: {}"
,
verifySignature
);
if
(
response
.
getStatus
()
==
HttpStatus
.
HTTP_OK
&&
verifySignature
)
{
String
body
=
response
.
getBody
();
JSONObject
jsonObject
=
JSONUtil
.
parseObj
(
body
);
String
prepayId
=
jsonObject
.
getStr
(
"prepay_id"
);
Map
<
String
,
String
>
map
=
WxPayKit
.
jsApiCreateSign
(
config
.
getAppId
(),
prepayId
,
config
.
getKeyPath
());
return
JSONUtil
.
toJsonStr
(
map
);
}
throw
new
RuntimeException
(
"下单失败!"
);
}
@Override
public
boolean
autoUpdateOrGetCertificate
(
String
serialNumber
)
throws
Exception
{
// 获取平台证书列表
IJPayHttpResponse
response
=
WxPayApi
.
v3
(
RequestMethodEnum
.
GET
,
WxDomainEnum
.
CHINA
.
toString
(),
OtherApiEnum
.
GET_CERTIFICATES
.
toString
(),
config
.
getMchId
(),
getSerialNumber
(),
null
,
config
.
getKeyPath
(),
""
);
// 接口响应使用的证书序列号,签名会使用到
String
responseSerialNumber
=
response
.
getHeader
(
"Wechatpay-Serial"
);
String
body
=
response
.
getBody
();
int
status
=
response
.
getStatus
();
if
(
status
==
IJPayConstants
.
CODE_200
)
{
Certificate
model
=
JSONUtil
.
toBean
(
body
,
Certificate
.
class
);
if
(
null
==
model
)
{
log
.
debug
(
"解析返回数据失败"
);
return
false
;
}
List
<
CertificateInfo
>
data
=
model
.
getData
();
if
(
CollUtil
.
isEmpty
(
data
))
{
log
.
debug
(
"未获取到任何有效平台证书"
);
return
false
;
}
log
.
debug
(
"总共获取到 {} 个平台证书"
,
data
.
size
());
CertificateInfo
certificateInfo
=
null
;
// 获取指定序列号的平台证书
if
(
CharSequenceUtil
.
isNotEmpty
(
serialNumber
))
{
Optional
<
CertificateInfo
>
optional
=
data
.
stream
()
.
filter
(
item
->
serialNumber
.
equals
(
item
.
getSerial_no
()))
.
findFirst
();
if
(
optional
.
isPresent
())
{
certificateInfo
=
optional
.
get
();
}
}
// 指定序列号的平台证书不存在,遍历获取可用的平台证书
if
(
null
==
certificateInfo
)
{
log
.
debug
(
"指定序列号 {} 的平台证书不存在,开始遍历获取可用的平台证书"
,
serialNumber
);
for
(
CertificateInfo
info
:
data
)
{
if
(
null
==
info
)
{
continue
;
}
String
expireTime
=
info
.
getExpire_time
();
String
expireTimeStr
=
DateTimeZoneUtil
.
timeZoneDateToStr
(
expireTime
);
Date
expireDate
=
DateUtil
.
parse
(
expireTimeStr
);
if
(
expireDate
.
before
(
new
Date
()))
{
log
.
debug
(
"序列号 {} 对应的平台证书已过期"
,
info
.
getSerial_no
());
continue
;
}
log
.
debug
(
"序列号 {} 对应的平台证书可用,忽略其他证书"
,
info
.
getSerial_no
());
certificateInfo
=
info
;
break
;
}
}
if
(
null
==
certificateInfo
)
{
log
.
debug
(
"未获取到平台证书"
);
return
false
;
}
// 保存证书的序列号
String
serialNo
=
certificateInfo
.
getSerial_no
();
EncryptCertificate
encryptCertificate
=
certificateInfo
.
getEncrypt_certificate
();
String
associatedData
=
encryptCertificate
.
getAssociated_data
();
String
cipherText
=
encryptCertificate
.
getCiphertext
();
String
nonce
=
encryptCertificate
.
getNonce
();
String
expireTime
=
certificateInfo
.
getExpire_time
();
boolean
isOk
=
savePlatformCert
(
associatedData
,
nonce
,
cipherText
,
config
.
getPlatformCertPath
());
if
(
isOk
)
{
log
.
debug
(
"平台证书保存成功,序列号为 {},失效时间为:{}, 保存路径为 {}"
,
serialNo
,
expireTime
,
config
.
getPlatformCertPath
());
if
(
CharSequenceUtil
.
equals
(
responseSerialNumber
,
serialNo
))
{
// 根据证书序列号查询对应的证书来验证签名结果
boolean
verifySignature
=
WxPayKit
.
verifySignature
(
response
,
config
.
getPlatformCertPath
());
log
.
debug
(
"使用序列号 {} 对应的平台证书签名验证结果 {}"
,
serialNo
,
verifySignature
);
return
verifySignature
;
}
return
true
;
}
}
return
false
;
}
/**
* 保存证书
*
* @param associatedData 关联数据
* @param nonce 随机数
* @param cipherText 加密报文
* @param certPath 证书路径
* @return 保存结果
* @throws Exception 异常信息
*/
protected
boolean
savePlatformCert
(
String
associatedData
,
String
nonce
,
String
cipherText
,
String
certPath
)
throws
Exception
{
AesUtil
aesUtil
=
new
AesUtil
(
config
.
getApiKey3
().
getBytes
(
StandardCharsets
.
UTF_8
));
// 平台证书密文解密 encrypt_certificate 中的 associated_data nonce ciphertext
String
publicKey
=
aesUtil
.
decryptToString
(
associatedData
.
getBytes
(
StandardCharsets
.
UTF_8
),
nonce
.
getBytes
(
StandardCharsets
.
UTF_8
),
cipherText
);
// 保存证书
FileWriter
writer
=
new
FileWriter
(
certPath
);
File
file
=
writer
.
write
(
publicKey
);
return
file
.
isFile
()
&&
file
.
exists
();
}
@Override
public
JsapiNotifyModel
notify
(
String
timestamp
,
String
nonce
,
String
serialNo
,
String
signature
,
String
result
)
{
log
.
info
(
"timestamp:{} nonce:{} serialNo:{} signature:{}"
,
timestamp
,
nonce
,
serialNo
,
signature
);
log
.
info
(
"支付通知密文 {}"
,
result
);
try
{
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
String
plainText
=
WxPayKit
.
verifyNotify
(
serialNo
,
result
,
signature
,
nonce
,
timestamp
,
config
.
getApiKey3
(),
config
.
getPlatformCertPath
()
);
log
.
info
(
"支付通知明文 {}"
,
plainText
);
return
JSON
.
parseObject
(
plainText
,
JsapiNotifyModel
.
class
);
}
catch
(
Exception
e
)
{
log
.
error
(
"系统异常"
,
e
);
throw
new
RuntimeException
(
"系统异常!"
);
}
}
@Override
public
JsapiNotifyModel
query
(
String
outTradeNo
)
{
try
{
Map
<
String
,
String
>
params
=
new
HashMap
<>(
16
);
params
.
put
(
"mchid"
,
config
.
getMchId
());
log
.
info
(
"统一查询订单参数 {},订单编号:{}"
,
JSONUtil
.
toJsonStr
(
params
),
outTradeNo
);
IJPayHttpResponse
response
=
WxPayApi
.
v3
(
RequestMethodEnum
.
GET
,
WxDomainEnum
.
CHINA
.
toString
(),
String
.
format
(
BasePayApiEnum
.
ORDER_QUERY_BY_OUT_TRADE_NO
.
toString
(),
outTradeNo
),
config
.
getMchId
(),
getSerialNumber
(),
null
,
config
.
getKeyPath
(),
params
);
log
.
info
(
"查询订单:{} 查询响应 {}"
,
outTradeNo
,
response
);
if
(
response
.
getStatus
()
==
IJPayConstants
.
CODE_200
)
{
// 根据证书序列号查询对应的证书来验证签名结果
boolean
verifySignature
=
WxPayKit
.
verifySignature
(
response
,
config
.
getPlatformCertPath
());
log
.
info
(
"verifySignature: {}"
,
verifySignature
);
//验签成功
if
(
verifySignature
)
{
JSONObject
result
=
JSONUtil
.
parseObj
(
response
.
getBody
());
return
JSON
.
parseObject
(
JSON
.
toJSONString
(
result
),
JsapiNotifyModel
.
class
);
}
}
throw
new
RuntimeException
(
"订单"
+
outTradeNo
+
"查询失败!"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"系统异常"
,
e
);
throw
new
RuntimeException
(
"订单"
+
outTradeNo
+
"查询失败!"
);
}
}
}
ruoyi-common/ruoyi-common-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
0 → 100644
浏览文件 @
d396743e
org.dromara.common.pay.config.WechatPayConfiguration
org.dromara.common.pay.service.IWxPayService
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/dubbo/RemoteOrderServiceImpl.java
浏览文件 @
d396743e
...
...
@@ -151,4 +151,5 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
return
null
;
}).
collect
(
Collectors
.
toList
());
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论