You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.0 KiB
217 lines
6.0 KiB
package pay_service
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/iGoogle-ink/gopay/v2"
|
|
"github.com/iGoogle-ink/gopay/v2/wechat"
|
|
"github.com/ouxuanserver/osmanthuswine/src/core"
|
|
"hudongzhuanjia/libs/wx"
|
|
"hudongzhuanjia/models"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
const CALLBACK_REFUND_URL = "https://api.ouxuanhudong.com/PcClient/common/WeChatOauthCtl/callbackRefund"
|
|
|
|
func RefundExtend(bm gopay.BodyMap) (*wechat.RefundResponse, error) {
|
|
|
|
err := bm.CheckEmptyError("nonce_str", "out_refund_no", "total_fee", "refund_fee")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if bm.Get("out_trade_no") == gopay.NULL && bm.Get("transaction_id") == gopay.NULL {
|
|
return nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
|
|
}
|
|
|
|
bs, err := ClientExtend(bm, wx.RefundURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
wxRsp := new(wechat.RefundResponse)
|
|
if err = xml.Unmarshal(bs, wxRsp); err != nil {
|
|
return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err)
|
|
}
|
|
return wxRsp, nil
|
|
}
|
|
|
|
func Refund(reason, outTradeNo, openId string, goodType, totalFee, refundFee int, userId, activityId int64) (*wechat.RefundResponse, error) {
|
|
//client := wechat.NewClient(wx.Appid, wx.Mchid, wx.ApiKey, true)
|
|
|
|
outRefundNo := gopay.GetRandomString(64)
|
|
// 初始化参数结构体
|
|
body := make(gopay.BodyMap)
|
|
body.Set("out_trade_no", outTradeNo)
|
|
body.Set("nonce_str", gopay.GetRandomString(32))
|
|
body.Set("sign_type", wechat.SignType_MD5)
|
|
body.Set("out_refund_no", outRefundNo)
|
|
body.Set("total_fee", totalFee)
|
|
body.Set("refund_fee", refundFee)
|
|
body.Set("notify_url", CALLBACK_REFUND_URL)
|
|
body.Set("refund_desc", reason)
|
|
body.Set("refund_fee_type", "CNY")
|
|
body.Set("appid", wx.Appid)
|
|
body.Set("mch_id", wx.Mchid)
|
|
|
|
res, err := RefundExtend(body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
//ok, err := wechat.VerifySign(wx.ApiKey, wechat.SignType_MD5, res)
|
|
//if err != nil {
|
|
// return nil, err
|
|
//}
|
|
//
|
|
//if !ok {
|
|
// return nil, errors.New("签名验证失败")
|
|
//}
|
|
|
|
if res.ReturnCode != wx.CODE_SUCCESS {
|
|
return nil, fmt.Errorf("network error, retrun_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
|
|
}
|
|
|
|
if res.ResultCode != wx.CODE_SUCCESS {
|
|
return nil, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
|
|
}
|
|
|
|
refund := new(models.UserRefund)
|
|
refund.OutTradeNo = outTradeNo
|
|
refund.Status = 0
|
|
refund.TotalFee = totalFee
|
|
refund.GoodType = goodType
|
|
refund.RefundDesc = reason
|
|
refund.FeeType = "CNY"
|
|
refund.OpenId = openId
|
|
refund.UserId = userId
|
|
refund.ActivityId = activityId
|
|
refund.IsDelete = false
|
|
refund.CreatedAt = time.Now()
|
|
refund.UpdatedAt = time.Now()
|
|
if _, err := core.GetXormAuto().InsertOne(refund); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return res, err
|
|
}
|
|
|
|
func CallbackRefund(req *http.Request) error {
|
|
res, err := wechat.ParseRefundNotifyResult(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
//ok, err := wechat.VerifySign(wx.ApiKey, wechat.SignType_MD5, res)
|
|
//if err != nil {
|
|
// return err
|
|
//}
|
|
//if !ok {
|
|
// return errors.New("sign verify failed")
|
|
//}
|
|
if res.ReturnCode != wx.CODE_SUCCESS {
|
|
return fmt.Errorf("network error, retrun_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
|
|
}
|
|
|
|
info, err := wechat.DecryptRefundNotifyReqInfo(res.ReqInfo, wx.ApiKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
userRefund := new(models.UserRefund)
|
|
exist, err := userRefund.GetByOutRefundNo(info.OutRefundNo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exist {
|
|
return errors.New("user refund not exist")
|
|
}
|
|
|
|
userRefund.Status = 1
|
|
userRefund.RefundStatus = info.RefundStatus
|
|
userRefund.TransactionId = info.TransactionId
|
|
userRefund.OutTradeNo = info.OutTradeNo
|
|
userRefund.RefundRecvAccount = info.RefundRecvAccout
|
|
userRefund.RefundAccount = info.RefundAccount
|
|
userRefund.SuccessTime = info.SuccessTime
|
|
if _, err := core.GetXormAuto().Id(userRefund.Id).Update(userRefund); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func QueryRefund(outTradeNo string) (*wechat.QueryRefundResponse, error) {
|
|
client := wechat.NewClient(wx.Appid, wx.Mchid, wx.ApiKey, true)
|
|
|
|
// 初始化参数结构体
|
|
body := make(gopay.BodyMap)
|
|
body.Set("out_trade_no", outTradeNo)
|
|
body.Set("nonce_str", gopay.GetRandomString(32))
|
|
body.Set("sign_type", wechat.SignType_MD5)
|
|
|
|
//请求申请退款
|
|
res, err := client.QueryRefund(body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ok, err := wechat.VerifySign(wx.ApiKey, wechat.SignType_MD5, res)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !ok {
|
|
return nil, errors.New("签名验证失败")
|
|
}
|
|
|
|
if res.ReturnCode != wx.CODE_SUCCESS {
|
|
return nil, fmt.Errorf("network error, retrun_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
|
|
}
|
|
|
|
if res.ResultCode != wx.CODE_SUCCESS {
|
|
return nil, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
|
|
}
|
|
|
|
fmt.Println("wxRsp:", *res)
|
|
return res, nil
|
|
}
|
|
|
|
func BatchQueryRefundByUserId(userId int64) error {
|
|
refunds := make([]*models.UserRefund, 0)
|
|
if err := core.GetXormAuto().Where("status = 0 and user_id=?", userId).Find(&refunds); err != nil {
|
|
return err
|
|
}
|
|
if err := batchQueryRefund(refunds); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
func BatchQueryRefundByActivityId(activityId int64) error {
|
|
refunds := make([]*models.UserRefund, 0)
|
|
if err := core.GetXormAuto().Where("status = 0 and user_id=?", activityId).Find(&refunds); err != nil {
|
|
return err
|
|
}
|
|
if err := batchQueryRefund(refunds); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func batchQueryRefund(refunds []*models.UserRefund) error {
|
|
for _, refund := range refunds {
|
|
res, err := QueryRefund(refund.OutTradeNo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
refund.RefundAccount = res.RefundAccount0
|
|
refund.RefundRecvAccount = res.RefundRecvAccout0
|
|
refund.RefundStatus = res.RefundStatus0
|
|
refund.Status = 1
|
|
refund.SuccessTime = res.RefundSuccessTime0
|
|
refund.WxRefundId = res.RefundId0
|
|
refund.TransactionId = res.TransactionId
|
|
if _, err = core.GetXormAuto().Id(refund.Id).Cols("refund_account, refund_recv_account, " +
|
|
"status, refund_status, success_time, wx_refund_id, transaction_id").Update(refund); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|