Giter Site home page Giter Site logo

wechatpay-apiv3 / wechatpay-go Goto Github PK

View Code? Open in Web Editor NEW
934.0 15.0 136.0 730 KB

微信支付 APIv3 的官方 Go Library

Home Page: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml

License: Apache License 2.0

Go 100.00%
go golang wechatpay wechatpay-apiv3 library sdk api-client api-sdk

wechatpay-go's Introduction

微信支付 API v3 Go SDK

GoDoc huntr licence

微信支付 APIv3 官方Go语言客户端代码库。

功能介绍

  1. 接口 SDK。详见 接口介绍
  2. HTTP 客户端 core.Client,支持请求签名和应答验签。如果 SDK 未支持你需要的接口,请用此客户端发起请求。
  3. 回调通知处理库 core/notify,支持微信支付回调通知的验签和解密。详见 回调通知验签与解密
  4. 证书下载、敏感信息加解密 等辅助能力。

兼容性

当前版本为测试版本,微信支付会尽量保持向后兼容。但可能因为可用性或易用性,同历史版本存在不兼容。如果你使用版本 <= v0.2.2,升级前请参考 升级指南

快速开始

安装

1、使用 Go Modules 管理你的项目

如果你的项目还不是使用 Go Modules 做依赖管理,在项目根目录下执行:

go mod init

2、无需 clone 仓库中的代码,直接在项目目录中执行:

go get -u github.com/wechatpay-apiv3/wechatpay-go

来添加依赖,完成 go.mod 修改与 SDK 下载。

发送请求

先初始化一个 core.Client 实例,再向微信支付发送请求。

package main

import (
	"context"
	"log"

	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/core/option"
	"github.com/wechatpay-apiv3/wechatpay-go/services/certificates"
	"github.com/wechatpay-apiv3/wechatpay-go/utils"
)

func main() {
	var (
		mchID                      string = "190000****"                                // 商户号
		mchCertificateSerialNumber string = "3775B6A45ACD588826D15E583A95F5DD********"  // 商户证书序列号
		mchAPIv3Key                string = "2ab9****************************"          // 商户APIv3密钥
	)

	// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
	mchPrivateKey, err := utils.LoadPrivateKeyWithPath("/path/to/merchant/apiclient_key.pem")
	if err != nil {
		log.Fatal("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 {
		log.Fatalf("new wechat pay client err:%s", err)
	}
	
	// 发送请求,以下载微信支付平台证书为例
	// https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay5_1.shtml
	svc := certificates.CertificatesApiService{Client: client}
	resp, result, err := svc.DownloadCertificates(ctx)
	log.Printf("status=%d resp=%s", result.Response.StatusCode, resp)
}

resp 是反序列化(UnmarshalJSON)后的应答。上例中是 services/certificates 包中的 *certificates.Certificate

result*core.APIResult 实例,包含了完整的请求报文 *http.Request 和应答报文 *http.Response

名词解释

  • 商户 API 证书,是用来证实商户身份的。证书中包含商户号、证书序列号、证书有效期等信息,由证书授权机构(Certificate Authority ,简称 CA)签发,以防证书被伪造或篡改。如何获取请见 商户 API 证书
  • 商户 API 私钥。商户申请商户 API 证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中。

⚠️ 不要把私钥文件暴露在公共场合,如上传到 Github,写在客户端代码等。

  • 微信支付平台证书。微信支付平台证书是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。商户使用微信支付平台证书中的公钥验证应答签名。获取微信支付平台证书需通过 获取平台证书列表 接口下载。
  • 证书序列号。每个证书都有一个由 CA 颁发的唯一编号,即证书序列号。扩展阅读 如何查看证书序列号
  • 微信支付 APIv3 密钥,是在回调通知和微信支付平台证书下载接口中,为加强数据安全,对关键信息 AES-256-GCM 加密时使用的对称加密密钥。

更多示例

JSAPI下单 为例

import (
	"log"
	"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
)

svc := jsapi.JsapiApiService{Client: client}
// 得到prepay_id,以及调起支付所需的参数和签名
resp, result, err := svc.PrepayWithRequestPayment(ctx,
	jsapi.PrepayRequest{
		Appid:       core.String("wxd678efh567hg6787"),
		Mchid:       core.String("1900009191"),
		Description: core.String("Image形象店-深圳腾大-QQ公仔"),
		OutTradeNo:  core.String("1217752501201407033233368018"),
		Attach:      core.String("自定义数据说明"),
		NotifyUrl:   core.String("https://www.weixin.qq.com/wxpay/pay.php"),
		Amount: &jsapi.Amount{
			Total: core.Int64(100),
		},
		Payer: &jsapi.Payer{
			Openid: core.String("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"),
		},
	},
)

if err == nil {
	log.Println(resp)
} else {
	log.Println(err)
}

查询订单 为例

import (
	"log"
	"github.com/wechatpay-apiv3/wechatpay-go/services/payments/jsapi"
)

svc := jsapi.JsapiApiService{Client: client}

resp, result, err := svc.QueryOrderById(ctx,
	jsapi.QueryOrderByIdRequest{
		TransactionId: core.String("4200000985202103031441826014"),
		Mchid:         core.String("1900009191"),
	},
)

if err == nil {
	log.Println(resp)
} else {
	log.Println(err)
}

图片上传API 为例:

import (
	"os"
	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/core/consts"
	"github.com/wechatpay-apiv3/wechatpay-go/services/fileuploader"
)

file, err := os.Open("resource/demo.jpg")
defer file.Close()
if err != nil {
	return err
}

svc := fileuploader.ImageUploader{Client: client}
resp, result, err := svc.Upload(ctx, file, "demo.jpg", consts.ImageJPG)

示例程序

为了方便开发者快速上手,微信支付给每个服务生成了示例代码 api_xx_example_test.go。请按需查阅。例如:

发送 HTTP 请求

如果 SDK 还未支持你需要的接口,使用 core.ClientGETPOST 等方法发送 HTTP 请求,而不用关注签名、验签等逻辑。

下载微信支付平台证书 为例:

result, err := client.Get(ctx, "https://api.mch.weixin.qq.com/v3/certificates")

使用 core.Client 发送 HTTP 请求后会得到 *core.APIResult 实例。

错误处理

以下情况,SDK 发送请求会返回 error

  • HTTP 网络错误,如应答接收超时或网络连接失败
  • 客户端失败,如生成签名失败
  • 服务器端返回了 2xx HTTP 状态码
  • 应答签名验证失败

为了方便使用,SDK 将服务器返回的 4xx5xx 错误,转换成了 APIError

// 错误处理示例
result, err := client.Get(ctx, "https://api.mch.weixin.qq.com/v3/certificates")
if err != nil {
	if core.IsAPIError(err, "INVALID_REQUEST") { 
		// 处理无效请求 
	}
	// 处理的其他错误
}

回调通知的验签与解密

  1. 使用微信支付平台证书(验签)和商户 APIv3 密钥(解密)初始化 notify.Handler
  2. 调用 handler.ParseNotifyRequest 验签,并解密报文。

初始化

  • 方法一(大多数场景):先手动注册下载器,再获取微信平台证书访问器。

适用场景: 仅需要对回调通知验证签名并解密的场景。例如,基础支付的回调通知。

ctx := context.Background()
// 1. 使用 `RegisterDownloaderWithPrivateKey` 注册下载器
err := downloader.MgrInstance().RegisterDownloaderWithPrivateKey(ctx, mchPrivateKey, mchCertificateSerialNumber, mchID, mchAPIV3Key)
// 2. 获取商户号对应的微信支付平台证书访问器
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID)
// 3. 使用证书访问器初始化 `notify.Handler`
handler := notify.NewNotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
  • 方法二:像 发送请求 那样使用 WithWechatPayAutoAuthCipher 初始化 core.Client,然后再用client进行接口调用。

适用场景:需要对回调通知验证签名并解密,并且后续需要使用 Client 的场景。例如,电子发票的回调通知,验签与解密后还需要通过 Client 调用用户填写抬头接口。

ctx := context.Background()
// 1. 使用商户私钥等初始化 client,并使它具有自动定时获取微信支付平台证书的能力
opts := []core.ClientOption{
	option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
}
client, err := core.NewClient(ctx, opts...)	
// 2. 获取商户号对应的微信支付平台证书访问器
certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchID)
// 3. 使用证书访问器初始化 `notify.Handler`
handler := notify.NewNotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))
// 4. 使用client进行接口调用
// ...
  • 方法三:使用本地的微信支付平台证书和商户 APIv3 密钥初始化 Handler

适用场景:首次通过工具下载平台证书到本地,后续使用本地管理的平台证书进行验签与解密。

// 1. 初始化商户API v3 Key及微信支付平台证书
mchAPIv3Key := "<your apiv3 key>"
wechatPayCert, err := utils.LoadCertificate("<your wechat pay certificate>")
// 2. 使用本地管理的微信支付平台证书获取微信支付平台证书访问器
certificateVisitor := core.NewCertificateMapWithList([]*x509.Certificate{wechatPayCert})
// 3. 使用apiv3 key、证书访问器初始化 `notify.Handler`
handler := notify.NewNotifyHandler(mchAPIv3Key, verifiers.NewSHA256WithRSAVerifier(certificateVisitor))

建议:为了正确使用平台证书下载管理器,你应阅读并理解 如何使用平台证书下载管理器

验签与解密

将支付回调通知中的内容,解析为 payments.Transaction

transaction := new(payments.Transaction)
notifyReq, err := handler.ParseNotifyRequest(context.Background(), request, transaction)
// 如果验签未通过,或者解密失败
if err != nil {
	fmt.Println(err)
	return
}
// 处理通知内容
fmt.Println(notifyReq.Summary)
fmt.Println(transaction.TransactionId)

将 SDK 未支持的回调消息体,解析至 map[string]interface{}

content := make(map[string]interface{})
notifyReq, err := handler.ParseNotifyRequest(context.Background(), request, &content)
// 如果验签未通过,或者解密失败
if err != nil {
	fmt.Println(err)
	return
}
// 处理通知内容
fmt.Println(notifyReq.Summary)
fmt.Println(content)

敏感信息加解密

为了保证通信过程中敏感信息字段(如用户的住址、银行卡号、手机号码等)的机密性,

  • 微信支付要求加密上行的敏感信息
  • 微信支付会加密下行的敏感信息

详见 接口规则 - 敏感信息加解密

(推荐)使用敏感信息加解密器

敏感信息加解密器 cipher.Cipher 能根据 API 契约自动处理敏感信息:

  • 发起请求时,开发者设置原文,加密器自动加密敏感信息,并设置 Wechatpay-Serial 请求头
  • 收到应答时,解密器自动解密敏感信息,开发者得到原文

使用敏感信息加解密器,只需通过 option.WithWechatPayCiphercore.Client 添加加解密器:

client, err := core.NewClient(
    context.Background(),
// 一次性设置 签名/验签/敏感字段加解密,并注册 平台证书下载器,自动定时获取最新的平台证书
    option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
    option.WithWechatPayCipher(
        encryptors.NewWechatPayEncryptor(downloader.MgrInstance().GetCertificateVisitor(mchID)),
        decryptors.NewWechatPayDecryptor(mchPrivateKey),
    ),
)

使用加解密算法工具包

步骤一:获取微信支付平台证书

请求的敏感信息,使用微信支付平台证书中的公钥加密。推荐 使用平台证书下载管理器 获取微信支付平台证书,或者 下载平台证书

步骤二:加解密

使用工具包 utils 中的函数,手动对敏感信息加解密。

package utils

// EncryptOAEPWithPublicKey 使用公钥加密
func EncryptOAEPWithPublicKey(message string, publicKey *rsa.PublicKey) (ciphertext string, err error)
// EncryptOAEPWithCertificate 使用证书中的公钥加密
func EncryptOAEPWithCertificate(message string, certificate *x509.Certificate) (ciphertext string, err error)

// DecryptOAEP 使用私钥解密
func DecryptOAEP(ciphertext string, privateKey *rsa.PrivateKey) (message string, err error)

rsa_crypto_test.go 中演示了如何使用以上函数做敏感信息加解密。

步骤三:设置 Wechatpay-Serial 请求头

请求的敏感信息加密后,在 HTTP 请求头中添加微信支付平台证书序列号 Wechatpay-Serial。该序列号用于告知微信支付加密使用的证书。

使用 core.ClientRequest 方法来传输自定义 HTTPHeader。

// Request 向微信支付发送请求
//
// 相比于 Get / Post / Put / Patch / Delete 方法,本方法支持设置更多内容
// 特别地,如果需要为当前请求设置 Header,应使用本方法
func (client *Client) Request(
	ctx context.Context,
	method, requestPath string,
	headerParams http.Header,
	queryParams url.Values,
	postBody interface{},
	contentType string,
) (result *APIResult, err error)

// 示例代码
// 微信支付平台证书序列号,对应加密使用的私钥
header.Add("Wechatpay-Serial", "5157F09EFDC096DE15EBE81A47057A72*******")
result, err := client.Request(
	ctx,
	"POST",
	"https://api.mch.weixin.qq.com/v3/profitsharing/receivers/add",
	header,
	nil,
	body,
	"application/json")

自定义签名生成器与验证器

当默认的本地签名和验签方式不适合你的系统时,实现 Signer 或者 Verifier 来定制签名和验签。

比如,你把商户私钥集中存储,业务系统通过远程调用获得请求签名。

// 签名器
type CustomSigner struct {
}

func (s *CustomSigner) Sign(ctx context.Context, message string) (*auth.SignatureResult, error) {
    // TODO: 远程调用获取签名信息
    return &auth.SignatureResult{MchID: "xxx", MchCertificateSerialNo: "xxx", Signature: "xxx"}, nil
}

// 校验器
type CustomVerifier struct {
}

func (v *CustomVerifier) Verify(ctx context.Context, serial, message, signature string) error {
    // TODO: 远程调用验签
    return nil
}

当你需要使用自定的签名器和校验器时,这样创建客户端

package core_test

import (
	"context"

	"path/to/your/custom_signer"
	"path/to/your/custom_verifier"

	"github.com/wechatpay-apiv3/wechatpay-go/core"
	"github.com/wechatpay-apiv3/wechatpay-go/core/auth/credentials"
	"github.com/wechatpay-apiv3/wechatpay-go/core/auth/validators"
	"github.com/wechatpay-apiv3/wechatpay-go/core/option"
)

func NewCustomClient(ctx context.Context, mchID string) (*core.Client, error) {
	signer := &custom_signer.CustomSigner{
		// ... 
	}
	verifier := &custom_verifier.CustomVerifier{
		// ...
	}

	opts := []core.ClientOption{
		option.WithSigner(signer),
		option.WithVerifier(verifier),
	}

	return core.NewClient(ctx, opts...)
}

常见问题

常见问题请见 FAQ.md

如何参与开发

微信支付欢迎来自社区的开发者贡献你们的想法和代码。请你在提交 PR 之前,先提一个对应的 issue 说明以下内容:

  • 背景(如,遇到的问题)和目的
  • 着重说明你的想法
  • 通过代码或者其他方式,简要的说明是如何实现的,或者它会是如何使用
  • 是否影响现有的接口

#35 是一个很好的参考。

测试

开发者提交的代码,应能通过本 SDK 所有的测试用例。

SDK 在单元测试中使用了 agiledragon/gomonkeystretchr/testify,测试前请确认相关的依赖。使用以下命令获取所有的依赖。

go get -t -v

由于 gomonkey 的原因,在执行测试用例时需要携带参数 -gcflags=all=-l。使用以下命令发起测试。

go test -gcflags=all=-l ./...

联系微信支付

如果你发现了 BUG,或者需要的功能还未支持,或者有任何疑问、建议,欢迎通过 issue 反馈。

也欢迎访问微信支付的 开发者社区

帮助微信支付改进 SDK

为了向广大开发者提供更好的使用体验,微信支付诚挚邀请您反馈使用微信支付 APIv3 SDK中的感受。 您的反馈将对改进 SDK 大有帮助,点击参与问卷调查

wechatpay-go's People

Contributors

a8520238 avatar alanfc666 avatar alexkie007 avatar bobbyz3g avatar bytechen avatar cadmusjiang avatar chaoyuxie avatar colindhlin avatar emmetzc avatar lddssxy avatar lianup avatar sexybear avatar shaojunda avatar tonytony2020 avatar v-jinyewang avatar whuwxl avatar xavierzho avatar xiaokang-chen avatar xy-peng avatar zhenyonghou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wechatpay-go's Issues

小提议:可否重新设计 auth.Validator?

  • Go 版本:1.16
  • wechatpay-go 版本:0.2.2

我在修复 notify/handler 的过程中发现有些坏味道代码,可能当初的设计是非常好的,只是加上 notify 后变得不那么合适了。
我个人感觉可以更新一下 Validator 的定义。
目前的定义是这样:

// Validator 应答报文验证器
type Validator interface {
	Validate(ctx context.Context, response *http.Response) error // 对 HTTP 应答报文进行验证
}

可否改为类似下面的 :

// Validator 验证器
type Validator interface {
	Validate(v Validatable) error {
}

// 可验证对象(表示业务上下文)
type Validatable interface {
	Verify(verifier auth.Verifier)
	// or
	GetVerifyArgs() (serialNo, message, sign string)
}

// 默认的验证器实现
type DefaultValidator struct {
	verifier auth.Verifier
}

func (dv *DefaultValidator) Validate(v Validatable) error {
	return  v.Verify(dv.verifier)
	// or
	serialNo, msg, sign := v.GetVerifyArgs()
	return dv.verifier.Verify(serialNo, msg, sign)
}

然后不同的业务上下文各自实现自己的 Validatable ,比如 http.Response 和 notify 就可以拆到各自的模块,互不相干。
两者在业务上确实也没啥关联,仅仅只是重用了一套验证逻辑(当然,也能重用一些小代码)。

如何调试沙箱环境

在这里请只反馈跟微信支付 Go 语言开发库 (wechatpay-go)的 bugfeature request

如果你在接入微信支付的过程中遇到了业务错误,推荐通过 腾讯客服自助服务专区 或者 微信支付在线技术支持 获取帮助,你也可以在微信开放社区的 开发者专区 反馈业务问题。

在反馈问题时,请提供你所使用的 Go 版本和 wechatpay-go 的版本,以及尽可能详细的日志和细节(如调用代码),以便于我们能更快的找到问题。
目前是不支持沙箱环境吗?

  • Go 版本:1.15
  • wechatpay-go 版本:v0.21

实例化client时,商户私钥应该如何配置

chPrivateKey *rsa.PrivateKey // 商户私钥
这个字段实在是不知道应该如何配置进行赋值,让您见笑了,我现在有
apiclient_key.pem, apiclient_cert.pem 两个文件,但是在代码中我实在是不知道如何实现这个字段
烦请告知如何赋值,感激不尽!

  • Go 版本:1.15
  • wechatpay-go 版本:0.25

client的实例初始化一定要证书么

微信支付的证书在文档说明里并不是太多的操作需要,可是在仓库的说明里初始化client又需要代入证书信息。
是v3的接口要求必须开通证书么?

你好

你好 我的返回的值了 但是类型是*payments.Transaction 这个我要怎么解析

notify.Handler 调用了GetBody函数,http server端拿到的request此函数值真是nil,文档也说明只有client端才能用此函数

在这里请只反馈跟微信支付 Go 语言开发库 (wechatpay-go)的 bugfeature request

如果你在接入微信支付的过程中遇到了业务错误,推荐通过 腾讯客服自助服务专区 或者 微信支付在线技术支持 获取帮助,你也可以在微信开放社区的 开发者专区 反馈业务问题。

在反馈问题时,请提供你所使用的 Go 版本和 wechatpay-go 的版本,以及尽可能详细的日志和细节(如调用代码),以便于我们能更快的找到问题。

  • Go 版本:1.16.3
  • wechatpay-go 版本:v0.2.2

WechatPayNotifyValidator Validate 传参建议

  • Go 版本:1.6.4
  • wechatpay-go 版本:v0.2.5

WechatPayNotifyValidatorValidate 直传*http.Request是不是太粗暴了 如果我用的别的 web 框架库将无法支持比如fasthttp 这个库内建了 Request 如果是需要取HTTP Header 可以构造个结构传递到方法内呀... 现在我只能将 Validate 内部方法提取出来重新实现一遍

调用jsapi返回报错如下

	resp, result, err := svc.Prepay(ctx,
		jsapi.PrepayRequest{
			Appid:       core.String(appId),
			Mchid:       core.String(mchId),
			Description: core.String(desc),
			OutTradeNo:  core.String(tradeNo),
			Attach:      core.String(attach),
			NotifyUrl:   core.String(notify),
			Amount: &jsapi.Amount{
				Total:    core.Int32(total),
				Currency: core.String("CNY"),
			},
			Payer: &jsapi.Payer{
				Openid: core.String(openId),
			},
		},
	)

prepay  validate verify fail serial=xxxxx    request-id=xxxxx-0 err=no serial number:xxxxxx    corresponding certificate  56111111787422951772160

服务商模式NewClient失败

服务商模式初始化客户端失败

信息都是正确的,特约商户模式可以。服务商模式就异常。

"init client setting err:decrypt downloaded certificate failed: crypto/aes: invalid key size 0"

  • Go 版本:go version go1.16.3 darwin/amd64
  • wechatpay-go 版本:0.2.5

v3沙箱可以通过改sandboxnew实现吗

尝试fork和更改const的url,后缀加上 "/sandboxnew"
但是初始化client报错, Prepay也显示serialize错误

问题:

  1. 是v3版本现在不支持sandbox吗,什么时候能支持呢

  2. 如果只是golang sdk还未提供支持,换一种语言的sdk能否解决?

Enum类型 UnmarshalJSON 的潜在不可兼容问题

目前model中的 Enum 类型自定义了 UnmarshalJSON 方法,会对应答中的 enum 值进行检查。这种检查会在服务增加枚举值时导致不兼容问题,如果商户不进行SDK升级会导致应答反序列化(Unmarshal)失败。
建议移除该检查。

  • Go 版本:any
  • wechatpay-go 版本:v0.2.5

Tag包和Master包的请求地址不一致

在本地debug时,发现v0.2.6中调用始终会出现以下错误:
call Prepay err:error http response:[StatusCode: 400 Code: "PARAM_ERROR"
Message: 输入源“/body/appid”映射到字段“公众号ID”必填性规则校验失败,此字段为必填项
Detail:
{
"location": "body",
"value": ""
}
Header:

  • Server=[nginx]
  • Keep-Alive=[timeout=8]
  • Wechatpay-Nonce=[aa5373a8719bd1d99cb13c8061bfbcda]
  • Wechatpay-Serial=[75F61B74B4D16B45E920861D4194BF27CB1425C6]
  • Date=[Sat, 18 Sep 2021 06:39:01 GMT]
  • Connection=[keep-alive]
  • Cache-Control=[no-cache, must-revalidate]
  • Request-Id=[088593968A0610EB0418E2A6E44820A62128956F-268435461]
  • Wechatpay-Timestamp=[1631947141]
  • Content-Type=[application/json; charset=utf-8]
  • Content-Length=[184]
  • Wechatpay-Signature=[FP/wZjL4EGROq9z2xT1Fpprus8/+SJ5+LvbhmkHBpMkeGUA+7DPWvlOYcdEAj96p7+RCxtBxiut7t01zbBvLL7JwX8GYkLheg3xGHOLDqxmqU/BOsfgIuSriA3FufNLe3C5JJhfbD5I5CvXzqlZnsiowDokrAaoz94JA6hqm56l09lpyKO6x9mlxc/0RKQeV6bUqb2PWhazT205iPqly1X57uUWgktixYgXFJIgrbmX1Co50fXTB6x9a9NdBA0O4z99j+1ZZJyMC9qCbDu0zB+nxFQVyI3pE61XSEsBU1tQPHNa0ILaksxH60BbUj3NFZ0t0PztCTsPhZsx5Qyc6IA==]
  • X-Content-Type-Options=[nosniff]
  • Content-Language=[zh-CN]]

然后用git clone拉下代码使用Master包调用就能正常使用,最后对比v0.2.6与Master包代码发现:wechatpay-go/services/partnerpayments/jsapi/api_jsapi.go:83两者路径出现差异一下为具体路径:
Master: localVarPath := consts.WechatPayAPIServer + "/v3/pay/partner/transactions/jsapi"
v0.2.6: localVarPath := consts.WechatPayAPIServer + "/v3/pay/transactions/jsapi"

请求是否为两者路径差异导致的这个错误?已经对比过两次调用的入参完全一致。

verify fail serial

在这里请只反馈跟微信支付 Go 语言开发库 (wechatpay-go)的 bugfeature request

如果你在接入微信支付的过程中遇到了业务错误,推荐通过 腾讯客服自助服务专区 或者 微信支付在线技术支持 获取帮助,你也可以在微信开放社区的 开发者专区 反馈业务问题。

在反馈问题时,请提供你所使用的 Go 版本和 wechatpay-go 的版本,以及尽可能详细的日志和细节(如调用代码),以便于我们能更快的找到问题。

  • Go 版本:
    go version go1.15.4 darwin/amd64
  • wechatpay-go 版本:
    github.com/wechatpay-apiv3/wechatpay-go v0.2.0

this issues like:
https://developers.weixin.qq.com/community/pay/doc/000a462c1a870000af0c814f157000

支付回调提示not valid wechatpay notify

用户在支付以后,回调接口报错

2021-08-26T07:44:46.190+0800	�[34mINFO�[0m	rest/user.go:208	resp:&{FAIL not valid wechatpay notify request: validate verify fail serial=[62602949721CAEC38677A4170A80C97DDB5A580C] request-id=[] err=certificate[62602949721CAEC38677A4170A80C97DDB5A580C] not found in verifier}

这是我回调函数的代码

	certPath := zconfig.GetString("weixin.cert")

	cert, err := utils.LoadCertificateWithPath(certPath)
	if err != nil {
		return nil, err
	}

	apiV3Key := zconfig.GetString("weixin.apiv3Key")

	handler := notify.NewNotifyHandler(apiV3Key, verifiers.NewSHA256WithRSAVerifier(core.NewCertificateMapWithList([]*x509.Certificate{cert})))

	content := new(contentType)

	notifyReq, err := handler.ParseNotifyRequest(ctx, req, content)

我看一下一下serial的值,这个62602949721CAEC38677A4170A80C97DDB5A580C跟证书申请的时候证书序列号并不一样,头部拿到值,与支付平台提供的证书序列号的值并不一致。

  • Go 版本:1.16
  • wechatpay-go 版本:v0.2.5

希望增加转账和分账接口

非常需要两个接口:

  1. 转账到微信零钱(用于提现)
  2. 服务商分账

希望有排期时间的告知,如果没有,只能用老版本了

【官方调查问卷】微信支付 API v3 Go SDK 开发者体验调查

为了向广大开发者提供更好的使用体验,微信支付诚挚邀请您将使用微信支付 API v3 SDK中的感受反馈给我们。本问卷可能会占用您不超过2分钟的时间,感谢您的支持。

问卷系统使用的腾讯问卷,您可以点击这里,或者扫描以下二维码参与调查。

qrcode

堂堂微信支付,为何SDK如此之烂?

你们瞧瞧自己写的 sdk ,shi 一样的代码,你们就不能封装的好点吗?
拿完 KPI 之后,项目就没人管了么?
你要么就别做,留这么烂的代码,shi 一样的说明文档,让人怎么用?

小程序微信支付结果通知未返回所需的 request-id

微信通知header如下

{
  host: '127.0.0.1:8099',
  connection: 'close',
  'content-length': '915',
  'wechatpay-nonce': 'zz0Hx4BPQJ5M6vmHfveBOuTABJVjLjE6',
  'wechatpay-serial': '5854C75E7AD35B656A1C9B3E20700A0323D5BC8F',
  'content-type': 'application/json',
  'wechatpay-signature': 'K8BNkGoGkzfvQ5n26NHzoj267CAHVDltBP6uGB8R5iU3sQSkDooKp9/yBxtlrXkfyvnrY6DBjBJbUcMuj4yEXuNuDDNcU2k5cMyjISI3aP9A+7fn8qS/pY2s8ZD0c0Noy0/Zs4p7TVawjIOwCivmgFp3D0sGRgMUfQU0yM/fKfjvb72v/8utE83xaBciwDzoGizI7EjsioFQB7T9kJpu9apV4dFBsfxxiULOhZvLYuqrtp9PJaUQbQdRHnipJHhiERwx26i7Xv940NFCm0xIwy2asl6/JZm98+gOFFwbfpj6BAJUgsArRZcTM15PHlvTRZXB737MTHHpM8jUh3KNKA==',
  'wechatpay-timestamp': '1625638767',
  pragma: 'no-cache',
  'user-agent': 'Mozilla/4.0',
  accept: '*/*'
}

微信通知body如下

{
  id: 'f994ecf7-60a3-537e-85d1-7dad28f7bfe8',
  create_time: '2021-07-07T14:19:27+08:00',
  resource_type: 'encrypt-resource',
  event_type: 'TRANSACTION.SUCCESS',
  summary: '支付成功',
  resource: {
    original_type: 'transaction',
    algorithm: 'AEAD_AES_256_GCM',
    ciphertext: 'ZetL1s9e/3nhpfCdyLEKobHv9JpPYmZJb9H2VglLoRo+IH+I8OgkzisraaH6oca/yKNGw67z8FQvakGO2M2K329ef4jvGymPXehFjHJNW8cOGH7xlrEbsj7Pg79P1dA1lXXXte6IJcTfHZLLpohUbqNFq5MTKCFZP4tjZcdU4izis7YNkQyUM1nSbS+ia0kg9AOy7rmN7nyFQ+UNeWU5nHHa5j7QDwp32DHzHyZHTY4GgWHqJ2NK4NI42o8IbDeHsraBodFItDMI/kd4NFYry38cFcfSSAN23CopHetud/Wog/8x4ufA3+2G2DW5ogbsVWUVUaPc5n5vZxRRpO/DulXlfEnnD0Bw7whxd2ZjB3T6uWPHqpfgnadjgmj+KydZBqbuL5tEUeC/wody2+G0uCAqGUF/an1LBwpZeGKg2UOmN9CJ7XFGXM5e4Dnh2Fgu/lUDiWd/okkrLhbkjePiMkTHUuc7RNBFg09saa1CmsaPNWeqIv3GuKumhh6D/zruEfy7NFPo183v/7S2yfnHla08tzYA1273WYVrxMN/Z7qiS9Tv71RuRJqaLKm4ShCa/5DxfgRVlA==',
    associated_data: 'transaction',
    nonce: 'uGIie22uk1w9'
  }
}

调用通知回调错误如下

not valid wechatpay notify request: validate verify fail serial=5854C75E7AD35B656A1C9B3E20700A0323D5BC8F request-id=5d781374-9d73-381a-8851-673de8004cbb err=certificate[5854C75E7AD35B656A1C9B3E20700A0323D5BC8F] not found in verifier

商户批量付款至用户零钱中的Demo不完善

TransferDetailList: []transferbatch.TransferDetailInput{transferbatch.TransferDetailInput{
  Openid:         core.String("o-MYE42l80oelYMDE34nYD456Xoy"),
  OutDetailNo:    core.String("x23zy545Bd5436"),
  TransferAmount: core.Int64(200000),
  TransferRemark: core.String("2020年4月报销"),
  UserIdCard:     nil,
  UserName:       nil,
}},

其中UserName和UserIdCard如何加密并赋值,可以给出示例吗

升级2.0时mod tidy错误

  • Go 版本:

go version go1.16.3 windows/amd64

  • wechatpay-go 版本:

go get -u

main imports
        github.com/wechatpay-apiv3/wechatpay-go/core/option: cannot find module providing package github.com/wechatpay-apiv3/wechatpay-go/core/option

手动改go.mod后
github.com/wechatpay-apiv3/wechatpay-go v0.2.0

go mod tidy

go: finding module for package github.com/wechatpay-apiv3/wechatpay-go/core/option
main imports
        github.com/wechatpay-apiv3/wechatpay-go/core/option: module github.com/wechatpay-apiv3/wechatpay-go@latest found (v0.2.0), but does not contain package github.com/wechatpay-apiv3/wechatpay-go/core/option

是否有计划支持服务商模式

  • Go 版本:1.64
  • wechatpay-go 版本:v0.2.3

想咨询下golang版本是否有计划支持服务商模式,现在的sdk看起来只支持直充模式,如果支持未来排期大概是什么样子的?

关于 微信支付退款的通知 NotifyUrl

我请问 我通过 refunddomestic 可以申请退款了, 可是我准备使用NotifyUrl ,接收退款通知的时候, 发现好像, 没有相关的解析模块。
另外, 我通过 支付模块 获取的 NotifyUrl 是通知一次的, 可是 我的退款NotifyUrl 接口的 是不断重复的。 是不是 支付模块的通知包里面有反馈 说已接受到通知, 可以不用在重复发送了。 而没有退款模块并且我只是简单打印了一下 ,故在不断发送给我?

  • Go 版本:最新
  • wechatpay-go 版本: 最新

validate verify fail

调用client.Post方法返回错误
validate verify fail serial=3BA696623B16A8D204DAC4EBFDA4703C7A89EEDB request-id=08E78DE5830610CB0718C2B8B74C20C55128C68803-0 err=no serial number:3BA696623B16A8D204DAC4EBFDA4703C7A89EEDB corresponding certificate
虽然显示了错误信息,但是也正常返回了相应结果

func main() {
	// 增加客户端配置
	opts := []option.ClientOption{
		option.WithMerchant(mchID, certificateSerialNumber, privateKey), // 设置商户信息,用于生成签名信息
		option.WithWechatPay(wechatPayCertificateList),                  // 设置微信支付平台证书信息,对回包进行校验
		option.WithHTTPClient(&http.Client{}),                           // 可以不设置
		option.WithTimeout(2 * time.Second),                             // 自行进行超时时间配置
		option.WithHeader(&http.Header{}),                               // 可以自行设置Header
	}
	client, err := core.NewClient(ctx, opts...)
	if err != nil {
		log.Printf("new wechat pay client err:%s", err.Error())
		return
	}
	// 后面可以开始写你的逻辑
	nm := NativePayModel{
		Appid:       "wx347d8b996e0b2d71",
		Mchid:       mchID,
		Description: "测试商品-2021-04-16",
		OutTradeNo:  gconv.String(gtime.Now().UnixNano()),
		NotifyUrl:   "http://api.hcyjk.com/apiv1/notify",
		Amount:      AmountModel{
			Total: 100,
		},
	}
	_response, _err := client.Post(ctx, "https://api.mch.weixin.qq.com/v3/pay/transactions/native", nm)
	if _err != nil {
		fmt.Println(fmt.Sprintf("请求出错,%s\n", _err.Error()))
	}

	fmt.Println("请求完成")
	if body, err := ioutil.ReadAll(_response.Body); err != nil{
		fmt.Println(err.Error())
	} else {
		fmt.Println(string(body))
	}
}

自定义 Downloader 使用的 Client

在使用 WithWechatPayAutoAuthCipher 创建 core.Client 时,会自动在 MgrInstance() 中新增一个 Downloader(如果不存在该商户的Downloader的话)。

这个Downloader是独立新建了一个 core.Client,这个时候如果开发者想要自定义 Downloader 使用的 core.Client(一般情况下是希望自定义其使用的 http.Client),就需要再次调用 MgrInstance().RegisterDownloader 方法重新注册一次 Downloader

这个过程很不友好,而且需要对SDK有充分的了解才会知道应该这么做。

需要有办法让这个过程,至少是「知道应该怎么做」的过程,更加清楚。

使用示例的demo无法初始化client

使用例子中的代码无法初始化client
{"file":"/Users/apple/business/kuzi-app/common/weixinPay/weixin_pay_client.go:64","func":"kuzi/app/common/weixinPay.NewWeixinPayClient","level":"error","msg":"new wechat pay client err:init client setting err:generate authorization err:you must set privatekey to use SHA256WithRSASigner","time":"2021-09-02T09:09:29+08:00"}

`import (
"context"
"crypto/rsa"
"net/http"

//"kuzi/app/app/common"
"kuzi/app/configs"

"github.com/sirupsen/logrus"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/utils"

)

var weixinPayClient *core.Client

// 示例参数,实际使用时请自行初始化
var (
mchID string // 商户号
mchCertificateSerialNumber string // 商户证书序列号
mchPrivateKey *rsa.PrivateKey // 商户私钥
mchAPIv3Key string // 商户APIv3密钥
customHTTPClient *http.Client // 可选,自定义客户端实例
)

func InitWeixinPayClient() {
mchID = configs.AppConfig.Weixin.MchId
mchCertificateSerialNumber = configs.AppConfig.Weixin.MchCertificateSerialNumber
mchPrivateKey = GetPrivateKey()
mchAPIv3Key = configs.AppConfig.Weixin.MchAPIv3Key
weixinPayClient = NewWeixinPayClient()

}

//获取商户私钥
func GetPrivateKey() *rsa.PrivateKey {
// 加载商户私钥
privateKeyPath := configs.AppConfig.Weixin.MchPrivateKeyPath
privateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath)

if err != nil {
	logrus.Errorf("load private err:%s", err.Error())
	return nil
}

return privateKey

}

func NewWeixinPayClient() *core.Client {
ctx := context.Background()
opts := []core.ClientOption{
// 一次性设置 签名/验签/敏感字段加解密,并注册 平台证书下载器,自动定时获取最新的平台证书
option.WithWechatPayAutoAuthCipher(mchID, mchCertificateSerialNumber, mchPrivateKey, mchAPIv3Key),
// 设置自定义 HTTPClient 实例,不设置时默认使用 http.Client{},并设置超时时间为 30s
//option.WithHTTPClient(customHTTPClient),
}
client, err := core.NewClient(ctx, opts...)
if err != nil {
logrus.Errorf("new wechat pay client err:%s", err.Error())
return nil
}
return client
}`

  • Go 版本:
  • wechatpay-go 版本:0.2.6

缺少MD5签名方法

目前在 wechatpay-apiv3/wechatpay-go/blob/main/utils/sign.go
有个RSA 的签名方法,但是原生app需要 MD5 的签名方法 希望能给加上

[QUESTION] 有哪些组件是协程安全的?

  • Go 版本: go version go1.16.4 linux/amd64
  • wechatpay-go 版本: v0.2.5

README里面介绍:

  • core.Client初始化完成后,可以在多个goroutine中并发使用。
    微信图片_20210818160100

还有哪些组件是协程安全的呢?比如可以在不同的协程里面安全使用同一个 notify.Handler 么?

使用七牛代理后无法go get

使用七牛国内代理后 无法拉取代码

GOPROXY="http://goproxy.cn" # go env 代理配置
go get github.com/wechatpay-apiv3/wechatpay-go v0.2.6 官方命令 如果不指定版本号那么默认拉取的是2.5版本

指定版本号则会出现404情况,还望告知如何获取最新0.26版本

  • Go 版本:go version go1.15 darwin/amd64
  • wechatpay-go 版本:v3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.