diff --git a/alipay_client.go b/alipay_client.go index 287ccbf3..b46bfbd5 100644 --- a/alipay_client.go +++ b/alipay_client.go @@ -207,7 +207,7 @@ func (a *AliPayClient) AliPayTradePageRefund(body BodyMap) (aliRsp *AliPayTradeP // alipay.trade.precreate(统一收单线下交易预创建) // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.precreate -func (a *AliPayClient) AliPayTradePrecreate(body BodyMap) (aliRsp *AlipayTradePrecreateResponse, err error) { +func (a *AliPayClient) AliPayTradePrecreate(body BodyMap) (aliRsp *AliPayTradePrecreateResponse, err error) { var bs []byte if body.Get("out_trade_no") == null { return nil, errors.New("out_trade_no is not allowed to be null") @@ -215,7 +215,7 @@ func (a *AliPayClient) AliPayTradePrecreate(body BodyMap) (aliRsp *AlipayTradePr if bs, err = a.doAliPay(body, "alipay.trade.precreate"); err != nil { return } - aliRsp = new(AlipayTradePrecreateResponse) + aliRsp = new(AliPayTradePrecreateResponse) if err = json.Unmarshal(bs, aliRsp); err != nil { return nil, err } @@ -319,7 +319,7 @@ func (a *AliPayClient) AliPayTradePagePay(body BodyMap) (payUrl string, err erro // alipay.fund.trans.toaccount.transfer(单笔转账到支付宝账户接口) // 文档地址:https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer -func (a *AliPayClient) AlipayFundTransToaccountTransfer(body BodyMap) (aliRsp *AlipayFundTransToaccountTransferResponse, err error) { +func (a *AliPayClient) AliPayFundTransToaccountTransfer(body BodyMap) (aliRsp *AliPayFundTransToaccountTransferResponse, err error) { var bs []byte if body.Get("out_biz_no") == null { return nil, errors.New("out_biz_no is not allowed to be null") @@ -327,7 +327,7 @@ func (a *AliPayClient) AlipayFundTransToaccountTransfer(body BodyMap) (aliRsp *A if bs, err = a.doAliPay(body, "alipay.fund.trans.toaccount.transfer"); err != nil { return } - aliRsp = new(AlipayFundTransToaccountTransferResponse) + aliRsp = new(AliPayFundTransToaccountTransferResponse) if err = json.Unmarshal(bs, aliRsp); err != nil { return nil, err } @@ -373,12 +373,12 @@ func (a *AliPayClient) AliPaySystemOauthToken(body BodyMap) (aliRsp *AliPaySyste // alipay.user.info.share(支付宝会员授权信息查询接口) // body:此接口无需body参数 // 文档地址:https://docs.open.alipay.com/api_2/alipay.user.info.share -func (a *AliPayClient) AlipayUserInfoShare() (aliRsp *AlipayUserInfoShareResponse, err error) { +func (a *AliPayClient) AliPayUserInfoShare() (aliRsp *AliPayUserInfoShareResponse, err error) { var bs []byte if bs, err = a.doAliPay(nil, "alipay.user.info.share"); err != nil { return nil, err } - aliRsp = new(AlipayUserInfoShareResponse) + aliRsp = new(AliPayUserInfoShareResponse) if err = json.Unmarshal(bs, aliRsp); err != nil { return nil, err } diff --git a/alipay_client_test.go b/alipay_client_test.go index ddbdf417..94bafdd0 100644 --- a/alipay_client_test.go +++ b/alipay_client_test.go @@ -30,8 +30,13 @@ func TestJsonToString(t *testing.T) { } type People struct { - Name string `json:"name"` - Age int `json:"age"` + Name string `json:"name,omitempty"` + Age int `json:"age,omitempty"` + List []*struct { + Address string `json:"address,omitempty"` + Age int `json:"age,omitempty"` + Phone string `json:"phone,omitempty"` + } `json:"list,omitempty"` } func TestAliPayParams(t *testing.T) { @@ -48,7 +53,7 @@ func TestAliPayParams(t *testing.T) { fmt.Println("result:", bodyMap.Get("people")) } -func TestVerifyAliPaySign(t *testing.T) { +func TestSyncVerifyAliPaySign(t *testing.T) { signData := `{"code":"10000","msg":"Success","buyer_logon_id":"854***@qq.com","buyer_pay_amount":"0.01","buyer_user_id":"2088102363632794","fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"gmt_payment":"2019-08-29 20:14:05","invoice_amount":"0.01","out_trade_no":"GZ201901301040361012","point_amount":"0.00","receipt_amount":"0.01","total_amount":"0.01","trade_no":"2019082922001432790585537960"}` sign := "bk3SzX0CZRI811IJioS2XKQHcgMixUT8mYyGQj+vcOAQas7GIYi6LpykqqSc3m7+yvqoG0TdX/c2JjYnpw/J53JxtC2IC4vsLuIPIgghVo5qafsfSxEJ22w20RZDatI2dYqFVcj8Jp+4aesQ8zMMNw7cX9NLyk7kw3DecYeyQp+zrZMueZPqLh88Z+54G+e6QuSU++0ouqQVd4PkpPqy6YI+8MdMUX4Ve0jOQxMmYH8BC6n5ZsTH/uEaLEtzYVZdSw/xdSQ7K1SH73aEH8XbRYx6rL7RkKksrdvhezX+ThDjQ+fTWjvNFrGcg3fmqXRy2elvoalu+BQmqlkWWjEJYA==" aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp8gueNlkbiDidz6FBQEBpqoRgH8h7JtsPtYW0nzAqy1MME4mFnDSMfSKlreUomS3a55gmBopL1eF4/Km/dEnaL5tCY9+24SKn1D4iyls+lvz/ZjvUjVwxoUYBh8kkcxMZSDeDz8//o+9qZTrICVP2a4sBB8T0XmU4gxfw8FsmtoomBH1nLk3AO7wgRN2a3+SRSAmxrhIGDmF1lljSlhY32eJpJ2TZQKaWNW+7yDBU/0Wt3kQVY84vr14yYagnSCiIfqyVFqePayRtmVJDr5qvSXr51tdqs2zKZCu+26X7JAF4BSsaq4gmY5DmDTm4TohCnBduI1+bPGD+igVmtl05wIDAQAB" @@ -59,6 +64,37 @@ func TestVerifyAliPaySign(t *testing.T) { } } +func TestVerifyAliPaySign(t *testing.T) { + // 测试,假数据,无法验签通过 + bm := make(BodyMap) + bm.Set("sign", "kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=") + bm.Set("sign_type", "RSA2") + bm.Set("total_amount", "2.00") + bm.Set("buyer_id", "2088102116773037") + bm.Set("body", "大乐透2.1") + bm.Set("trade_no", "2016071921001003030200089909") + bm.Set("refund_fee", "0.00") + bm.Set("notify_time", "2016-07-19 14:10:49") + bm.Set("subject", "大乐透2.1") + bm.Set("charset", "utf-8") + bm.Set("notify_type", "trade_status_sync") + bm.Set("out_trade_no", "0719141034-6418") + bm.Set("gmt_close", "2016-07-19 14:10:46") + bm.Set("gmt_payment", "2016-07-19 14:10:47") + bm.Set("trade_status", "TRADE_SUCCESS") + bm.Set("version", "1.0") + bm.Set("gmt_create", "2016-07-19 14:10:44") + bm.Set("app_id", "2015102700040153") + bm.Set("seller_id", "2088102119685838") + bm.Set("notify_id", "4a91b7a78a503640467525113fb7d8bg8e") + + ok, err := VerifyAliPaySign("aliPayPublicKey", bm) + if err != nil { + fmt.Println("err:", err) + return + } + fmt.Println("OK:", ok) +} func TestSubString(t *testing.T) { str := `{"alipay_trade_pay_response":{"code":"10000","msg":"Success","buyer_logon_id":"854***@qq.com","buyer_pay_amount":"0.01","buyer_user_id":"2088102363632794","fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"gmt_payment":"2019-08-29 20:22:02","invoice_amount":"0.01","out_trade_no":"GZ201901301040361013","point_amount":"0.00","receipt_amount":"0.01","total_amount":"0.01","trade_no":"2019082922001432790585666965"},"sign":"DSX/wmE0nnuxQrWfJZtq0fNntcx5UYtVV35P2VZpoTC2KlIWr4eGNiXcetbb7AkI/1Tyd0+cNtcGMgB7SYzTB15/wDE0vJ+eT5ucqhNkER1kcuCC0k9OkZzU5w8wCJzOgAy52Wso9KnrwkY86mJWt3dC8DNCCi1rlf1a8bTGIBG/diJaKAgP1lGT3aW8jeGGM98zLabqDUNvck2qkgctGR49kBb0ZYmIzmY0x5goVyKnaCkcC/d1VTIIMz81mJbeqU8UZk6TqEplCC8J+dYEUj04pAO4/lwIg/YZdKj3Pz1136/+uy669Pew88+74J/u/zPsehC44PxcUk9YKmkNyw=="}` diff --git a/alipay_params.go b/alipay_params.go index a9b74c7d..0599a628 100644 --- a/alipay_params.go +++ b/alipay_params.go @@ -43,26 +43,26 @@ func (a *AliPayClient) SetAppCertSN(appCertSN string) (client *AliPayClient) { return a } -//设置 支付宝根证书SN +// 设置 支付宝根证书SN // alipayRootCertSN:支付宝根证书SN,通过 gopay.GetCertSN() 获取 func (a *AliPayClient) SetAliPayRootCertSN(alipayRootCertSN string) (client *AliPayClient) { a.AlipayRootCertSN = alipayRootCertSN return a } -//设置支付后的ReturnUrl +// 设置支付后的ReturnUrl func (a *AliPayClient) SetReturnUrl(url string) (client *AliPayClient) { a.ReturnUrl = url return a } -//设置支付宝服务器主动通知商户服务器里指定的页面http/https路径。 +// 设置支付宝服务器主动通知商户服务器里指定的页面http/https路径。 func (a *AliPayClient) SetNotifyUrl(url string) (client *AliPayClient) { a.NotifyUrl = url return a } -//设置编码格式,如utf-8,gbk,gb2312等,默认推荐使用 utf-8 +// 设置编码格式,如utf-8,gbk,gb2312等,默认推荐使用 utf-8 func (a *AliPayClient) SetCharset(charset string) (client *AliPayClient) { if charset == null { a.Charset = "utf-8" @@ -72,7 +72,7 @@ func (a *AliPayClient) SetCharset(charset string) (client *AliPayClient) { return a } -//设置签名算法类型,目前支持RSA2和RSA,默认推荐使用 RSA2 +// 设置签名算法类型,目前支持RSA2和RSA,默认推荐使用 RSA2 func (a *AliPayClient) SetSignType(signType string) (client *AliPayClient) { if signType == null { a.SignType = "RSA2" @@ -82,19 +82,19 @@ func (a *AliPayClient) SetSignType(signType string) (client *AliPayClient) { return a } -//设置应用授权 +// 设置应用授权 func (a *AliPayClient) SetAppAuthToken(appAuthToken string) (client *AliPayClient) { a.AppAuthToken = appAuthToken return a } -//设置用户信息授权 +// 设置用户信息授权 func (a *AliPayClient) SetAuthToken(authToken string) (client *AliPayClient) { a.AuthToken = authToken return a } -//获取参数签名 +// 获取参数签名 func getRsaSign(bm BodyMap, signType, privateKey string) (sign string, err error) { var ( block *pem.Block @@ -131,7 +131,7 @@ func getRsaSign(bm BodyMap, signType, privateKey string) (sign string, err error return } -//格式化请求URL参数 +// 格式化请求URL参数 func FormatAliPayURLParam(body BodyMap) (urlParam string) { v := url.Values{} for key, value := range body { diff --git a/alipay_rsp.go b/alipay_rsp.go index 979b7555..ebc2f4cc 100644 --- a/alipay_rsp.go +++ b/alipay_rsp.go @@ -1,40 +1,40 @@ package gopay type AliPayNotifyRequest struct { - NotifyTime string `json:"notify_time,omitempty"` - NotifyType string `json:"notify_type,omitempty"` - NotifyId string `json:"notify_id,omitempty"` - AppId string `json:"app_id,omitempty"` - Charset string `json:"charset,omitempty"` - Version string `json:"version,omitempty"` - SignType string `json:"sign_type,omitempty"` - Sign string `json:"sign,omitempty"` - AuthAppId string `json:"auth_app_id,omitempty"` - TradeNo string `json:"trade_no,omitempty"` - OutTradeNo string `json:"out_trade_no,omitempty"` - OutBizNo string `json:"out_biz_no,omitempty"` - BuyerId string `json:"buyer_id,omitempty"` - BuyerLogonId string `json:"buyer_logon_id,omitempty"` - SellerId string `json:"seller_id,omitempty"` - SellerEmail string `json:"seller_email,omitempty"` - TradeStatus string `json:"trade_status,omitempty"` - TotalAmount string `json:"total_amount,omitempty"` - ReceiptAmount string `json:"receipt_amount,omitempty"` - InvoiceAmount string `json:"invoice_amount,omitempty"` - BuyerPayAmount string `json:"buyer_pay_amount,omitempty"` - PointAmount string `json:"point_amount,omitempty"` - RefundFee string `json:"refund_fee,omitempty"` - Subject string `json:"subject,omitempty"` - Body string `json:"body,omitempty"` - GmtCreate string `json:"gmt_create,omitempty"` - GmtPayment string `json:"gmt_payment,omitempty"` - GmtRefund string `json:"gmt_refund,omitempty"` - GmtClose string `json:"gmt_close,omitempty"` - FundBillList []fundBillListInfo `json:"fund_bill_list,omitempty"` - PassbackParams string `json:"passback_params,omitempty"` - VoucherDetailList []voucherDetailListInfo `json:"voucher_detail_list,omitempty"` - Method string `json:"method,omitempty"` //电脑网站支付 支付宝请求 return_url 同步返回参数 - Timestamp string `json:"timestamp,omitempty"` //电脑网站支付 支付宝请求 return_url 同步返回参数 + NotifyTime string `json:"notify_time,omitempty"` + NotifyType string `json:"notify_type,omitempty"` + NotifyId string `json:"notify_id,omitempty"` + AppId string `json:"app_id,omitempty"` + Charset string `json:"charset,omitempty"` + Version string `json:"version,omitempty"` + SignType string `json:"sign_type,omitempty"` + Sign string `json:"sign,omitempty"` + AuthAppId string `json:"auth_app_id,omitempty"` + TradeNo string `json:"trade_no,omitempty"` + OutTradeNo string `json:"out_trade_no,omitempty"` + OutBizNo string `json:"out_biz_no,omitempty"` + BuyerId string `json:"buyer_id,omitempty"` + BuyerLogonId string `json:"buyer_logon_id,omitempty"` + SellerId string `json:"seller_id,omitempty"` + SellerEmail string `json:"seller_email,omitempty"` + TradeStatus string `json:"trade_status,omitempty"` + TotalAmount string `json:"total_amount,omitempty"` + ReceiptAmount string `json:"receipt_amount,omitempty"` + InvoiceAmount string `json:"invoice_amount,omitempty"` + BuyerPayAmount string `json:"buyer_pay_amount,omitempty"` + PointAmount string `json:"point_amount,omitempty"` + RefundFee string `json:"refund_fee,omitempty"` + Subject string `json:"subject,omitempty"` + Body string `json:"body,omitempty"` + GmtCreate string `json:"gmt_create,omitempty"` + GmtPayment string `json:"gmt_payment,omitempty"` + GmtRefund string `json:"gmt_refund,omitempty"` + GmtClose string `json:"gmt_close,omitempty"` + FundBillList []*fundBillListInfo `json:"fund_bill_list,omitempty"` + PassbackParams string `json:"passback_params,omitempty"` + VoucherDetailList []*voucherDetailListInfo `json:"voucher_detail_list,omitempty"` + Method string `json:"method,omitempty"` //电脑网站支付 支付宝请求 return_url 同步返回参数 + Timestamp string `json:"timestamp,omitempty"` //电脑网站支付 支付宝请求 return_url 同步返回参数 } type fundBillListInfo struct { @@ -68,9 +68,9 @@ type AliPayUserPhone struct { //=================================================== type AliPayTradePayResponse struct { - Response payResponse `json:"alipay_trade_pay_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *payResponse `json:"alipay_trade_pay_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type payResponse struct { @@ -94,7 +94,7 @@ type payResponse struct { PointAmount string `json:"point_amount,omitempty"` InvoiceAmount string `json:"invoice_amount,omitempty"` GmtPayment string `json:"gmt_payment,omitempty"` - FundBillList []struct { + FundBillList []*struct { FundChannel string `json:"fund_channel,omitempty"` BankCode string `json:"bank_code,omitempty"` Amount string `json:"amount,omitempty"` @@ -104,7 +104,7 @@ type payResponse struct { StoreName string `json:"store_name,omitempty"` BuyerUserId string `json:"buyer_user_id,omitempty"` DiscountGoodsDetail string `json:"discount_goods_detail,omitempty"` - VoucherDetailList []struct { + VoucherDetailList []*struct { Id string `json:"id,omitempty"` Name string `json:"name,omitempty"` Type string `json:"type,omitempty"` @@ -131,9 +131,9 @@ type payResponse struct { //=================================================== type AliPayTradeQueryResponse struct { - Response queryResponse `json:"alipay_trade_query_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *queryResponse `json:"alipay_trade_query_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type queryResponse struct { @@ -160,7 +160,7 @@ type queryResponse struct { ReceiptAmount string `json:"receipt_amount,omitempty"` StoreId string `json:"store_id,omitempty"` TerminalId string `json:"terminal_id,omitempty"` - FundBillList []struct { + FundBillList []*struct { FundChannel string `json:"fund_channel,omitempty"` BankCode string `json:"bank_code,omitempty"` Amount string `json:"amount,omitempty"` @@ -171,8 +171,8 @@ type queryResponse struct { ChargeAmount string `json:"charge_amount,omitempty"` ChargeFlags string `json:"charge_flags,omitempty"` SettlementId string `json:"settlement_id,omitempty"` - TradeSettleInfo struct { - TradeSettleDetailList []struct { + TradeSettleInfo *struct { + TradeSettleDetailList []*struct { OperationType string `json:"operation_type,omitempty"` OperationSerialNo string `json:"operation_serial_no,omitempty"` OperationDt string `json:"operation_dt,omitempty"` @@ -194,9 +194,9 @@ type queryResponse struct { //=================================================== type AliPayTradeCreateResponse struct { - Response createResponse `json:"alipay_trade_create_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *createResponse `json:"alipay_trade_create_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type createResponse struct { @@ -210,9 +210,9 @@ type createResponse struct { //=================================================== type AliPayTradeCloseResponse struct { - Response closeResponse `json:"alipay_trade_close_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *closeResponse `json:"alipay_trade_close_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type closeResponse struct { @@ -226,9 +226,9 @@ type closeResponse struct { //=================================================== type AliPayTradeCancelResponse struct { - Response cancelResponse `json:"alipay_trade_cancel_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *cancelResponse `json:"alipay_trade_cancel_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type cancelResponse struct { @@ -246,8 +246,8 @@ type cancelResponse struct { //=================================================== type AliPaySystemOauthTokenResponse struct { - Response oauthTokenInfo `json:"alipay_system_oauth_token_response,omitempty"` - ErrorResponse struct { + Response *oauthTokenInfo `json:"alipay_system_oauth_token_response,omitempty"` + ErrorResponse *struct { Code string `json:"code,omitempty"` Msg string `json:"msg,omitempty"` SubCode string `json:"sub_code,omitempty"` @@ -266,10 +266,10 @@ type oauthTokenInfo struct { } //=================================================== -type AlipayUserInfoShareResponse struct { - Response userInfoShare `json:"alipay_user_info_share_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` +type AliPayUserInfoShareResponse struct { + Response *userInfoShare `json:"alipay_user_info_share_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type userInfoShare struct { @@ -291,27 +291,27 @@ type userInfoShare struct { //=================================================== type AliPayTradeRefundResponse struct { - Response refundResponse `json:"alipay_trade_refund_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *refundResponse `json:"alipay_trade_refund_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type refundResponse struct { - Code string `json:"code,omitempty"` - Msg string `json:"msg,omitempty"` - SubCode string `json:"sub_code,omitempty"` - SubMsg string `json:"sub_msg,omitempty"` - TradeNo string `json:"trade_no,omitempty"` - OutTradeNo string `json:"out_trade_no,omitempty"` - BuyerLogonId string `json:"buyer_logon_id,omitempty"` - FundChange string `json:"fund_change,omitempty"` - RefundFee string `json:"refund_fee,omitempty"` - RefundCurrency string `json:"refund_currency,omitempty"` - GmtRefundPay string `json:"gmt_refund_pay,omitempty"` - RefundDetailItemList []tradeFundBill `json:"refund_detail_item_list,omitempty"` - StoreName string `json:"store_name,omitempty"` - BuyerUserId string `json:"buyer_user_id,omitempty"` - RefundPresetPaytoolList []struct { + Code string `json:"code,omitempty"` + Msg string `json:"msg,omitempty"` + SubCode string `json:"sub_code,omitempty"` + SubMsg string `json:"sub_msg,omitempty"` + TradeNo string `json:"trade_no,omitempty"` + OutTradeNo string `json:"out_trade_no,omitempty"` + BuyerLogonId string `json:"buyer_logon_id,omitempty"` + FundChange string `json:"fund_change,omitempty"` + RefundFee string `json:"refund_fee,omitempty"` + RefundCurrency string `json:"refund_currency,omitempty"` + GmtRefundPay string `json:"gmt_refund_pay,omitempty"` + RefundDetailItemList []*tradeFundBill `json:"refund_detail_item_list,omitempty"` + StoreName string `json:"store_name,omitempty"` + BuyerUserId string `json:"buyer_user_id,omitempty"` + RefundPresetPaytoolList []*struct { Amount []string `json:"amount,omitempty"` AssertTypeCode string `json:"assert_type_code,omitempty"` } `json:"refund_preset_paytool_list,omitempty"` @@ -331,9 +331,9 @@ type tradeFundBill struct { //=================================================== type AliPayTradeFastpayRefundQueryResponse struct { - Response refundQueryResponse `json:"alipay_trade_fastpay_refund_query_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *refundQueryResponse `json:"alipay_trade_fastpay_refund_query_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type refundQueryResponse struct { @@ -347,7 +347,7 @@ type refundQueryResponse struct { RefundReason string `json:"refund_reason,omitempty"` TotalAmount string `json:"total_amount,omitempty"` RefundAmount string `json:"refund_amount,omitempty"` - RefundRoyaltys []struct { + RefundRoyaltys []*struct { RefundAmount string `json:"refund_amount,omitempty"` RoyaltyType string `json:"royalty_type,omitempty"` ResultCode string `json:"result_code,omitempty"` @@ -356,20 +356,20 @@ type refundQueryResponse struct { TransIn string `json:"trans_in,omitempty"` TransInEmail string `json:"trans_in_email,omitempty"` } `json:"refund_royaltys,omitempty"` - GmtRefundPay string `json:"gmt_refund_pay,omitempty"` - RefundDetailItemList []tradeFundBill `json:"refund_detail_item_list,omitempty"` - SendBackFee string `json:"send_back_fee,omitempty"` - RefundSettlementId string `json:"refund_settlement_id,omitempty"` - PresentRefundBuyerAmount string `json:"present_refund_buyer_amount,omitempty"` - PresentRefundDiscountAmount string `json:"present_refund_discount_amount,omitempty"` - PresentRefundMdiscountAmount string `json:"present_refund_mdiscount_amount,omitempty"` + GmtRefundPay string `json:"gmt_refund_pay,omitempty"` + RefundDetailItemList []*tradeFundBill `json:"refund_detail_item_list,omitempty"` + SendBackFee string `json:"send_back_fee,omitempty"` + RefundSettlementId string `json:"refund_settlement_id,omitempty"` + PresentRefundBuyerAmount string `json:"present_refund_buyer_amount,omitempty"` + PresentRefundDiscountAmount string `json:"present_refund_discount_amount,omitempty"` + PresentRefundMdiscountAmount string `json:"present_refund_mdiscount_amount,omitempty"` } //=================================================== type AliPayTradeOrderSettleResponse struct { - Response orderSettleResponse `json:"alipay_trade_order_settle_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *orderSettleResponse `json:"alipay_trade_order_settle_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type orderSettleResponse struct { Code string `json:"code,omitempty"` @@ -380,10 +380,10 @@ type orderSettleResponse struct { } //=================================================== -type AlipayTradePrecreateResponse struct { - Response precreateResponse `json:"alipay_trade_precreate_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` +type AliPayTradePrecreateResponse struct { + Response *precreateResponse `json:"alipay_trade_precreate_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type precreateResponse struct { @@ -397,9 +397,9 @@ type precreateResponse struct { //=================================================== type AliPayTradePageRefundResponse struct { - Response pageRefundResponse `json:"alipay_trade_page_refund_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *pageRefundResponse `json:"alipay_trade_page_refund_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type pageRefundResponse struct { @@ -414,10 +414,10 @@ type pageRefundResponse struct { } //=================================================== -type AlipayFundTransToaccountTransferResponse struct { - Response transToaccountTransferResponse `json:"alipay_fund_trans_toaccount_transfer_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` +type AliPayFundTransToaccountTransferResponse struct { + Response *transToaccountTransferResponse `json:"alipay_fund_trans_toaccount_transfer_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type transToaccountTransferResponse struct { @@ -432,9 +432,9 @@ type transToaccountTransferResponse struct { //=================================================== type ZhimaCreditScoreGetResponse struct { - Response scoreGetResponse `json:"zhima_credit_score_get_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *scoreGetResponse `json:"zhima_credit_score_get_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type scoreGetResponse struct { @@ -448,9 +448,9 @@ type scoreGetResponse struct { //=================================================== type AliPayOpenAuthTokenAppResponse struct { - Response authTokenAppResponse `json:"alipay_open_auth_token_app_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *authTokenAppResponse `json:"alipay_open_auth_token_app_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type authTokenAppResponse struct { @@ -464,7 +464,7 @@ type authTokenAppResponse struct { AppRefreshToken string `json:"app_refresh_token,omitempty"` ExpiresIn int `json:"expires_in,omitempty"` ReExpiresIn int `json:"re_expires_in,omitempty"` - Tokens []struct { + Tokens []*struct { AppAuthToken string `json:"app_auth_token,omitempty"` AppRefreshToken string `json:"app_refresh_token,omitempty"` AuthAppId string `json:"auth_app_id,omitempty"` @@ -476,9 +476,9 @@ type authTokenAppResponse struct { //=================================================== type AliPayUserCertifyOpenInitResponse struct { - Response userCertifyOpenInitResponse `json:"alipay_user_certify_open_initialize_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *userCertifyOpenInitResponse `json:"alipay_user_certify_open_initialize_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type userCertifyOpenInitResponse struct { @@ -491,9 +491,9 @@ type userCertifyOpenInitResponse struct { //=================================================== type AliPayUserCertifyOpenCertifyResponse struct { - Response userCertifyOpenCertifyResponse `json:"alipay_user_certify_open_certify_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *userCertifyOpenCertifyResponse `json:"alipay_user_certify_open_certify_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type userCertifyOpenCertifyResponse struct { @@ -505,9 +505,9 @@ type userCertifyOpenCertifyResponse struct { //=================================================== type AliPayUserCertifyOpenQueryResponse struct { - Response userCertifyOpenQueryResponse `json:"alipay_user_certify_open_query_response,omitempty"` - SignData string `json:"-"` - Sign string `json:"sign"` + Response *userCertifyOpenQueryResponse `json:"alipay_user_certify_open_query_response,omitempty"` + SignData string `json:"-"` + Sign string `json:"sign"` } type userCertifyOpenQueryResponse struct { diff --git a/alipay_service_api.go b/alipay_service_api.go index 9e36054a..5d7c8d6e 100644 --- a/alipay_service_api.go +++ b/alipay_service_api.go @@ -22,7 +22,7 @@ import ( ) // 允许进行 sn 提取的证书签名算法 -var allowSignatureAlgorithm map[string]bool = map[string]bool{ +var allowSignatureAlgorithm = map[string]bool{ "MD2-RSA": true, "MD5-RSA": true, "SHA1-RSA": true, @@ -34,54 +34,82 @@ var allowSignatureAlgorithm map[string]bool = map[string]bool{ "SHA512-RSAPSS": true, } +// 解析支付宝支付异步通知的结果到BodyMap +// req:*http.Request +// 返回参数bm:Notify请求的参数 +// 返回参数err:错误信息 +// 文档:https://docs.open.alipay.com/203/105286/ +func ParseAliPayNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error) { + if err = req.ParseForm(); err != nil { + return nil, err + } + var form map[string][]string = req.Form + bm = make(BodyMap, len(form)) + for k, v := range form { + if len(v) == 1 { + bm.Set(k, v[0]) + } + } + return +} + // ParseAliPayNotifyResult 解析支付宝支付完成后的Notify信息 +// req:*http.Request +// 返回参数notifyReq:Notify请求的参数 +// 返回参数err:错误信息 +// 文档:https://docs.open.alipay.com/203/105286/ func ParseAliPayNotifyResult(req *http.Request) (notifyReq *AliPayNotifyRequest, err error) { notifyReq = new(AliPayNotifyRequest) - notifyReq.NotifyTime = req.FormValue("notify_time") - notifyReq.NotifyType = req.FormValue("notify_type") - notifyReq.NotifyId = req.FormValue("notify_id") - notifyReq.AppId = req.FormValue("app_id") - notifyReq.Charset = req.FormValue("charset") - notifyReq.Version = req.FormValue("version") - notifyReq.SignType = req.FormValue("sign_type") - notifyReq.Sign = req.FormValue("sign") - notifyReq.AuthAppId = req.FormValue("auth_app_id") - notifyReq.TradeNo = req.FormValue("trade_no") - notifyReq.OutTradeNo = req.FormValue("out_trade_no") - notifyReq.OutBizNo = req.FormValue("out_biz_no") - notifyReq.BuyerId = req.FormValue("buyer_id") - notifyReq.BuyerLogonId = req.FormValue("buyer_logon_id") - notifyReq.SellerId = req.FormValue("seller_id") - notifyReq.SellerEmail = req.FormValue("seller_email") - notifyReq.TradeStatus = req.FormValue("trade_status") - notifyReq.TotalAmount = req.FormValue("total_amount") - notifyReq.ReceiptAmount = req.FormValue("receipt_amount") - notifyReq.InvoiceAmount = req.FormValue("invoice_amount") - notifyReq.BuyerPayAmount = req.FormValue("buyer_pay_amount") - notifyReq.PointAmount = req.FormValue("point_amount") - notifyReq.RefundFee = req.FormValue("refund_fee") - notifyReq.Subject = req.FormValue("subject") - notifyReq.Body = req.FormValue("body") - notifyReq.GmtCreate = req.FormValue("gmt_create") - notifyReq.GmtPayment = req.FormValue("gmt_payment") - notifyReq.GmtRefund = req.FormValue("gmt_refund") - notifyReq.GmtClose = req.FormValue("gmt_close") - billList := req.FormValue("fund_bill_list") + if err = req.ParseForm(); err != nil { + return + } + notifyReq.NotifyTime = req.Form.Get("notify_time") + notifyReq.NotifyType = req.Form.Get("notify_type") + notifyReq.NotifyId = req.Form.Get("notify_id") + notifyReq.AppId = req.Form.Get("app_id") + notifyReq.Charset = req.Form.Get("charset") + notifyReq.Version = req.Form.Get("version") + notifyReq.SignType = req.Form.Get("sign_type") + notifyReq.Sign = req.Form.Get("sign") + notifyReq.AuthAppId = req.Form.Get("auth_app_id") + notifyReq.TradeNo = req.Form.Get("trade_no") + notifyReq.OutTradeNo = req.Form.Get("out_trade_no") + notifyReq.OutBizNo = req.Form.Get("out_biz_no") + notifyReq.BuyerId = req.Form.Get("buyer_id") + notifyReq.BuyerLogonId = req.Form.Get("buyer_logon_id") + notifyReq.SellerId = req.Form.Get("seller_id") + notifyReq.SellerEmail = req.Form.Get("seller_email") + notifyReq.TradeStatus = req.Form.Get("trade_status") + notifyReq.TotalAmount = req.Form.Get("total_amount") + notifyReq.ReceiptAmount = req.Form.Get("receipt_amount") + notifyReq.InvoiceAmount = req.Form.Get("invoice_amount") + notifyReq.BuyerPayAmount = req.Form.Get("buyer_pay_amount") + notifyReq.PointAmount = req.Form.Get("point_amount") + notifyReq.RefundFee = req.Form.Get("refund_fee") + notifyReq.Subject = req.Form.Get("subject") + notifyReq.Body = req.Form.Get("body") + notifyReq.GmtCreate = req.Form.Get("gmt_create") + notifyReq.GmtPayment = req.Form.Get("gmt_payment") + notifyReq.GmtRefund = req.Form.Get("gmt_refund") + notifyReq.GmtClose = req.Form.Get("gmt_close") + notifyReq.PassbackParams = req.Form.Get("passback_params") + + billList := req.Form.Get("fund_bill_list") if billList != null { - bills := make([]fundBillListInfo, 0) + bills := make([]*fundBillListInfo, 0) if err = json.Unmarshal([]byte(billList), &bills); err != nil { - return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error()) + return nil, fmt.Errorf(`"fund_bill_list" xml.Unmarshal:%s`, err.Error()) } notifyReq.FundBillList = bills } else { notifyReq.FundBillList = nil } - notifyReq.PassbackParams = req.FormValue("passback_params") - detailList := req.FormValue("voucher_detail_list") + + detailList := req.Form.Get("voucher_detail_list") if detailList != null { - details := make([]voucherDetailListInfo, 0) + details := make([]*voucherDetailListInfo, 0) if err = json.Unmarshal([]byte(detailList), &details); err != nil { - return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error()) + return nil, fmt.Errorf(`"voucher_detail_list" xml.Unmarshal:%s`, err.Error()) } notifyReq.VoucherDetailList = details } else { @@ -109,7 +137,7 @@ A:开发者上传自己的应用公钥证书后,开放平台会为开发者 // VerifyAliPaySign 支付宝同步返回验签或异步通知验签 // 注意:APP支付,手机网站支付,电脑网站支付 暂不支持同步返回验签 // aliPayPublicKey:支付宝公钥 -// bean: 同步返回验签时,此参数为 aliRsp.SignData ;异步通知验签时,此参数为异步通知解析的结构体 notifyReq +// bean: 同步返回验签时,此参数为字符串 aliRsp.SignData ;异步通知验签时,此参数为异步通知解析的结构体或BodyMap:notifyReq 或 bm // syncSign:同步返回验签时,此参数必传,即:aliRsp.Sign ;异步通知验签时,不传此参数,否则会出错。 // 返回参数ok:是否验签通过 // 返回参数err:错误信息 @@ -132,18 +160,28 @@ func VerifyAliPaySign(aliPayPublicKey string, bean interface{}, syncSign ...stri signData = bean.(string) goto Verify } - if bs, err = json.Marshal(bean); err != nil { - return false, fmt.Errorf("json.Marshal:%s", err.Error()) - } bm = make(BodyMap) - if err = json.Unmarshal(bs, &bm); err != nil { - return false, fmt.Errorf("json.Unmarshal:%s", err.Error()) - } - bodySign = bm.Get("sign") - bodySignType = bm.Get("sign_type") - bm.Remove("sign") - bm.Remove("sign_type") - signData = bm.EncodeAliPaySignParams() + if reflect.ValueOf(bean).Kind() == reflect.Map { + if bm, ok = bean.(BodyMap); ok { + bodySign = bm.Get("sign") + bodySignType = bm.Get("sign_type") + bm.Remove("sign") + bm.Remove("sign_type") + signData = bm.EncodeAliPaySignParams() + } + } else { + if bs, err = json.Marshal(bean); err != nil { + return false, fmt.Errorf("json.Marshal:%s", err.Error()) + } + if err = json.Unmarshal(bs, &bm); err != nil { + return false, fmt.Errorf("json.Unmarshal:%s", err.Error()) + } + bodySign = bm.Get("sign") + bodySignType = bm.Get("sign_type") + bm.Remove("sign") + bm.Remove("sign_type") + signData = bm.EncodeAliPaySignParams() + } Verify: pKey = FormatAliPayPublicKey(aliPayPublicKey) if err = verifyAliPaySign(signData, bodySign, bodySignType, pKey); err != nil { diff --git a/constant.go b/constant.go index 4bcff4d8..69be7274 100644 --- a/constant.go +++ b/constant.go @@ -5,22 +5,22 @@ const ( TimeLayout string = "2006-01-02 15:04:05" DateLayout string = "2006-01-02" Version string = "1.4.3" - //微信 - //=========================================================================================== + // 微信 + // =========================================================================================== - //境外国家地区 - China Country = 1 //中国国内 - China2 Country = 2 //中国国内(冗灾方案) - SoutheastAsia Country = 3 //东南亚 - Other Country = 4 //其他国家 + // 境外国家地区 + China Country = 1 // 中国国内 + China2 Country = 2 // 中国国内(冗灾方案) + SoutheastAsia Country = 3 // 东南亚 + Other Country = 4 // 其他国家 - //URL + // URL wxBaseUrlCh = "https://api.mch.weixin.qq.com/" //中国国内 wxBaseUrlCh2 = "https://api2.mch.weixin.qq.com/" //中国国内 wxBaseUrlHk = "https://apihk.mch.weixin.qq.com/" //东南亚 wxBaseUrlUs = "https://apius.mch.weixin.qq.com/" //其他 - //正式 + // 正式 wxMicropay = "pay/micropay" //提交付款码支付 wxUnifiedorder = "pay/unifiedorder" //统一下单 wxOrderquery = "pay/orderquery" //查询订单 @@ -40,7 +40,7 @@ const ( wxEntrustApplyPay = "pay/pappayapply" //申请扣款 wxEntrustQueryOrder = "pay/paporderquery" //查询扣款订单 - //SanBox + // SanBox wxSandboxGetsignkey = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey" wxSandboxMicropay = "sandboxnew/pay/micropay" wxSandboxUnifiedorder = "sandboxnew/pay/unifiedorder" @@ -53,21 +53,21 @@ const ( wxSandboxDownloadfundflow = "sandboxnew/pay/downloadfundflow" wxSandboxBatchquerycomment = "sandboxnew/billcommentsp/batchquerycomment" - //支付类型 + // 支付类型 TradeType_Mini = "JSAPI" TradeType_JsApi = "JSAPI" TradeType_App = "APP" TradeType_H5 = "MWEB" TradeType_Native = "NATIVE" - //签名方式 + // 签名方式 SignType_MD5 = "MD5" SignType_HMAC_SHA256 = "HMAC-SHA256" - //支付宝 - //=========================================================================================== + // 支付宝 + // ========================================================================================== - //URL + // URL zfbBaseUrl = "https://openapi.alipay.com/gateway.do" zfbSandboxBaseUrl = "https://openapi.alipaydev.com/gateway.do" zfbBaseUrlUtf8 = "https://openapi.alipay.com/gateway.do?charset=utf-8" diff --git a/examples/alipay/alipay_AlipayFundTransToaccountTransfer.go b/examples/alipay/alipay_AlipayFundTransToaccountTransfer.go index a9942142..aad84a2d 100644 --- a/examples/alipay/alipay_AlipayFundTransToaccountTransfer.go +++ b/examples/alipay/alipay_AlipayFundTransToaccountTransfer.go @@ -6,7 +6,7 @@ import ( "github.com/iGoogle-ink/gopay" ) -func AlipayFundTransToaccountTransfer() { +func AliPayFundTransToaccountTransfer() { privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY=" //初始化支付宝客户端 // appId:应用ID @@ -27,7 +27,7 @@ func AlipayFundTransToaccountTransfer() { body.Set("payee_real_name", "沙箱环境") body.Set("remark", "转账测试") //创建订单 - aliRsp, err := client.AlipayFundTransToaccountTransfer(body) + aliRsp, err := client.AliPayFundTransToaccountTransfer(body) if err != nil { fmt.Println("err:", err) return diff --git a/examples/alipay/alipay_AlipayOpenAuthTokenApp.go b/examples/alipay/alipay_AlipayOpenAuthTokenApp.go index 99e48f93..65180f92 100644 --- a/examples/alipay/alipay_AlipayOpenAuthTokenApp.go +++ b/examples/alipay/alipay_AlipayOpenAuthTokenApp.go @@ -6,7 +6,7 @@ import ( "github.com/iGoogle-ink/gopay" ) -func AlipayOpenAuthTokenApp() { +func AliPayOpenAuthTokenApp() { privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY=" //privateKey := "MIIEowIBAAKCAQEAu8U3O5C6g1KRyZySX1NiVbakSk6+rE5GBt7xEPsRXEtaRsL3YQQOC95+0pGaLTvGTkzZ2sfSZ6mvl9ryYQ1uBAAqSoGWm24djxpwm7JJrkbOsTiKCmB4JnI5xIvvoLZApwtC4USlNSytxXMoxSrTc6lo41ev0ENnh4+dhL9iokLH35uGjHyVi8ovCpo940X8BIlmta3WBGmLIU3s5xGwUwqRHFlWySxaCuEuhhQsodAoqWV9HpM549uVXZCiqkUDugUnfIaUM7vlgMgNa0ol81a7GdQnqmqyg7XMH81chPWWrUQCo5E7oXWXFwSMraNwZbw4qBZYMGLGuKqNqbscqwIDAQABAoIBAC9f38KYjmZJs9yxM0D30cycazEQUw04JnTfVOUa41Ns85b849tHYZ/fABJyh/q3pR3mR+TqG4zqBBKFPDf+Ym6B+CmaLnyCuNR9MEIoJmzhEo8mG7Xohwf0M90CDXB36zH6JmKdpi0XW7SAjJ3KY1VAPeV2Hzalev553p06iFE1pp4wtvF/XFeensGQG58tBCDuzhzxNMZfDqOJPx35Q5HIuW5CS1JdclY7SZol7i5HtgaSkjVQ/3wKRZCK4nTOoQW5uh4ogdI4KKDX7cFmQESxMNsCo+A9oQYOoD7yw9wsCkENlPyUDbAcFNFTDWpOAVXn/M0jQWQDzaT7GlhrqlkCgYEA+QFTewivhL+nmbcTrgscyzFNeoeBOct9MH8YJNWIblKT35Lg0HT1UAW9Jey46d6al+Xz/0sM0c+3nbYb9Va2oPahW70hmbTchBrqKAh/svb9yCeWw5i6NuzUNRZ5kz5ufr42XRRVNR2IJ2Av4RGfVA7W/uhAnIZBPngk5CoyfgcCgYEAwQuH9DH46fvKTB+B1kDngpKQw9Jn2ZXVz8dyYnhdH/SZgohwD/jTldx9ck42bFw4+3qHI6DJSxBxqeuaGQqmD5Y3YStP3Gb33EABACpLt1NV4AId8rWfrizJTxy5+PJONHNmDNL0Fyv53qtsG1rv+Unye6Pfeo6pkKmK49u/Az0CgYEAtR3Oz934dNFGohs1GFIC5pT86xPm3dfyPjUjpZ8ftkcgQe2+0kFQMZ2LACvYMFv3DGd5e4bmUzIIN5G/cktZWWkq4uSFrRyNjRVanjXYVJ8s5spM8gaD4/GNRPQNCBnQGyZVuoxQkeriHunqyYWc43JL1Wuvm2pXyI1xH/jFcz8CgYB1IN34mGmC7rcrwOIycWcGno8fgYZpSrRUQZtxi75VKUALJ2V3C261uvaSaEo1LS+Vxh5Ay8nWtb+BbeYt03w2cNphJrpp7D/vbxYsV31hWjr8k8w/+1tLfvkV+0QLfFlfEbWVill3xcLyC+ioIGECTI/H3QI3hl/z2irfXfFjsQKBgA+vBD22XWD1drUccPA0mMJdVMW/yrd3HVbHLVHaNqkdPFUAN8k27icXxdE2gKoHWmDeW0SZ5Wm7Hc+79f222ZS401vzlL78sIXBydYlsxn3zDowt5U9WTDPVxoqx+aStUriDPiV3fnxj9D/Q4IAEYlqI1gjRBF1o15zRFQZAkJv" //初始化支付宝客户端 diff --git a/examples/alipay/alipay_AlipayUserInfoShare.go b/examples/alipay/alipay_AlipayUserInfoShare.go index 69ff445e..c6c1bbeb 100644 --- a/examples/alipay/alipay_AlipayUserInfoShare.go +++ b/examples/alipay/alipay_AlipayUserInfoShare.go @@ -6,7 +6,7 @@ import ( "github.com/iGoogle-ink/gopay" ) -func AlipayUserInfoShare() { +func AliPayUserInfoShare() { aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB" privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY=" //初始化支付宝客户端 @@ -20,7 +20,7 @@ func AlipayUserInfoShare() { SetAuthToken("authusrB3888b190f6df4aea964d66129f8a5X11") //发起请求 - aliRsp, err := client.AlipayUserInfoShare() + aliRsp, err := client.AliPayUserInfoShare() if err != nil { fmt.Println("err:", err) return diff --git a/util.go b/util.go index 9a538826..b5e0f67e 100644 --- a/util.go +++ b/util.go @@ -17,29 +17,12 @@ import ( type BodyMap map[string]interface{} -//设置参数 -// value:仅支持类型 string,int,int64,float32,float64,ptr,struct,slice,map 类型,其他类型一律设置空字符串 +// 设置参数 func (bm BodyMap) Set(key string, value interface{}) { - vKind := reflect.ValueOf(value).Kind() - switch vKind { - case reflect.String: - bm[key] = value.(string) - case reflect.Int: - bm[key] = Int2String(value.(int)) - case reflect.Int64: - bm[key] = Int642String(value.(int64)) - case reflect.Float32: - bm[key] = Float32ToString(value.(float32)) - case reflect.Float64: - bm[key] = Float64ToString(value.(float64)) - case reflect.Ptr, reflect.Struct, reflect.Map, reflect.Slice: - bm[key] = value - default: - bm[key] = null - } + bm[key] = value } -//获取参数 +// 获取参数 func (bm BodyMap) Get(key string) string { if bm == nil { return null @@ -73,7 +56,7 @@ func jsonToString(v interface{}) (str string) { return } -//删除参数 +// 删除参数 func (bm BodyMap) Remove(key string) { delete(bm, key) } @@ -165,20 +148,22 @@ func (bm BodyMap) EncodeAliPaySignParams() string { } sort.Strings(keyList) for _, k := range keyList { - buf.WriteString(k) - buf.WriteByte('=') - buf.WriteString(bm.Get(k)) - buf.WriteByte('&') + if v := bm.Get(k); v != null { + buf.WriteString(k) + buf.WriteByte('=') + buf.WriteString(v) + buf.WriteByte('&') + } } return buf.String()[:buf.Len()-1] } -//HttpAgent +// HttpAgent func HttpAgent() (agent *gorequest.SuperAgent) { return gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true}) } -//获取随机字符串 +// 获取随机字符串 // length:字符串长度 func GetRandomString(length int) string { str := "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz" @@ -195,26 +180,26 @@ func GetRandomString(length int) string { return string(result) } -//解析时间 +// 解析时间 func ParseDateTime(timeStr string) (datetime time.Time) { datetime, _ = time.ParseInLocation(TimeLayout, timeStr, time.Local) return } -//字符串转Float64 +// 字符串转Float64 func String2Float64(floatStr string) (floatNum float64) { floatNum, _ = strconv.ParseFloat(floatStr, 64) return } -//字符串转Float32 +// 字符串转Float32 func String2Float32(floatStr string) (floatNum float32) { float, _ := strconv.ParseFloat(floatStr, 32) floatNum = float32(float) return } -//Float64转字符串 +// Float64转字符串 // floatNum:float64数字 // prec:精度位数(不传则默认float数字精度) func Float64ToString(floatNum float64, prec ...int) (floatStr string) { @@ -226,7 +211,7 @@ func Float64ToString(floatNum float64, prec ...int) (floatStr string) { return } -//Float32转字符串 +// Float32转字符串 // floatNum:float32数字 // prec:精度位数(不传则默认float数字精度) func Float32ToString(floatNum float32, prec ...int) (floatStr string) { @@ -238,66 +223,66 @@ func Float32ToString(floatNum float32, prec ...int) (floatStr string) { return } -//字符串转Int +// 字符串转Int func String2Int(intStr string) (intNum int) { intNum, _ = strconv.Atoi(intStr) return } -//字符串转Int32 +// 字符串转Int32 func String2Int32(intStr string) (int32Num int32) { intNum, _ := strconv.Atoi(intStr) int32Num = int32(intNum) return } -//字符串转Int64 +// 字符串转Int64 func String2Int64(intStr string) (int64Num int64) { intNum, _ := strconv.Atoi(intStr) int64Num = int64(intNum) return } -//Int转字符串 +// Int转字符串 func Int2String(intNum int) (intStr string) { intStr = strconv.Itoa(intNum) return } -//Int32转字符串 +// Int32转字符串 func Int322String(intNum int32) (int32Str string) { - //10, 代表10进制 + // 10, 代表10进制 int32Str = strconv.FormatInt(int64(intNum), 10) return } -//Int64转字符串 +// Int64转字符串 func Int642String(intNum int64) (int64Str string) { - //10, 代表10进制 + // 10, 代表10进制 int64Str = strconv.FormatInt(intNum, 10) return } -//解密填充模式(去除补全码) PKCS7UnPadding -//解密时,需要在最后面去掉加密时添加的填充byte +// 解密填充模式(去除补全码) PKCS7UnPadding +// 解密时,需要在最后面去掉加密时添加的填充byte func PKCS7UnPadding(origData []byte) (bs []byte) { length := len(origData) - unPaddingNumber := int(origData[length-1]) //找到Byte数组最后的填充byte 数字 + unPaddingNumber := int(origData[length-1]) // 找到Byte数组最后的填充byte 数字 if unPaddingNumber <= 16 { - bs = origData[:(length - unPaddingNumber)] //只截取返回有效数字内的byte数组 + bs = origData[:(length - unPaddingNumber)] // 只截取返回有效数字内的byte数组 } else { bs = origData } return } -//解密填充模式(去除补全码) PKCS5UnPadding -//解密时,需要在最后面去掉加密时添加的填充byte +// 解密填充模式(去除补全码) PKCS5UnPadding +// 解密时,需要在最后面去掉加密时添加的填充byte func PKCS5UnPadding(origData []byte) (bs []byte) { length := len(origData) - unPaddingNumber := int(origData[length-1]) //找到Byte数组最后的填充byte + unPaddingNumber := int(origData[length-1]) // 找到Byte数组最后的填充byte if unPaddingNumber <= 16 { - bs = origData[:(length - unPaddingNumber)] //只截取返回有效数字内的byte数组 + bs = origData[:(length - unPaddingNumber)] // 只截取返回有效数字内的byte数组 } else { bs = origData } diff --git a/wechat_client.go b/wechat_client.go index 731310e4..e6f94319 100644 --- a/wechat_client.go +++ b/wechat_client.go @@ -336,7 +336,7 @@ func (w *WeChatClient) Transfer(body BodyMap, certFilePath, keyFilePath, pkcs12F return } -// 公众号纯签约 +// 公众号纯签约(未完成) // 文档地址:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_1&index=1 func (w *WeChatClient) EntrustPublic(body BodyMap) (bs []byte, err error) { bs, err = w.doWeChat(body, wxEntrustPublic) @@ -344,7 +344,7 @@ func (w *WeChatClient) EntrustPublic(body BodyMap) (bs []byte, err error) { return nil, nil } -//向微信发送请求 ok +// 向微信发送请求 ok func (w *WeChatClient) doWeChat(body BodyMap, path string, tlsConfig ...*tls.Config) (bytes []byte, err error) { body.Set("appid", w.AppId) body.Set("mch_id", w.MchId) diff --git a/wechat_client_test.go b/wechat_client_test.go index 1b7af49a..2dbae2c2 100644 --- a/wechat_client_test.go +++ b/wechat_client_test.go @@ -138,3 +138,25 @@ func TestDecryptRefundNotifyReqInfo(t *testing.T) { } fmt.Println("refundNotify:", *refundNotify) } + +func TestBodyMap_Set_Get(t *testing.T) { + bm := make(BodyMap) + sceneInfo := make(map[string]map[string]string) + h5Info := make(map[string]string) + h5Info["type"] = "Wap" + h5Info["wap_url"] = "http://www.gopay.ink" + h5Info["wap_name"] = "H5测试支付" + sceneInfo["h5_info"] = h5Info + bm.Set("scene_info", sceneInfo) + fmt.Println("Get1:", bm.Get("scene_info")) + + bm.Set("student", &Student{ + Name: "Jerry", + Age: 26, + Sign: "123465", + Phone: "123654987", + }) + + fmt.Println("Get2:", bm.Get("student")) + +} diff --git a/wechat_rsp.go b/wechat_rsp.go index 7a813708..3fd702b6 100644 --- a/wechat_rsp.go +++ b/wechat_rsp.go @@ -322,23 +322,23 @@ type WeChatUserInfo struct { // 微信小程序解密后 用户手机号结构体 type WeChatUserPhone struct { - PhoneNumber string `json:"phoneNumber,omitempty"` - PurePhoneNumber string `json:"purePhoneNumber,omitempty"` - CountryCode string `json:"countryCode,omitempty"` - Watermark watermarkInfo `json:"watermark,omitempty"` + PhoneNumber string `json:"phoneNumber,omitempty"` + PurePhoneNumber string `json:"purePhoneNumber,omitempty"` + CountryCode string `json:"countryCode,omitempty"` + Watermark *watermarkInfo `json:"watermark,omitempty"` } // 微信小程序解密后 用户信息结构体 type WeChatAppletUserInfo struct { - OpenId string `json:"openId,omitempty"` - NickName string `json:"nickName,omitempty"` - Gender int `json:"gender,omitempty"` - City string `json:"city,omitempty"` - Province string `json:"province,omitempty"` - Country string `json:"country,omitempty"` - AvatarUrl string `json:"avatarUrl,omitempty"` - UnionId string `json:"unionId,omitempty"` - Watermark watermarkInfo `json:"watermark,omitempty"` + OpenId string `json:"openId,omitempty"` + NickName string `json:"nickName,omitempty"` + Gender int `json:"gender,omitempty"` + City string `json:"city,omitempty"` + Province string `json:"province,omitempty"` + Country string `json:"country,omitempty"` + AvatarUrl string `json:"avatarUrl,omitempty"` + UnionId string `json:"unionId,omitempty"` + Watermark *watermarkInfo `json:"watermark,omitempty"` } type watermarkInfo struct { diff --git a/wechat_service_api.go b/wechat_service_api.go index 5a74aca1..48de9119 100644 --- a/wechat_service_api.go +++ b/wechat_service_api.go @@ -19,7 +19,7 @@ import ( "strings" ) -//获取微信支付所需参数里的Sign值(通过支付参数计算Sign值) +// 获取微信支付所需参数里的Sign值(通过支付参数计算Sign值) // 注意:BodyMap中如无 sign_type 参数,默认赋值 sign_type 为 MD5 // appId:应用ID // mchId:商户ID @@ -46,7 +46,7 @@ func GetWeChatParamSign(appId, mchId, apiKey string, bm BodyMap) (sign string) { return } -//获取微信支付沙箱环境所需参数里的Sign值(通过支付参数计算Sign值) +// 获取微信支付沙箱环境所需参数里的Sign值(通过支付参数计算Sign值) // 注意:沙箱环境默认 sign_type 为 MD5 // appId:应用ID // mchId:商户ID @@ -69,7 +69,7 @@ func GetWeChatSanBoxParamSign(appId, mchId, apiKey string, bm BodyMap) (sign str return } -//解析微信支付异步通知的结果到BodyMap +// 解析微信支付异步通知的结果到BodyMap // req:*http.Request // 返回参数bm:Notify请求的参数 // 返回参数err:错误信息 @@ -85,7 +85,7 @@ func ParseWeChatNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error) return } -//解析微信支付异步通知的参数 +// 解析微信支付异步通知的参数 // req:*http.Request // 返回参数notifyReq:Notify请求的参数 // 返回参数err:错误信息