|
|
package pay_service
import ( "encoding/xml" "fmt" pay_core "github.com/chanxuehong/wechat/mch/core" "github.com/chanxuehong/wechat/mch/pay" "hudongzhuanjia/logger" "hudongzhuanjia/models" "hudongzhuanjia/utils" "hudongzhuanjia/utils/define" "strconv" "time" )
const CallbackOrderUrl = "https://api.ouxuanhudong.com/PcClient/common/WeChatOauthCtl/callbackOrder"
func UnifiedOrder(content, openId string, fee, goodType, userId, activityId, expireAt int64) (map[string]interface{}, error) { client, err := Client() if err != nil { return nil, err }
outTradeNo := utils.RandomStr(32) nonceStr := utils.RandomStr(32) body := make(map[string]string, 0) body["body"] = content body["out_trade_no"] = outTradeNo body["total_fee"] = fmt.Sprint(fee) body["notify_url"] = CallbackOrderUrl body["trade_type"] = "JSAPI" body["nonce_str"] = nonceStr body["sign_type"] = pay_core.SignType_MD5 body["openid"] = openId //body["time_expire"] = pay_core.FormatTime(time.Unix(expireAt, 0))
resp, err := pay.UnifiedOrder(client, body) if err != nil { return nil, err }
// 记录这次订单
userOrder := new(models.UserOrder) userOrder.Body = content userOrder.UserId = userId userOrder.ActivityId = activityId userOrder.FeeType = "CNY" userOrder.GoodType = goodType userOrder.OpenId = openId userOrder.OutTradeNo = outTradeNo userOrder.ExpireAt = expireAt userOrder.TotalFee = fee userOrder.TradeType = "JSAPI" userOrder.PrepayId = resp["prepay_id"] userOrder.Status = 0 if _, err = models.Add(userOrder); err != nil { return nil, err }
//获取H5支付需要的paySign
timestamp := strconv.FormatInt(time.Now().Unix(), 10) pac := "prepay_id=" + resp["prepay_id"] paySign := pay_core.JsapiSign(client.AppId(), timestamp, nonceStr, pac, pay_core.SignType_MD5, define.ApiKey)
//go PutOrderDelayQueue(userOrder)
return map[string]interface{}{ "appid": client.AppId(), "timestamp": timestamp, "nonce_str": nonceStr, "package": pac, "sign_type": pay_core.SignType_MD5, "pay_sign": paySign, "out_trade_no": outTradeNo, "user_order_id": userOrder.Id, }, nil }
func ReOrder(outTradeNo string) (map[string]interface{}, error) { userOrder := new(models.UserOrder) exist, err := userOrder.GetByOutTradeNo(outTradeNo) if err != nil { return nil, err } if !exist { return nil, fmt.Errorf("订单不存在") }
timestamp := strconv.FormatInt(time.Now().Unix(), 10) nonceStr := utils.RandomStr(32) //获取H5支付需要的paySign
pac := "prepay_id=" + userOrder.PrepayId paySign := pay_core.JsapiSign(define.AppId, timestamp, nonceStr, pac, pay_core.SignType_MD5, define.ApiKey) //go PutOrderDelayQueue(userOrder)
return map[string]interface{}{ "appid": define.AppId, "timestamp": timestamp, "nonce_str": nonceStr, "package": pac, "sign_type": pay_core.SignType_MD5, "pay_sign": paySign, "out_trade_no": outTradeNo, "user_order_id": userOrder.Id, }, nil
}
// Notify
type NotifyOrderParam struct { XMLName struct{} `xml:"xml" json:"-"`
ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"` ReturnMsg string `xml:"return_msg,omitempty" json:"return_msg,omitempty"` ResultCode string `xml:"result_code,omitempty" json:"result_code,omitempty"` ErrCode string `xml:"err_code,omitempty" json:"err_code,omitempty"` ErrCodeDes string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"` Appid string `xml:"appid,omitempty" json:"appid,omitempty"` MchId string `xml:"mch_id,omitempty" json:"mch_id,omitempty"` DeviceInfo string `xml:"device_info,omitempty" json:"device_info,omitempty"` NonceStr string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"` Sign string `xml:"sign,omitempty" json:"sign,omitempty"` SignType string `xml:"sign_type,omitempty" json:"sign_type,omitempty"` Openid string `xml:"openid,omitempty" json:"openid,omitempty"` IsSubscribe string `xml:"is_subscribe,omitempty" json:"is_subscribe,omitempty"` TradeType string `xml:"trade_type,omitempty" json:"trade_type,omitempty"` BankType string `xml:"bank_type,omitempty" json:"bank_type,omitempty"` TotalFee int `xml:"total_fee,omitempty" json:"total_fee,omitempty"` SettlementTotalFee int `xml:"settlement_total_fee,omitempty" json:"settlement_total_fee,omitempty"` FeeType string `xml:"fee_type,omitempty" json:"fee_type,omitempty"` CashFee int `xml:"cash_fee,omitempty" json:"cash_fee,omitempty"` CashFeeType string `xml:"cash_fee_type,omitempty" json:"cash_fee_type,omitempty"` TransactionId string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"` OutTradeNo string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"` TimeEnd string `xml:"time_end,omitempty" json:"time_end,omitempty"` }
func NotifyOrder(body string) (*models.UserOrder, error) { res := NotifyOrderParam{} err := xml.Unmarshal([]byte(body), &res) if err != nil { err = fmt.Errorf("xml unmarsal error:%+v", err) return nil, err }
if res.ReturnCode != define.CODE_SUCCESS { err = fmt.Errorf("network error, retrun_code: %+v and return_msg: %+v", res.ReturnCode, res.ReturnMsg) return nil, err }
if res.ResultCode != define.CODE_SUCCESS { err = fmt.Errorf("trade error, result_code: %+v and err_code: %+v and err_desc: %+v", res.ResultCode, res.ErrCode, res.ErrCodeDes) return nil, err }
order := new(models.UserOrder) exist, err := order.GetByOutTradeNo(res.OutTradeNo) if err != nil || !exist { err = fmt.Errorf("user order get by out_trade_no: %+v, error: %+v, exist: %+v", res.OutTradeNo, err, exist) return nil, err }
order.TransactionId = res.TransactionId order.Status = 1 _, err = models.Update(order.Id, order, "status", "transaction_id") if err != nil { return nil, err }
err = HandleSuccess(order) if err != nil { logger.Error(fmt.Sprintf("callback 错误处理: %v", err)) return nil, err } return order, nil
}
func OrderQuery(outTradeNo string) (map[string]string, error) { client, err := Client() if err != nil { return nil, err }
body := make(map[string]string) body["out_trade_no"] = outTradeNo body["nonce_str"] = utils.RandomStr(32) body["sign_type"] = pay_core.SignType_MD5
res, err := pay.OrderQuery(client, body) if err != nil { return nil, err }
return res, nil }
func Close(outTradeNo string) error { client, err := Client() if err != nil { return err } body := make(map[string]string) body["out_trade_no"] = outTradeNo body["nonce_str"] = utils.RandomStr(32) body["sign_type"] = pay_core.SignType_MD5
_, err = pay.CloseOrder(client, body) // 请求关闭订单,成功后得到结果
if err != nil { return err } return nil }
const CallbackRefundUrl = "https://api.ouxuanhudong.com/PcClient/common/WeChatOauthCtl/callbackRefund"
func Refund(reason, outTradeNo string) (map[string]string, error) { userOrder := new(models.UserOrder) exist, err := userOrder.GetByOutTradeNo(outTradeNo) if err != nil { return nil, err }
if !exist { return nil, fmt.Errorf("订单不存在") } client, err := Client()
outRefundNo := utils.RandomStr(64) nonceStr := utils.RandomStr(32) body := make(map[string]string, 0) body["out_trade_no"] = outTradeNo body["out_refund_no"] = outRefundNo body["total_fee"] = fmt.Sprint(userOrder.TotalFee) body["refund_fee"] = fmt.Sprint(userOrder.TotalFee) body["nonce_str"] = nonceStr body["sign_type"] = pay_core.SignType_MD5 body["refund_desc"] = reason body["notify_url"] = CallbackRefundUrl
res, err := pay.Refund(client, body) //
if err != nil { return nil, err } userOrder.Status = 3 _, err = models.Update(userOrder.Id, userOrder, "status") if err != nil { return nil, err }
//go PutOrderDelayQueue(userOrder) // 退款查询
return res, nil }
func QueryRefund(outTradeNo string) (*pay.RefundQueryResponse, error) { client, err := Client() if err != nil { return nil, err }
res, err := pay.RefundQuery2(client, &pay.RefundQueryRequest{ OutTradeNo: outTradeNo, NonceStr: utils.RandomStr(32), SignType: pay_core.SignType_MD5, }) //请求申请退款
if err != nil { return nil, err } return res, nil }
type NotifyRefundParam struct { XMLName struct{} `xml:"xml" json:"-"`
ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"` ReturnMsg string `xml:"return_msg,omitempty" json:"return_msg,omitempty"` ResultCode string `xml:"result_code,omitempty" json:"result_code,omitempty"` ErrCode string `xml:"err_code,omitempty" json:"err_code,omitempty"` ErrCodeDes string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"` Appid string `xml:"appid,omitempty" json:"appid,omitempty"` MchId string `xml:"mch_id,omitempty" json:"mch_id,omitempty"` NonceStr string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"` ReqInfo string `xml:"req_info,omitempty" json:"req_info,omitempty"` TransactionId string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"` OutTradeNo string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"` RefundId string `xml:"refund_id,omitempty" json:"refund_id,omitempty"` OutRefundNo string `xml:"out_refund_no,omitempty" json:"out_refund_no,omitempty"` TotalFee int `xml:"total_fee,omitempty" json:"total_fee,omitempty"` SettlementTotalFee int `xml:"settlement_total_fee,omitempty" json:"settlement_total_fee,omitempty"` RefundFee int `xml:"refund_fee,omitempty" json:"refund_fee,omitempty"` SettlementRefundFee int `xml:"settlement_refund_fee,omitempty" json:"settlement_refund_fee,omitempty"` RefundStatus string `xml:"refund_status,omitempty" json:"refund_status,omitempty"` SuccessTime string `xml:"success_time,omitempty" json:"success_time,omitempty"` RefundRecvAccout string `xml:"refund_recv_accout,omitempty" json:"refund_recv_accout,omitempty"` RefundAccount string `xml:"refund_account,omitempty" json:"refund_account,omitempty"` RefundRequestSource string `xml:"refund_request_source,omitempty" json:"refund_request_source,omitempty"` }
func NotifyRefund(body string) (*models.UserOrder, error) { res := NotifyRefundParam{} err := xml.Unmarshal([]byte(body), &res) if err != nil { err = fmt.Errorf("xml unmarsal error: %+v", err) return nil, err }
logger.Error("return-->", res.ReturnCode == define.CODE_SUCCESS) logger.Error("result-->", res.ResultCode == define.CODE_SUCCESS) logger.Error(res) if res.ReturnCode != define.CODE_SUCCESS { err = fmt.Errorf("network error, retrun_code: %+v and return_msg: %+v", res.ReturnCode, res.ReturnMsg) return nil, err }
if res.ResultCode != define.CODE_SUCCESS { err = fmt.Errorf("trade error, result_code: %+v and err_code: %+v and err_desc: %+v", res.ResultCode, res.ErrCode, res.ErrCodeDes) return nil, err }
order := new(models.UserOrder) exist, err := order.GetByOutTradeNo(res.OutTradeNo) if err != nil || !exist { err = fmt.Errorf("user order get by out_trade_no: %+v, error: %+v, exist: %+v", res.OutTradeNo, err, exist) return nil, err }
order.RefundRecvAccount = res.RefundRecvAccout order.RefundAccount = res.RefundAccount order.TransactionId = res.TransactionId order.Status = 4 _, err = models.Update(order.Id, order, "status", "transaction_id") if err != nil { return nil, err } return order, nil }
|