feat: 微信支付错误提示,跳转return
This commit is contained in:
parent
cacfbccbcf
commit
964a0808b9
|
@ -77,6 +77,7 @@ const (
|
|||
OrderNotSupportRefundPart = 1413
|
||||
OrderRefundAmountError = 1414
|
||||
OrderPayChannelChange = 1415
|
||||
OrderPayRequestLogNotExist = 1416
|
||||
// 关闭订单
|
||||
CloseOrderPayed = 1420
|
||||
|
||||
|
@ -159,15 +160,16 @@ var MsgZH = map[int]string{
|
|||
RequestLogNotFound: "未找到日志信息",
|
||||
RequestResponseValid: "上游返回格式无效",
|
||||
|
||||
OrdersNotFound: "未找到订单",
|
||||
OrdersExist: "订单已存在",
|
||||
OrderTypeNotFount: "未知的支付方式",
|
||||
OrderIsDelete: "订单已删除",
|
||||
OrderStatusErr: "订单状态错误",
|
||||
OrderClosed: "订单已关闭,无法继续支付",
|
||||
OrderFailed: "订单支付失败,请重新发起",
|
||||
OrderPayed: "订单已支付成功,请勿重复支付",
|
||||
OrderPayChannelChange: "支付方式不一致,切换支付方式请关闭原订单生成新订单",
|
||||
OrdersNotFound: "未找到订单",
|
||||
OrdersExist: "订单已存在",
|
||||
OrderTypeNotFount: "未知的支付方式",
|
||||
OrderIsDelete: "订单已删除",
|
||||
OrderStatusErr: "订单状态错误",
|
||||
OrderClosed: "订单已关闭,无法继续支付",
|
||||
OrderFailed: "订单支付失败,请重新发起",
|
||||
OrderPayed: "订单已支付成功,请勿重复支付",
|
||||
OrderPayChannelChange: "支付方式不一致,切换支付方式请关闭原订单生成新订单",
|
||||
OrderPayRequestLogNotExist: "订单下单数据不存在",
|
||||
|
||||
NotifySendFail: "回调发送失败",
|
||||
RefundOrderNotFound: "退款订单未找到",
|
||||
|
|
|
@ -49,3 +49,8 @@ func (m *OrderRequestLogRepo) OrderRequestLogBackendList(conn builder.Cond, page
|
|||
repo.Join("left", "orders", "orders.app_id = order_request_log.app_id and orders.out_trade_no = order_request_log.out_trade_no")
|
||||
return repo.Desc("order_request_log.create_time").FindAndCount(orderLogList)
|
||||
}
|
||||
|
||||
// 查询订单日志
|
||||
func (m *OrderRequestLogRepo) OrderRequestLogGet(orderLog *orderrequestlogmodel.OrderRequestLog, conn builder.Cond) (bool, error) {
|
||||
return m.repo.Where(conn).Get(orderLog)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"PaymentCenter/app/services"
|
||||
"PaymentCenter/app/services/thirdpay"
|
||||
"PaymentCenter/app/third/paymentService"
|
||||
"PaymentCenter/app/utils"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -193,11 +194,6 @@ func BrokerWechatUrl(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
// 首页
|
||||
func Index(c *gin.Context) {
|
||||
c.HTML(200, "index.html", gin.H{})
|
||||
}
|
||||
|
||||
// 拼接微信授权链接
|
||||
func GetWxAuthUrl(c *gin.Context) {
|
||||
req, _ := controllers.GetRequest(c).(*front.GetWxAuthUrlRequest)
|
||||
|
@ -222,10 +218,12 @@ func GetWxCode(c *gin.Context) {
|
|||
|
||||
// 微信JSAPI 支付接口
|
||||
/*
|
||||
预支付接口实现如下功能:
|
||||
1.订单请求参数
|
||||
2.订单信息存数据
|
||||
3.返回用户授权地址
|
||||
4.用户授权后获取code
|
||||
wxjsapi接口实现如下功能:
|
||||
4.用户授权后获取code,statu传的是订单号
|
||||
5.通过code获取openid
|
||||
6.通过openid请求微信下单,返回支付参数
|
||||
7.支付参数聚合,签名,返回支付参数给前端
|
||||
|
@ -236,7 +234,7 @@ func WxJsApiPay(c *gin.Context) {
|
|||
|
||||
rsp, code := thirdpay.WxJsApiPay(*req)
|
||||
if code == errorcode.Success {
|
||||
c.HTML(http.StatusOK, "index.html", gin.H{
|
||||
c.HTML(http.StatusOK, "success.html", gin.H{
|
||||
"appId": rsp.AppId,
|
||||
"timeStamp": rsp.TimeStamp,
|
||||
"nonceStr": rsp.NonceStr,
|
||||
|
@ -245,6 +243,19 @@ func WxJsApiPay(c *gin.Context) {
|
|||
"paySign": rsp.PaySign,
|
||||
})
|
||||
} else {
|
||||
controllers.ApiRes(c, rsp, code, rsp.ThirdMsg)
|
||||
utils.Log(c, "", "WxJsApiPay,支付失败code=", code, "msg=", rsp.ThirdMsg)
|
||||
errmsg := rsp.ThirdMsg
|
||||
data := make(map[string]interface{})
|
||||
_ = json.Unmarshal([]byte(rsp.ThirdMsg), &data)
|
||||
if message, ok := data["message"]; ok {
|
||||
errmsg = message.(string)
|
||||
}
|
||||
if errmsg == "" {
|
||||
errmsg = errorcode.GetMsg(code, "")
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "fail.html", gin.H{
|
||||
"errmsg": errmsg,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,12 +71,12 @@ func RegisterRoute(router *gin.Engine) {
|
|||
router.LoadHTMLGlob("./front/templates/*")
|
||||
wx := v1.Group("/wx", middlewares.ValidateRequest())
|
||||
{
|
||||
wx.GET("/index", front.Index) // 获取页面
|
||||
wx.POST("/getWxAuthUrl", front.GetWxAuthUrl) // 获取授权codeUrl
|
||||
wx.GET("/getWxAuth", front.GetWxAuth) // 获取openId
|
||||
wx.GET("/getCode", front.GetWxCode) // 接收微信code
|
||||
}
|
||||
|
||||
// 微信jsapi支付链接
|
||||
router.GET(common.WXCodeRedirectAddress, middlewares.ValidateRequest(), front.WxJsApiPay)
|
||||
|
||||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
|
|
|
@ -149,3 +149,17 @@ func PayOrderCheckRepeat(order *ordersmodel.Orders, conn builder.Cond) (exist bo
|
|||
}
|
||||
return true, code
|
||||
}
|
||||
|
||||
// 商户请求日志
|
||||
func OrderRequestLogs(req *orderrequestlogmodel.OrderRequestLog) (bool, error) {
|
||||
requestRepo := data.NewOrderRequestLogRepo(paychannelmodel.GetInstance().GetDb())
|
||||
conn := builder.NewCond()
|
||||
if req.OutTradeNo != "" {
|
||||
conn = conn.And(builder.Eq{"out_trade_no": req.OutTradeNo})
|
||||
}
|
||||
if req.AppId > 0 {
|
||||
conn = conn.And(builder.Eq{"app_id": req.AppId})
|
||||
}
|
||||
|
||||
return requestRepo.OrderRequestLogGet(req, conn)
|
||||
}
|
||||
|
|
|
@ -129,9 +129,15 @@ func (w *Pay) PayUrl() (url string) {
|
|||
case common.PAY_CHANNEL_WECHAT_JSAPI:
|
||||
// 获取授权链接
|
||||
res.Result, res.Code = w.GetWxAuthUrl(w.PayParam.Channel.AppId, w.Order.Id)
|
||||
case common.PAY_CHANNEL_ALIPAY_WEB | common.PAY_CHANNEL_WECHAT_H5:
|
||||
case common.PAY_CHANNEL_ALIPAY_WEB:
|
||||
// 支付宝h5
|
||||
res = paymentService.PaymentService(*w.ctx, *thirdPay)
|
||||
|
||||
case common.PAY_CHANNEL_WECHAT_H5:
|
||||
// 微信h5支付
|
||||
res = paymentService.PaymentService(*w.ctx, *thirdPay)
|
||||
if res.Result != "" {
|
||||
res.Result = config.GetConf().PayService.Host + "/pay/front/api/v1/brokerWechatUrl" + "?url=" + res.Result
|
||||
}
|
||||
default:
|
||||
w.PayCode = errorcode.PayChannelNotBuild
|
||||
return
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"PaymentCenter/app/constants/common"
|
||||
"PaymentCenter/app/constants/errorcode"
|
||||
"PaymentCenter/app/http/entities/front"
|
||||
"PaymentCenter/app/models/orderrequestlogmodel"
|
||||
"PaymentCenter/app/models/ordersmodel"
|
||||
"PaymentCenter/app/models/paychannelmodel"
|
||||
"PaymentCenter/app/services"
|
||||
|
@ -127,12 +128,13 @@ func GetWxAuth(param front.GetWxAuthRequest) (rsp front.GetWxAuthResponse, code
|
|||
7.支付参数聚合,签名,返回支付参数给前端
|
||||
*/
|
||||
type wxJsapiPay struct {
|
||||
code int
|
||||
msg string
|
||||
param front.WxJsApiPayRequest
|
||||
order *ordersmodel.Orders
|
||||
payChannel paychannelmodel.PayChannel
|
||||
wxConfig paymentService.WxPay
|
||||
code int
|
||||
msg string
|
||||
param front.WxJsApiPayRequest
|
||||
order *ordersmodel.Orders
|
||||
payChannel paychannelmodel.PayChannel
|
||||
wxConfig paymentService.WxPay
|
||||
orderPayRequest front.PayReqs
|
||||
|
||||
openId string // 用户openid
|
||||
}
|
||||
|
@ -144,6 +146,15 @@ func newWxJsapiPay(param front.WxJsApiPayRequest) *wxJsapiPay {
|
|||
func (this *wxJsapiPay) getOrder() {
|
||||
order := new(ordersmodel.Orders)
|
||||
this.order, this.code = services.OrderFindOne(order, builder.Eq{"id": this.param.State})
|
||||
if this.code != errorcode.Success {
|
||||
return
|
||||
}
|
||||
switch this.order.Status {
|
||||
case common.ORDER_STATUS_PAYED:
|
||||
this.code = errorcode.OrderPayed
|
||||
case common.ORDER_STATUS_CLOSE:
|
||||
this.code = errorcode.OrderClosed
|
||||
}
|
||||
}
|
||||
func (this *wxJsapiPay) getPayChannel() {
|
||||
payChannel := paychannelmodel.PayChannel{Id: this.order.PayChannelId}
|
||||
|
@ -151,6 +162,29 @@ func (this *wxJsapiPay) getPayChannel() {
|
|||
this.payChannel = payChannel
|
||||
}
|
||||
|
||||
// 获取下单的请求参数
|
||||
func (this *wxJsapiPay) getOrderRequestLogs() {
|
||||
orderRequestLog := orderrequestlogmodel.OrderRequestLog{
|
||||
OutTradeNo: this.order.OutTradeNo,
|
||||
AppId: this.order.AppId,
|
||||
}
|
||||
has, err := services.OrderRequestLogs(&orderRequestLog)
|
||||
if err != nil {
|
||||
this.code = handErr(err)
|
||||
return
|
||||
}
|
||||
if !has {
|
||||
this.code = errorcode.OrderPayRequestLogNotExist
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(orderRequestLog.MerchantRequest), &this.orderPayRequest)
|
||||
if err != nil {
|
||||
this.code = handErr(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (this *wxJsapiPay) getOpenId() {
|
||||
var err error
|
||||
//// 配置支付的解析
|
||||
|
@ -251,7 +285,11 @@ func WxJsApiPay(param front.WxJsApiPayRequest) (response front.WxJsApiPayRespons
|
|||
if task.code != errorcode.Success {
|
||||
return response, task.code
|
||||
}
|
||||
|
||||
// 获取下单的请求参数
|
||||
task.getOrderRequestLogs()
|
||||
if task.code != errorcode.Success {
|
||||
return response, task.code
|
||||
}
|
||||
// 2 通过code获取openid
|
||||
task.getOpenId()
|
||||
if task.code != errorcode.Success {
|
||||
|
@ -269,7 +307,7 @@ func WxJsApiPay(param front.WxJsApiPayRequest) (response front.WxJsApiPayRespons
|
|||
Description: order.Desc,
|
||||
Amount: order.Amount,
|
||||
PayerClientIp: param.ClientIp,
|
||||
ReturnUrl: "",
|
||||
ReturnUrl: task.orderPayRequest.ReturnUrl,
|
||||
Wx: task.wxConfig,
|
||||
Ali: paymentService.AliPay{},
|
||||
OpenId: task.openId,
|
||||
|
|
|
@ -129,8 +129,8 @@ func WxJsApiPayInfo(c context.Context, payOrderRequest PayOrderRequest) (string,
|
|||
return "", err
|
||||
}
|
||||
if wxRsp.Code != wechat.Success || wxRsp.Response.PrepayId == "" {
|
||||
//logger.Error(c, "WxJsApiPayInfo 发生错误", fmt.Sprintf("错误状态码:%d, 错误信息:%s", wxRsp.Code, wxRsp.Error))
|
||||
return "", errors.New(fmt.Sprintf("发起支付失败,失败状态码:%d, 失败原因:%s", wxRsp.Code, wxRsp.Error))
|
||||
logger.Error(c, "WxJsApiPayInfo 发生错误", fmt.Sprintf("错误状态码:%d, 错误信息:%s", wxRsp.Code, wxRsp.Error))
|
||||
return "", errors.New(wxRsp.Error)
|
||||
}
|
||||
//if payOrderRequest.ReturnUrl != "" {
|
||||
// values := url.Values{}
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<title>微信支付</title>
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.success,
|
||||
.error {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#right {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 100px auto 20px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid rgb(104, 225, 52);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#right::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 88px;
|
||||
height: 50px;
|
||||
border: 5px solid rgb(104, 225, 52);
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
transform: rotate(-45deg) translate(7px, -10px);
|
||||
}
|
||||
|
||||
.success-txt {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
color: rgb(104, 225, 52);
|
||||
}
|
||||
|
||||
#error {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 100px auto 20px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid rgb(244, 57, 52);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#error::before {
|
||||
content: "\2715";
|
||||
display: block;
|
||||
color: rgb(244, 57, 52);
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.error-txt {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
color: rgb(244, 57, 52);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="success">
|
||||
<span id="right"></span>
|
||||
<span class="success-txt">支付成功</span>
|
||||
</div>
|
||||
<div class="error">
|
||||
<span id="error"></span>
|
||||
<span class="error-txt">支付失败 {{.errmsg}}</span>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementsByClassName('error')[0].style.display = 'block';
|
||||
document.getElementsByClassName('success')[0].style.display = 'none';
|
||||
document.getElementsByClassName('error')[0].innerHTML = res.err_msg || '支付失败';
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,44 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>微信支付</title>
|
||||
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function onBridgeReady() {
|
||||
WeixinJSBridge.invoke(
|
||||
'getBrandWCPayRequest', {
|
||||
"appId": "{{.appId}}", //公众号ID,由商户传入
|
||||
"timeStamp": "{{.timeStamp}}", //时间戳,自1970年以来的秒数
|
||||
"nonceStr": "{{.nonceStr}}", //随机串
|
||||
"package": "{{.package}}",
|
||||
"signType": "{{.signType}}", //微信签名方式:
|
||||
"paySign": "{{.paySign}}" //微信签名
|
||||
},
|
||||
function (res) {
|
||||
if (res.err_msg == "get_brand_wcpay_request:ok") {
|
||||
// 使用以上方式判断前端返回,微信团队郑重提示:
|
||||
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
|
||||
alert('支付成功');
|
||||
} else {
|
||||
alert('支付失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof WeixinJSBridge == "undefined") {
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
|
||||
} else if (document.attachEvent) {
|
||||
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
|
||||
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
|
||||
}
|
||||
} else {
|
||||
onBridgeReady();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<title>微信支付</title>
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.success,
|
||||
.error {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#right {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 100px auto 20px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid rgb(104, 225, 52);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#right::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 88px;
|
||||
height: 50px;
|
||||
border: 5px solid rgb(104, 225, 52);
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
transform: rotate(-45deg) translate(7px, -10px);
|
||||
}
|
||||
|
||||
.success-txt {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
color: rgb(104, 225, 52);
|
||||
}
|
||||
|
||||
#error {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
margin: 100px auto 20px;
|
||||
border-radius: 50%;
|
||||
border: 5px solid rgb(244, 57, 52);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#error::before {
|
||||
content: "\2715";
|
||||
display: block;
|
||||
color: rgb(244, 57, 52);
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.error-txt {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
color: rgb(244, 57, 52);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="success">
|
||||
<span id="right"></span>
|
||||
<span class="success-txt">支付成功</span>
|
||||
</div>
|
||||
<div class="error">
|
||||
<span id="error"></span>
|
||||
<span class="error-txt">支付失败</span>
|
||||
</div>
|
||||
<script>
|
||||
function onBridgeReady() {
|
||||
WeixinJSBridge.invoke(
|
||||
'getBrandWCPayRequest', {
|
||||
"appId": "{{.appId}}",
|
||||
"timeStamp": "{{.timeStamp}}",
|
||||
"nonceStr": "{{.nonceStr}}",
|
||||
"package": "{{.package}}",
|
||||
"signType": "{{.signType}}",
|
||||
"paySign": "{{.paySign}}"
|
||||
},
|
||||
function (res) {
|
||||
if (res.err_msg == "get_brand_wcpay_request:ok") {
|
||||
// 使用以上方式判断前端返回,微信团队郑重提示:
|
||||
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
|
||||
document.getElementsByClassName('success')[0].style.display = 'block';
|
||||
document.getElementsByClassName('error')[0].style.display = 'none';
|
||||
} else {
|
||||
document.getElementsByClassName('error')[0].style.display = 'block';
|
||||
document.getElementsByClassName('success')[0].style.display = 'none';
|
||||
document.getElementsByClassName('error')[0].innerHTML = res.err_msg || '支付失败';
|
||||
}
|
||||
});
|
||||
}
|
||||
if (typeof WeixinJSBridge == "undefined") {
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
|
||||
} else if (document.attachEvent) {
|
||||
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
|
||||
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
|
||||
}
|
||||
} else {
|
||||
onBridgeReady();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue