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.

171 lines
4.4 KiB

4 years ago
package alipay
import (
"errors"
"fmt"
"github.com/jinzhu/gorm"
"github.com/shopspring/decimal"
"io/ioutil"
"log"
"net/http"
"net/url"
"recook/internal/api/mobile/pay/public"
"recook/internal/model/aftersales"
"strings"
"time"
)
type RefundPublicParam struct {
AppID string `json:"app_id"` // 支付宝分配给开发者的应用ID
Method string `json:"method"` // 接口名称
Charset string `json:"charset"` // 请求使用的编码格式如utf-8
SignType string `json:"sign_type"` // 商户生成签名字符串所使用的签名算法类型目前支持RSA2和RSA推荐使用RSA2
Sign string `json:"sign"` // 商户请求参数的签名串
Timestamp string `json:"timestamp"` // 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
Version string `json:"version"` // 调用的接口版本固定为1.0
BizContent string `json:"biz_content"`
}
func newPublicParam(d *RefundDetailParam) RefundPublicParam {
ts := time.Now().Format("2006-01-02 15:04:05")
biz, _ := json.Marshal(d)
return RefundPublicParam{
AppID: AppID,
Method: "alipay.trade.refund",
Charset: "utf-8",
SignType: "RSA2",
Version: "1.0",
Timestamp: ts,
BizContent: string(biz),
}
}
func (r *RefundPublicParam) generateRequestParam() string {
r.Sign = generateSign(r)
m := struct2MapWhenAlipay(r)
p := url.Values{}
for k, v := range m {
if len(v) > 0 {
p.Add(k, v)
}
}
return p.Encode()
}
type RefundDetailParam struct {
OutTradeNo string `json:"out_trade_no"`
RefundAmount string `json:"refund_amount"`
OutRequestNo string `json:"out_request_no"`
}
/*
{
"alipay_trade_refund_response": {
"code": "20000",
"msg": "Service Currently Unavailable",
"sub_code": "isp.unknow-error",
"sub_msg": "系统繁忙"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
{
"alipay_trade_refund_response": {
"code": "10000",
"msg": "Success",
"trade_no": "支付宝交易号",
"out_trade_no": "6823789339978248",
"buyer_logon_id": "159****5620",
"fund_change": "Y",
"refund_fee": 88.88,
"refund_currency": "USD",
"gmt_refund_pay": "2014-11-27 15:45:57",
"refund_detail_item_list": [
{
"fund_channel": "ALIPAYACCOUNT",
"bank_code": "CEB",
"amount": 10,
"real_amount": 11.21,
"fund_type": "DEBIT_CARD"
}
],
"store_name": "望湘园联洋店",
"buyer_user_id": "2088101117955611",
"refund_preset_paytool_list": {
"amount": [
12.21
],
"assert_type_code": "盒马礼品卡:HEMA抓猫猫红包:T_CAT_COUPON"
},
"refund_settlement_id": "2018101610032004620239146945",
"present_refund_buyer_amount": "88.88",
"present_refund_discount_amount": "88.88",
"present_refund_mdiscount_amount": "88.88"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
*/
type RefundResult struct {
Response struct {
Code string `json:"code"`
} `json:"alipay_trade_refund_response"`
Sign string `json:"sign"`
}
func Refund(tx *gorm.DB, asGoods *aftersales.Goods) error {
//这边判断是否有金额
if asGoods.RefundAmount.GreaterThan(decimal.NewFromFloat(0.0)) {
detailParam := RefundDetailParam{
OutTradeNo: asGoods.TradeNo,
RefundAmount: asGoods.RefundAmount.Truncate(2).String(),
OutRequestNo: asGoods.RefundNo,
}
pub := newPublicParam(&detailParam)
if err := requestOrderRefund(&pub); err != nil {
return err
}
}
return public.SyncRefundSuccessCallback(tx, asGoods)
}
func requestOrderRefund(param *RefundPublicParam) error {
client := &http.Client{}
request, err := http.NewRequest("POST", RefundURL, strings.NewReader(param.generateRequestParam()))
if err != nil {
return err
}
request.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
response, err := client.Do(request)
if err != nil {
return err
}
defer func() { _ = response.Body.Close() }()
result, err := ioutil.ReadAll(response.Body)
if err != nil {
return err
}
fmt.Println("===============================")
fmt.Println(string(result))
var r RefundResult
err = json.Unmarshal(result, &r)
if err != nil {
return err
}
if r.Response.Code != "10000" {
log.Println(r)
return errors.New("支付宝退款请求结果不对")
}
return nil
}