package service import ( "bytes" "encoding/json" "errors" "fmt" "io" "net/http" "strconv" "time" "yuleduiPay/repo" "yuleduiPay/service/po" "yuleduiPay/service/vo" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/guid" ) type Pay struct { payOrderRepo repo.PayOrder shopRepo repo.Shop } var YSEPAYURL = "https://qrcode.ysepay.com/gateway.do" //银盛的微信小程序接口地址 // 微信小程序,扫码支付 func (t *Pay) PayQrCode(r *ghttp.Request) { g.Log().Line().Print(nil, r.Request) //todo req := vo.PayQrCodeReq{} err := r.Parse(&req) if err != nil { r.SetError(err) return } g.Log().Line().Printf(nil, "%+v", req) //获取订单信息 shop, err := t.shopRepo.GetShopById(req.ShopId) if err != nil { r.SetError(err) return } //创建订单记录 payOrder := po.PayOrder{} payOrder.OrderId = guid.S() payOrder.Price, err = strconv.ParseFloat(req.Price, 64) if err != nil { r.SetError(err) return } payOrder.Amount, err = strconv.ParseFloat(req.Amount, 64) if err != nil { r.SetError(err) return } payOrder.Bean, err = strconv.ParseFloat(req.Bean, 64) if err != nil { r.SetError(err) return } payOrder.OpenId = req.OpenId payOrder.Mobile = req.Mobile payOrder.ShopId = req.ShopId payOrder.Created = gtime.Now() payOrder.Updated = payOrder.Created err = t.payOrderRepo.CreatePayOrder(&payOrder) if err != nil { r.SetError(err) return } jsonBytes, err := t.ysePayRequestJson(shop, &payOrder) //组织银盛请求json if err != nil { r.SetError(err) return } //java 项目处理sign字段 jsonResp, err := t.ysePayPost(jsonBytes) //Post请求银盛接口 if err != nil { r.SetError(err) return } yseResp, err := t.yseRespHandler(jsonResp) //解析银盛应答报文 if err != nil { r.SetError(err) return } if yseResp.OutTradeNo != payOrder.OpenId { errStr := fmt.Sprintf("银盛返回订单号错误,银盛订单号:%s,余乐兑订单号:%s", yseResp.OutTradeNo, payOrder.OpenId) r.SetError(errors.New(errStr)) return } //更新支付订单表字段 updates := g.Map{"ysePayStatus": yseResp.TradeStatus, "updated": time.Now()} err = t.payOrderRepo.UpdatePayOrderByOrderId(updates, payOrder.OpenId) if err != nil { r.SetError(err) } return } func (t *Pay) yseRespHandler(jsonResp []byte) (*vo.WeixinPayResp, error) { ysePayResp := &vo.PayResp{} err := json.Unmarshal(jsonResp, ysePayResp) if err != nil { return nil, err } yseWeiXinPayResp := &vo.WeixinPayResp{} err = json.Unmarshal([]byte(ysePayResp.YsepayOnlineWeixinPayResponse), yseWeiXinPayResp) if yseWeiXinPayResp.Code != "10000" { return nil, errors.New("银盛应答返回错误:" + yseWeiXinPayResp.Msg) } return yseWeiXinPayResp, err } func (t *Pay) ysePayPost(jsonBytes []byte) ([]byte, error) { resp, err := http.Post(YSEPAYURL, "application/json", bytes.NewReader(jsonBytes)) if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) } func (t *Pay) ysePayRequestJson(shop *po.Shop, payOrder *po.PayOrder) ([]byte, error) { jsonMap := g.Map{} //公共请求参数 jsonMap["method"] = "ysepay.online.weixin.pay" //接口名称,固定值 certId := g.Cfg().MustGet(nil, "ysepay.CERTID") jsonMap["partner_id"] = certId //在银盛支付开设的服务商商户号 jsonMap["timestamp"] = time.Now().Format("2006-01-02 15:04:05") //发送请求的时间 jsonMap["charset"] = "UTF-8" //商户网站使用的编码格式 jsonMap["sign_type"] = "SM" //报文签名算法 //sign 需要java项目处理 todo notifyUrl := g.Cfg().MustGet(nil, "ysepay.notifyUrl") jsonMap["notify_url"] = notifyUrl //交易成功异步通知到商户的后台地址 jsonMap["version"] = "3.0" //接口版本 //业务请求参数 businessMap := g.Map{} businessMap["orderId"] = payOrder.OpenId //订单编号 businessMap["shopdate"] = payOrder.Created.Format("20060102") //商户系统的交易发生日期格式 businessMap["subject"] = "余乐兑小程序订单" //订单备注 businessMap["total_amount"] = payOrder.Price //该笔订单的资金总额 businessMap["currency"] = "CNY" //默认人民币 //订单备注 businessMap["seller_id"] = shop.AccountNumber //商户ID businessMap["seller_name"] = shop.ShopName //店铺名称 businessMap["timeout_express"] = "1h" //设置未付款交易的超时时间,一个小时 businessMap["sub_openid"] = payOrder.OpenId //微信OpenId businessMap["is_minipg"] = "1" //微信小程序支付:1 appId := g.Cfg().MustGet(nil, "weixin.appId") businessMap["appid"] = appId //微信小程序APPID b, err := json.Marshal(businessMap) if err != nil { return nil, err } jsonMap["biz_content"] = string(b) return json.Marshal(jsonMap) }