123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- package talent_service
- import (
- "context"
- "fmt"
- "github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/net/ghttp"
- "github.com/gogf/gf/os/glog"
- "github.com/gogf/gf/os/gtime"
- "github.com/wechatpay-apiv3/wechatpay-go/core"
- "github.com/wechatpay-apiv3/wechatpay-go/core/option"
- "github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
- wxUtils "github.com/wechatpay-apiv3/wechatpay-go/utils"
- "math/rand"
- "strconv"
- "time"
- "youngmini_server/app/dao"
- "youngmini_server/app/model"
- "youngmini_server/app/model/talent_model"
- "youngmini_server/app/utils"
- )
- var (
- mchID string = "1615933939" // 商户号
- mchCertificateSerialNumber string = "636DC3B258E436FAD123DAC6453E485CCDBF8770" // 商户证书序列号
- mchAPIv3Key string = "zwbx8iae5llhpwj48guterlpodt3xngo" // 商户APIv3密钥
- keyFilePath string = "./config/secret/apiclient_key.pem" // 密钥文件路径
- )
- func generatePayOrderNumber(talentId int) string {
- orderNo := gtime.Now().Format("YmdHis")
- rand.Seed(time.Now().UnixNano())
- r := rand.Intn(899)
- orderNo += strconv.Itoa(r + 100)
- orderNo += fmt.Sprintf("%04d", talentId)
- return orderNo
- }
- func WxPayOnTalentRequestPay(r *ghttp.Request) *TalentHttpResult {
- tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
- if err != nil {
- return &TalentHttpResult{Code: -1, Msg: "Get talent id failed"}
- }
- // 获取上传参数
- var payInfo *talent_model.WxPrepayRequestData
- err = r.ParseForm(&payInfo)
- if err != nil {
- return &TalentHttpResult{Code: -2, Msg: "param error"}
- }
- // 获取达人信息
- var talentInfo *model.TalentInfo
- err = g.DB().Model(dao.TalentInfo.Table).Scan(&talentInfo, dao.TalentInfo.Columns.Id, tid)
- if err != nil {
- return &TalentHttpResult{Code: -3, Msg: "query talent info failed"}
- }
- if talentInfo.InBlacklist >= 1 {
- return &TalentHttpResult{Code: -4, Msg: "talent in blacklist"}
- }
- // 获取任务信息
- var taskInfo *talent_model.TaskDetail
- err = g.DB().Model(dao.TaskBaseInfo.Table).WithAll().Where(dao.TaskBaseInfo.Columns.TaskId, payInfo.TaskId).Scan(&taskInfo)
- if err != nil || taskInfo == nil {
- return &TalentHttpResult{Code: -5, Msg: "query task info failed"}
- }
- // 任务当前不是执行状态,返回
- if taskInfo.TaskStatus != 2 {
- return &TalentHttpResult{Code: -6, Msg: "task can not sign up"}
- }
- // 任务已截止报名
- if taskInfo.DeadlineTime.Before(gtime.Now()) {
- return &TalentHttpResult{Code: -7, Msg: "task sign up has finished"}
- }
- // 如果任务不需要拍单,或拍单方式为不拍单则返回
- if taskInfo.IsBuySamples == nil || taskInfo.IsBuySamples.BuySamplesType != 1 {
- return &TalentHttpResult{Code: -8, Msg: "task do not need buy samples"}
- }
- // 任务拍单费用和上传的拍单费用不符,返回
- if taskInfo.IsBuySamples.BuySamplesCost != payInfo.BuySamplesCost {
- return &TalentHttpResult{Code: -9, Msg: "task buy samples cost != input cost"}
- }
- mchPrivateKey, err := wxUtils.LoadPrivateKeyWithPath(keyFilePath)
- if err != nil {
- glog.Error("load merchant private key error")
- return &TalentHttpResult{Code: -10, Msg: "load client key failed"}
- }
- ctx := context.Background()
- // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
- opts := []core.ClientOption{
- option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
- }
- client, err := core.NewClient(ctx, opts...)
- if err != nil {
- glog.Error("new wechat pay client err:", err)
- return &TalentHttpResult{Code: -11, Msg: "create client failed"}
- }
- orderNumber := generatePayOrderNumber(talentInfo.Id)
- svc := jsapi.JsapiApiService{Client: client}
- // 得到prepay_id,以及调起支付所需的参数和签名
- resp, result, err := svc.PrepayWithRequestPayment(ctx,
- jsapi.PrepayRequest{
- Appid: core.String(g.Config().GetString("miniapp.appid")),
- Mchid: core.String(mchID),
- Description: core.String("拍单费用_" + strconv.Itoa(taskInfo.TaskId) + "_" +taskInfo.TaskName + "_" + payInfo.PlatformNickname),
- OutTradeNo: core.String(orderNumber),
- Attach: core.String("报名任务拍单费用"),
- NotifyUrl: core.String("https://www.weixin.qq.com/wxpay/pay.php"),
- Amount: &jsapi.Amount{
- Total: core.Int64(payInfo.BuySamplesCost),
- },
- Payer: &jsapi.Payer{
- Openid: core.String(talentInfo.TalentWxOpenid),
- },
- },
- )
- if err != nil {
- // 处理错误
- glog.Error("call Prepay err:%s", err)
- return &TalentHttpResult{Code: -12, Msg: "request prepay info failed"}
- }
- // 处理返回结果
- glog.Println("status=%d resp=%s", result.Response.StatusCode, resp)
- if result.Response.StatusCode != 200 {
- glog.Println(result.Response)
- }
- // 将支付记录写入数据库
- _, err = g.DB().Model(dao.WxPayOrder.Table).Insert(model.WxPayOrder{
- OutTradeNo: orderNumber,
- WxOrderNo: "",
- PayAmount: payInfo.BuySamplesCost,
- TaskName: taskInfo.TaskName,
- PayReason: 1,
- TalentId: talentInfo.Id,
- TalentWxNickname: talentInfo.TalentWxNickname,
- TalentPlatformAccountName: payInfo.PlatformNickname,
- TaskId: taskInfo.TaskId,
- TaskPlatform: taskInfo.TaskPlatform,
- Success: 0,
- CreateAt: gtime.Now(),
- Desc: "",
- })
- if err != nil {
- return &TalentHttpResult{Code: -13, Msg: "insert wx pay order failed"}
- }
- return &TalentHttpResult{Code: 0, Msg: "success", Data: talent_model.WxPrepayResponseData{
- OutTradeNo: orderNumber,
- WxResp: resp,
- }}
- }
- func WxPayQueryOrderById(r *ghttp.Request) *TalentHttpResult {
- transactionId := r.GetRequestString("transaction_id", "nil")
- if transactionId == "nil" {
- glog.Error("not input transaction_id param")
- return &TalentHttpResult{Code: -2, Msg: "input transaction_id param"}
- }
- // 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
- mchPrivateKey, err := wxUtils.LoadPrivateKeyWithPath(keyFilePath)
- if err != nil {
- glog.Error("load merchant private key error")
- return &TalentHttpResult{Code: -3, Msg: "load merchant private key error"}
- }
- ctx := context.Background()
- // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
- opts := []core.ClientOption{
- option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
- }
- client, err := core.NewClient(ctx, opts...)
- if err != nil {
- glog.Error("new wechat pay client err:%s", err)
- return &TalentHttpResult{Code: -4, Msg: "load merchant private key error"}
- }
- svc := jsapi.JsapiApiService{Client: client}
- resp, _, err := svc.QueryOrderById(ctx,
- jsapi.QueryOrderByIdRequest{
- TransactionId: core.String(transactionId),
- Mchid: core.String(mchID),
- },
- )
- if err != nil {
- // 处理错误
- glog.Error("call WxPayQueryOrderById err:%s", err)
- return &TalentHttpResult{Code: -5, Msg: "call WxPayQueryOrderById failed"}
- }
- // TODO:支付结果写入数据库
- _, err = g.DB().Model(dao.WxPayOrder.Table).Update(g.Map{
- dao.WxPayOrder.Columns.WxOrderNo: resp.TransactionId,
- dao.WxPayOrder.Columns.Success: 1,
- dao.WxPayOrder.Columns.Desc: resp.TradeStateDesc,
- }, dao.WxPayOrder.Columns.OutTradeNo, resp.OutTradeNo)
- if err != nil {
- glog.Error("wxpay_handler.WxPayQueryOrderById Update database failed, order number = ", resp.OutTradeNo)
- return &TalentHttpResult{Code: -6, Msg: "Update database failed"}
- }
- return &TalentHttpResult{Code: 0, Msg: "success"}
- }
- func QueryOrderByOutTradeNo(r *ghttp.Request) *TalentHttpResult {
- outTradeNo := r.GetRequestString("out_trade_no", "nil")
- if outTradeNo == "nil" {
- glog.Error("not input out_trade_no param")
- return &TalentHttpResult{Code: -2, Msg: "input transaction_id param"}
- }
- g.DB().Model()
- // 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
- mchPrivateKey, err := wxUtils.LoadPrivateKeyWithPath(keyFilePath)
- if err != nil {
- glog.Error("load merchant private key error")
- return &TalentHttpResult{Code: -3, Msg: "load merchant private key error"}
- }
- ctx := context.Background()
- // 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
- opts := []core.ClientOption{
- option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
- }
- client, err := core.NewClient(ctx, opts...)
- if err != nil {
- glog.Error("new wechat pay client err:%s", err)
- return &TalentHttpResult{Code: -4, Msg: "load merchant private key error"}
- }
- svc := jsapi.JsapiApiService{Client: client}
- resp, _, err := svc.QueryOrderByOutTradeNo(ctx,
- jsapi.QueryOrderByOutTradeNoRequest{
- OutTradeNo: core.String(outTradeNo),
- Mchid: core.String(mchID),
- },
- )
- if err != nil {
- // 处理错误
- glog.Error("call QueryOrderByOutTradeNo err:%s", err)
- return &TalentHttpResult{Code: -5, Msg: "call QueryOrderByOutTradeNo failed"}
- }
- // TODO:支付结果写入数据库
- _, err = g.DB().Model(dao.WxPayOrder.Table).Update(g.Map{
- dao.WxPayOrder.Columns.WxOrderNo: resp.TransactionId,
- dao.WxPayOrder.Columns.Success: 1,
- dao.WxPayOrder.Columns.Desc: resp.TradeStateDesc,
- }, dao.WxPayOrder.Columns.OutTradeNo, resp.OutTradeNo)
- if err != nil {
- glog.Error("wxpay_handler.WxPayQueryOrderById Update database failed, order number = ", resp.OutTradeNo)
- return &TalentHttpResult{Code: -6, Msg: "Update database failed"}
- }
- return &TalentHttpResult{Code: 0, Msg: "success"}
- }
- func OnWxPayNotify(r *ghttp.Request) {
- wxSignature := r.GetHeader("Wechatpay-Signature")
- if wxSignature == "" {
- glog.Error("OnWxPayNotify header not contain Wechatpay-Signature property")
- r.Response.WriteJsonExit(g.Map{
- "code": "FAILED",
- "message": "header中不包括Wechatpay-Signature",
- })
- }
- }
|