1.引入的包
import (
"context"
"crypto/x509"
"encoding/json"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
wxutils "github.com/wechatpay-apiv3/wechatpay-go/utils"
)
2.建立请求vx的client
type OrderService struct{}
func (orderService *OrderService)SetUp()(opt []core.ClientOption, err error){
//商户号
mchID := global.GVA_CONFIG.VX.Payid
//商户证书序列号
mchCertSerialNumber := global.GVA_CONFIG.VX.CerSerial
//商户私钥文件路径
privateKeyPath := global.GVA_CONFIG.VX.PrivateKey
//平台证书文件路径
wechatCertificatePath := global.GVA_CONFIG.VX.Certificate
// 加载商户私钥
privateKey, err := wxutils.LoadPrivateKeyWithPath(privateKeyPath)
if err != nil {
fmt.Printf("load private err:%s", err.Error())
return nil, err
}
// 加载微信支付平台证书
wechatPayCertificate, err := wxutils.LoadCertificateWithPath(wechatCertificatePath)
if err != nil {
fmt.Printf("load certificate err:%s",err)
return nil, err
}
//设置header头中authorization信息
opts := []core.ClientOption{
option.WithMerchantCredential(mchID, mchCertSerialNumber, privateKey), // 设置商户相关配置
option.WithWechatPayCertificate([]*x509.Certificate{wechatPayCertificate}), // 设置微信支付平台证书,用于校验回包信息用
option.WithoutValidator(),//跳过证书的效验
}
return opts, nil
}
3.生成预支付请求,并生成签名信息
func (orderService *OrderService)VxCreateOrder(openid string,mineOrder Order)(error, map[string]string) {
// 初始化客户端
ctx := context.TODO()
opts, err := orderService.SetUp() //第二段代码中的函数
if err != nil {
return err, nil
}
client, err := core.NewClient(ctx, opts...)
//_, err = core.NewClient(ctx, opts...)
if err != nil{
fmt.Printf("init client err:%s",err)
return err, nil
}
//设置请求地址
URL := "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
//设置请求信息,此处也可以使用结构体来进行请求
mapInfo := map[string]interface{}{
"mchid": global.GVA_CONFIG.VX.Payid,
"out_trade_no": mineOrder.OrderId,
"appid": global.GVA_CONFIG.VX.AppId,
"description": mineOrder.BuyGoodsInfo(),
"notify_url": global.GVA_CONFIG.VX.NotifyUrl,
"amount": map[string]interface{}{
"total": mineOrder.CurPriceCent(),
"currency": "CNY",
},
"payer": map[string]interface{}{
"openid": openid,
},
}
//fmt.Print(URL,mapInfo)
// 发起请求
response, err := client.Post(ctx, URL, mapInfo)
if err != nil{
fmt.Printf("client post err:%s",err)
return err, nil
}
// 校验回包内容是否有逻辑错误
err = core.CheckResponse(response.Response)
if err != nil{
fmt.Printf("check response err:%s",err)
return err, nil
}
// 读取回包信息
body, err := ioutil.ReadAll(response.Response.Body)
if err != nil{
fmt.Printf("read response body err:%s",err)
return err, nil
}
return nil, orderService.MakeReturnMsg(body)
}
func (orderService *OrderService)MakeReturnMsg(body []byte)map[string]string{
var prepaymap map[string]string
_ = json.Unmarshal(body,&prepaymap)
// 时间戳
timeStamp:=strconv.FormatInt(time.Now().Unix(),10)
// 任意长度的随机字符串即可
nonceStr:=comFunc.RandStr(16)
packageStr:="prepay_id="+prepaymap["prepay_id"]
sb := strings.Builder{}
sb.WriteString(global.GVA_CONFIG.VX.AppId+"\n")
sb.WriteString(timeStamp+"\n")
sb.WriteString(nonceStr+"\n")
sb.WriteString(packageStr+"\n")
privateKey, err := wxutils.LoadPrivateKeyWithPath(global.GVA_CONFIG.VX.PrivateKey)
if err != nil{
log.Println("load err:",err)
}
sign,err:= wxutils.SignSHA256WithRSA(sb.String(), privateKey)
if err != nil{
log.Println("sign error :",err)
}
resultMap:=make(map[string]string)
resultMap["timeStamp"]=timeStamp
resultMap["nonceStr"]=nonceStr
resultMap["package"]=packageStr
resultMap["signType"]="RSA"
resultMap["paySign"]=sign
resultMap["prepay_id"]=prepaymap["prepay_id"]
return resultMap
}
4.收到vx的订单回传信息,注意是使用post回传的
// 使用gin的外部接口
func (orderApi *OrderApi) NotifyOrder(c *gin.Context) {
body,_ := ioutil.ReadAll(c.Request.Body)
b,s := orderService.DecodeNotify(body)
log.Println(b,s)
response.OkWithMessage("收到", c)
}
// 直接使用接口解密
func (orderService *OrderService)DecodeNotify(body []byte)(bool, string){
var prepaymap map[string]interface{}
_ = json.Unmarshal(body,&prepaymap)
var prepaymap2 = prepaymap["resource"].(map[string]interface{})
nonce := prepaymap2["nonce"].(string)
associatedData := prepaymap2["associated_data"].(string)
ciphertext := prepaymap2["ciphertext"].(string)
apiV3key := global.GVA_CONFIG.VX.Apiv3Key
tx,err := wxutils.DecryptAES256GCM(apiV3key, associatedData,nonce,ciphertext)
if err != nil{
log.Println(err)
return false,""
}
var datamap map[string]string
_ = json.Unmarshal([]byte(tx),&datamap)
return true, datamap["out_trade_no"]
}
*获取商家序列号,参考文档 证书查看
$ openssl x509 -in xxx_xxxx_cert.pem -noout -serial