瀏覽代碼

update wepay API v3

ls 2 周之前
父節點
當前提交
a719095ae3
共有 2 個文件被更改,包括 252 次插入0 次删除
  1. 79 0
      wechat/pay_v3.go
  2. 173 0
      wechat/structure_v3.go

+ 79 - 0
wechat/pay_v3.go

@@ -1 +1,80 @@
 package wechat
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"encoding/base64"
+	"encoding/json"
+	"strings"
+
+	"git.chuangxin1.com/cx/myth/util"
+)
+
+// DecryptAES256GCM 使用 AEAD_AES_256_GCM 算法进行解密
+func DecryptAES256GCM(aesKey, associatedData, nonce, ciphertext string) (dataBytes []byte, err error) {
+	var (
+		decodedCiphertext []byte
+		c                 cipher.Block
+		gcm               cipher.AEAD
+	)
+	decodedCiphertext, err = base64.StdEncoding.DecodeString(ciphertext)
+	if err != nil {
+		return
+	}
+	c, err = aes.NewCipher([]byte(aesKey))
+	if err != nil {
+		return
+	}
+	gcm, err = cipher.NewGCM(c)
+	if err != nil {
+		return
+	}
+	dataBytes, err = gcm.Open(nil, []byte(nonce), decodedCiphertext, []byte(associatedData))
+	return
+}
+
+// Unmarshal 解析结构
+func (r *PayResultNotifyV3) Unmarshal(body []byte) (err error) {
+	err = json.Unmarshal(body, &r)
+	return
+}
+
+// IsEntranceStateChange 是否微信支付分停车 状态变更通知
+func (r *PayResultNotifyV3) IsEntranceStateChange() bool {
+	return strings.Compare(r.EventType, "VEHICLE.ENTRANCE_STATE_CHANGE") == 0
+}
+
+// IsTransactionSuccess 是否支付到账通知
+func (r *PayResultNotifyV3) IsTransactionSuccess() bool {
+	return strings.Compare(r.EventType, "TRANSACTION.SUCCESS") == 0
+}
+
+// IsTradeSuccess 是否支付成功
+func (r *PayOrderInfoV3) IsTradeSuccess() bool {
+	return strings.Compare(r.TradeState, "SUCCESS") == 0
+}
+
+// Unmarshal 解析结构
+func (r *PayScoreParkingNotifyV3Result) Unmarshal(body []byte) (err error) {
+	err = json.Unmarshal(body, &r)
+	return
+}
+
+// Unmarshal 解析结构
+func (r *PayScoreParkingNotifyV3Result) String() (s string) {
+	bs, _ := json.Marshal(r)
+	s = util.BytesToString(bs)
+	return
+}
+
+// Unmarshal 解析结构
+func (r *PayRefundInfoV3) Unmarshal(body []byte) (err error) {
+	err = json.Unmarshal(body, &r)
+	return
+}
+
+// Unmarshal 解析结构
+func (r *PayOrderInfoV3) Unmarshal(body []byte) (err error) {
+	err = json.Unmarshal(body, &r)
+	return
+}

+ 173 - 0
wechat/structure_v3.go

@@ -1,5 +1,7 @@
 package wechat
 
+import "time"
+
 /* ******************************************
 	HTTP Status code
 
@@ -29,3 +31,174 @@ type WepayResponseMessageV3 struct {
 	Message string              `json:"message"`
 	Detail  WepayResponseDetail `json:"detail"`
 }
+
+// PayResultNotifyV3Resource 微信支付 V3 支付通知 resource 数据结构
+type PayResultNotifyV3Resource struct {
+	// 原始类型 原始回调类型,为transaction
+	OriginalType string `json:"original_type"`
+	// 加密算法类型 对开启结果数据进行加密的加密算法,目前只支持AEAD_AES_256_GCM
+	Algorithm string `json:"algorithm"`
+	// 数据密文 Base64编码后的开启/停用结果数据密文
+	Ciphertext string `json:"ciphertext"`
+	// 附加数据
+	AssociatedData string `json:"associated_data"`
+	// 随机串 加密使用的随机串
+	Nonce string `json:"nonce"`
+}
+
+// PayResultNotifyV3 微信支付 V3 支付通知数据结构
+type PayResultNotifyV3 struct {
+	// 通知ID
+	ID string `json:"id"`
+	// 通知创建的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
+	CreateTime time.Time `json:"create_time"`
+	// 知的资源数据类型,支付成功通知为encrypt-resource
+	ResourceType string `json:"resource_type"`
+	// 通知的类型,支付成功通知的类型为TRANSACTION.SUCCESS 通
+	EventType string `json:"event_type"`
+	// 回调摘要 示例值:支付成功
+	Summary string `json:"summary"`
+	// 通知资源数据
+	Resource PayResultNotifyV3Resource `json:"resource"`
+}
+
+// PayOrderPayerV3 微信支付 V3 支付订单支付人信息
+type PayOrderPayerV3 struct {
+	// OpenID 用户标识 用户在直连商户appid下的唯一标识
+	OpenID string `json:"openid"`
+}
+
+// PayOrderAmountV3 微信支付 V3 支付订单支金额信息
+type PayOrderAmountV3 struct {
+	// Total 总金额 订单总金额,单位为分
+	Total int `json:"total"`
+	// PayerTotal 用户支付金额 用户支付金额,单位为分。(指使用优惠券的情况下,这里等于总金额-优惠券金额)
+	PayerTotal int `json:"payer_total"`
+	// Currency 货币类型 CNY:人民币,境内商户号仅支持人民币
+	Currency string `json:"currency"`
+	// PayerCurrency 用户支付币种
+	PayerCurrency string `json:"payer_currency"`
+}
+
+// PayOrderInfoV3 微信支付 V3 支付订单信息
+type PayOrderInfoV3 struct {
+	// MchID 直连商户号 直连商户的商户号,由微信支付生成并下发
+	MchID string `json:"mchid"`
+	// AppID 应用ID 直连商户申请的公众号或移动应用appid
+	AppID string `json:"appid"`
+	// OutTradeNo 商户订单号 户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
+	OutTradeNo string `json:"out_trade_no"`
+	// TransactionID 微信支付订单号 微信支付系统生成的订单号
+	TransactionID string `json:"transaction_id"`
+	// TradeType 交易类型 枚举值:
+	//  JSAPI:公众号支付
+	//  NATIVE:扫码支付
+	//  APP:APP支付
+	//  MICROPAY:付款码支付
+	//  MWEB:H5支付
+	//  FACEPAY:刷脸支付
+	TradeType string `json:"trade_type"`
+	// TradeState 交易状态 枚举值:
+	//  SUCCESS:支付成功
+	//  REFUND:转入退款
+	//  NOTPAY:未支付
+	//  CLOSED:已关闭
+	//  REVOKED:已撤销(仅付款码支付会返回)
+	//  USERPAYING:用户支付中(仅付款码支付会返回)
+	//  PAYERROR:支付失败(仅付款码支付会返回)
+	TradeState string `json:"trade_state"`
+	// TradeStateDesc 交易状态描述
+	TradeStateDesc string `json:"trade_state_desc"`
+	// BankType 付款银行 银行类型,采用字符串类型的银行标识
+	BankType string `json:"bank_type"`
+	// Attach 附加数据 在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段
+	Attach string `json:"attach"`
+	// SuccessTime 支付完成时间 支付完成时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE
+	SuccessTime time.Time `json:"success_time"`
+	// Payer 支付者信息
+	Payer PayOrderPayerV3 `json:"payer"`
+	// Amount 订单金额信息,当支付成功时返回该字段
+	Amount PayOrderAmountV3 `json:"amount"`
+}
+
+// PayRefundAmountV3 微信支付 V3 退款订单支金额信息
+type PayRefundAmountV3 struct {
+	// Total 总金额 订单总金额,单位为分
+	Total int `json:"total"`
+	// Refund 退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额,如果有使用券,后台会按比例退。
+	Refund int `json:"refund"`
+	// PayerTotal 用户支付金额 用户实际支付金额,单位为分,只能为整数
+	PayerTotal int `json:"payer_total"`
+	// PayerRefund 用户退款金额 退款给用户的金额,不包含所有优惠券金额
+	PayerRefund int `json:"payer_refund"`
+}
+
+// PayRefundInfoV3 微信支付 V3 退款通知订单信息
+type PayRefundInfoV3 struct {
+	// MchID 直连商户号 直连商户的商户号,由微信支付生成并下发
+	MchID string `json:"mchid"`
+	// 商户订单号
+	OutTradeNo string `json:"out_trade_no"`
+	// 微信支付订单号
+	TransactionID string `json:"transaction_id"`
+	// 商户退款单号
+	OutRefundNo string `json:"out_refund_no"`
+	// 微信支付退款单号
+	RefundID string `json:"refund_id"`
+	// 退款状态,枚举值:
+	//    SUCCESS:退款成功
+	//    CLOSED:退款关闭
+	//    ABNORMAL:退款异常
+	RefundStatus string `json:"refund_status"`
+	// 退款成功时间
+	//   1、退款成功时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
+	//    2、当退款状态为退款成功时返回此参数
+	SuccessTime string `json:"success_time"`
+	// 退款入账账户 取当前退款单的退款入账方。
+	//    1、退回银行卡:{银行名称}{卡类型}{卡尾号}
+	//    2、退回支付用户零钱: 支付用户零钱
+	//    3、退还商户: 商户基本账户、商户结算银行账户
+	//    4、退回支付用户零钱通:支付用户零钱通
+	UserReceivedAccount string `json:"user_received_account"`
+	// 金额信息
+	Amount PayRefundAmountV3 `json:"amount"`
+}
+
+// PayScoreParkingNotifyV3Result 微信支付分停车 状态变更通知
+type PayScoreParkingNotifyV3Result struct {
+	// 调用接口提交的商户号
+	MchID string `json:"sp_mchid"`
+	// 调用接口提交的子商户号
+	SubMchID string `json:"sub_mchid"`
+	// 车主服务为商户分配的入场ID
+	ParkingID string `json:"parking_id"`
+	// 商户侧入场标识ID,在同一个商户号下唯一
+	OutParkingNo string `json:"out_parking_no"`
+	// 车牌号,仅包括省份+车牌,不包括特殊字符。
+	PlateNumber string `json:"plate_number"`
+	// 车牌颜色,枚举值:
+	//  BLUE:蓝色
+	//  GREEN:绿色
+	//  YELLOW:黄色
+	//  BLACK:黑色
+	//  WHITE:白色
+	//  LIMEGREEN:黄绿色
+	PlateColor string `json:"plate_color"`
+	// 入场时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
+	StartTime time.Time `json:"start_time"`
+	// 所在停车位车场的名称
+	ParkingName string `json:"parking_name"`
+	// 停车场的免费停车时长
+	FreeDuration int `json:"free_duration"`
+	// 本次入场车牌的服务状态
+	//  NORMAL:正常状态,可以使用车主服务
+	//  BLOCKED:不可用状态,暂时不可以使用车主服务
+	ParkingState string `json:"parking_state"`
+	// 不可用服务状态描述,返回车牌状态为BLOCKED,会返回该字段,描述具体BLOCKED的原因,
+	//  PAUSE:已暂停车主服务;
+	//  OVERDUE:已授权签约但欠费,不能提供服务,商户提示用户进行还款,
+	//  REMOVE:用户移除车牌导致车牌不可用。请跳转到授权/开通接口。
+	BlockedStateDescription string `json:"blocked_state_description"`
+	// 状态变更的发生时间(毫秒级),遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
+	StateUpdateTime time.Time `json:"state_update_time"`
+}