Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
N
nyx
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
发现
nyx
Commits
10c6f395
Commit
10c6f395
authored
Nov 17, 2020
by
jscat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nyx javaapp: 架构更新
1. 新增支付功能
parent
40eaa636
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
456 行增加
和
2 行删除
+456
-2
app/nyx_app_key/api/pom.xml
+20
-0
app/nyx_app_key/api/src/main/java/cn/com/fun/nyxkey/api/utils/PayUtil.java
+171
-0
app/nyx_app_key/api/src/main/java/cn/com/fun/nyxkey/api/web/controller/PayApiController.java
+242
-0
app/nyx_app_key/api/src/main/resources/config/application-dev.yml
+4
-0
app/nyx_app_key/api/src/main/resources/config/application-production.yml
+4
-0
app/nyx_app_key/api/src/main/resources/config/application.yml
+9
-2
app/nyx_app_key/pom.xml
+6
-0
没有找到文件。
app/nyx_app_key/api/pom.xml
查看文件 @
10c6f395
...
...
@@ -196,6 +196,26 @@
<version>
3.3.3
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.springboot/best-pay-sdk jscat 2020/11/16-->
<dependency>
<groupId>
cn.springboot
</groupId>
<artifactId>
best-pay-sdk
</artifactId>
<version>
1.3.3
</version>
</dependency>
<!--wxPay jscat 2020/11/17 -->
<dependency>
<groupId>
com.github.wxpay
</groupId>
<artifactId>
wxpay-sdk
</artifactId>
<version>
0.0.3
</version>
</dependency>
<dependency>
<groupId>
com.thoughtworks.xstream
</groupId>
<artifactId>
xstream
</artifactId>
<version>
1.4.9
</version>
</dependency>
</dependencies>
<build>
...
...
app/nyx_app_key/api/src/main/java/cn/com/fun/nyxkey/api/utils/PayUtil.java
0 → 100644
查看文件 @
10c6f395
package
cn
.
com
.
fun
.
nyxkey
.
api
.
utils
;
import
org.jdom.input.SAXBuilder
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStream
;
import
java.math.BigDecimal
;
import
java.net.InetAddress
;
import
java.net.UnknownHostException
;
import
java.text.SimpleDateFormat
;
import
java.util.*
;
public
class
PayUtil
{
/**
* 获取当前机器的ip
*/
public
static
String
getLocalIp
()
{
InetAddress
ia
=
null
;
String
localip
=
null
;
try
{
ia
=
ia
.
getLocalHost
();
localip
=
ia
.
getHostAddress
();
}
catch
(
UnknownHostException
e
)
{
e
.
printStackTrace
();
}
return
localip
;
}
@SuppressWarnings
(
"rawtypes"
)
public
static
String
getRequestXml
(
SortedMap
<
Object
,
Object
>
parameters
)
{
StringBuffer
sb
=
new
StringBuffer
();
sb
.
append
(
"<xml>"
);
Set
es
=
parameters
.
entrySet
();
Iterator
it
=
es
.
iterator
();
while
(
it
.
hasNext
())
{
Map
.
Entry
entry
=
(
Map
.
Entry
)
it
.
next
();
String
k
=
(
String
)
entry
.
getKey
();
String
v
=
(
String
)
entry
.
getValue
();
if
(
"attach"
.
equalsIgnoreCase
(
k
)
||
"body"
.
equalsIgnoreCase
(
k
)
||
"sign"
.
equalsIgnoreCase
(
k
))
{
sb
.
append
(
"<"
+
k
+
">"
+
"<![CDATA["
+
v
+
"]]></"
+
k
+
">"
);
}
else
{
sb
.
append
(
"<"
+
k
+
">"
+
v
+
"</"
+
k
+
">"
);
}
}
sb
.
append
(
"</xml>"
);
return
sb
.
toString
();
}
/**
* 创建签名Sign
*/
@SuppressWarnings
(
"rawtypes"
)
public
static
String
createSign
(
String
characterEncoding
,
Map
<
String
,
String
>
parameters
,
String
key
)
{
StringBuffer
sb
=
new
StringBuffer
();
Set
es
=
parameters
.
entrySet
();
Iterator
<?>
it
=
es
.
iterator
();
while
(
it
.
hasNext
())
{
Map
.
Entry
entry
=
(
Map
.
Entry
)
it
.
next
();
String
k
=
(
String
)
entry
.
getKey
();
if
(
entry
.
getValue
()
!=
null
||
!
""
.
equals
(
entry
.
getValue
()))
{
String
v
=
String
.
valueOf
(
entry
.
getValue
());
if
(
null
!=
v
&&
!
""
.
equals
(
v
)
&&
!
"sign"
.
equals
(
k
)
&&
!
"key"
.
equals
(
k
))
{
sb
.
append
(
k
+
"="
+
v
+
"&"
);
}
}
}
sb
.
append
(
"key="
+
key
);
String
sign
=
MD5Util
.
encrypt
(
sb
.
toString
()).
toUpperCase
();
return
sign
;
}
/**
* 生成随机数
*/
public
static
String
makeUUID
(
int
len
)
{
return
UUID
.
randomUUID
().
toString
().
replaceAll
(
"-"
,
""
).
substring
(
0
,
len
);
}
/**
* 生成订单号
*/
public
static
String
generateOrderNo
()
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyMMdd"
);
return
sdf
.
format
(
new
Date
())
+
makeUUID
(
16
);
}
/**
* 解析xml
*/
public
static
Map
doXMLParse
(
String
strxml
)
throws
Exception
{
strxml
=
strxml
.
replaceFirst
(
"encoding=\".*\""
,
"encoding=\"UTF-8\""
);
if
(
null
==
strxml
||
""
.
equals
(
strxml
))
{
return
null
;
}
Map
m
=
new
HashMap
();
InputStream
in
=
new
ByteArrayInputStream
(
strxml
.
getBytes
(
"UTF-8"
));
SAXBuilder
builder
=
new
SAXBuilder
();
org
.
jdom
.
Document
doc
=
builder
.
build
(
in
);
org
.
jdom
.
Element
root
=
doc
.
getRootElement
();
List
list
=
root
.
getChildren
();
Iterator
it
=
list
.
iterator
();
while
(
it
.
hasNext
())
{
org
.
jdom
.
Element
e
=
(
org
.
jdom
.
Element
)
it
.
next
();
String
k
=
e
.
getName
();
String
v
=
""
;
List
children
=
e
.
getChildren
();
if
(
children
.
isEmpty
())
{
v
=
e
.
getTextNormalize
();
}
else
{
v
=
getChildrenText
(
children
);
}
m
.
put
(
k
,
v
);
}
//关闭流
in
.
close
();
return
m
;
}
/**
* 获取子节点的xml
*/
public
static
String
getChildrenText
(
List
children
)
{
StringBuffer
sb
=
new
StringBuffer
();
if
(!
children
.
isEmpty
())
{
Iterator
it
=
children
.
iterator
();
while
(
it
.
hasNext
())
{
org
.
jdom
.
Element
e
=
(
org
.
jdom
.
Element
)
it
.
next
();
String
name
=
e
.
getName
();
String
value
=
e
.
getTextNormalize
();
List
list
=
e
.
getChildren
();
sb
.
append
(
"<"
+
name
+
">"
);
if
(!
list
.
isEmpty
())
{
sb
.
append
(
getChildrenText
(
list
));
}
sb
.
append
(
value
);
sb
.
append
(
"</"
+
name
+
">"
);
}
}
return
sb
.
toString
();
}
/**
* 转换金额到整型
*/
public
static
String
moneyToIntegerStr
(
Double
money
)
{
BigDecimal
decimal
=
new
BigDecimal
(
money
);
int
amount
=
decimal
.
multiply
(
new
BigDecimal
((
100
)))
.
setScale
(
0
,
BigDecimal
.
ROUND_HALF_UP
).
intValue
();
return
String
.
valueOf
(
amount
);
}
/**
* 微信下单,map to xml
* @param params 参数
* @return String
*/
@Deprecated
public
static
String
mapToXml
(
Map
<
String
,
String
>
params
)
{
StringBuilder
xml
=
new
StringBuilder
();
xml
.
append
(
"<xml>"
);
for
(
Map
.
Entry
<
String
,
String
>
entry
:
params
.
entrySet
())
{
String
key
=
entry
.
getKey
();
String
value
=
entry
.
getValue
();
// 略过空值
if
(
StringUtils
.
isEmpty
(
value
))
continue
;
xml
.
append
(
"<"
).
append
(
key
).
append
(
"><![CDATA["
);
xml
.
append
(
entry
.
getValue
());
xml
.
append
(
"]]></"
).
append
(
key
).
append
(
">"
);
}
xml
.
append
(
"</xml>"
);
return
xml
.
toString
();
}
public
static
String
create_timestamp
()
{
return
Long
.
toString
(
System
.
currentTimeMillis
()
/
1000
);
}
}
\ No newline at end of file
app/nyx_app_key/api/src/main/java/cn/com/fun/nyxkey/api/web/controller/PayApiController.java
0 → 100644
查看文件 @
10c6f395
package
cn
.
com
.
fun
.
nyxkey
.
api
.
web
.
controller
;
/*
API接口
用于小程序的支付接口
*/
import
cn.com.fun.nyxkey.api.common.JSONResult
;
import
cn.com.fun.nyxkey.api.utils.PayUtil
;
import
cn.com.fun.nyxkey.api.web.common.HttpRequest
;
import
com.alibaba.fastjson.JSONObject
;
import
com.github.wxpay.sdk.WXPayUtil
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiOperation
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.math.BigDecimal
;
import
java.sql.Timestamp
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.TreeMap
;
import
java.util.UUID
;
import
static
org
.
apache
.
commons
.
codec
.
digest
.
MessageDigestAlgorithms
.
MD5
;
/**
* Created by jscat on 2020-11-16.
*/
@RestController
@RequestMapping
(
"/api"
)
public
class
PayApiController
{
@Value
(
"${weixin.appid}"
)
private
String
appid
;
@Value
(
"${weixin.secret}"
)
private
String
secret
;
//商家号id
@Value
(
"${weixin.mchid}"
)
public
String
mchid
;
//商家密钥key
@Value
(
"${weixin.mchkey}"
)
public
String
mchkey
;
//商家密钥key
@Value
(
"${weixin.notifyUrl}"
)
public
String
notifyUrl
;
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
PayApiController
.
class
);
/**
* @Description 统一下单
* @date jscat 2020/11/16
* https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
*
* 微信支付接口签名验证工具
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
*
* 微信公众号支付对接流程 @Java
* https://blog.csdn.net/l15810356216/article/details/88356295
*
* @param
* @return Map
*/
@ApiOperation
(
value
=
"微信支付统一下单"
,
notes
=
"微信支付统一下单"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
"openId"
,
value
=
"openId"
,
required
=
true
,
dataType
=
"String"
,
defaultValue
=
"1"
),
@ApiImplicitParam
(
name
=
"money"
,
value
=
"标价金额"
,
required
=
true
,
dataType
=
"String"
,
defaultValue
=
"1"
),
@ApiImplicitParam
(
name
=
"body"
,
value
=
"商品描述"
,
required
=
true
,
dataType
=
"String"
,
defaultValue
=
"1"
)
})
@RequestMapping
(
value
=
"/nyx/wx/pay/orders"
,
method
=
RequestMethod
.
GET
)
public
Map
<
String
,
Object
>
orders
(
@RequestParam
(
value
=
"openId"
,
required
=
true
,
defaultValue
=
"1"
)
String
openId
,
@RequestParam
(
value
=
"money"
,
required
=
true
,
defaultValue
=
"1"
)
Double
money
,
@RequestParam
(
value
=
"body"
,
required
=
true
,
defaultValue
=
"0"
)
String
body
,
HttpServletRequest
request
)
throws
Exception
{
Map
<
String
,
Object
>
resMap
=
new
HashMap
<
String
,
Object
>();
LOGGER
.
info
(
"=============code:{}"
);
try
{
// 拼接统一下单地址参数
Map
<
String
,
String
>
paraMap
=
new
TreeMap
<
String
,
String
>();
//获取请求ip地址
String
ip
=
request
.
getHeader
(
"x-forwarded-for"
);
if
(
ip
==
null
||
ip
.
length
()
==
0
||
"unknown"
.
equalsIgnoreCase
(
ip
)){
ip
=
request
.
getHeader
(
"Proxy-Client-IP"
);
}
if
(
ip
==
null
||
ip
.
length
()
==
0
||
"unknown"
.
equalsIgnoreCase
(
ip
)){
ip
=
request
.
getHeader
(
"WL-Proxy-Client-IP"
);
}
if
(
ip
==
null
||
ip
.
length
()
==
0
||
"unknown"
.
equalsIgnoreCase
(
ip
)){
ip
=
request
.
getRemoteAddr
();
}
if
(
ip
.
indexOf
(
","
)!=-
1
){
String
[]
ips
=
ip
.
split
(
","
);
ip
=
ips
[
0
].
trim
();
}
paraMap
.
put
(
"appid"
,
appid
);
// 商家平台ID
paraMap
.
put
(
"body"
,
body
);
// 商家名称-销售商品类目、String(128)
paraMap
.
put
(
"mch_id"
,
mchid
);
// 商户ID
paraMap
.
put
(
"nonce_str"
,
WXPayUtil
.
generateNonceStr
());
// UUID
paraMap
.
put
(
"notify_url"
,
notifyUrl
);
// 此路径是微信服务器调用支付结果通知路径随意写
paraMap
.
put
(
"openid"
,
openId
);
paraMap
.
put
(
"out_trade_no"
,
PayUtil
.
generateOrderNo
());
// 订单号,每次都不同
paraMap
.
put
(
"sign_type"
,
MD5
);
paraMap
.
put
(
"spbill_create_ip"
,
ip
);
paraMap
.
put
(
"total_fee"
,
PayUtil
.
moneyToIntegerStr
(
money
));
// 支付金额,单位分
paraMap
.
put
(
"trade_type"
,
"JSAPI"
);
// 支付类型
String
sign
=
PayUtil
.
createSign
(
"UTF-8"
,
paraMap
,
mchkey
);
paraMap
.
put
(
"sign"
,
sign
);
String
xml
=
WXPayUtil
.
mapToXml
(
paraMap
);
// 将所有参数(map)转xml格式
// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
String
unifiedorder_url
=
"https://api.mch.weixin.qq.com/pay/unifiedorder"
;
System
.
out
.
println
(
"xml为:"
+
xml
);
String
xmlStr
=
HttpRequest
.
sendPost
(
unifiedorder_url
,
xml
);
System
.
out
.
println
(
"xmlStr为:"
+
xmlStr
);
// 以下内容是返回前端页面的json数据
String
prepay_id
=
""
;
// 预支付id
if
(
xmlStr
.
indexOf
(
"SUCCESS"
)
!=
-
1
)
{
Map
<
String
,
String
>
map
=
WXPayUtil
.
xmlToMap
(
xmlStr
);
prepay_id
=
(
String
)
map
.
get
(
"prepay_id"
);
}
Map
<
String
,
String
>
payMap
=
new
TreeMap
<
String
,
String
>();
payMap
.
put
(
"appId"
,
appid
);
payMap
.
put
(
"timeStamp"
,
new
Timestamp
(
System
.
currentTimeMillis
())
+
""
);
payMap
.
put
(
"nonceStr"
,
WXPayUtil
.
generateNonceStr
());
payMap
.
put
(
"signType"
,
"MD5"
);
payMap
.
put
(
"package"
,
"prepay_id="
+
prepay_id
);
LOGGER
.
info
(
"=======prepay_id:"
+
prepay_id
);
String
paySign
=
PayUtil
.
createSign
(
"UTF-8"
,
payMap
,
mchkey
);
payMap
.
put
(
"prepay_id"
,
prepay_id
);
payMap
.
put
(
"paySign"
,
paySign
);
//将这个6个参数传给前端
resMap
.
put
(
"code"
,
1
);
resMap
.
put
(
"payMap"
,
payMap
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
resMap
.
put
(
"code"
,
0
);
resMap
.
put
(
"msg"
,
"调用统一订单接口错误"
);
}
return
resMap
;
}
/**
* @Title: callback
* @Description: 支付完成的回调函数
* @param:
* @return:
*/
@RequestMapping
(
value
=
"/nyx/wx/pay/notify"
,
method
=
RequestMethod
.
POST
)
public
String
callback
(
HttpServletRequest
request
,
HttpServletResponse
response
)
{
System
.
out
.
println
(
"微信支付成功,微信发送的callback信息,请注意修改订单信息"
);
InputStream
is
=
null
;
try
{
is
=
request
.
getInputStream
();
// 获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
String
xml
=
InputStream2String
(
is
);
Map
<
String
,
String
>
notifyMap
=
WXPayUtil
.
xmlToMap
(
xml
);
// 将微信发的xml转map
System
.
out
.
println
(
"微信返回给回调函数的信息为:"
+
xml
);
if
(
notifyMap
.
get
(
"return_code"
).
equals
(
"SUCCESS"
)){
if
(
notifyMap
.
get
(
"result_code"
).
equals
(
"SUCCESS"
)){
String
ordersSn
=
notifyMap
.
get
(
"out_trade_no"
);
// 商户订单号
String
amountpaid
=
notifyMap
.
get
(
"total_fee"
);
// 实际支付的订单金额:单位 分
BigDecimal
amountPay
=
(
new
BigDecimal
(
amountpaid
).
divide
(
new
BigDecimal
(
"100"
))).
setScale
(
2
);
// 将分转换成元-实际支付金额:元
/*
* 以下是自己的业务处理------仅做参考 更新order对应字段/已支付金额/状态码
*/
System
.
out
.
println
(
"===notify===回调方法已经被调!!!"
);
}
}
System
.
out
.
println
(
"<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>"
);
// 告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
response
.
getWriter
().
write
(
"<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>"
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(
is
!=
null
)
{
try
{
is
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
return
null
;
}
public
static
String
InputStream2String
(
InputStream
is
)
throws
IOException
{
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
byte
[]
buffer
=
new
byte
[
1024
];
int
len
=
-
1
;
while
((
len
=
is
.
read
(
buffer
))
!=
-
1
)
{
baos
.
write
(
buffer
,
0
,
len
);
}
baos
.
close
();
is
.
close
();
byte
[]
lens
=
baos
.
toByteArray
();
String
result
=
new
String
(
lens
,
"UTF-8"
);
//内容乱码处理
return
result
;
}
}
app/nyx_app_key/api/src/main/resources/config/application-dev.yml
查看文件 @
10c6f395
...
...
@@ -76,3 +76,6 @@ aliyun:
dir
:
user-dir/
dirQrcode
:
qrcode-dir/
dirLogo
:
logo-dir/
weixin
:
notifyUrl
:
https://wx.hisuhong.com/api/nyx/wx/pay/notify
\ No newline at end of file
app/nyx_app_key/api/src/main/resources/config/application-production.yml
查看文件 @
10c6f395
...
...
@@ -60,3 +60,6 @@ aliyun:
dir
:
user-dir/
dirQrcode
:
qrcode-dir/
dirLogo
:
logo-dir/
weixin
:
notifyUrl
:
https://fun.hisuhong.com/api/nyx/wx/pay/notify
\ No newline at end of file
app/nyx_app_key/api/src/main/resources/config/application.yml
查看文件 @
10c6f395
...
...
@@ -67,9 +67,16 @@ app:
cron
:
genT_match_rank
:
0 0/20 * * * ?
#mchkey: 在API调用时用来按照指定规则对你的请求参数进行签名,服务器收到你的请求时会进行签名验证
#keyPath: 在调用微信支付安全级别较高的接口(如:退款、企业红包、企业付款)时,会使用到API证书
weixin
:
appid
:
'
wx72555e77d9e5cee2'
secret
:
'
072986d584176aa5aa9b1531841779f2'
appid
:
wx72555e77d9e5cee2
secret
:
072986d584176aa5aa9b1531841779f2
mpAppId
:
mchid
:
1604143639
mchkey
:
6D5129322127E2D33DEE90F4E2EA97A5
keyPath
:
appAppId
:
aliyun
:
oss
:
...
...
app/nyx_app_key/pom.xml
查看文件 @
10c6f395
...
...
@@ -138,6 +138,12 @@
<version>
2.9.2
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-configuration-processor
</artifactId>
<optional>
true
</optional>
</dependency>
</dependencies>
</dependencyManagement>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论