互动
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

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
}