2024-11-05 08:32:10 +08:00
|
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
2024-11-05 17:34:58 +08:00
|
|
|
|
"encoding/json"
|
2024-11-05 08:32:10 +08:00
|
|
|
|
"errors"
|
2024-11-05 17:34:58 +08:00
|
|
|
|
"fmt"
|
2024-11-22 09:23:33 +08:00
|
|
|
|
"io"
|
|
|
|
|
"net/http"
|
2024-11-05 08:32:10 +08:00
|
|
|
|
"strconv"
|
2024-11-22 09:23:33 +08:00
|
|
|
|
"strings"
|
2024-11-05 17:34:58 +08:00
|
|
|
|
"time"
|
2024-11-07 18:07:35 +08:00
|
|
|
|
"yuleduiPay/common"
|
2024-11-05 08:32:10 +08:00
|
|
|
|
"yuleduiPay/repo"
|
|
|
|
|
"yuleduiPay/service/po"
|
|
|
|
|
"yuleduiPay/service/vo"
|
|
|
|
|
|
2024-11-22 09:23:33 +08:00
|
|
|
|
"context"
|
|
|
|
|
|
|
|
|
|
"math/rand"
|
|
|
|
|
|
|
|
|
|
"github.com/gogf/gf/os/gctx"
|
2024-11-05 08:32:10 +08:00
|
|
|
|
"github.com/gogf/gf/v2/frame/g"
|
2024-11-05 09:49:02 +08:00
|
|
|
|
"github.com/gogf/gf/v2/os/gtime"
|
2024-11-05 08:32:10 +08:00
|
|
|
|
"github.com/gogf/gf/v2/util/guid"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Pay struct {
|
|
|
|
|
payOrderRepo repo.PayOrder
|
2024-11-05 09:49:02 +08:00
|
|
|
|
shopRepo repo.Shop
|
2024-11-22 09:23:33 +08:00
|
|
|
|
userRepo repo.User
|
2024-11-05 08:32:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-18 09:15:45 +08:00
|
|
|
|
// 微信和支付宝小程序,扫码支付
|
2024-11-22 09:23:33 +08:00
|
|
|
|
func (t *Pay) GetReduction(ctx context.Context, req *vo.GetReductionReq) (resp *vo.GetReductionResp, err error) {
|
|
|
|
|
resp = &vo.GetReductionResp{}
|
|
|
|
|
shopAdmin, err := t.shopRepo.GetShopAdminByShopId(req.ShopId)
|
2024-11-05 08:32:10 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-22 09:23:33 +08:00
|
|
|
|
rand_reduction := shopAdmin.RandReduction
|
|
|
|
|
r := rand.New(rand.NewSource(time.Now().UnixNano())) //以当前时间纳秒为种子
|
|
|
|
|
fmt.Println(rand_reduction)
|
|
|
|
|
resp.Reduction = r.Int63n(rand_reduction + 1)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 微信和支付宝小程序,扫码支付
|
|
|
|
|
func (t *Pay) PayQrCode(ctx context.Context, req *vo.PayQrCodeReq) (resp *vo.PayQrCodeResp, err error) {
|
2024-11-05 08:32:10 +08:00
|
|
|
|
g.Log().Line().Printf(nil, "%+v", req)
|
2024-11-22 09:23:33 +08:00
|
|
|
|
|
2024-11-18 09:15:45 +08:00
|
|
|
|
//计算金豆和随机立减,算出最终打给银盛的钱
|
2024-11-22 09:23:33 +08:00
|
|
|
|
payOrder, err := t.getAmount(req.Price, req.Reduction, req.Bean)
|
2024-11-05 08:32:10 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-22 09:23:33 +08:00
|
|
|
|
|
|
|
|
|
//获取商铺信息
|
|
|
|
|
shop, err := t.shopRepo.GetShopById(req.ShopId)
|
2024-11-05 08:32:10 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-22 09:23:33 +08:00
|
|
|
|
|
|
|
|
|
//创建订单记录
|
|
|
|
|
payOrder.OrderId = guid.S()
|
2024-11-05 08:32:10 +08:00
|
|
|
|
payOrder.OpenId = req.OpenId
|
|
|
|
|
payOrder.Mobile = req.Mobile
|
|
|
|
|
payOrder.ShopId = req.ShopId
|
2024-11-07 18:07:35 +08:00
|
|
|
|
payOrder.Channel = req.Channel
|
2024-11-05 09:49:02 +08:00
|
|
|
|
payOrder.Created = gtime.Now()
|
2024-11-05 08:32:10 +08:00
|
|
|
|
payOrder.Updated = payOrder.Created
|
|
|
|
|
|
2024-11-22 09:23:33 +08:00
|
|
|
|
err = t.payOrderRepo.CreatePayOrder(payOrder)
|
2024-11-05 08:32:10 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-05 17:34:58 +08:00
|
|
|
|
|
2024-11-22 09:23:33 +08:00
|
|
|
|
yseRespBytes, err := t.ysePayRequestJson(shop, payOrder) //访问java项目,获取银盛返回的结果
|
2024-11-05 17:34:58 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-18 09:15:45 +08:00
|
|
|
|
fmt.Println(string(yseRespBytes))
|
|
|
|
|
g.Log().Line().Printf(nil, string(yseRespBytes))
|
2024-11-07 18:07:35 +08:00
|
|
|
|
|
2024-11-08 15:19:11 +08:00
|
|
|
|
yseResp, err := t.yseParseResp(payOrder.Channel, yseRespBytes) //解析报文返回的报文
|
2024-11-05 17:34:58 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-08 15:19:11 +08:00
|
|
|
|
fmt.Println(yseResp)
|
2024-11-22 09:23:33 +08:00
|
|
|
|
if yseResp.OutTradeNo != payOrder.OrderId {
|
2024-11-05 17:34:58 +08:00
|
|
|
|
errStr := fmt.Sprintf("银盛返回订单号错误,银盛订单号:%s,余乐兑订单号:%s", yseResp.OutTradeNo, payOrder.OpenId)
|
2024-11-22 09:23:33 +08:00
|
|
|
|
err = errors.New(errStr)
|
2024-11-05 17:34:58 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
//更新支付订单表字段
|
|
|
|
|
updates := g.Map{"ysePayStatus": yseResp.TradeStatus, "updated": time.Now()}
|
|
|
|
|
err = t.payOrderRepo.UpdatePayOrderByOrderId(updates, payOrder.OpenId)
|
|
|
|
|
if err != nil {
|
2024-11-22 09:23:33 +08:00
|
|
|
|
return
|
2024-11-05 17:34:58 +08:00
|
|
|
|
}
|
2024-11-22 09:23:33 +08:00
|
|
|
|
resp = &vo.PayQrCodeResp{}
|
|
|
|
|
resp.OrderId = payOrder.OrderId
|
|
|
|
|
resp.Bean = payOrder.Bean
|
|
|
|
|
resp.Reduction = payOrder.RandReduce
|
|
|
|
|
resp.JsapiPayInfo = yseResp.JsapiPayInfo
|
2024-11-05 08:32:10 +08:00
|
|
|
|
return
|
2024-11-05 17:34:58 +08:00
|
|
|
|
}
|
2024-11-22 09:23:33 +08:00
|
|
|
|
|
|
|
|
|
func (t *Pay) getAmount(orderPrice string, reduction int, bean float64) (payOrder *po.PayOrder, err error) {
|
|
|
|
|
payOrder = &po.PayOrder{}
|
|
|
|
|
/*
|
|
|
|
|
shopAdmin, err := t.shopRepo.GetShopAdminByShopId(shopId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return payOrder, err
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
price, err := strconv.ParseFloat(orderPrice, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
payOrder.Price = price
|
|
|
|
|
payOrder.Bean = bean * 0.15
|
|
|
|
|
price = price - payOrder.Bean //去除金豆后的价格
|
|
|
|
|
payOrder.RandReduce = float64(reduction) * 0.01
|
|
|
|
|
payOrder.Amount = price - payOrder.RandReduce //去除随机立减和金豆后的价格
|
|
|
|
|
if payOrder.Amount < 0.01 {
|
|
|
|
|
err = errors.New("支付金额小于1分,失败")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 微信用户登录
|
|
|
|
|
func (t *Pay) Login(ctx context.Context, req *vo.WxLoginReq) (res *vo.WxLoginRes, err error) {
|
|
|
|
|
fmt.Println("11-----", req)
|
|
|
|
|
|
|
|
|
|
res, err = t.wxAuthorize(req.JsCode)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//根据openId查询手机号
|
|
|
|
|
userItem, _ := t.userRepo.GetUserByWxId(res.OpenId)
|
|
|
|
|
res.Mobile = userItem.Mobile
|
|
|
|
|
res.Bean = userItem.Bean
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用户注册
|
|
|
|
|
func (t *Pay) WxRegister(ctx context.Context, req *vo.WxMobileReq) (res *vo.WxMobileRes, err error) {
|
|
|
|
|
fmt.Println("WxRegister----", req)
|
|
|
|
|
value, err := g.Redis().Get(ctx, "WxAccessToken")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Println("1111111", err)
|
|
|
|
|
accessToken := value.String()
|
|
|
|
|
fmt.Println("-------", accessToken)
|
|
|
|
|
if accessToken == "" { //从微信小程序获取token,并更新redis
|
|
|
|
|
fmt.Println("2222222")
|
|
|
|
|
accessToken, err = t.getWeiXinAccessToken()
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println("444--", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fmt.Println("----> ", accessToken)
|
|
|
|
|
//获取手机号
|
|
|
|
|
mobile, err := t.getUserPhoneNumber(req.Code, accessToken)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
res = &vo.WxMobileRes{}
|
|
|
|
|
res.Mobile = mobile
|
|
|
|
|
//查询此手机号在数据库中是否存在
|
|
|
|
|
ok, err := t.userRepo.MobileExist(mobile)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if ok { //如果存在,更新openId
|
|
|
|
|
updates := g.Map{"wx_id": req.OpenId, "update_time": gtime.Now()}
|
|
|
|
|
err = t.userRepo.UpdatesUser(updates, mobile)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//不存在的,创建
|
|
|
|
|
user := po.User{}
|
|
|
|
|
user.UserId = guid.S()
|
|
|
|
|
user.WxId = req.OpenId
|
|
|
|
|
user.Mobile = mobile
|
|
|
|
|
user.CreateTime = gtime.Now()
|
|
|
|
|
user.UpdateTime = user.CreateTime
|
|
|
|
|
err = t.userRepo.CreateUser(&user)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
res = &vo.WxMobileRes{}
|
|
|
|
|
res.Mobile = mobile
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-08 15:19:11 +08:00
|
|
|
|
func (t *Pay) yseParseResp(channel int, respBytes []byte) (*vo.BusPayResp, error) {
|
|
|
|
|
yepayOnlineWeixinPayResponse := &vo.BusPayResp{}
|
|
|
|
|
if channel == 1 { //微信
|
|
|
|
|
ysePayResp := &vo.WxPayResp{}
|
2024-11-22 09:23:33 +08:00
|
|
|
|
fmt.Println("999-------> ", string(respBytes))
|
2024-11-08 15:19:11 +08:00
|
|
|
|
err := json.Unmarshal(respBytes, ysePayResp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
fmt.Println("银盛返回的应答:", ysePayResp)
|
|
|
|
|
yepayOnlineWeixinPayResponse = &ysePayResp.YsepayOnlineWeixinPayResponse
|
|
|
|
|
} else { //支付宝
|
|
|
|
|
ysePayResp := &vo.ZfbPayResp{}
|
|
|
|
|
err := json.Unmarshal(respBytes, ysePayResp)
|
2024-11-07 18:07:35 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2024-11-08 15:19:11 +08:00
|
|
|
|
fmt.Println("银盛返回的应答:", ysePayResp)
|
|
|
|
|
yepayOnlineWeixinPayResponse = &ysePayResp.YsepayOnlineAlijsapiPayResponse
|
2024-11-05 17:34:58 +08:00
|
|
|
|
|
2024-11-08 15:19:11 +08:00
|
|
|
|
}
|
|
|
|
|
if yepayOnlineWeixinPayResponse.Code != "10000" {
|
|
|
|
|
return nil, errors.New("银盛应答返回错误:" + yepayOnlineWeixinPayResponse.Msg)
|
|
|
|
|
}
|
|
|
|
|
return yepayOnlineWeixinPayResponse, nil
|
2024-11-07 18:07:35 +08:00
|
|
|
|
}
|
2024-11-08 15:19:11 +08:00
|
|
|
|
|
|
|
|
|
func (t *Pay) ysePayRequestJson(shop *po.Shop, payOrder *po.PayOrder) ([]byte, error) {
|
2024-11-05 17:34:58 +08:00
|
|
|
|
//业务请求参数
|
2024-11-07 18:07:35 +08:00
|
|
|
|
busReq := vo.PayBusReq{}
|
|
|
|
|
busReq.OutTradeNo = payOrder.OrderId //订单编号
|
|
|
|
|
busReq.Shopdate = payOrder.Created.Format("20060102") //商户系统的交易发生日期格式
|
|
|
|
|
busReq.Subject = "余乐兑小程序订单" //订单备注
|
2024-11-22 09:23:33 +08:00
|
|
|
|
busReq.TotalAmount = fmt.Sprintf("%.2f", payOrder.Amount) //该笔订单的资金总额,保留两位小数
|
2024-11-07 18:07:35 +08:00
|
|
|
|
busReq.Currency = "CNY" //默认人民币
|
2024-11-22 09:23:33 +08:00
|
|
|
|
busReq.SellerId = shop.ChildMerchNumber //银盛商户ID
|
2024-11-07 18:07:35 +08:00
|
|
|
|
busReq.TimeoutExpress = "1h" //设置未付款交易的超时时间,一个小时
|
|
|
|
|
busReq.BusinessCode = g.Cfg().MustGet(nil, "ysepay.busCode").String() //业务代码
|
|
|
|
|
|
|
|
|
|
var bjson []byte
|
|
|
|
|
var err error
|
|
|
|
|
if payOrder.Channel == 1 { //微信渠道
|
|
|
|
|
wxBusReq := vo.PayWxBusReq{PayBusReq: busReq}
|
|
|
|
|
wxBusReq.SubOpenid = payOrder.OpenId //微信用户ID
|
|
|
|
|
wxBusReq.IsMinipg = "1" //微信小程序支付:1
|
|
|
|
|
wxBusReq.Appid = g.Cfg().MustGet(nil, "weixin.appId").String() //微信小程序APPID
|
|
|
|
|
bjson, err = json.Marshal(wxBusReq)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
} else { //支付宝渠道
|
|
|
|
|
zfBusReq := vo.PayZfBusReq{PayBusReq: busReq}
|
|
|
|
|
zfBusReq.BuyerId = payOrder.OpenId //支付宝用户ID
|
|
|
|
|
bjson, err = json.Marshal(zfBusReq)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
commonReq := vo.PayCommonReq{}
|
|
|
|
|
if payOrder.Channel == 1 { //微信渠道
|
|
|
|
|
commonReq.Method = "ysepay.online.weixin.pay"
|
|
|
|
|
} else { //支付宝渠道
|
|
|
|
|
commonReq.Method = "ysepay.online.alijsapi.pay"
|
|
|
|
|
}
|
|
|
|
|
commonReq.PartnerId = g.Cfg().MustGet(nil, "ysepay.CERTID").String() //在银盛支付开设的服务商商户号
|
|
|
|
|
commonReq.Timestamp = time.Now().Format("2006-01-02 15:04:05") //发送请求的时间
|
|
|
|
|
commonReq.Charset = "UTF-8" //商户网站使用的编码格式
|
|
|
|
|
commonReq.SignType = "SM" //报文签名算法
|
|
|
|
|
commonReq.NotifyUrl = g.Cfg().MustGet(nil, "ysepay.notifyUrl").String() //交易成功异步通知到商户的后台地址
|
|
|
|
|
commonReq.Version = "3.0" //接口版本
|
|
|
|
|
|
2024-11-08 15:19:11 +08:00
|
|
|
|
commonReq.BizContent = string(bjson)
|
2024-11-07 18:07:35 +08:00
|
|
|
|
bjson, err = json.Marshal(&commonReq)
|
2024-11-05 17:34:58 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2024-11-07 18:07:35 +08:00
|
|
|
|
url := g.Cfg().MustGet(nil, "ysepay.url").String()
|
2024-11-08 15:19:11 +08:00
|
|
|
|
xxx := string(bjson)
|
|
|
|
|
fmt.Println(xxx)
|
|
|
|
|
//发送给java项目,让其访问银盛接口
|
|
|
|
|
bjson, err = common.HttpPost(url, "application/json", bjson)
|
2024-11-07 18:07:35 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2024-11-08 15:19:11 +08:00
|
|
|
|
return bjson, err
|
2024-11-05 08:32:10 +08:00
|
|
|
|
}
|
2024-11-22 09:23:33 +08:00
|
|
|
|
|
|
|
|
|
// 微信授权获取openId
|
|
|
|
|
func (t *Pay) wxAuthorize(jsCode string) (*vo.WxLoginRes, error) {
|
|
|
|
|
var urlResp *http.Response
|
|
|
|
|
var err error
|
|
|
|
|
appid := g.Cfg().MustGet(nil, "weixin.appId").String()
|
|
|
|
|
wxSecret := g.Cfg().MustGet(nil, "weixin.secret").String()
|
|
|
|
|
wx_url := "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid +
|
|
|
|
|
"&secret=" + wxSecret + "&js_code=" + jsCode + "&grant_type=authorization_code"
|
|
|
|
|
fmt.Println("jsCode:", jsCode)
|
|
|
|
|
for i := 0; i < 2; i++ { // 失败一次,再次调用
|
|
|
|
|
urlResp, err = http.Get(wx_url)
|
|
|
|
|
if err == nil { // 成功的话,跳出
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
body, err := io.ReadAll(urlResp.Body)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
urlResp.Body.Close()
|
|
|
|
|
sessionResp := vo.WxLoginRes{} // 用户标志信息
|
|
|
|
|
err = json.Unmarshal(body, &sessionResp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if sessionResp.ErrCode != 0 {
|
|
|
|
|
err = errors.New("errCode:" + strconv.Itoa(sessionResp.ErrCode) + " errMsg:" + sessionResp.ErrMsg)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return &sessionResp, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取accessToken
|
|
|
|
|
func (t *Pay) getWeiXinAccessToken() (string, error) {
|
|
|
|
|
type WeiXinAccessResp struct {
|
|
|
|
|
AccessToken string `json:"access_token"` // 获取到的凭证
|
|
|
|
|
ExpiresIn int `json:"expires_in"` // 凭证有效时间 单位:秒。目前是7200秒之内的值。
|
|
|
|
|
Errcode int `json:"errcode"`
|
|
|
|
|
Errmsg string `json:"errmsg"`
|
|
|
|
|
}
|
|
|
|
|
type WxSessionResp struct {
|
|
|
|
|
OpenId string `json:"openid"` // 用户唯一标识
|
|
|
|
|
SessionKey string `json:"session_key"` // 会话密钥
|
|
|
|
|
UnionId string `json:"unionid"` // 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回
|
|
|
|
|
ErrCode int `json:"errcode"` // 错误码
|
|
|
|
|
ErrMsg string `json:"errmsg"` // 错误信息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp := WeiXinAccessResp{}
|
|
|
|
|
appid := g.Cfg().MustGet(nil, "weixin.appId").String()
|
|
|
|
|
wxSecret := g.Cfg().MustGet(nil, "weixin.secret").String()
|
|
|
|
|
url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +
|
|
|
|
|
appid + "&secret=" + wxSecret
|
|
|
|
|
fmt.Println("获取token:", url)
|
|
|
|
|
var urlResp *http.Response
|
|
|
|
|
var err error
|
|
|
|
|
for i := 0; i < 2; i++ { // 失败一次,再次调用
|
|
|
|
|
urlResp, err = http.Get(url)
|
|
|
|
|
if err == nil { // 成功的话,跳出
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
body, err := io.ReadAll(urlResp.Body)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
urlResp.Body.Close()
|
|
|
|
|
fmt.Println(string(body))
|
|
|
|
|
sessionResp := WxSessionResp{}
|
|
|
|
|
err = json.Unmarshal(body, &resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if resp.Errcode != 0 {
|
|
|
|
|
err = errors.New(sessionResp.ErrMsg)
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
// AccessToken 存入Redis中
|
|
|
|
|
live := resp.ExpiresIn - 60*10 // 提前10分钟过期
|
|
|
|
|
ctx := gctx.New()
|
|
|
|
|
err = g.Redis().SetEX(ctx, "WxAccessToken", resp.AccessToken, int64(live))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return resp.AccessToken, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取手机号
|
|
|
|
|
func (s *Pay) getUserPhoneNumber(code, accessToken string) (string, error) {
|
|
|
|
|
type WeiXinWatermark struct {
|
|
|
|
|
Appid string `json:"appid"` // 小程序appid
|
|
|
|
|
Timestamp int `json:"timestamp"` // 用户获取手机号操作的时间戳
|
|
|
|
|
}
|
|
|
|
|
type WeixinPhoneInfo struct {
|
|
|
|
|
PhoneNumber string `json:"phoneNumber"` // 用户绑定的手机号(国外手机号会有区号)
|
|
|
|
|
PurePhoneNumber string `json:"purePhoneNumber"` // 没有区号的手机号
|
|
|
|
|
CountryCode string `json:"countryCode"` // 区号
|
|
|
|
|
Watermark WeiXinWatermark `json:"watermark"` // 数据水印
|
|
|
|
|
}
|
|
|
|
|
type WeiXinMobileResp struct {
|
|
|
|
|
Errcode int `json:"errcode"`
|
|
|
|
|
Errmsg string `json:"errmsg"`
|
|
|
|
|
PhoneInfo WeixinPhoneInfo `json:"phone_info"` // 用户手机号信息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type WeiXinMobileReq struct {
|
|
|
|
|
Code string `json:"code"` // 前端传的Code
|
|
|
|
|
}
|
|
|
|
|
req := WeiXinMobileReq{Code: code}
|
|
|
|
|
url := "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken
|
|
|
|
|
fmt.Println("Code:", req.Code)
|
|
|
|
|
reqParam, err := json.Marshal(&req)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
reqBody := strings.NewReader(string(reqParam))
|
|
|
|
|
httpReq, err := http.NewRequest("POST", url, reqBody)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
httpReq.Header.Add("Content-Type", "application/json")
|
|
|
|
|
var urlResp *http.Response
|
|
|
|
|
for i := 0; i < 2; i++ { // 失败一次,再次调用
|
|
|
|
|
urlResp, err = http.DefaultClient.Do(httpReq)
|
|
|
|
|
if err == nil { // 成功的话,跳出
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
body, err := io.ReadAll(urlResp.Body)
|
|
|
|
|
urlResp.Body.Close()
|
|
|
|
|
resp := WeiXinMobileResp{}
|
|
|
|
|
fmt.Println(string(body))
|
|
|
|
|
err = json.Unmarshal(body, &resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
if resp.Errcode != 0 {
|
|
|
|
|
fmt.Println(resp)
|
|
|
|
|
err = errors.New(resp.Errmsg)
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
return resp.PhoneInfo.PhoneNumber, nil
|
|
|
|
|
}
|