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.

117 lines
2.9 KiB

package wxpay
import (
"encoding/base64"
"encoding/xml"
"github.com/gin-gonic/gin"
"github.com/nanjishidu/gomini/gocrypto"
"io/ioutil"
"log"
"net/http"
"recook/internal/v2/logic/pay"
"recook/tools"
"strings"
)
/*
<xml>
<return_code>SUCCESS</return_code>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[TeqClE3i0mvn3DrK]]></nonce_str>
<req_info><![CDATA[T87GAHG17TGAHG1TGHAHAHA1Y1CIOA9UGJH1GAHV871HAGAGQYQQPOOJMXNBCXBVNMNMAJAA]]></req_info>
</xml>
*/
/*
<root>
<out_refund_no><![CDATA[131811191610442717309]]></out_refund_no>
<out_trade_no><![CDATA[71106718111915575302817]]></out_trade_no>
<refund_account><![CDATA[REFUND_SOURCE_RECHARGE_FUNDS]]></refund_account>
<refund_fee><![CDATA[3960]]></refund_fee>
<refund_id><![CDATA[50000408942018111907145868882]]></refund_id>
<refund_recv_accout><![CDATA[支付用户零钱]]></refund_recv_accout>
<refund_request_source><![CDATA[API]]></refund_request_source>
<refund_status><![CDATA[SUCCESS]]></refund_status>
<settlement_refund_fee><![CDATA[3960]]></settlement_refund_fee>
<settlement_total_fee><![CDATA[3960]]></settlement_total_fee>
<success_time><![CDATA[2018-11-19 16:24:13]]></success_time>
<total_fee><![CDATA[3960]]></total_fee>
<transaction_id><![CDATA[4200000215201811190261405420]]></transaction_id>
</root>
*/
type RefundCallbackNotification struct {
XMLName xml.Name `xml:"xml"`
AppID string `xml:"appid"`
MchId string `xml:"mch_id"` // 商户号
NonceStr string `xml:"nonce_str"` // 随机字符串
ReqInfo string `xml:"req_info"`
}
type RefundReqInfo struct {
XMLName xml.Name `xml:"root"`
OutRefundNo string `xml:"out_refund_no"`
RefundFee uint `xml:"refund_fee"`
RefundStatus string `xml:"refund_status"`
SuccessTime string `xml:"success_time"`
}
func (r *RefundReqInfo) IsOk() bool {
return r.RefundStatus == "SUCCESS"
}
func RefundCallback(c *gin.Context) {
FAIL := gin.H{
"return_code": "FAIL",
"return_msg": "OK",
}
SUCCESS := gin.H{
"return_code": "SUCCESS",
"return_msg": "OK",
}
body, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
panic(err)
}
var notification RefundCallbackNotification
err = xml.Unmarshal(body, &notification)
if err != nil {
log.Println(err)
c.XML(http.StatusOK, FAIL)
return
}
_ = gocrypto.SetAesKey(strings.ToLower(tools.MD5(APIKey)))
str, _ := base64.StdEncoding.DecodeString(notification.ReqInfo)
deBody, err := gocrypto.AesECBDecrypt(str)
if err != nil {
log.Println(err)
c.XML(http.StatusOK, FAIL)
return
}
var info RefundReqInfo
err = xml.Unmarshal(deBody, &info)
if err != nil {
log.Println(err)
c.XML(http.StatusOK, FAIL)
return
}
if info.IsOk() == false {
log.Println(info)
c.XML(http.StatusOK, FAIL)
return
}
if err = pay.AsyncRefundSuccessCallback(info.OutRefundNo); err != nil {
log.Println(err)
c.XML(http.StatusOK, FAIL)
return
}
c.XML(http.StatusOK, SUCCESS)
}