├── .github
├── douyin_jerry.png
├── jetbrains.png
├── qq_gopay.png
├── wechat_jerry.png
├── workflows
│ └── go.yml
├── wx_gopay.png
├── zanshang.png
├── zanshang_wx.png
└── zanshang_zfb.png
├── .gitignore
├── LICENSE
├── README.md
├── alipay
├── ant.go
├── ant_test.go
├── cert
│ ├── alipayPublicCert.crt
│ ├── alipayRootCert.crt
│ ├── appPublicCert.crt
│ ├── cert.go
│ └── java_sdk.txt
├── client.go
├── client_request.go
├── client_test.go
├── commerce_api.go
├── common_api.go
├── common_api_test.go
├── customs.go
├── data_api.go
├── data_api_test.go
├── error.go
├── error_test.go
├── face.go
├── funds_api.go
├── funds_api_test.go
├── goods_api.go
├── goods_api_test.go
├── koubei_api.go
├── koubei_api_test.go
├── marketing_activity.go
├── marketing_api.go
├── marketing_api_test.go
├── marketing_card.go
├── marketing_voucher.go
├── member_api.go
├── member_api_test.go
├── merchant_api.go
├── merchant_qipan.go
├── mode_funds.go
├── model.go
├── model_ant.go
├── model_commerce.go
├── model_customs.go
├── model_data.go
├── model_face.go
├── model_koubei.go
├── model_market.go
├── model_member.go
├── model_merchant.go
├── model_ocr.go
├── model_payment.go
├── model_smilepay.go
├── model_zhima.go
├── notify.go
├── ocr.go
├── param.go
├── payment_api.go
├── payment_api_test.go
├── sign.go
├── sign_test.go
├── smilepay.go
├── third_auth.go
├── third_dev.go
├── util_api.go
├── util_api_test.go
├── v3
│ ├── activity_api.go
│ ├── ad_api.go
│ ├── ad_api_test.go
│ ├── ant_api.go
│ ├── campaign_api.go
│ ├── card_api.go
│ ├── cert.go
│ ├── client.go
│ ├── client_test.go
│ ├── constant.go
│ ├── credit.go
│ ├── face_verify_api.go
│ ├── fund_auth_api.go
│ ├── marketing_api.go
│ ├── marketing_api_test.go
│ ├── member_api.go
│ ├── member_api_test.go
│ ├── merchant_api.go
│ ├── model.go
│ ├── model_activity.go
│ ├── model_ad.go
│ ├── model_ant.go
│ ├── model_campaign.go
│ ├── model_card.go
│ ├── model_credit.go
│ ├── model_face_verify.go
│ ├── model_fund_auth.go
│ ├── model_marketing.go
│ ├── model_member.go
│ ├── model_merchant.go
│ ├── model_payment.go
│ ├── model_transfer.go
│ ├── payment_api.go
│ ├── payment_api_test.go
│ ├── request.go
│ ├── sign.go
│ └── transfer_api.go
├── zhima_api.go
└── zhima_api_test.go
├── allinpay
├── api.go
├── cert
│ └── cert.go
├── client.go
├── client_test.go
├── error.go
├── model.go
├── pay.go
├── pay_test.go
└── sign.go
├── apple
├── cert.go
├── client.go
├── client_test.go
├── constant.go
├── consumption.go
├── doc.go
├── error.go
├── notification_v2.go
├── notification_v2_model.go
├── notification_v2_test.go
├── order.go
├── order_model.go
├── order_test.go
├── refund.go
├── refund_model.go
├── refund_test.go
├── subscription.go
├── subscription_model.go
├── subscription_test.go
├── token.go
├── transaction.go
├── transaction_model.go
├── transaction_test.go
├── unsign_jwt.go
├── unsign_jwt_test.go
├── verify.go
├── verify_model.go
└── verify_test.go
├── body_map.go
├── body_map_test.go
├── constant.go
├── doc
├── alipay.md
├── alipay_v3.md
├── allinpay.md
├── apple.md
├── lakala.md
├── paypal.md
├── qq.md
├── saobei.md
├── wechat_v2.md
└── wechat_v3.md
├── error.go
├── examples
├── alipay
│ ├── alipay_OpenAuthTokenApp.go
│ ├── alipay_ServiceApi.go
│ ├── alipay_SystemOauthToken.go
│ ├── alipay_TradeAppPay.go
│ ├── alipay_TradeCancel.go
│ ├── alipay_TradeClose.go
│ ├── alipay_TradeCreate.go
│ ├── alipay_TradeFastPayRefundQuery.go
│ ├── alipay_TradeOrderSettle.go
│ ├── alipay_TradePagePay.go
│ ├── alipay_TradePay.go
│ ├── alipay_TradePrecreate.go
│ ├── alipay_TradeQuery.go
│ ├── alipay_TradeRefund.go
│ ├── alipay_TradeWapPay.go
│ ├── alipay_UserCertifyOpenCertify.go
│ ├── alipay_UserCertifyOpenInit.go
│ ├── alipay_UserCertifyOpenQuery.go
│ ├── alipay_UserInfoAuth.go
│ ├── alipay_UserInfoShare.go
│ └── alipay_ZhimaCreditEpSceneRatingInitialize.go
├── main.go
└── wechat
│ ├── wx_BatchQueryComment.go
│ ├── wx_CloseOrder.go
│ ├── wx_DownloadBill.go
│ ├── wx_DownloadFundFlow.go
│ ├── wx_Micropay.go
│ ├── wx_QueryOrder.go
│ ├── wx_QueryRefund.go
│ ├── wx_Refund.go
│ ├── wx_RefundV3.go
│ ├── wx_Reverse.go
│ ├── wx_ServiceApi.go
│ ├── wx_Transfer.go
│ └── wx_UnifiedOrder.go
├── go.mod
├── go.sum
├── gopay_test.go
├── lakala
├── client.go
├── client_test.go
├── common_api.go
├── constant.go
├── custom_api.go
├── h5.go
├── jsapi.go
├── mini_program.go
├── model.go
├── qr_code.go
├── retail_pay.go
├── sdk_payment.go
└── web_gateway.go
├── logo.png
├── paypal
├── access_token.go
├── client.go
├── client_test.go
├── constant.go
├── invoice.go
├── invoice_test.go
├── model.go
├── model_product.go
├── model_subscription.go
├── order.go
├── order_test.go
├── payment.go
├── payment_test.go
├── payment_token.go
├── payment_token_test.go
├── payout.go
├── payout_test.go
├── product.go
├── product_test.go
├── request.go
├── subscriptions.go
├── subscriptions_test.go
├── tracking.go
├── tracking_test.go
├── webhook.go
└── webhook_test.go
├── pkg
├── jwt
│ ├── claims.go
│ ├── ecdsa.go
│ ├── errors.go
│ ├── hmac.go
│ ├── map_claims.go
│ ├── parser.go
│ ├── rsa.go
│ ├── rsa_pss.go
│ ├── signing_method.go
│ └── token.go
└── xhttp
│ ├── README.md
│ ├── client.go
│ ├── model.go
│ ├── request.go
│ ├── transport_default_js.go
│ └── transport_default_other.go
├── qq
├── client.go
├── client_test.go
├── model.go
├── oplatform_api.go
├── param.go
├── payment_api.go
└── red.go
├── release_note.md
├── saobei
├── account.go
├── api.go
├── cert
│ └── cert.go
├── client.go
├── client_test.go
├── consts.go
├── error.go
├── merchant.go
├── model.go
├── pay.go
├── pay_test.go
└── sign.go
├── support_note.txt
└── wechat
├── applet_api.go
├── base_api.go
├── base_api_test.go
├── client.go
├── client_test.go
├── constant.go
├── customs.go
├── merchant.go
├── merchant_test.go
├── model.go
├── notify.go
├── notify_test.go
├── oplatform_api.go
├── papay.go
├── papay_test.go
├── param.go
├── red.go
├── sign.go
└── v3
├── activity.go
├── applyment_for_sub.go
├── bank.go
├── bill.go
├── business_circle.go
├── cert.go
├── client.go
├── client_test.go
├── complaint.go
├── constant.go
├── discount_card.go
├── ecommerce.go
├── encrypt_decrypt.go
├── encrypt_decrypt_test.go
├── fapiao.go
├── gold_plan.go
├── market_activity.go
├── market_busifavor.go
├── market_favor.go
├── market_media.go
├── market_partner.go
├── media.go
├── merchant.go
├── model.go
├── model_activity.go
├── model_applyment.go
├── model_bank.go
├── model_bill.go
├── model_business.go
├── model_complaint.go
├── model_discount.go
├── model_ecommerce.go
├── model_fapiao.go
├── model_favor.go
├── model_media.go
├── model_merchant.go
├── model_parking.go
├── model_partner.go
├── model_pay.go
├── model_profit.go
├── model_refund.go
├── model_score.go
├── model_transfer.go
├── model_transfer_bills.go
├── model_violation.go
├── notify.go
├── palm.go
├── papay.go
├── parking.go
├── pay.go
├── pay_combine.go
├── pay_partner.go
├── profit_share.go
├── refund.go
├── request.go
├── score.go
├── sign.go
├── sign_test.go
├── smart_guide.go
├── transfer.go
├── transfer_bills.go
├── violation.go
└── withdraw.go
/.github/douyin_jerry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/douyin_jerry.png
--------------------------------------------------------------------------------
/.github/jetbrains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/jetbrains.png
--------------------------------------------------------------------------------
/.github/qq_gopay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/qq_gopay.png
--------------------------------------------------------------------------------
/.github/wechat_jerry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/wechat_jerry.png
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a golang project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
3 |
4 | name: Run Tests
5 |
6 | on:
7 | push:
8 | branches: [ "main" ]
9 | pull_request:
10 | branches: [ "main" ]
11 |
12 | jobs:
13 |
14 | lint:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: Checkout repository
18 | uses: actions/checkout@v4
19 |
20 | - name: Set up Go
21 | uses: actions/setup-go@v5
22 | with:
23 | go-version: '1.23'
24 |
25 | - name: Setup golangci-lint
26 | uses: golangci/golangci-lint-action@v6
27 | with:
28 | version: latest
29 | args: -v --disable=unused
30 |
31 | test:
32 | needs: lint
33 | strategy:
34 | matrix:
35 | os: [ ubuntu-latest ]
36 | go: [ '1.22' , '1.23', '1.24' ]
37 | runs-on: ${{ matrix.os }}
38 | steps:
39 | - name: Checkout Code
40 | uses: actions/checkout@v4
41 |
42 | - name: Set up Go ${{ matrix.go }}
43 | uses: actions/setup-go@v5
44 | with:
45 | go-version: ${{ matrix.go }}
46 |
47 | - name: Test
48 | run: go test -v ./...
49 |
--------------------------------------------------------------------------------
/.github/wx_gopay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/wx_gopay.png
--------------------------------------------------------------------------------
/.github/zanshang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/zanshang.png
--------------------------------------------------------------------------------
/.github/zanshang_wx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/zanshang_wx.png
--------------------------------------------------------------------------------
/.github/zanshang_zfb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/.github/zanshang_zfb.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # idea ignore
2 | .idea/
3 | .vscode/
4 | .vendor/
5 | *.ipr
6 | *.iml
7 | *.iws
8 |
9 | # system ignore
10 | .DS_Store
11 | Thumbs.db
12 |
13 | # temp ignore
14 | *.log
15 | *.cache
16 | *.diff
17 | *.exe
18 | *.patch
19 | *.tmp
20 | main
--------------------------------------------------------------------------------
/alipay/cert/alipayPublicCert.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDszCCApugAwIBAgIQICMGCYNKwsloIKi8XMlUgzANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE
3 | BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv
4 | biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1
5 | dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjMwNjA5MTI1MjAzWhcNMjQwNjA4MTI1MjAzWjCB
6 | hDELMAkGA1UEBhMCQ04xHzAdBgNVBAoMFmxhZ21pczYyNTRAc2FuZGJveC5jb20xDzANBgNVBAsM
7 | BkFsaXBheTFDMEEGA1UEAww65pSv5LuY5a6dKOS4reWbvSnnvZHnu5zmioDmnK/mnInpmZDlhazl
8 | j7gtMjA4ODcyMTAwMzIzNjQ0MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJN/z9yl
9 | +66sFRDJG2ZWPND6gSsTR7DAeKucCm6SlNimX3w4opVd2z6Rz5tcB2iRyh7nZoq1Vo5+uZSLKaiD
10 | IAOEaFNwn9LBLPDH/WgM79BeOygFm9qAYQ8kHGBrR37Sxu6tphgWpVyu0yVlgNvgwdlALX2RCwUW
11 | lYbGhe2wpBndxo00lwWXMlwEoYJx/eAu8k69iEW7/kp8HnU3Qih8V76D0bwAcpTvSq8fDIsiRAgQ
12 | X0EnAOu0rC/hNTCojFXTKJs5UxEO1tFBALc5huGkTM0qd9C4IIrdcR+xysjloEhN18tC0+/FSm6h
13 | kbggE+iE+QAPY6kgGzgX7e4oCRZM/bMCAwEAAaMSMBAwDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3
14 | DQEBCwUAA4IBAQCcCBpLhvl+6fO21kJvL+FIaWgAoCpLuQGQYS1cX9pn+BNHNL8Ur2i0Se7IkL4z
15 | USM4ETULw6RtzoARgIlpSbpSQkZOvyUysOv+ou5rmhUZGtSA2BHwoTHoNWdpmlbps61v7AjQeZTX
16 | rhzdJ7ipLutSNsFiQf0TRjshq79wpIFPwsDO68hrDx6QTMlFqW0/uXv7dERDac9uemCBvePeJVrt
17 | xhqFXuzE5ZvgtuFXW9pIeXwq7B4xNuwfpXQWdxAPyo2Up//0wJdy90gtfESfO8fCYATPtptnB4lP
18 | KHqoqQsuV3xw2P4o/+pmMBgj6hhhoZILLNUJ2Il9PgLEkvkCwRXR
19 | -----END CERTIFICATE-----
20 | -----BEGIN CERTIFICATE-----
21 | MIIDszCCApugAwIBAgIQIBkIGbgVxq210KxLJ+YA/TANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UE
22 | BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxJTAjBgNVBAsMHENlcnRpZmljYXRpb24gQXV0
23 | aG9yaXR5IHRlc3QxNjA0BgNVBAMMLUFudCBGaW5hbmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
24 | dHkgUjEgdGVzdDAeFw0xOTA4MTkxMTE2MDBaFw0yNDA4MDExMTE2MDBaMIGRMQswCQYDVQQGEwJD
25 | TjEbMBkGA1UECgwSQW50IEZpbmFuY2lhbCB0ZXN0MSUwIwYDVQQLDBxDZXJ0aWZpY2F0aW9uIEF1
26 | dGhvcml0eSB0ZXN0MT4wPAYDVQQDDDVBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
27 | aXR5IENsYXNzIDIgUjEgdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMh4FKYO
28 | ZyRQHD6eFbPKZeSAnrfjfU7xmS9Yoozuu+iuqZlb6Z0SPLUqqTZAFZejOcmr07ln/pwZxluqplxC
29 | 5+B48End4nclDMlT5HPrDr3W0frs6Xsa2ZNcyil/iKNB5MbGll8LRAxntsKvZZj6vUTMb705gYgm
30 | VUMILwi/ZxKTQqBtkT/kQQ5y6nOZsj7XI5rYdz6qqOROrpvS/d7iypdHOMIM9Iz9DlL1mrCykbBi
31 | t25y+gTeXmuisHUwqaRpwtCGK4BayCqxRGbNipe6W73EK9lBrrzNtTr9NaysesT/v+l25JHCL9tG
32 | wpNr1oWFzk4IHVOg0ORiQ6SUgxZUTYcCAwEAAaMSMBAwDgYDVR0PAQH/BAQDAgTwMA0GCSqGSIb3
33 | DQEBCwUAA4IBAQBWThEoIaQoBX2YeRY/I8gu6TYnFXtyuCljANnXnM38ft+ikhE5mMNgKmJYLHvT
34 | yWWWgwHoSAWEuml7EGbE/2AK2h3k0MdfiWLzdmpPCRG/RJHk6UB1pMHPilI+c0MVu16OPpKbg5Vf
35 | LTv7dsAB40AzKsvyYw88/Ezi1osTXo6QQwda7uefvudirtb8FcQM9R66cJxl3kt1FXbpYwheIm/p
36 | j1mq64swCoIYu4NrsUYtn6CV542DTQMI5QdXkn+PzUUly8F6kDp+KpMNd0avfWNL5+O++z+F5Szy
37 | 1CPta1D7EQ/eYmMP+mOQ35oifWIoFCpN6qQVBS/Hob1J/UUyg7BW
38 | -----END CERTIFICATE-----
39 |
--------------------------------------------------------------------------------
/alipay/cert/appPublicCert.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDmTCCAoGgAwIBAgIQICMGCXK2Am4QGbc/5Yi2QjANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE
3 | BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv
4 | biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1
5 | dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjMwNjA5MTI1MjAyWhcNMjQwNjEzMTI1MjAyWjBr
6 | MQswCQYDVQQGEwJDTjEfMB0GA1UECgwWbGFnbWlzNjI1NEBzYW5kYm94LmNvbTEPMA0GA1UECwwG
7 | QWxpcGF5MSowKAYDVQQDDCEyMDg4NzIxMDAzMjM2NDQyLTIwMjEwMDAxMjI2NzIzODgwggEiMA0G
8 | CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDTHpBfR55b5dE2Hi78EbVGzK5hiweap6eTgas9XwS
9 | WtQQ3qctHBJcZIgi4i7IKjS3izAI2n1DniD4BSakB114EJiEcqsBgbifXUyddRiiwR7jfDNSF3s9
10 | penFy0WVIqEWBgGJftxCD87xOEcknQfRDL6T000naAyd8/KmT3/jcOy0eYoRVC+BClyCeGVsrxfi
11 | 2EgrjNbTHAeAOFIB5m71Au9/9xzY90qZ3nGJRQzsns+3BPtW9sojbt9g4F7WHHGu+ljq9wYYZqXz
12 | GE04oP56KpcCA+AhFi5eouk+Bpg4iaOecf2UinOOsI7SextrVPi2icOOnmO/QVpIrA5MCM7pAgMB
13 | AAGjEjAQMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEAZc2RyiGKftnKi/0zIUUl
14 | xKDPyUdVBBYDagcraHROKXafsZEnhO/cdBPC3VAJEiygNvddB51l088cGb8pGS2VqTQqR/Ehmd1x
15 | kLMleWlUocX0Mwctz/J6jNp9/JKcVe1jk492HR7Csqjf+hvsajIVliIWzuhzB7C0eNEb46Js/G8T
16 | QmsX92eHI0r2pcmsVr+PmDioLu4H4miKrDRhXNXLQ2AQfxPOCOtxt0tSNrB97bDNSwB1O4OItmr/
17 | Cimb7l1nqxY3BOY5o8iAWLv4wG4giYu9LSrEJW0nWa2JG059kMlWLSVe7Afx0GzMVQUP6NJNdulP
18 | ddebveu2CNZcJ7ipbA==
19 | -----END CERTIFICATE-----
--------------------------------------------------------------------------------
/alipay/cert/java_sdk.txt:
--------------------------------------------------------------------------------
1 |
2 | // Java SDK 获取Root证书SN AntCertificationUtil.getRootCertSN();
3 | /**
4 | * 从公钥证书中提取公钥序列号
5 | *
6 | * @param certPath 公钥证书存放路径,例如:/home/admin/cert.crt
7 | * @return 公钥证书序列号
8 | * @throws AlipayApiException
9 | */
10 | public static String getCertSN(String certPath) throws AlipayApiException {
11 | InputStream inputStream = null;
12 | try {
13 | inputStream = new FileInputStream(certPath);
14 | CertificateFactory cf = CertificateFactory.getInstance("X.509");
15 | X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
16 | MessageDigest md = MessageDigest.getInstance("MD5");
17 | md.update((cert.getIssuerX500Principal().getName() + cert.getSerialNumber()).getBytes());
18 | String certSN = new BigInteger(1, md.digest()).toString(16);
19 | //BigInteger会把0省略掉,需补全至32位
20 | certSN = fillMD5(certSN);
21 | return certSN;
22 |
23 | } catch (NoSuchAlgorithmException e) {
24 | throw new AlipayApiException(e);
25 | } catch (IOException e) {
26 | throw new AlipayApiException(e);
27 | } catch (CertificateException e) {
28 | throw new AlipayApiException(e);
29 | } finally {
30 | try {
31 | if (inputStream != null) {
32 | inputStream.close();
33 | }
34 | } catch (IOException e) {
35 | throw new AlipayApiException(e);
36 | }
37 | }
38 | }
39 |
40 | // Java SDK 获取证书SN AlipaySignature.getCertSN();
41 | /**
42 | * 获取根证书序列号
43 | *
44 | * @param rootCertContent
45 | * @return
46 | */
47 | public static String getRootCertSN(String rootCertContent) {
48 | String rootCertSN = null;
49 | try {
50 | X509Certificate[] x509Certificates = readPemCertChain(rootCertContent);
51 | MessageDigest md = MessageDigest.getInstance("MD5");
52 | for (X509Certificate c : x509Certificates) {
53 | if (c.getSigAlgOID().startsWith("1.2.840.113549.1.1")) {
54 | md.update((c.getIssuerX500Principal().getName() + c.getSerialNumber()).getBytes());
55 | String certSN = new BigInteger(1, md.digest()).toString(16);
56 | //BigInteger会把0省略掉,需补全至32位
57 | certSN = fillMD5(certSN);
58 | if (StringUtils.isEmpty(rootCertSN)) {
59 | rootCertSN = certSN;
60 | } else {
61 | rootCertSN = rootCertSN + "_" + certSN;
62 | }
63 | }
64 |
65 | }
66 | } catch (Exception e) {
67 | AlipayLogger.logBizError(("提取根证书失败"));
68 | }
69 | return rootCertSN;
70 |
71 | }
72 |
73 | private static String fillMD5(String md5) {
74 | return md5.length() == 32 ? md5 : fillMD5("0" + md5);
75 | }
76 |
--------------------------------------------------------------------------------
/alipay/client_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "context"
5 | "os"
6 | "testing"
7 |
8 | "github.com/go-pay/gopay"
9 | "github.com/go-pay/gopay/alipay/cert"
10 | "github.com/go-pay/util"
11 | "github.com/go-pay/xlog"
12 | )
13 |
14 | var (
15 | ctx = context.Background()
16 | client *Client
17 | err error
18 | )
19 |
20 | func TestMain(m *testing.M) {
21 | xlog.SetLevel(xlog.DebugLevel)
22 | // 初始化支付宝客户端
23 | // appid:应用ID
24 | // privateKey:应用私钥,支持PKCS1和PKCS8
25 | // isProd:是否是正式环境,沙箱环境请选择新版沙箱应用。
26 | client, err = NewClient(cert.Appid, cert.PrivateKey, false)
27 | if err != nil {
28 | xlog.Error(err)
29 | return
30 | }
31 | // Debug开关,输出/关闭日志
32 | client.DebugSwitch = gopay.DebugOff
33 |
34 | // 配置公共参数
35 | client.SetCharset("utf-8").
36 | SetSignType(RSA2).
37 | // SetAppAuthToken("")
38 | SetReturnUrl("https://www.fmm.ink").
39 | SetNotifyUrl("https://www.fmm.ink")
40 |
41 | // 设置biz_content加密KEY,设置此参数默认开启加密(目前不可用,设置后会报错)
42 | //client.SetAESKey("KvKUTqSVZX2fUgmxnFyMaQ==")
43 |
44 | // 自动同步验签(只支持证书模式)
45 | // 传入 支付宝公钥证书 alipayPublicCert.crt 内容
46 | client.AutoVerifySign(cert.AlipayPublicContentRSA2)
47 |
48 | // 传入证书内容
49 | err := client.SetCertSnByContent(cert.AppPublicContent, cert.AlipayRootContent, cert.AlipayPublicContentRSA2)
50 | // 传入证书文件路径
51 | //err := client.SetCertSnByPath("cert/appPublicCert.crt", "cert/alipayRootCert.crt", "cert/alipayPublicCert.crt")
52 | if err != nil {
53 | xlog.Debug("SetCertSn:", err)
54 | return
55 | }
56 | os.Exit(m.Run())
57 | }
58 |
59 | func TestClient_PostAliPayAPISelfV2(t *testing.T) {
60 | bm := make(gopay.BodyMap)
61 |
62 | // 自定义公共参数(根据自己需求,需要独立设置的自行设置,不需要单独设置的,共享client的配置)
63 | bm.Set("app_id", "appid")
64 | bm.Set(AppAuthToken, "xxx")
65 | bm.Set("auth_token", "auth_token")
66 |
67 | // biz_content
68 | bm.SetBodyMap("biz_content", func(bz gopay.BodyMap) {
69 | bz.Set("subject", "预创建创建订单")
70 | bz.Set("out_trade_no", util.RandomString(32))
71 | bz.Set("total_amount", "100")
72 | })
73 |
74 | aliPsp := new(TradePrecreateResponse)
75 | err := client.PostAliPayAPISelfV2(ctx, bm, "alipay.trade.precreate", aliPsp)
76 | if err != nil {
77 | xlog.Error(err)
78 | return
79 | }
80 | xlog.Debug(aliPsp.Response)
81 | }
82 |
83 | // =================================================
84 |
85 | func TestDecryptOpenDataToBodyMap(t *testing.T) {
86 | data := "MkvuiIZsGOC8S038cu/JIpoRKnF+ZFjoIRGf5d/K4+ctYjCtb/eEkwgrdB5TeH/93bxff1Ylb+SE+UGStlpvcg=="
87 | key := "TDftre9FpItr46e9BVNJcw=="
88 | bm, err := DecryptOpenDataToBodyMap(data, key)
89 | if err != nil {
90 | xlog.Errorf("DecryptOpenDataToBodyMap(%s,%s),error:%+v", data, key, err)
91 | return
92 | }
93 | xlog.Info("bm:", bm)
94 | }
95 |
--------------------------------------------------------------------------------
/alipay/common_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TestMonitorHeartbeatSyn(t *testing.T) {
10 | appid := "2016091200494382"
11 | 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="
12 | bizContent := "{任意值}"
13 |
14 | rsp, err := MonitorHeartbeatSyn(ctx, appid, privateKey, RSA2, bizContent)
15 | if err != nil {
16 | xlog.Errorf("MonitorHeartbeatSyn(),error:%+v", err)
17 | return
18 | }
19 | xlog.Info("rsp.Response:", *rsp.Response)
20 | }
21 |
22 | func TestDecryptOpenDataToStruct(t *testing.T) {
23 | data := "MkvuiIZsGOC8S038cu/JIpoRKnF+ZFjoIRGf5d/K4+ctYjCtb/eEkwgrdB5TeH/93bxff1Ylb+SE+UGStlpvcg=="
24 | key := "TDftre9FpItr46e9BVNJcw=="
25 | rsp := new(UserPhone)
26 | err := DecryptOpenDataToStruct(data, key, rsp)
27 | if err != nil {
28 | xlog.Error("err:", err)
29 | return
30 | }
31 | xlog.Debug("rsp.Code:", rsp.Code)
32 | xlog.Debug("rsp.Msg:", rsp.Msg)
33 | xlog.Debug("rsp.SubCode:", rsp.SubCode)
34 | xlog.Debug("rsp.SubMsg:", rsp.SubMsg)
35 | xlog.Debug("rsp.Mobile:", rsp.Mobile)
36 | }
37 |
--------------------------------------------------------------------------------
/alipay/data_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func TestClient_DataBillDownloadUrlQuery(t *testing.T) {
11 | bm := make(gopay.BodyMap)
12 | bm.Set("bill_type", "trade").
13 | Set("bill_date", "2016-04-05")
14 | rsp, err := client.DataBillDownloadUrlQuery(ctx, bm)
15 | if err != nil {
16 | xlog.Error(err)
17 | return
18 | }
19 | xlog.Debug("rsp:", rsp)
20 | }
21 |
--------------------------------------------------------------------------------
/alipay/error.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | )
7 |
8 | // BizErr 用于判断支付宝的业务逻辑是否有错误
9 | type BizErr struct {
10 | Code string `json:"code"`
11 | Msg string `json:"msg"`
12 | SubCode string `json:"sub_code"`
13 | SubMsg string `json:"sub_msg"`
14 | }
15 |
16 | // bizErrCheck 检查业务码是否为10000 否则返回一个BizErr
17 | func bizErrCheck(errRsp ErrorResponse) error {
18 | if errRsp.Code != "10000" {
19 | return &BizErr{
20 | Code: errRsp.Code,
21 | Msg: errRsp.Msg,
22 | SubCode: errRsp.SubCode,
23 | SubMsg: errRsp.SubMsg,
24 | }
25 | }
26 | return nil
27 | }
28 |
29 | // bizErrCheckTradePay 检查业务码是否为10000、10003,否则返回一个BizErr
30 | func bizErrCheckTradePay(errRsp ErrorResponse) error {
31 | if errRsp.Code != "10000" && errRsp.Code != "10003" {
32 | return &BizErr{
33 | Code: errRsp.Code,
34 | Msg: errRsp.Msg,
35 | SubCode: errRsp.SubCode,
36 | SubMsg: errRsp.SubMsg,
37 | }
38 | }
39 | return nil
40 | }
41 |
42 | func (e *BizErr) Error() string {
43 | return fmt.Sprintf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, e.Code, e.Msg, e.SubCode, e.SubMsg)
44 | }
45 |
46 | func IsBizError(err error) (*BizErr, bool) {
47 | var bizErr *BizErr
48 | if errors.As(err, &bizErr) {
49 | return bizErr, true
50 | }
51 | return nil, false
52 | }
53 |
--------------------------------------------------------------------------------
/alipay/error_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestBizErr_BizErrCheck(t *testing.T) {
8 | bizErrRsp := ErrorResponse{
9 | Code: "40004",
10 | Msg: "NOT_FOUND",
11 | }
12 | if bizErrCheck(bizErrRsp) == nil {
13 | t.Fail()
14 | }
15 |
16 | noBizErrRsp := ErrorResponse{
17 | Code: "10000",
18 | Msg: "SUCCEED",
19 | }
20 |
21 | if bizErrCheck(noBizErrRsp) != nil {
22 | t.Fail()
23 | }
24 | }
25 |
26 | func TestBizErr_AsBizError(t *testing.T) {
27 | type args struct {
28 | errRsp ErrorResponse
29 | }
30 | tests := []struct {
31 | name string
32 | args args
33 | wantIsBizError bool
34 | }{
35 | {
36 | name: "",
37 | args: args{
38 | errRsp: ErrorResponse{
39 | Code: "40004",
40 | Msg: "NOT_FOUND",
41 | },
42 | },
43 | wantIsBizError: true,
44 | },
45 | {
46 | name: "",
47 | args: args{
48 | errRsp: ErrorResponse{
49 | Code: "10000",
50 | Msg: "SUCCEED",
51 | },
52 | },
53 | wantIsBizError: false,
54 | },
55 | }
56 | for _, tt := range tests {
57 | t.Run(tt.name, func(t *testing.T) {
58 | err := bizErrCheck(tt.args.errRsp)
59 | _, ok := IsBizError(err)
60 | if ok != tt.wantIsBizError {
61 | t.Errorf("isBizError got = %v, want %v", ok, tt.wantIsBizError)
62 | }
63 | })
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/alipay/goods_api.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // alipay.merchant.item.file.upload(商品文件上传接口)
12 | // 文档地址:https://opendocs.alipay.com/apis/api_4/alipay.merchant.item.file.upload
13 | func (a *Client) MerchantItemFileUpload(ctx context.Context, bm gopay.BodyMap) (aliRsp *MerchantItemFileUploadRsp, err error) {
14 | err = bm.CheckEmptyError("scene", "file_content")
15 | if err != nil {
16 | return nil, err
17 | }
18 | var bs []byte
19 | if bs, err = a.FileUploadRequest(ctx, bm, "alipay.merchant.item.file.upload"); err != nil {
20 | return nil, err
21 | }
22 | aliRsp = new(MerchantItemFileUploadRsp)
23 | if err = json.Unmarshal(bs, aliRsp); err != nil {
24 | return nil, err
25 | }
26 | if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
27 | info := aliRsp.Response
28 | return aliRsp, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
29 | }
30 | signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
31 | aliRsp.SignData = signData
32 | return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
33 | }
34 |
--------------------------------------------------------------------------------
/alipay/goods_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "io"
5 | "os"
6 | "testing"
7 |
8 | "github.com/go-pay/gopay"
9 | "github.com/go-pay/xlog"
10 | )
11 |
12 | func TestMerchantItemFileUpload(t *testing.T) {
13 | // 请求参数
14 | logo, err := os.Open("../logo.png")
15 | if err != nil {
16 | xlog.Errorf("os.Open(%s),error:%+v", "../logo.png", err)
17 | return
18 | }
19 | xlog.Warnf("fileName: %s", logo.Name())
20 | allBs, err := io.ReadAll(logo)
21 | if err != nil {
22 | xlog.Errorf("io.ReadAll(%s),error:%+v", logo.Name(), err)
23 | return
24 | }
25 | f := &gopay.File{
26 | Name: "logo.png",
27 | Content: allBs,
28 | }
29 | bm := make(gopay.BodyMap)
30 | bm.Set("scene", "SYNC_ORDER") // 素材固定值
31 | bm.SetFormFile("file_content", f)
32 | aliRsp, err := client.MerchantItemFileUpload(ctx, bm)
33 | if err != nil {
34 | xlog.Errorf("client.MerchantItemFileUpload(),error:%+v", err)
35 | return
36 | }
37 | xlog.Debug("aliRsp:", *aliRsp)
38 | }
39 |
--------------------------------------------------------------------------------
/alipay/model_commerce.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | type CommerceTransportNfccardSendRsp struct {
4 | Response *CommerceTransportNfccardSend `json:"alipay_commerce_transport_nfccard_send_response"`
5 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
6 | SignData string `json:"-"`
7 | Sign string `json:"sign"`
8 | }
9 |
10 | type CommerceAirCallcenterTradeApplyRsp struct {
11 | Response *CommerceAirCallcenterTradeApply `json:"alipay_commerce_air_callcenter_trade_apply_response"`
12 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
13 | SignData string `json:"-"`
14 | Sign string `json:"sign"`
15 | }
16 |
17 | type CommerceBenefitApplyRsp struct {
18 | Response *CommerceBenefitApply `json:"alipay_commerce_operation_gamemarketing_benefit_apply_response"`
19 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
20 | SignData string `json:"-"`
21 | Sign string `json:"sign"`
22 | }
23 |
24 | type CommerceBenefitVerifyRsp struct {
25 | Response *CommerceBenefitVerify `json:"alipay_commerce_operation_gamemarketing_benefit_verify_response"`
26 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
27 | SignData string `json:"-"`
28 | Sign string `json:"sign"`
29 | }
30 |
31 | // =========================================================分割=========================================================
32 |
33 | type CommerceTransportNfccardSend struct {
34 | ErrorResponse
35 | }
36 |
37 | type CommerceAirCallcenterTradeApply struct {
38 | ErrorResponse
39 | }
40 |
41 | type CommerceBenefitApply struct {
42 | ErrorResponse
43 | ApplyVoucherCodeList string `json:"apply_voucher_code_list,omitempty"`
44 | }
45 |
46 | type CommerceBenefitVerify struct {
47 | ErrorResponse
48 | VoucherVerifyStatus bool `json:"voucher_verify_status,omitempty"`
49 | }
50 |
--------------------------------------------------------------------------------
/alipay/model_customs.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | type TradeCustomsDeclareRsp struct {
4 | Response *TradeCustomsDeclare `json:"alipay_trade_customs_declare_response"`
5 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
6 | SignData string `json:"-"`
7 | Sign string `json:"sign"`
8 | }
9 |
10 | // =========================================================分割=========================================================
11 |
12 | type TradeCustomsDeclare struct {
13 | ErrorResponse
14 | TradeNo string `json:"trade_no,omitempty"`
15 | AlipayDeclareNo string `json:"alipay_declare_no"`
16 | PayCode string `json:"pay_code,omitempty"`
17 | PayTransactionId string `json:"pay_transaction_id,omitempty"`
18 | TotalAmount string `json:"total_amount,omitempty"`
19 | Currency string `json:"currency,omitempty"`
20 | VerDept string `json:"ver_dept,omitempty"`
21 | IdentityCheck string `json:"identity_check,omitempty"`
22 | }
23 |
--------------------------------------------------------------------------------
/alipay/model_ocr.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | type OcrServerDetectRsp struct {
4 | Response *OcrServerDetect `json:"datadigital_fincloud_generalsaas_ocr_server_detect_response"`
5 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
6 | SignData string `json:"-"`
7 | Sign string `json:"sign"`
8 | }
9 |
10 | type OcrMobileInitializeRsp struct {
11 | Response *OcrMobileInitialize `json:"datadigital_fincloud_generalsaas_ocr_mobile_initialize_response"`
12 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
13 | SignData string `json:"-"`
14 | Sign string `json:"sign"`
15 | }
16 |
17 | type OcrCommonDetectRsp struct {
18 | Response *OcrCommonDetect `json:"datadigital_fincloud_generalsaas_ocr_common_detect_response"`
19 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
20 | SignData string `json:"-"`
21 | Sign string `json:"sign"`
22 | }
23 |
24 | // =========================================================分割=========================================================
25 |
26 | type OcrServerDetect struct {
27 | ErrorResponse
28 | OcrData string `json:"ocr_data"`
29 | CertifyId string `json:"certify_id"`
30 | }
31 |
32 | type OcrMobileInitialize struct {
33 | ErrorResponse
34 | CertifyId string `json:"certify_id"`
35 | }
36 |
37 | type OcrCommonDetect struct {
38 | ErrorResponse
39 | CertifyId string `json:"certify_id"`
40 | OcrData string `json:"ocr_data"`
41 | }
42 |
--------------------------------------------------------------------------------
/alipay/model_smilepay.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | type ZolozAuthenticationSmilepayInitializeRsp struct {
4 | Response *ZolozAuthenticationSmilepayInitialize `json:"zoloz_authentication_smilepay_initialize_response"`
5 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
6 | SignData string `json:"-"`
7 | Sign string `json:"sign"`
8 | }
9 |
10 | type ZolozAuthenticationCustomerFtokenQueryRsp struct {
11 | Response *ZolozAuthenticationCustomerFtokenQuery `json:"zoloz_authentication_customer_ftoken_query_response"`
12 | AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
13 | SignData string `json:"-"`
14 | Sign string `json:"sign"`
15 | }
16 |
17 | // =========================================================分割=========================================================
18 |
19 | type ZolozAuthenticationSmilepayInitialize struct {
20 | ErrorResponse
21 | RetCodeSub string `json:"ret_code_sub"`
22 | RetMessageSub string `json:"ret_message_sub"`
23 | ZimId string `json:"zim_id"`
24 | ZimInitClientData string `json:"zim_init_client_data"`
25 | }
26 |
27 | type ZolozAuthenticationCustomerFtokenQuery struct {
28 | ErrorResponse
29 | Uid string `json:"uid"`
30 | OpenId string `json:"open_id"`
31 | UidTelPairList []*UidTelPair `json:"uid_tel_pair_list"`
32 | AgeCheckResult string `json:"age_check_result"`
33 | CertNo string `json:"cert_no"`
34 | CertName string `json:"cert_name"`
35 | FaceId string `json:"face_id"`
36 | }
37 |
38 | type UidTelPair struct {
39 | UserId string `json:"user_id"`
40 | OpenId string `json:"open_id"`
41 | }
42 |
--------------------------------------------------------------------------------
/alipay/smilepay.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // zoloz.authentication.smilepay.initialize(刷脸支付初始化)
12 | // 文档地址:https://opendocs.alipay.com/open/2f7c1d5f_zoloz.authentication.smilepay.initialize
13 | func (a *Client) ZolozAuthenticationSmilepayInitialize(ctx context.Context, bm gopay.BodyMap) (aliRsp *ZolozAuthenticationSmilepayInitializeRsp, err error) {
14 | var bs []byte
15 | if bs, err = a.doAliPay(ctx, bm, "zoloz.authentication.smilepay.initialize"); err != nil {
16 | return nil, err
17 | }
18 | aliRsp = new(ZolozAuthenticationSmilepayInitializeRsp)
19 | if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
20 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
21 | }
22 | if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
23 | return aliRsp, err
24 | }
25 | signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
26 | aliRsp.SignData = signData
27 | return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
28 | }
29 |
30 | // zoloz.authentication.customer.ftoken.query(查询刷脸结果信息接口)
31 | // 文档地址:https://opendocs.alipay.com/open/c8e4d285_zoloz.authentication.customer.ftoken.query
32 | func (a *Client) ZolozAuthenticationCustomerFtokenQuery(ctx context.Context, bm gopay.BodyMap) (aliRsp *ZolozAuthenticationCustomerFtokenQueryRsp, err error) {
33 | err = bm.CheckEmptyError("ftoken", "biz_type")
34 | if err != nil {
35 | return nil, err
36 | }
37 | var bs []byte
38 | if bs, err = a.doAliPay(ctx, bm, "zoloz.authentication.customer.ftoken.query"); err != nil {
39 | return nil, err
40 | }
41 | aliRsp = new(ZolozAuthenticationCustomerFtokenQueryRsp)
42 | if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
43 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
44 | }
45 | if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
46 | return aliRsp, err
47 | }
48 | signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
49 | aliRsp.SignData = signData
50 | return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
51 | }
52 |
--------------------------------------------------------------------------------
/alipay/util_api.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "context"
5 | "encoding/base64"
6 | "encoding/json"
7 | "fmt"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // alipay.open.app.alipaycert.download(应用支付宝公钥证书下载)
13 | // 文档地址:https://opendocs.alipay.com/apis/api_9/alipay.open.app.alipaycert.download
14 | func (a *Client) PublicCertDownload(ctx context.Context, bm gopay.BodyMap) (aliRsp *PublicCertDownloadRsp, err error) {
15 | err = bm.CheckEmptyError("alipay_cert_sn")
16 | if err != nil {
17 | return nil, err
18 | }
19 | var bs []byte
20 | if bs, err = a.doAliPay(ctx, bm, "alipay.open.app.alipaycert.download"); err != nil {
21 | return nil, err
22 | }
23 | aliRsp = new(PublicCertDownloadRsp)
24 | if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
25 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
26 | }
27 | if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
28 | return aliRsp, err
29 | }
30 | certBs, err := base64.StdEncoding.DecodeString(aliRsp.Response.AlipayCertContent)
31 | if err != nil {
32 | return nil, fmt.Errorf("AlipayCertContent(%s)_DecodeErr:%+v", aliRsp.Response.AlipayCertContent, err)
33 | }
34 | aliRsp.Response.AlipayCertContent = string(certBs)
35 | return aliRsp, nil
36 | }
37 |
--------------------------------------------------------------------------------
/alipay/util_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/gopay/alipay/cert"
8 | "github.com/go-pay/xlog"
9 | )
10 |
11 | func TestClient_OpenAuthTokenApp(t *testing.T) {
12 | // 请求参数
13 | bm := make(gopay.BodyMap)
14 | bm.Set("grant_type", "authorization_code").
15 | Set("code", "866185490c4e40efa9f71efea6766X02")
16 |
17 | // 发起请求
18 | aliRsp, err := client.OpenAuthTokenApp(ctx, bm)
19 | if err != nil {
20 | if bizErr, ok := IsBizError(err); ok {
21 | xlog.Errorf("%+v", bizErr)
22 | // do something
23 | return
24 | }
25 | return
26 | }
27 | xlog.Debug("aliRsp:", *aliRsp)
28 | }
29 |
30 | func TestClient_OpenAuthTokenAppQuery(t *testing.T) {
31 | // 请求参数
32 | bm := make(gopay.BodyMap)
33 | bm.Set(AppAuthToken, "202212BB9e1cd0c2e0ab489393aa2570ec4faX87")
34 |
35 | // 发起请求
36 | aliRsp, err := client.OpenAuthTokenAppQuery(ctx, bm)
37 | if err != nil {
38 | if bizErr, ok := IsBizError(err); ok {
39 | xlog.Errorf("%+v", bizErr)
40 | // do something
41 | return
42 | }
43 | return
44 | }
45 | xlog.Debug("aliRsp:", *aliRsp)
46 | }
47 |
48 | func TestClient_UserInfoAuth(t *testing.T) {
49 | // 请求参数
50 | bm := make(gopay.BodyMap)
51 | // 接口权限值,目前只支持auth_user和auth_base两个值。具体说明看文档介绍
52 | bm.Set("scopes", []string{"auth_user"}).
53 | Set("state", "init")
54 |
55 | // 发起请求
56 | html, err := client.UserInfoAuth(ctx, bm)
57 | if err != nil {
58 | if bizErr, ok := IsBizError(err); ok {
59 | xlog.Errorf("%+v", bizErr)
60 | // do something
61 | return
62 | }
63 | return
64 | }
65 | xlog.Debugf("html: %s", string(html))
66 | }
67 |
68 | func TestClient_UserInfoShare(t *testing.T) {
69 | // 发起请求
70 | aliRsp, err := client.UserInfoShare(ctx, "authbseBb6dd42c0d93a47dfa1b23aa725778X18")
71 | if err != nil {
72 | xlog.Errorf("%+v", err)
73 | return
74 | }
75 | xlog.Debug("aliRsp:", *aliRsp)
76 |
77 | // 同步返回验签
78 | ok, err := VerifySyncSignWithCert(cert.AlipayPublicContentRSA2, aliRsp.SignData, aliRsp.Sign)
79 | if err != nil {
80 | xlog.Error(err)
81 | }
82 | xlog.Debug("ok:", ok)
83 | }
84 |
85 | func TestClient_PublicCertDownload(t *testing.T) {
86 | // 请求参数
87 | bm := make(gopay.BodyMap)
88 | bm.Set("alipay_cert_sn", "52c63ed47b57c049b4bc9bea9da02c2a")
89 |
90 | // 发起请求
91 | aliRsp, err := client.PublicCertDownload(ctx, bm)
92 | if err != nil {
93 | //xlog.Errorf("client.UserInfoShare(),error:%+v", err)
94 | return
95 | }
96 | xlog.Debugf("aliRsp.Response.AlipayCertContent:\n %s", aliRsp.Response.AlipayCertContent)
97 | }
98 |
--------------------------------------------------------------------------------
/alipay/v3/ad_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/util/js"
8 | "github.com/go-pay/xlog"
9 | )
10 |
11 | func TestAdReportdataQuery(t *testing.T) {
12 | // 请求参数
13 | bm := make(gopay.BodyMap)
14 | // err = bm.CheckEmptyError("biz_token", "alipay_pid", "query_type", "ad_level", "start_date", "end_date", "principal_tag")
15 | bm.Set("biz_token", "e09d869511189c24ce13fe3xxxxxx").
16 | Set("alipay_pid", "123456789010").
17 | Set("query_type", "SUM").
18 | Set("ad_level", "PLAN").
19 | Set("start_date", "20210801").
20 | Set("end_date", "20210802").
21 | Set("principal_tag", "shybo")
22 | // 创建订单
23 | aliRsp, err := client.AdReportdataQuery(ctx, bm)
24 | if err != nil {
25 | xlog.Errorf("client.AdReportdataQuery(), err:%v", err)
26 | return
27 | }
28 | xlog.Debugf("aliRsp:%s", js.MarshalString(aliRsp))
29 |
30 | if aliRsp.StatusCode != Success {
31 | xlog.Errorf("aliRsp.StatusCode:%d", aliRsp.StatusCode)
32 | return
33 | }
34 | xlog.Debug("aliRsp.CrowdNo:", aliRsp.DataList)
35 | }
36 |
37 | func TestAdPromotepageBatchquery(t *testing.T) {
38 | // 请求参数
39 | bm := make(gopay.BodyMap)
40 | // err = bm.CheckEmptyError("biz_token", "principal_tag", "page_no", "page_size")
41 | bm.Set("biz_token", "e09d869511189c24ce13fe3xxxxxx").
42 | Set("principal_tag", "shybo").
43 | Set("page_no", 1).
44 | Set("page_size", 10)
45 | // 创建订单
46 | aliRsp, err := client.AdPromotepageBatchquery(ctx, bm)
47 | if err != nil {
48 | xlog.Errorf("client.AdPromotepageBatchquery(), err:%v", err)
49 | return
50 | }
51 | xlog.Debugf("aliRsp:%s", js.MarshalString(aliRsp))
52 |
53 | if aliRsp.StatusCode != Success {
54 | xlog.Errorf("aliRsp.StatusCode:%d", aliRsp.StatusCode)
55 | return
56 | }
57 | xlog.Debug("aliRsp.Total:", aliRsp.Total)
58 | xlog.Debug("aliRsp.List:", aliRsp.List)
59 | }
60 |
--------------------------------------------------------------------------------
/alipay/v3/marketing_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "io"
5 | "os"
6 | "testing"
7 |
8 | "github.com/go-pay/gopay"
9 | "github.com/go-pay/xlog"
10 | )
11 |
12 | func TestMarketingMaterialImageUpload(t *testing.T) {
13 | // 请求参数
14 | logo, err := os.Open("../../logo.png")
15 | if err != nil {
16 | xlog.Errorf("os.Open(%s),error:%+v", "../logo.png", err)
17 | return
18 | }
19 | xlog.Warnf("fileName: %s", logo.Name())
20 | allBs, err := io.ReadAll(logo)
21 | if err != nil {
22 | xlog.Errorf("io.ReadAll(%s),error:%+v", logo.Name(), err)
23 | return
24 | }
25 | f := &gopay.File{
26 | Name: "logo.png",
27 | Content: allBs,
28 | }
29 | bm := make(gopay.BodyMap)
30 | bm.Set("file_key", "PROMO_VOUCHER_IMAGE").
31 | SetFormFile("file_content", f)
32 | aliRsp, err := client.MarketingMaterialImageUpload(ctx, bm)
33 | if err != nil {
34 | xlog.Errorf("client.MarketingMaterialImageUpload(),error:%+v", err)
35 | return
36 | }
37 | xlog.Debug("aliRsp:", *aliRsp)
38 | }
39 |
--------------------------------------------------------------------------------
/alipay/v3/member_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/util/js"
8 | "github.com/go-pay/xlog"
9 | )
10 |
11 | func TestClient_SystemOauthToken(t *testing.T) {
12 | // 请求参数
13 | bm := make(gopay.BodyMap)
14 | bm.Set("grant_type", "authorization_code").
15 | Set("code", "309cd66a1c024e4b9d89f7241db4UA18").
16 | Set(HeaderAppAuthToken, "202504BBcb0db76aff98487fb3fd2b733a474X87")
17 |
18 | // 发起请求
19 | aliRsp, err := client.SystemOauthToken(ctx, bm)
20 | if err != nil {
21 | xlog.Errorf("%+v", err)
22 | return
23 | }
24 | xlog.Debugf("aliRsp: %s", js.MarshalString(aliRsp))
25 | }
26 |
27 | func TestClient_UserInfoShare(t *testing.T) {
28 | // 请求参数
29 | bm := make(gopay.BodyMap)
30 | bm.Set("auth_token", "authbseB27c501c0804548b09e1f121ae0835X18").
31 | Set(HeaderAppAuthToken, "202504BB06476f1dc64f465997935ecf5072eX88")
32 |
33 | // 发起请求
34 | aliRsp, err := client.UserInfoShare(ctx, bm)
35 | if err != nil {
36 | xlog.Errorf("%+v", err)
37 | return
38 | }
39 | xlog.Debug("aliRsp:", js.MarshalString(aliRsp))
40 | }
41 |
42 | func TestClient_UserAuthRelationshipQuery(t *testing.T) {
43 | // 请求参数
44 | bm := make(gopay.BodyMap)
45 | bm.Set("scopes", "auth_user").
46 | Set("open_id", "018OacbttSLyJtNfdPbDOcaGoo-ncctDVT45IdYxaUsmIY8")
47 | // 发起请求
48 | aliRsp, err := client.UserAuthRelationshipQuery(ctx, bm)
49 | if err != nil {
50 | xlog.Errorf("%+v", err)
51 | return
52 | }
53 | xlog.Debug("aliRsp:", js.MarshalString(aliRsp))
54 | }
55 |
--------------------------------------------------------------------------------
/alipay/v3/model.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | // HTTP 状态码
4 | // 常见的 HTTP 状态码见下表。
5 | // HTTP 状态码 错误类型 一般的解决方案
6 | // 200 - OK 处理成功 -
7 | // 202 - Accepted 服务器已接受请求,但尚未处理 请使用原参数重复请求一遍。
8 | // 204 - No Content 处理成功,无返回Body -
9 | // 400 - Bad Request 协议或者参数非法 请检查请求参数是否符合要求。
10 | // 401 - Unauthorized 调用未授权 请检查签名参数和方法是否都符合签名算法要求。
11 | // 403 - Forbidden 无权限调用 请检查产品权限开通情况,可联系产品或商务申请。
12 | // 404 - Not Found 请求的资源不存在 请检查需要查询的 id 或者请求 URL 是否正确。
13 | // 429 - Too Many Requests 请求超过频率限制 请求未受理,请降低频率后重试。
14 | // 500 - Server Error 系统错误 按具体接口的错误指引进行重试。
15 |
16 | type ErrResponse struct {
17 | Code string `json:"code"` // 详细错误码,参考接口描述及公共错误码,商家需要对该错误码处理。
18 | Message string `json:"message"` // 错误描述,具体错误原因的文字描述,开发者可参考该描述判断错误原因。
19 | Details []*Detail `json:"details,omitempty"`
20 | Links []*Link `json:"links,omitempty"`
21 | }
22 |
23 | type Detail struct {
24 | Field string `json:"field"`
25 | Value string `json:"value"`
26 | Location string `json:"location"`
27 | Issue string `json:"issue"`
28 | Description string `json:"description"`
29 | }
30 |
31 | type Link struct {
32 | Link string `json:"link"`
33 | Desc string `json:"desc"`
34 | Rel string `json:"rel"`
35 | }
36 |
--------------------------------------------------------------------------------
/alipay/v3/model_campaign.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | type MarketingCampaignCashCreateRsp struct {
4 | StatusCode int `json:"status_code"`
5 | ErrResponse ErrResponse `json:"-"`
6 |
7 | CrowdNo string `json:"crowd_no"`
8 | PayUrl string `json:"pay_url"`
9 | OriginCrowdNo string `json:"origin_crowd_no"`
10 | }
11 |
12 | type MarketingCampaignCashTriggerRsp struct {
13 | StatusCode int `json:"status_code"`
14 | ErrResponse ErrResponse `json:"-"`
15 |
16 | TriggerResult string `json:"trigger_result"`
17 | PrizeAmount string `json:"prize_amount"`
18 | RepeatTriggerFlag string `json:"repeat_trigger_flag"`
19 | PartnerId string `json:"partner_id"`
20 | ErrorMsg string `json:"error_msg"`
21 | CouponName string `json:"coupon_name"`
22 | PrizeMsg string `json:"prize_msg"`
23 | MerchantLogo string `json:"merchant_logo"`
24 | BizNo string `json:"biz_no"`
25 | OutBizNo string `json:"out_biz_no"`
26 | }
27 |
28 | type MarketingCampaignCashStatusModifyRsp struct {
29 | StatusCode int `json:"status_code"`
30 | ErrResponse ErrResponse `json:"-"`
31 | }
32 |
33 | type MarketingCampaignCashListQueryRsp struct {
34 | StatusCode int `json:"status_code"`
35 | ErrResponse ErrResponse `json:"-"`
36 |
37 | PageSize string `json:"page_size"`
38 | CampList []struct {
39 | CrowdNo string `json:"crowd_no"`
40 | OriginCrowdNo string `json:"origin_crowd_no"`
41 | CampStatus string `json:"camp_status"`
42 | CouponName string `json:"coupon_name"`
43 | } `json:"camp_list"`
44 | PageIndex string `json:"page_index"`
45 | TotalSize string `json:"total_size"`
46 | }
47 |
48 | type MarketingCampaignCashDetailQueryRsp struct {
49 | StatusCode int `json:"status_code"`
50 | ErrResponse ErrResponse `json:"-"`
51 |
52 | CrowdNo string `json:"crowd_no"`
53 | CouponName string `json:"coupon_name"`
54 | PrizeMsg string `json:"prize_msg"`
55 | PrizeType string `json:"prize_type"`
56 | StartTime string `json:"start_time"`
57 | EndTime string `json:"end_time"`
58 | TotalAmount float64 `json:"total_amount"`
59 | SendAmount float64 `json:"send_amount"`
60 | TotalNum int `json:"total_num"`
61 | TotalCount int `json:"total_count"`
62 | OriginCrowdNo string `json:"origin_crowd_no"`
63 | CampStatus string `json:"camp_status"`
64 | }
65 |
--------------------------------------------------------------------------------
/alipay/v3/model_marketing.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | type MarketingActivityDeliveryCreateRsp struct {
4 | StatusCode int `json:"status_code"`
5 | ErrResponse ErrResponse `json:"-"`
6 |
7 | DeliveryId string `json:"delivery_id"`
8 | DeliveryGuidePreviewUrl string `json:"delivery_guide_preview_url"`
9 | }
10 |
11 | type MarketingActivityDeliveryQueryRsp struct {
12 | StatusCode int `json:"status_code"`
13 | ErrResponse ErrResponse `json:"-"`
14 |
15 | DeliveryId string `json:"delivery_id"`
16 | DeliveryStatus string `json:"delivery_status"`
17 | DeliveryBoothCode string `json:"delivery_booth_code"`
18 | DeliveryErrorMsg string `json:"delivery_error_msg"`
19 | DeliveryBaseInfo struct {
20 | DeliveryName string `json:"delivery_name"`
21 | DeliveryBeginTime string `json:"delivery_begin_time"`
22 | DeliveryEndTime string `json:"delivery_end_time"`
23 | DeliveryMaterial struct {
24 | DeliverySingleMaterial struct {
25 | DeliveryImage string `json:"delivery_image"`
26 | } `json:"delivery_single_material"`
27 | } `json:"delivery_material"`
28 | } `json:"delivery_base_info"`
29 | DeliveryPlayConfig struct {
30 | DeliverySingleSendConfig struct {
31 | DeliveryContentInfo struct {
32 | DeliveryContentType string `json:"delivery_content_type"`
33 | DeliveryActivityContent struct {
34 | ActivityId string `json:"activity_id"`
35 | } `json:"delivery_activity_content"`
36 | } `json:"delivery_content_info"`
37 | DeliveryContentConfig struct {
38 | DeliverySendGuide struct {
39 | DeliveryGuideUrl string `json:"delivery_guide_url"`
40 | } `json:"delivery_send_guide"`
41 | } `json:"delivery_content_config"`
42 | } `json:"delivery_single_send_config"`
43 | } `json:"delivery_play_config"`
44 | DeliveryTargetRule struct {
45 | DeliveryCityCodeRule struct {
46 | CityCodes []string `json:"city_codes"`
47 | AllCity bool `json:"all_city"`
48 | } `json:"delivery_city_code_rule"`
49 | DeliveryRecallMode string `json:"delivery_recall_mode"`
50 | } `json:"delivery_target_rule"`
51 | }
52 |
53 | type MarketingActivityDeliveryStopRsp struct {
54 | StatusCode int `json:"status_code"`
55 | ErrResponse ErrResponse `json:"-"`
56 |
57 | DeliveryId string `json:"delivery_id"`
58 | }
59 |
60 | type MarketingMaterialImageUploadRsp struct {
61 | StatusCode int `json:"status_code"`
62 | ErrResponse ErrResponse `json:"-"`
63 |
64 | ResourceId string `json:"resource_id"`
65 | ResourceEnhance bool `json:"resource_enhance"`
66 | ResourceUrl string `json:"resource_url"`
67 | }
68 |
--------------------------------------------------------------------------------
/alipay/v3/model_member.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | type SystemOauthTokenRsp struct {
4 | StatusCode int `json:"status_code"`
5 | ErrResponse ErrResponse `json:"-"`
6 |
7 | AccessToken string `json:"access_token"`
8 | RefreshToken string `json:"refresh_token"`
9 | OpenId string `json:"open_id"`
10 | ReExpiresIn int `json:"re_expires_in"`
11 | AuthStart string `json:"auth_start"`
12 | ExpiresIn int `json:"expires_in"`
13 | }
14 |
15 | type UserCertifyOpenQueryRsp struct {
16 | StatusCode int `json:"status_code"`
17 | ErrResponse ErrResponse `json:"-"`
18 |
19 | Passed string `json:"passed"`
20 | IdentityInfo string `json:"identity_info"`
21 | MaterialInfo string `json:"material_info"`
22 | FailReason string `json:"fail_reason"`
23 | }
24 |
25 | type UserCertifyOpenInitializeRsp struct {
26 | StatusCode int `json:"status_code"`
27 | ErrResponse ErrResponse `json:"-"`
28 |
29 | CertifyId string `json:"certify_id"`
30 | }
31 |
32 | type UserInfoShareRsp struct {
33 | StatusCode int `json:"status_code"`
34 | ErrResponse ErrResponse `json:"-"`
35 |
36 | UserId string `json:"user_id"`
37 | OpenId string `json:"open_id"`
38 | Avatar string `json:"avatar"`
39 | City string `json:"city"`
40 | NickName string `json:"nick_name"`
41 | Province string `json:"province"`
42 | Gender string `json:"gender"`
43 | }
44 |
45 | type UserAuthRelationshipQueryRsp struct {
46 | StatusCode int `json:"status_code"`
47 | ErrResponse ErrResponse `json:"-"`
48 |
49 | QueryDetail string `json:"query_detail"`
50 | }
51 |
52 | type UserDelOauthDetailQueryRsp struct {
53 | StatusCode int `json:"status_code"`
54 | ErrResponse ErrResponse `json:"-"`
55 |
56 | Details []*UserDelOauthDetail `json:"details"`
57 | }
58 |
59 | type UserDelOauthDetail struct {
60 | DelAuthTime string `json:"del_auth_time"`
61 | UserId string `json:"user_id"`
62 | OpenId string `json:"open_id"`
63 | }
64 |
--------------------------------------------------------------------------------
/alipay/v3/payment_api_test.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/util"
8 | "github.com/go-pay/util/js"
9 | "github.com/go-pay/xlog"
10 | )
11 |
12 | func TestTradePrecreate(t *testing.T) {
13 | // 请求参数
14 | bm := make(gopay.BodyMap)
15 | bm.Set("subject", "预创建创建订单").
16 | Set("out_trade_no", util.RandomString(32)).
17 | Set("total_amount", "0.01")
18 |
19 | // 创建订单
20 | aliRsp, err := client.TradePrecreate(ctx, bm)
21 | if err != nil {
22 | xlog.Errorf("client.TradePrecreate(), err:%v", err)
23 | return
24 | }
25 | xlog.Debugf("aliRsp:%s", js.MarshalString(aliRsp))
26 |
27 | if aliRsp.StatusCode != Success {
28 | xlog.Errorf("aliRsp.StatusCode:%d", aliRsp.StatusCode)
29 | return
30 | }
31 | xlog.Debug("aliRsp.QrCode:", aliRsp.QrCode)
32 | xlog.Debug("aliRsp.OutTradeNo:", aliRsp.OutTradeNo)
33 | }
34 |
35 | func TestTradeCreate(t *testing.T) {
36 | // 请求参数
37 | bm := make(gopay.BodyMap)
38 | bm.Set("subject", "创建订单").
39 | Set("out_trade_no", util.RandomString(32)).
40 | Set("total_amount", "0.01").
41 | Set("product_code", "JSAPI_PAY").
42 | Set("op_app_id", "2021005143630063"). // 小程序的APPID
43 | Set("buyer_open_id", "018OacbttSLyJtNfdPbDOcaGoo-ncctDVT45IdYxaUsmIY8")
44 |
45 | // 创建订单
46 | aliRsp, err := client.TradeCreate(ctx, bm)
47 | if err != nil {
48 | xlog.Errorf("client.TradeCreate(), err:%v", err)
49 | return
50 | }
51 | xlog.Debugf("aliRsp:%s", js.MarshalString(aliRsp))
52 |
53 | if aliRsp.StatusCode != Success {
54 | xlog.Errorf("aliRsp.StatusCode:%d", aliRsp.StatusCode)
55 | return
56 | }
57 | xlog.Debug("aliRsp.TradeNo:", aliRsp.TradeNo)
58 | xlog.Debug("aliRsp.OutTradeNo:", aliRsp.OutTradeNo)
59 | }
60 |
--------------------------------------------------------------------------------
/allinpay/api.go:
--------------------------------------------------------------------------------
1 | package allinpay
2 |
3 | const (
4 | // 统一支付接口
5 | payPath = "/unitorder/pay"
6 | // 统一扫码接口
7 | scanQrPath = "/unitorder/scanqrpay"
8 | // 交易查询接口
9 | queryPath = "/tranx/query"
10 | // 交易退款接口
11 | refundPath = "/tranx/refund"
12 | // 交易取消接口
13 | cancelPath = "/tranx/cancel"
14 | // 订单关闭
15 | closePath = "/unitorder/close"
16 | )
17 |
--------------------------------------------------------------------------------
/allinpay/cert/cert.go:
--------------------------------------------------------------------------------
1 | package cert
2 |
3 | const (
4 | CusId = "990361082416001"
5 | AppId = "00012395"
6 | PrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCW/IG0a0swTXKqT6h9rEDh7i2LS1+92Ab/e4ZbNT+zWKzYPkbJ96EphN49ik7gMK1BOaMS9C+AgGvEDgizGxTR+RoRsbbeTqBMdVm2rDUK4tnlVHoWEa5eDOLomzb4EJs03OJ91qcgJk9neCTEkntXWcBKNNXEvlCFXAPEfsaccEXmi2ouYyaqT5cYBihULYB7DTTPXsOg09A/KjICSJIBGTFRjjpfwgXisjBaNjOWYAlXHF3UVisMlZueKVWnO1USdWK24gQEis1HSf0mj61rAVQMt5/dkMYbxVQlQvKlJFMXt/koKzo1GoanMfyFSg0iyI6zcBWynhmBIASwwkdzAgMBAAECggEAO/vYOcnQhsGWFvRrr3XiFwAtZuQMhtsOuKwl7hFjG8jUblqbe/ydseV/93n9qRKdmkagM1UAlDAw4CRlL2bIaDzrLvFoAbzB8W5DtI+IySjjwTjFAgSHPgUnlpqnhXjveFpyvuSq49pkfGpeTRwW1VaqTrDb5nxnd/vc4VEubZKO6D1wgUpyczNiqvjfEecX0gwLHtwUI6jqMYcq0bRCJ5aXqXZHBqIDZ+2j9wpBx0CvdNdRULYAwO824xLxmCu3cIAUBntTsZ6MlBjIfYHdXJY3jOwK2AR+RPJ3NDPotgwf9JkxcAGRqC47GEn1Wjz1iDglhLnasPHYeOXczLsAfQKBgQDJYL4CIXPNfAbCdJKGb0H2kKrkG4Jt2PnYKySFLKzY9HvKnco9h+6t6lxvtTlWZtb8gLwiDsqaP4X24W6pVwedkSSK8JPbjaepDA7gzqCGRE7IVJLMU6PO8j0DNXGT5z9whNQJXWv6qIlC3AeWBHNov0b2BK7RXWr54YP5tpoChwKBgQC/8K54scZYV/XlYmaFQnzv9ZCUaLrPyvpDzXi0jxmIuYs2uslWKnsXzgGZNcbaDdIRa0T4xNHCVkbb3AW2QfEqXA+TUjse877znScTkfdVsW0dADHEm5YN9Ec1sxPQI4IUaWqC//59AjewfDJS6lEcerGvIZLPVG6y1L7E0AcStQKBgQDIrWSMQQPiyO7/hyWhXGvypxX1fUiL6QaJmeyp3exdw709G+M3UCfVHlCBbao25QLm2+8fTXgvIJCChwI9NKI9Li+pWbcuuspSltaYxrCHPLj5v/YOMmdySkns0axehLreiS+4KWX6g0tN2nCg2cycnMi9T8tajmqVm1tmVMbDLwKBgFC6/ddcBq3vyUhC3BYewgf3xGj3p+NwX1UXXjarnbTJPcm2RKrOUVnQ1xFG8i2S9JFJCgiMWCGiQkmFQI3JLJOBhzeStbUuFlnG9sGfemV7rAYvp78nJbUW0sC+Yo3/8V1+fUM+Qx73SM8dXdlMHvOYk5WyzFoSDEGBg/+p89+lAoGBAMhuMLE0K1mDxF4fp9Bpxvu2xhJuFYfBQNizUQE4nPvjG7czFv7UZXhO9ml6OOf9483YBHi9O3uhMTjiiqnFVcJrjiy3bhsdamm9FnO7GMgoZ7QOlq8LNikVRuPj+udSwrF3ICVAMMKq8bAxzZTGQoAH2He3S5K4dY+kGbsTsQxt"
7 | PublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm9OV6zH5DYH/ZnAVYHscEELdCNfNTHGuBv1nYYEY9FrOzE0/4kLl9f7Y9dkWHlc2ocDwbrFSm0Vqz0q2rJPxXUYBCQl5yW3jzuKSXif7q1yOwkFVtJXvuhf5WRy+1X5FOFoMvS7538No0RpnLzmNi3ktmiqmhpcY/1pmt20FHQQIDAQAB"
8 | )
9 |
--------------------------------------------------------------------------------
/allinpay/client_test.go:
--------------------------------------------------------------------------------
1 | package allinpay
2 |
3 | import (
4 | "context"
5 | "os"
6 | "testing"
7 |
8 | "github.com/go-pay/gopay/allinpay/cert"
9 | "github.com/go-pay/xlog"
10 | )
11 |
12 | var (
13 | ctx = context.Background()
14 | client *Client
15 | err error
16 | )
17 |
18 | func TestMain(m *testing.M) {
19 | // 初始化通联客户端
20 | // cusId: 实际交易商户号
21 | // appid:平台分配的APPID
22 | // privateKey:商户的RSA私钥
23 | // publicKey:通联的公钥
24 | // isProd:是否是正式环境
25 | client, err = NewClient(cert.CusId, cert.AppId, cert.PrivateKey, cert.PublicKey, true)
26 | if err != nil {
27 | xlog.Error(err)
28 | return
29 | }
30 |
31 | os.Exit(m.Run())
32 | }
33 |
--------------------------------------------------------------------------------
/allinpay/error.go:
--------------------------------------------------------------------------------
1 | package allinpay
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | // BizErr 用于判断通联的业务逻辑是否有错误
8 | type BizErr struct {
9 | Code string `json:"code"`
10 | Msg string `json:"msg"`
11 | }
12 |
13 | // bizErrCheck 检查返回码是否为SUCCESS 否则返回一个BizErr
14 | func bizErrCheck(resp RspBase) error {
15 | if resp.RetCode != "SUCCESS" {
16 | return &BizErr{
17 | Code: resp.RetCode,
18 | Msg: resp.RetMsg,
19 | }
20 | }
21 | return nil
22 | }
23 |
24 | func (e *BizErr) Error() string {
25 | return fmt.Sprintf(`{"code":"%s","msg":"%s"}`, e.Code, e.Msg)
26 | }
27 |
--------------------------------------------------------------------------------
/allinpay/model.go:
--------------------------------------------------------------------------------
1 | package allinpay
2 |
3 | const (
4 | // URL
5 | baseUrl = "https://vsp.allinpay.com/apiweb"
6 | sandboxBaseUrl = "https://syb-test.allinpay.com/apiweb"
7 |
8 | RSA = "RSA"
9 | SM2 = "SM2"
10 |
11 | // OrderTypeReqSN 商家自由订单号
12 | OrderTypeReqSN = "reqsn"
13 | // OrderTypeTrxId 通联生产支付号
14 | OrderTypeTrxId = "trxid"
15 |
16 | // PayTypeWXScan 微信扫码支付
17 | PayTypeWXScan = "W01"
18 | // PayTypeWXJS 微信JS支付
19 | PayTypeWXJS = "W02"
20 | // PayTypeWXMini 微信小程序支付
21 | PayTypeWXMini = "W03"
22 | // PayTypeAliScan 支付宝扫码支付
23 | PayTypeAliScan = "A01"
24 | // PayTypeAliJS 支付宝JS支付
25 | PayTypeAliJS = "A02"
26 | // PayTypeAliApp 支付宝APP支付
27 | PayTypeAliApp = "A03"
28 | // PayTypeQQScan 手机QQ扫码支付
29 | PayTypeQQScan = "Q01"
30 | // PayTypeQQJS 手机QQ JS支付
31 | PayTypeQQJS = "Q02"
32 | // PayTypeUniPay 银联扫码支付(CSB)
33 | PayTypeUniPay = "U01"
34 | // PayTypeUniJS 银联JS支付
35 | PayTypeUniJS = "U02"
36 | // PayTypeNumH5 数字货币H5
37 | PayTypeNumH5 = "S01"
38 | )
39 |
40 | type RspBase struct {
41 | RetCode string `json:"retcode"`
42 | RetMsg string `json:"retmsg"`
43 | Sign string `json:"sign"`
44 | Cusid string `json:"cusid"`
45 | Appid string `json:"appid"`
46 | }
47 |
48 | // PayRsp 通用支付响应
49 | type PayRsp struct {
50 | RspBase
51 | Trxid string `json:"trxid"`
52 | ChnlTrxId string `json:"chnltrxid"`
53 | Reqsn string `json:"reqsn"`
54 | RandomStr string `json:"randomstr"`
55 | TrxStatus string `json:"trxstatus"`
56 | FinTime string `json:"fintime"`
57 | ErrMsg string `json:"errmsg"`
58 | PayInfo string `json:"payinfo"`
59 | }
60 |
61 | // ScanPayRsp 扫码支付、订单查询响应
62 | type ScanPayRsp struct {
63 | RspBase
64 | Trxid string `json:"trxid"`
65 | ChnlTrxId string `json:"chnltrxid"`
66 | Reqsn string `json:"reqsn"`
67 | TrxStatus string `json:"trxstatus"`
68 | Acct string `json:"acct"`
69 | TrxCode string `json:"trxcode"`
70 | FinTime string `json:"fintime"`
71 | ErrMsg string `json:"errmsg"`
72 | RandomStr string `json:"randomstr"`
73 | InitAmt string `json:"initamt"`
74 | TrxAmt string `json:"trxamt"`
75 | Fee string `json:"fee"`
76 | Cmid string `json:"cmid"`
77 | Chnlid string `json:"chnlid"`
78 | ChnlData string `json:"chnldata"`
79 | AcctType string `json:"accttype"`
80 | }
81 |
82 | // RefundRsp 退款响应
83 | type RefundRsp struct {
84 | RspBase
85 | Trxid string `json:"trxid"`
86 | Reqsn string `json:"reqsn"`
87 | TrxStatus string `json:"trxstatus"`
88 | FinTime string `json:"fintime"`
89 | ErrMsg string `json:"errmsg"`
90 | Fee string `json:"fee"`
91 | TrxCode string `json:"trxCode"`
92 | RandomStr string `json:"randomstr"`
93 | ChnlTrxId string `json:"chnltrxid"`
94 | }
95 |
96 | // CloseRsp 关闭响应
97 | type CloseRsp struct {
98 | RspBase
99 | TrxStatus string `json:"trxstatus"`
100 | }
101 |
--------------------------------------------------------------------------------
/allinpay/pay_test.go:
--------------------------------------------------------------------------------
1 | package allinpay
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func TestClient_ScanPay(t *testing.T) {
11 | // 扫码支付
12 | // 请求参数
13 | bm := make(gopay.BodyMap)
14 | bm.Set("trxamt", "1").
15 | Set("reqsn", "larry01").
16 | Set("body", "支付测试").
17 | SetBodyMap("terminfo", func(b gopay.BodyMap) {
18 | b.Set("devicetype", "10").
19 | Set("termno", "00000001")
20 | }).
21 | Set("authcode", "131104796948096102")
22 | // 创建订单
23 | resp, err := client.ScanPay(ctx, bm)
24 | xlog.Debugf("allRsp:%+v", resp)
25 | if err != nil {
26 | xlog.Errorf("%+v", err)
27 | return
28 | }
29 | }
30 |
31 | func TestClient_Query(t *testing.T) {
32 | // 查询订单
33 | resp, err := client.Query(ctx, OrderTypeReqSN, "larry01")
34 | xlog.Debugf("aliRsp:%+v", resp)
35 | if err != nil {
36 | xlog.Errorf("%+v", err)
37 | return
38 | }
39 | }
40 |
41 | func TestClient_Refund(t *testing.T) {
42 | // 请求参数
43 | bm := make(gopay.BodyMap)
44 | bm.Set("trxamt", "1").
45 | Set("reqsn", "relarry01").
46 | Set("remark", "支付测试退款").
47 | Set("oldreqsn", "larry01")
48 |
49 | // 退款
50 | resp, err := client.Refund(ctx, bm)
51 | xlog.Debugf("allRsp:%+v", resp)
52 | if err != nil {
53 | xlog.Errorf("%+v", err)
54 | return
55 | }
56 | }
57 |
58 | func TestClient_Cancel(t *testing.T) {
59 | // 订单退款
60 | bm := make(gopay.BodyMap)
61 | bm.Set("trxamt", "1").
62 | Set("reqsn", "cclarry01").
63 | Set("remark", "支付测试取消").
64 | Set("oldreqsn", "larry01")
65 |
66 | // 取消订单
67 | resp, err := client.Cancel(ctx, bm)
68 | xlog.Debugf("allRsp:%+v", resp)
69 | if err != nil {
70 | xlog.Errorf("%+v", err)
71 | return
72 | }
73 | }
74 |
75 | func TestClient_Close(t *testing.T) {
76 | // 订单关闭
77 | bm := make(gopay.BodyMap)
78 | bm.Set("oldreqsn", "larry01")
79 | // 创建订单
80 | resp, err := client.Close(ctx, bm)
81 | xlog.Debugf("allRsp:%+v", resp)
82 | if err != nil {
83 | xlog.Errorf("%+v", err)
84 | return
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/allinpay/sign.go:
--------------------------------------------------------------------------------
1 | package allinpay
2 |
3 | import (
4 | "crypto"
5 | "crypto/rsa"
6 | "encoding/base64"
7 | "encoding/json"
8 | "fmt"
9 |
10 | "github.com/go-pay/gopay"
11 | )
12 |
13 | // verifySign 验证响应签名
14 | func (c *Client) verifySign(bs []byte) (err error) {
15 | bm := gopay.BodyMap{}
16 | if err = json.Unmarshal(bs, &bm); err != nil {
17 | return err
18 | }
19 | sign := bm.Get("sign")
20 | bm.Remove("sign")
21 | signData := bm.EncodeAliPaySignParams()
22 | signBytes, _ := base64.StdEncoding.DecodeString(sign)
23 | hashs := crypto.SHA1
24 | c.mu.Lock()
25 | defer func() {
26 | c.sha1Hash.Reset()
27 | c.mu.Unlock()
28 | }()
29 | c.sha1Hash.Write([]byte(signData))
30 | if err = rsa.VerifyPKCS1v15(c.publicKey, hashs, c.sha1Hash.Sum(nil), signBytes); err != nil {
31 | return fmt.Errorf("[%w]: %v", gopay.VerifySignatureErr, err)
32 | }
33 | return nil
34 | }
35 |
--------------------------------------------------------------------------------
/apple/cert.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "crypto/ecdsa"
5 | "crypto/x509"
6 | "encoding/pem"
7 | "errors"
8 | )
9 |
10 | // ParseECPrivateKeyFromPEM parses a PEM encoded Elliptic Curve Private Key Structure
11 | func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
12 | var err error
13 | // Parse PEM block
14 | var block *pem.Block
15 | if block, _ = pem.Decode(key); block == nil {
16 | return nil, errors.New("decode private key error")
17 | }
18 | // Parse the key
19 | var parsedKey any
20 | if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil {
21 | if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
22 | return nil, err
23 | }
24 | }
25 | pkey, ok := parsedKey.(*ecdsa.PrivateKey)
26 | if !ok {
27 | return nil, errors.New("private key must be ECP private key")
28 | }
29 | return pkey, nil
30 | }
31 |
--------------------------------------------------------------------------------
/apple/client_test.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 | "os"
6 | "testing"
7 |
8 | "github.com/go-pay/xlog"
9 | )
10 |
11 | var (
12 | ctx = context.Background()
13 | client *Client
14 | err error
15 |
16 | iss = "57246542-96fe-1a63-e053-0824d011072a"
17 | bid = "com.example.testbundleid2021"
18 | kid = "2X9R4HXF34"
19 | )
20 |
21 | func TestMain(m *testing.M) {
22 | xlog.SetLevel(xlog.DebugLevel)
23 | // 初始化客户端
24 | // iss:issuer ID
25 | // bid:bundle ID
26 | // kid:private key ID
27 | // privateKey:私钥文件读取后的字符串内容
28 | // isProd:是否是正式环境
29 | client, err = NewClient(iss, bid, kid, "privateKey", false)
30 | if err != nil {
31 | xlog.Error(err)
32 | return
33 | }
34 |
35 | os.Exit(m.Run())
36 | }
37 |
--------------------------------------------------------------------------------
/apple/constant.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | const (
4 | hostUrl = "https://api.storekit.itunes.apple.com"
5 | sandBoxHostUrl = "https://api.storekit-sandbox.itunes.apple.com"
6 |
7 | // Get Transaction History
8 | getTransactionHistory = "/inApps/v1/history/%s" // transactionId
9 |
10 | // Get Transaction History
11 | getTransactionHistoryV2 = "/inApps/v2/history/%s" // transactionId
12 |
13 | // Get Transaction Info
14 | getTransactionInfo = "/inApps/v1/transactions/%s" // transactionId
15 |
16 | // Get All Subscription Statuses
17 | getAllSubscriptionStatuses = "/inApps/v1/subscriptions/%s" // transactionId
18 |
19 | // Send Consumption Information
20 | sendConsumptionInformation = "/inApps/v1/transactions/consumption/%s" // transactionId
21 |
22 | // Look Up Order ID
23 | lookUpOrderID = "/inApps/v1/lookup/%s" // orderId
24 |
25 | // Get Subscription Status
26 | getRefundHistory = "/inApps/v2/refund/lookup/%s" // transactionId
27 |
28 | // Get Notification History
29 | getNotificationHistory = "/inApps/v1/notifications/history"
30 | )
31 |
--------------------------------------------------------------------------------
/apple/consumption.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "net/http"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // SendConsumptionInformation Send Consumption Information
12 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/send_consumption_information
13 | func (c *Client) SendConsumptionInformation(ctx context.Context, transactionId string, bm gopay.BodyMap) (err error) {
14 | path := fmt.Sprintf(sendConsumptionInformation, transactionId)
15 | res, _, err := c.doRequestPut(ctx, path, bm)
16 | if err != nil {
17 | return err
18 | }
19 | if res.StatusCode != http.StatusAccepted {
20 | return fmt.Errorf("http.stauts_code = %d", res.StatusCode)
21 | }
22 | return nil
23 | }
24 |
--------------------------------------------------------------------------------
/apple/doc.go:
--------------------------------------------------------------------------------
1 | // apple 苹果应用内支付SDK(目前仅支持一个校验逻辑--服务端模式)。
2 | // 整体流程简述:
3 | // 1. app从服务端获取待支付订单ID(这个订单ID是自己服务端产生的订单信息)和待付费productId(如果在苹果上配置了多个productId,则需要从服务端拉取自己的商品和苹果商品关联信息,这里的是指在苹果的productId);
4 | // 2. app根据productId,发起应用内支付;
5 | // 3. app得到支付成功结果,并将支付结果的receipt信息以及第一步的待支付订单ID发回自己的服务端,服务端调用SDK的Verify,得到校验结果(表示该支付信息是否是苹果处理的);
6 | // 4. 如果校验成功则表示苹果支付完成,根据第三步传回的订单ID来处理自己的后续业务逻辑;
7 | //
8 | // 综上:当使用苹果的应用内支付时,其实是由自己的客户端APP来发起的“支付结果通知”请求来推动业务支付流程的数据流转。
9 | // 参考文档:https://help.apple.com/app-store-connect/#/devb57be10e7
10 | // **注:实际测试时发现校验接口的返回信息和文档介绍的返回信息仅状态码字段可以对应,其他内容基本不匹配,返回信息可以参考client_test.go**
11 | package apple
12 |
--------------------------------------------------------------------------------
/apple/error.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import "fmt"
4 |
5 | // StatusCodeErr 用于判断Apple的status_code错误
6 | type StatusCodeErr struct {
7 | ErrorCode int `json:"errorCode,omitempty"`
8 | ErrorMessage string `json:"errorMessage,omitempty"`
9 | }
10 |
11 | // statusCodeErrCheck 检查状态码是否为非200错误
12 | func statusCodeErrCheck(errRsp StatusCodeErr) error {
13 | if errRsp.ErrorCode != 0 {
14 | return &StatusCodeErr{
15 | ErrorCode: errRsp.ErrorCode,
16 | ErrorMessage: errRsp.ErrorMessage,
17 | }
18 | }
19 | return nil
20 | }
21 |
22 | func (e *StatusCodeErr) Error() string {
23 | return fmt.Sprintf(`{"errorCode":"%d","errorMessage":"%s"}`, e.ErrorCode, e.ErrorMessage)
24 | }
25 |
26 | func IsStatusCodeError(err error) (*StatusCodeErr, bool) {
27 | if bizErr, ok := err.(*StatusCodeErr); ok {
28 | return bizErr, true
29 | }
30 | return nil, false
31 | }
32 |
--------------------------------------------------------------------------------
/apple/notification_v2.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // rootPEM is from `openssl x509 -inform der -in AppleRootCA-G3.cer -out apple_root.pem`
13 | const rootPEM = `
14 | -----BEGIN CERTIFICATE-----
15 | MIICQzCCAcmgAwIBAgIILcX8iNLFS5UwCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwS
16 | QXBwbGUgUm9vdCBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9u
17 | IEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcN
18 | MTQwNDMwMTgxOTA2WhcNMzkwNDMwMTgxOTA2WjBnMRswGQYDVQQDDBJBcHBsZSBS
19 | b290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9y
20 | aXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzB2MBAGByqGSM49
21 | AgEGBSuBBAAiA2IABJjpLz1AcqTtkyJygRMc3RCV8cWjTnHcFBbZDuWmBSp3ZHtf
22 | TjjTuxxEtX/1H7YyYl3J6YRbTzBPEVoA/VhYDKX1DyxNB0cTddqXl5dvMVztK517
23 | IDvYuVTZXpmkOlEKMaNCMEAwHQYDVR0OBBYEFLuw3qFYM4iapIqZ3r6966/ayySr
24 | MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gA
25 | MGUCMQCD6cHEFl4aXTQY2e3v9GwOAEZLuN+yRhHFD/3meoyhpmvOwgPUnPWTxnS4
26 | at+qIxUCMG1mihDK1A3UT82NQz60imOlM27jbdoXt2QfyFMm+YhidDkLF1vLUagM
27 | 6BgD56KyKA==
28 | -----END CERTIFICATE-----
29 | `
30 |
31 | // DecodeSignedPayload 解析SignedPayload数据
32 | func DecodeSignedPayload(signedPayload string) (payload *NotificationV2Payload, err error) {
33 | if signedPayload == "" {
34 | return nil, fmt.Errorf("signedPayload is empty")
35 | }
36 | payload = &NotificationV2Payload{}
37 | if err = ExtractClaims(signedPayload, payload); err != nil {
38 | return nil, err
39 | }
40 | return
41 | }
42 |
43 | // GetNotificationHistory Get Notification History
44 | // rsp.NotificationHistory[x].SignedPayload use apple.DecodeSignedPayload() to decode
45 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/get_notification_history
46 | func (c *Client) GetNotificationHistory(ctx context.Context, paginationToken string, bm gopay.BodyMap) (rsp *NotificationHistoryRsp, err error) {
47 | path := getNotificationHistory
48 | // Note: Omit this parameter the first time you call this endpoint.
49 | if paginationToken != "" {
50 | path += "?paginationToken=" + paginationToken
51 | }
52 |
53 | res, bs, err := c.doRequestPost(ctx, path, bm)
54 | if err != nil {
55 | return nil, err
56 | }
57 | rsp = &NotificationHistoryRsp{}
58 | if err = json.Unmarshal(bs, rsp); err != nil {
59 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
60 | }
61 | if res.StatusCode == http.StatusOK {
62 | return rsp, nil
63 | }
64 | if err = statusCodeErrCheck(rsp.StatusCodeErr); err != nil {
65 | return rsp, err
66 | }
67 | return rsp, nil
68 | }
69 |
--------------------------------------------------------------------------------
/apple/order.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // LookUpOrderId Look Up Order ID
13 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/look_up_order_id
14 | func (c *Client) LookUpOrderId(ctx context.Context, orderId string) (rsp *LookUpOrderIdRsp, err error) {
15 | path := fmt.Sprintf(lookUpOrderID, orderId)
16 | res, bs, err := c.doRequestGet(ctx, path)
17 | if err != nil {
18 | return nil, err
19 | }
20 | rsp = &LookUpOrderIdRsp{}
21 | if err = json.Unmarshal(bs, rsp); err != nil {
22 | return rsp, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
23 | }
24 | if res.StatusCode == http.StatusOK {
25 | return rsp, nil
26 | }
27 | if err = statusCodeErrCheck(rsp.StatusCodeErr); err != nil {
28 | return rsp, err
29 | }
30 | return rsp, nil
31 | }
32 |
--------------------------------------------------------------------------------
/apple/order_model.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | type LookUpOrderIdRsp struct {
4 | StatusCodeErr
5 | Status int `json:"status,omitempty"` // 0-valid,1-invalid
6 | SignedTransactions []SignedTransaction `json:"signedTransactions,omitempty"`
7 | }
8 |
--------------------------------------------------------------------------------
/apple/refund.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // GetRefundHistory Get Refund History
13 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/get_refund_history
14 | func (c *Client) GetRefundHistory(ctx context.Context, transactionId, revision string) (rsp *RefundHistoryRsp, err error) {
15 | path := fmt.Sprintf(getRefundHistory, transactionId)
16 | if revision != "" {
17 | path = fmt.Sprintf(getRefundHistory, transactionId) + "?revision=" + revision
18 | }
19 | res, bs, err := c.doRequestGet(ctx, path)
20 | if err != nil {
21 | return nil, err
22 | }
23 | rsp = &RefundHistoryRsp{}
24 | if err = json.Unmarshal(bs, rsp); err != nil {
25 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
26 | }
27 | if res.StatusCode == http.StatusOK {
28 | return rsp, nil
29 | }
30 | if err = statusCodeErrCheck(rsp.StatusCodeErr); err != nil {
31 | return rsp, err
32 | }
33 | return rsp, nil
34 | }
35 |
--------------------------------------------------------------------------------
/apple/refund_model.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | type RefundHistoryRsp struct {
4 | StatusCodeErr
5 | HasMore bool `json:"hasMore"`
6 | Revision string `json:"revision"`
7 | SignedTransactions []SignedTransaction `json:"signedTransactions"`
8 | }
9 |
--------------------------------------------------------------------------------
/apple/refund_test.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TestGetRefundHistory(t *testing.T) {
10 | rsp, err := client.GetRefundHistory(ctx, "2000000184445477", "revision")
11 | if err != nil {
12 | if statusErr, ok := IsStatusCodeError(err); ok {
13 | xlog.Errorf("%+v", statusErr)
14 | // do something
15 | return
16 | }
17 | xlog.Errorf("client.GetRefundHistory(),err:%+v", err)
18 | return
19 | }
20 | for _, v := range rsp.SignedTransactions {
21 | transaction, _ := v.DecodeSignedTransaction()
22 | xlog.Debugf("refund transactions:%+v", transaction)
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/apple/subscription.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // GetAllSubscriptionStatuses Get All Subscription Statuses
13 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/get_all_subscription_statuses
14 | func (c *Client) GetAllSubscriptionStatuses(ctx context.Context, transactionId string) (rsp *AllSubscriptionStatusesRsp, err error) {
15 | path := fmt.Sprintf(getAllSubscriptionStatuses, transactionId)
16 | res, bs, err := c.doRequestGet(ctx, path)
17 | if err != nil {
18 | return nil, err
19 | }
20 | rsp = &AllSubscriptionStatusesRsp{}
21 | if err = json.Unmarshal(bs, rsp); err != nil {
22 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
23 | }
24 | if res.StatusCode == http.StatusOK {
25 | return rsp, nil
26 | }
27 | if err = statusCodeErrCheck(rsp.StatusCodeErr); err != nil {
28 | return rsp, err
29 | }
30 | return rsp, nil
31 | }
32 |
--------------------------------------------------------------------------------
/apple/subscription_model.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import "fmt"
4 |
5 | type AllSubscriptionStatusesRsp struct {
6 | StatusCodeErr
7 | AppAppleId int `json:"appAppleId"`
8 | BundleId string `json:"bundleId"`
9 | Environment string `json:"environment"`
10 | Data []*SubscriptionGroupIdentifierItem `json:"data"`
11 | }
12 |
13 | type SubscriptionGroupIdentifierItem struct {
14 | SubscriptionGroupIdentifier string `json:"subscriptionGroupIdentifier"`
15 | LastTransactions []*LastTransactionsItem `json:"lastTransactions"`
16 | }
17 |
18 | type LastTransactionsItem struct {
19 | OriginalTransactionId string `json:"originalTransactionId"`
20 | Status int `json:"status"`
21 | SignedRenewalInfo string `json:"signedRenewalInfo"`
22 | SignedTransactionInfo string `json:"signedTransactionInfo"`
23 | }
24 |
25 | func (d *LastTransactionsItem) DecodeRenewalInfo() (ri *RenewalInfo, err error) {
26 | if d.SignedRenewalInfo == "" {
27 | return nil, fmt.Errorf("SignedRenewalInfo is empty")
28 | }
29 | ri = &RenewalInfo{}
30 | if err = ExtractClaims(d.SignedRenewalInfo, ri); err != nil {
31 | return nil, err
32 | }
33 | return ri, nil
34 | }
35 |
36 | func (d *LastTransactionsItem) DecodeTransactionInfo() (ti *TransactionInfo, err error) {
37 | if d.SignedTransactionInfo == "" {
38 | return nil, fmt.Errorf("signedTransactionInfo is empty")
39 | }
40 | ti = &TransactionInfo{}
41 | if err = ExtractClaims(d.SignedTransactionInfo, ti); err != nil {
42 | return nil, err
43 | }
44 | return ti, nil
45 | }
46 |
--------------------------------------------------------------------------------
/apple/token.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/go-pay/gopay/pkg/jwt"
7 | )
8 |
9 | type CustomClaims struct {
10 | jwt.Claims
11 | Iss string `json:"iss"`
12 | Iat int64 `json:"iat"`
13 | Exp int64 `json:"exp"`
14 | Aud string `json:"aud"`
15 | Bid string `json:"bid"`
16 | }
17 |
18 | func (c *Client) generatingToken() (string, error) {
19 | claims := CustomClaims{
20 | Iss: c.iss,
21 | Iat: time.Now().Unix(),
22 | Exp: time.Now().Add(5 * time.Minute).Unix(),
23 | Aud: "appstoreconnect-v1",
24 | Bid: c.bid,
25 | }
26 |
27 | token := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
28 | token.Header = map[string]any{
29 | "alg": "ES256",
30 | "kid": c.kid,
31 | "typ": "JWT",
32 | }
33 |
34 | accessToken, err := token.SignedString(c.privateKey)
35 | if err != nil {
36 | return "", err
37 | }
38 | return accessToken, nil
39 | }
40 |
--------------------------------------------------------------------------------
/apple/transaction.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // GetTransactionHistory Get Transaction History
13 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history
14 | func (c *Client) GetTransactionHistory(ctx context.Context, transactionId string, bm gopay.BodyMap) (rsp *TransactionHistoryRsp, err error) {
15 | path := fmt.Sprintf(getTransactionHistory, transactionId) + "?" + bm.EncodeURLParams()
16 | res, bs, err := c.doRequestGet(ctx, path)
17 | if err != nil {
18 | return nil, err
19 | }
20 | rsp = &TransactionHistoryRsp{}
21 | if err = json.Unmarshal(bs, rsp); err != nil {
22 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
23 | }
24 | if res.StatusCode == http.StatusOK {
25 | return rsp, nil
26 | }
27 | if err = statusCodeErrCheck(rsp.StatusCodeErr); err != nil {
28 | return rsp, err
29 | }
30 | return rsp, nil
31 | }
32 |
33 | // GetTransactionHistoryV2 Get Transaction History v2
34 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/get-v2-history-_transactionid_
35 | func (c *Client) GetTransactionHistoryV2(ctx context.Context, transactionId string, bm gopay.BodyMap) (rsp *TransactionHistoryRsp, err error) {
36 | path := fmt.Sprintf(getTransactionHistoryV2, transactionId) + "?" + bm.EncodeURLParams()
37 | res, bs, err := c.doRequestGet(ctx, path)
38 | if err != nil {
39 | return nil, err
40 | }
41 | rsp = &TransactionHistoryRsp{}
42 | if err = json.Unmarshal(bs, rsp); err != nil {
43 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
44 | }
45 | if res.StatusCode == http.StatusOK {
46 | return rsp, nil
47 | }
48 | if err = statusCodeErrCheck(rsp.StatusCodeErr); err != nil {
49 | return rsp, err
50 | }
51 | return rsp, nil
52 | }
53 |
54 | // GetTransactionInfo Get Transaction Info
55 | // Doc: https://developer.apple.com/documentation/appstoreserverapi/get_transaction_info
56 | func (c *Client) GetTransactionInfo(ctx context.Context, transactionId string) (rsp *TransactionInfoRsp, err error) {
57 | path := fmt.Sprintf(getTransactionInfo, transactionId)
58 | res, bs, err := c.doRequestGet(ctx, path)
59 | if err != nil {
60 | return nil, err
61 | }
62 | rsp = &TransactionInfoRsp{}
63 | if err = json.Unmarshal(bs, rsp); err != nil {
64 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
65 | }
66 | if res.StatusCode == http.StatusOK {
67 | return rsp, nil
68 | }
69 | if err = statusCodeErrCheck(rsp.StatusCodeErr); err != nil {
70 | return rsp, err
71 | }
72 | return rsp, nil
73 | }
74 |
--------------------------------------------------------------------------------
/apple/verify.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/go-pay/gopay/pkg/xhttp"
7 | )
8 |
9 | const (
10 | // is the URL when testing your app in the sandbox and while your application is in review
11 | UrlSandbox = "https://sandbox.itunes.apple.com/verifyReceipt"
12 | // is the URL when your app is live in the App Store
13 | UrlProd = "https://buy.itunes.apple.com/verifyReceipt"
14 | )
15 |
16 | // VerifyReceipt 请求APP Store 校验支付请求,实际测试时发现这个文档介绍的返回信息只有那个status==0表示成功可以用,其他的返回信息跟文档对不上
17 | // url:取 UrlProd 或 UrlSandbox
18 | // pwd:苹果APP秘钥,https://help.apple.com/app-store-connect/#/devf341c0f01
19 | // 文档:https://developer.apple.com/documentation/appstorereceipts/verifyreceipt
20 | func VerifyReceipt(ctx context.Context, url, pwd, receipt string) (rsp *VerifyResponse, err error) {
21 | req := &VerifyRequest{Receipt: receipt, Password: pwd}
22 | rsp = new(VerifyResponse)
23 | _, err = xhttp.NewClient().Req(xhttp.TypeJSON).Post(url).SendStruct(req).EndStruct(ctx, rsp)
24 | if err != nil {
25 | return nil, err
26 | }
27 | return rsp, nil
28 | }
29 |
--------------------------------------------------------------------------------
/apple/verify_test.go:
--------------------------------------------------------------------------------
1 | package apple
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TestVerify(t *testing.T) {
10 | pwd := ""
11 | receipt := ""
12 | rsp, err := VerifyReceipt(ctx, UrlSandbox, pwd, receipt)
13 | if err != nil {
14 | xlog.Error(err)
15 | return
16 | }
17 | /**
18 | {
19 | "receipt":{
20 | "original_purchase_date_pst":"2021-08-14 05:28:17 America/Los_Angeles",
21 | "purchase_date_ms":"1628944097586",
22 | "unique_identifier":"13f339a765b706f8775f729723e9b889b0cbb64e",
23 | "original_transaction_id":"1000000859439868",
24 | "bvrs":"10",
25 | "transaction_id":"1000000859439868",
26 | "quantity":"1",
27 | "in_app_ownership_type":"PURCHASED",
28 | "unique_vendor_identifier":"6DFDEA8B-38CE-4710-A1E1-BAEB8B66FEBD",
29 | "item_id":"1581250870",
30 | "version_external_identifier":"0",
31 | "bid":"com.huochai.main",
32 | "is_in_intro_offer_period":"false",
33 | "product_id":"10002",
34 | "purchase_date":"2021-08-14 12:28:17 Etc/GMT",
35 | "is_trial_period":"false",
36 | "purchase_date_pst":"2021-08-14 05:28:17 America/Los_Angeles",
37 | "original_purchase_date":"2021-08-14 12:28:17 Etc/GMT",
38 | "original_purchase_date_ms":"1628944097586"
39 | },
40 | "status":0
41 | }
42 | */
43 | if rsp.Receipt != nil {
44 | xlog.Debugf("receipt:%+v", rsp.Receipt)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/constant.go:
--------------------------------------------------------------------------------
1 | package gopay
2 |
3 | const (
4 | NULL = ""
5 | SUCCESS = "SUCCESS"
6 | FAIL = "FAIL"
7 | OK = "OK"
8 | DebugOff = 0
9 | DebugOn = 1
10 | Version = "v1.5.113"
11 | )
12 |
13 | type DebugSwitch int8
14 |
--------------------------------------------------------------------------------
/doc/allinpay.md:
--------------------------------------------------------------------------------
1 | ## 通联支付
2 |
3 |
4 | - 通联支付:[官方文档中心](https://aipboss.allinpay.com/know/devhelp/index.php)
5 |
6 |
7 |
8 | > 具体API使用介绍,请参考`gopay/allinpay/client_test.go`,`gopay/allinpay/pay_test.go` 等xxx_test.go
9 |
10 | ### 通联支付 API
11 |
12 | * 统一支付接口(暂无账号为测试可用性):`client.Pay()`
13 | * 统一扫码接口: `client.ScanPay()`
14 | * 撤销订单:`client.Cancel()`
15 | * 交易退款:`client.Refund()`
16 | * 交易结果查询:`client.Query()`
17 | * 关闭订单:`client.Close()`
18 | * 申请退款:`client.Refund()`
19 |
--------------------------------------------------------------------------------
/doc/lakala.md:
--------------------------------------------------------------------------------
1 | ## 拉卡拉网关支付
2 |
3 | - 拉卡拉网关支付:[官方文档中心](https://payjp.lakala.com/docs/cn)
4 |
5 | ### 回调通知解析
6 |
7 | ```
8 | notifyReq, err := lakala.ParseNotify()
9 | if err != nil {
10 | xlog.Error(err)
11 | return
12 | }
13 | ```
14 |
15 | ### 拉卡拉 API
16 |
17 | * QRCode
18 | * 创建QRCode支付单:`client.CreateQRCodeOrder()`
19 | * 创建Native QRCode支付单:`client.CreateNativeQRCodeOrder()`
20 | * QRCode支付跳转页:`client.QRCodePay()`
21 | * JSAPI
22 | * 创建JSAPI订单:`client.CreateJSAPIOrder()`
23 | * 创建Native JSAPI订单(offline):`client.CreateNativeJSApiOrder()`
24 | * 微信JSAPI支付跳转页:`client.JSAPIWechatPay()`
25 | * 支付宝JSAPI支付跳转页:`client.JSAPIAlipayPay()`
26 | * Alipay+ JSAPI支付跳转页:`client.JSAPIAlipayPlusPay()`
27 | * MobileH5
28 | * 创建H5支付单:`client.CreateH5PayOrder()`
29 | * H5支付跳转页:`client.H5Pay()`
30 | * H5支付跳转页(Alipay+):`client.H5AlipayPlusPay()`
31 | * Miniprogram Payment
32 | * 创建小程序订单:`client.CreateMiniProgramOrder()`
33 | * Channel Web Gateway
34 | * 创建渠道Web网关订单:`client.CreateWebGatewayOrder()`
35 | * SDKPayment
36 | * 创建SDK订单(Online):`client.CreateSDKPaymentOrder()`
37 | * CommonApi
38 | * 获取当前汇率:`client.GetExchangeRate()`
39 | * 获取加密密钥:`client.GetEncrypt()`
40 | * 关闭订单:`client.CloseOrder()`
41 | * 查询订单状态:`client.OrderStatus()`
42 | * 申请退款:`client.ApplyRefund()`
43 | * 查询退款状态:`client.RefundQuery()`
44 | * 查看订单:`client.OrderList()`
45 | * 查看账单流水:`client.TransactionList()`
46 | * 查看清算详情:`client.Settlements()`
47 | * 查询可用钱包:`client.ConsultPayment()`
48 | * 获取优惠券信息:`client.GetCoupon()`
49 | * Custom
50 | * 创建报关单(非拆单):`client.CreateReportSingle()`
51 | * 创建报关单(拆单):`client.CreateReportSeparate()`
52 | * 报关状态查询:`client.ReportStatus()`
53 | * 报关子单状态查询:`client.ReportSubStatus()`
54 | * 修改报关信息(非拆单):`client.ModifyReportSingle()`
55 | * 修改报关信息(拆单):`client.ModifyReportSeparate()`
56 | * 重推报关(非拆单):`client.ResendReportSingle()`
57 | * 报关单子单重推:`client.ResendReportSeparate()`
58 |
--------------------------------------------------------------------------------
/doc/qq.md:
--------------------------------------------------------------------------------
1 | ## QQ
2 |
3 | > QQ支付 使用方法请参考 `GoPay微信v2文档` 的文档
4 |
5 | > GoPay微信v2文档:[GoPay微信v2文档](https://github.com/go-pay/gopay/blob/main/doc/wechat_v2.md)
6 |
7 | ### QQ支付 API
8 |
9 | * 提交付款码支付:`client.MicroPay()`
10 | * 撤销订单:`client.Reverse()`
11 | * 统一下单:`client.UnifiedOrder()`
12 | * 订单查询:`client.OrderQuery()`
13 | * 关闭订单:`client.CloseOrder()`
14 | * 申请退款:`client.Refund()`
15 | * 退款查询:`client.RefundQuery()`
16 | * 交易账单:`client.StatementDown()`
17 | * 资金账单:`client.AccRoll()`
18 | * 创建现金红包(未测试可用性):`client.SendCashRed()`
19 | * 对账单下载(未测试可用性):`client.DownloadRedListFile()`
20 | * 查询红包详情(未测试可用性):`client.QueryRedInfo()`
21 | * 自定义方法请求微信API接口:`client.PostQQAPISelf()`
22 |
23 | ### QQ公共 API
24 |
25 | * `qq.ParseNotifyToBodyMap()` => 解析QQ支付异步通知的结果到BodyMap
26 | * `qq.ParseNotify()` => 解析QQ支付异步通知的参数
27 | * `qq.VerifySign()` => QQ同步返回参数验签或异步通知参数验签
28 | * `qq.GetAccessToken()` => 获取 AccessToken 信息
29 | * `qq.GetOpenId()` => 获取 Openid 信息
30 | * `qq.GetUserInfo()` => 获取用户信息
31 |
32 | ---
--------------------------------------------------------------------------------
/doc/saobei.md:
--------------------------------------------------------------------------------
1 | ## 扫呗支付 API
2 |
3 |
4 | - 扫呗支付:[官方文档中心](https://help.lcsw.cn/xrmpic/q6imdiojes7iq5y1/qg52lx)
5 |
6 |
7 |
8 | > 具体API使用介绍,请参考`gopay/saobei/client_test.go`
9 |
10 |
11 | ### 支付2.0接口
12 | > 请参考`gopay/saobei/pay_test.go`,
13 | * 小程序支付接口(暂无账号为测试可用性):`client.MiniPay()`
14 | * 付款码支付 `client.BarcodePay()`
15 | * 支付查询 `client.Query()`
16 | * 退款申请 `client.Refund()`
17 | * 退款订单查询 `client.QueryRefund()`
18 |
19 | ### 资金接口
20 | > 请参考`gopay/saobei/merchant_test.go`,
21 |
22 | ### CBK企业钱包分账
23 | > 请参考`gopay/saobei/account_test.go`,
--------------------------------------------------------------------------------
/error.go:
--------------------------------------------------------------------------------
1 | package gopay
2 |
3 | import "errors"
4 |
5 | var (
6 | MissWechatInitParamErr = errors.New("missing wechat init parameter")
7 | MissAlipayInitParamErr = errors.New("missing alipay init parameter")
8 | MissPayPalInitParamErr = errors.New("missing paypal init parameter")
9 | MissAppleInitParamErr = errors.New("missing apple init parameter")
10 | MissLakalaInitParamErr = errors.New("missing lakala init parameter")
11 | MissParamErr = errors.New("missing required parameter")
12 | MarshalErr = errors.New("marshal error")
13 | UnmarshalErr = errors.New("unmarshal error")
14 | SignatureErr = errors.New("signature error")
15 | VerifySignatureErr = errors.New("verify signature error")
16 | CertNotMatchErr = errors.New("cert not match error")
17 | GetSignDataErr = errors.New("get signature data error")
18 | BodyMapNilErr = errors.New("body map is nil")
19 | )
20 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_SystemOauthToken.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func SystemOauthToken() {
10 | 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="
11 | //初始化支付宝客户端
12 | // appId:应用ID
13 | // privateKey:应用秘钥
14 | // isProd:是否是正式环境
15 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
16 | if err != nil {
17 | xlog.Error(err)
18 | return
19 | }
20 | //配置公共参数
21 | client.SetCharset("utf-8").
22 | SetSignType(alipay.RSA2).
23 | SetNotifyUrl("https://www.fmm.ink")
24 |
25 | //请求参数
26 | bm := make(gopay.BodyMap)
27 | bm.Set("grant_type", "authorization_code")
28 | bm.Set("code", "3a06216ac8f84b8c93507bb9774bWX11")
29 |
30 | //发起请求
31 | aliRsp, err := client.SystemOauthToken(ctx, bm)
32 | if err != nil {
33 | xlog.Error("err:", err)
34 | return
35 | }
36 | xlog.Debug("aliRsp:", *aliRsp)
37 | xlog.Debug("aliRsp:", aliRsp.Response.AccessToken)
38 | xlog.Debug("aliRsp:", aliRsp.SignData)
39 |
40 | //支付宝小程序创建订单
41 | bm2 := make(gopay.BodyMap)
42 | bm2.Set("subject", "创建订单")
43 | bm2.Set("buyer_id", aliRsp.Response.UserId)
44 | bm2.Set("out_trade_no", "GZ201901301040355708")
45 | bm2.Set("total_amount", "0.01")
46 |
47 | rsp, err := client.TradeCreate(ctx, bm2)
48 | if err != nil {
49 | xlog.Error("err:", err)
50 | return
51 | }
52 | xlog.Debug("rsp:", *rsp)
53 | xlog.Debug("TradeNo:", rsp.Response.TradeNo)
54 | }
55 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeAppPay.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeAppPay() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2).
24 | SetNotifyUrl("https://www.fmm.ink")
25 |
26 | //请求参数
27 | bm := make(gopay.BodyMap)
28 | bm.Set("subject", "测试APP支付")
29 | bm.Set("out_trade_no", "GZ201901301040355706100469")
30 | bm.Set("total_amount", "1.00")
31 | //手机APP支付参数请求
32 | payParam, err := client.TradeAppPay(ctx, bm)
33 | if err != nil {
34 | xlog.Error("err:", err)
35 | return
36 | }
37 | xlog.Debug("payParam:", payParam)
38 | }
39 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeCancel.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeCancel() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2).
24 | SetNotifyUrl("https://www.fmm.ink")
25 |
26 | //请求参数
27 | bm := make(gopay.BodyMap)
28 | bm.Set("out_trade_no", "GYWX201901301040355706100457")
29 | //撤销支付订单
30 | aliRsp, err := client.TradeCancel(ctx, bm)
31 | if err != nil {
32 | xlog.Error("err:", err)
33 | return
34 | }
35 | xlog.Debug("aliRsp:", *aliRsp)
36 | }
37 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeClose.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeClose() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2).
24 | SetNotifyUrl("https://www.fmm.ink")
25 |
26 | //请求参数
27 | bm := make(gopay.BodyMap)
28 | bm.Set("out_trade_no", "GYWX201901301040355706100459")
29 | //条码支付
30 | aliRsp, err := client.TradeClose(ctx, bm)
31 | if err != nil {
32 | xlog.Error("err:", err)
33 | return
34 | }
35 | xlog.Debug("aliRsp:", *aliRsp)
36 | }
37 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeFastPayRefundQuery.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeFastPayRefundQuery() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2)
24 |
25 | //请求参数
26 | bm := make(gopay.BodyMap)
27 | bm.Set("out_trade_no", "GZ201907301420334577")
28 | bm.Set("out_request_no", "GZ201907301420334577")
29 | //发起退款查询请求
30 | aliRsp, err := client.TradeFastPayRefundQuery(ctx, bm)
31 | if err != nil {
32 | xlog.Error("err:", err)
33 | return
34 | }
35 | xlog.Debug("aliRsp:", *aliRsp)
36 | }
37 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeOrderSettle.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeOrderSettle() {
10 | 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="
11 | //初始化支付宝客户端
12 | // appId:应用ID
13 | // privateKey:应用秘钥
14 | // isProd:是否是正式环境
15 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
16 | if err != nil {
17 | xlog.Error(err)
18 | return
19 | }
20 | //配置公共参数
21 | client.SetCharset("utf-8").
22 | SetSignType(alipay.RSA2)
23 |
24 | //请求参数
25 | bm := make(gopay.BodyMap)
26 | bm.Set("out_request_no", "201907301518083384")
27 | bm.Set("trade_no", "2019072522001484690549776067")
28 |
29 | var listParams []*alipay.RoyaltyDetailInfoPojo
30 | listParams = append(listParams, &alipay.RoyaltyDetailInfoPojo{
31 | RoyaltyType: "transfer",
32 | TransOut: "2088802095984694",
33 | TransOutType: "userId",
34 | TransInType: "userId",
35 | TransIn: "2088102363632794",
36 | Amount: "0.01",
37 | Desc: "分账给2088102363632794",
38 | })
39 |
40 | bm.Set("royalty_parameters", listParams)
41 | xlog.Debug("listParams:", bm.GetString("royalty_parameters"))
42 |
43 | //发起交易结算接口
44 | aliRsp, err := client.TradeOrderSettle(ctx, bm)
45 | if err != nil {
46 | xlog.Error("err:", err)
47 | return
48 | }
49 | xlog.Debug("aliRsp:", *aliRsp)
50 | }
51 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradePagePay.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradePagePay() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2).
24 | SetNotifyUrl("https://www.fmm.ink")
25 |
26 | //请求参数
27 | bm := make(gopay.BodyMap)
28 | bm.Set("subject", "网站测试支付")
29 | bm.Set("out_trade_no", "GZ201901301040355706100469")
30 | bm.Set("total_amount", "88.88")
31 | bm.Set("product_code", "FAST_INSTANT_TRADE_PAY")
32 |
33 | //电脑网站支付请求
34 | payUrl, err := client.TradePagePay(ctx, bm)
35 | if err != nil {
36 | xlog.Error("err:", err)
37 | return
38 | }
39 | xlog.Debug("payUrl:", payUrl)
40 | }
41 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradePrecreate.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradePrecreate() {
10 | 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="
11 | //初始化支付宝客户端
12 | // appId:应用ID
13 | // privateKey:应用私钥,支持PKCS1和PKCS8
14 | // isProd:是否是正式环境
15 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
16 | if err != nil {
17 | xlog.Error(err)
18 | return
19 | }
20 | //配置公共参数
21 | client.SetCharset("utf-8").
22 | SetSignType(alipay.RSA2).
23 | SetNotifyUrl("https://www.fmm.ink")
24 |
25 | //请求参数
26 | bm := make(gopay.BodyMap)
27 | bm.Set("subject", "预创建创建订单")
28 | bm.Set("out_trade_no", "GZ201907301040355704")
29 | bm.Set("total_amount", "100")
30 | //创建订单
31 | aliRsp, err := client.TradePrecreate(ctx, bm)
32 | if err != nil {
33 | xlog.Error("err:", err)
34 | return
35 | }
36 | xlog.Debug("aliRsp:", *aliRsp)
37 | xlog.Debug("aliRsp.QrCode:", aliRsp.Response.QrCode)
38 | xlog.Debug("aliRsp.OutTradeNo:", aliRsp.Response.OutTradeNo)
39 | }
40 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeQuery.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeQuery() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用秘钥
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2).
24 | SetAppAuthToken("201908BB03f542de8ecc42b985900f5080407abc")
25 |
26 | //请求参数
27 | bm := make(gopay.BodyMap)
28 | bm.Set("out_trade_no", "GZ201909081743431443")
29 |
30 | //查询订单
31 | aliRsp, err := client.TradeQuery(ctx, bm)
32 | if err != nil {
33 | xlog.Error("err:", err)
34 | return
35 | }
36 | xlog.Debug("aliRsp:", *aliRsp)
37 | }
38 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeRefund.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeRefund() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2)
24 |
25 | //请求参数
26 | bm := make(gopay.BodyMap)
27 | bm.Set("out_trade_no", "GZ201907301420334577")
28 | bm.Set("refund_amount", "5")
29 | bm.Set("refund_reason", "测试退款")
30 | //发起退款请求
31 | aliRsp, err := client.TradeRefund(ctx, bm)
32 | if err != nil {
33 | xlog.Error("err:", err)
34 | return
35 | }
36 | xlog.Debug("aliRsp:", *aliRsp)
37 | }
38 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_TradeWapPay.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TradeWapPay() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用秘钥
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2).
24 | //SetReturnUrl("https://www.fmm.ink").
25 | SetNotifyUrl("https://www.fmm.ink")
26 | //请求参数
27 | bm := make(gopay.BodyMap)
28 | bm.Set("subject", "手机网站测试支付")
29 | bm.Set("out_trade_no", "GZ201901301040355703")
30 | bm.Set("quit_url", "https://www.fmm.ink")
31 | bm.Set("total_amount", "100.00")
32 | bm.Set("product_code", "QUICK_WAP_WAY")
33 | //手机网站支付请求
34 | payUrl, err := client.TradeWapPay(ctx, bm)
35 | if err != nil {
36 | xlog.Error("err:", err)
37 | return
38 | }
39 | xlog.Debug("payUrl:", payUrl)
40 | }
41 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_UserCertifyOpenCertify.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func UserCertifyOpenCertify() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2)
24 |
25 | // 请求参数
26 | bm := make(gopay.BodyMap)
27 | // 本次申请操作的唯一标识,由开放认证初始化接口调用后生成,后续的操作都需要用到
28 | bm.Set("certify_id", "OC201809253000000393900404029253")
29 |
30 | //发起请求
31 | certifyUrl, err := client.UserCertifyOpenCertify(ctx, bm)
32 | if err != nil {
33 | xlog.Error("err:", err)
34 | return
35 | }
36 | xlog.Debug("certifyUrl:", certifyUrl)
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_UserCertifyOpenQuery.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func UserCertifyOpenQuery() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用私钥,支持PKCS1和PKCS8
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2)
24 |
25 | // 请求参数
26 | bm := make(gopay.BodyMap)
27 | // 本次申请操作的唯一标识,由开放认证初始化接口调用后生成,后续的操作都需要用到
28 | bm.Set("certify_id", "OC201809253000000393900404029253")
29 |
30 | //发起请求
31 | aliRsp, err := client.UserCertifyOpenQuery(ctx, bm)
32 | if err != nil {
33 | xlog.Error("err:", err)
34 | return
35 | }
36 | xlog.Debug("aliRsp:", *aliRsp)
37 | xlog.Debug("aliRsp.Response.Passed:", aliRsp.Response.Passed)
38 | }
39 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_UserInfoAuth.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func UserInfoAuth() {
10 | //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
11 | 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="
12 | //初始化支付宝客户端
13 | // appId:应用ID
14 | // privateKey:应用秘钥
15 | // isProd:是否是正式环境
16 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
17 | if err != nil {
18 | xlog.Error(err)
19 | return
20 | }
21 | //配置公共参数
22 | client.SetCharset("utf-8").
23 | SetSignType(alipay.RSA2)
24 |
25 | // 请求参数
26 | bm := make(gopay.BodyMap)
27 | // 接口权限值,目前只支持auth_user和auth_base两个值。具体说明看文档介绍
28 | bm.Set("scopes", []string{"auth_user"})
29 | bm.Set("state", "init")
30 |
31 | // 发起请求
32 | aliRsp, err := client.UserInfoAuth(ctx, bm)
33 | if err != nil {
34 | xlog.Error("err:", err)
35 | return
36 | }
37 | xlog.Debug("aliRsp:", aliRsp)
38 | }
39 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_UserInfoShare.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay/alipay"
5 | "github.com/go-pay/xlog"
6 | )
7 |
8 | func UserInfoShare() {
9 | aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
10 | 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="
11 | //初始化支付宝客户端
12 | // appId:应用ID
13 | // privateKey:应用私钥,支持PKCS1和PKCS8
14 | // isProd:是否是正式环境
15 | client, err := alipay.NewClient("2016091200494382", privateKey, false)
16 | if err != nil {
17 | xlog.Error(err)
18 | return
19 | }
20 | //配置公共参数
21 | client.SetCharset("utf-8").
22 | SetSignType(alipay.RSA2)
23 |
24 | // 发起请求
25 | aliRsp, err := client.UserInfoShare(ctx, "authusrB3888b190f6df4aea964d66129f8a5X11")
26 | if err != nil {
27 | xlog.Error("err:", err)
28 | return
29 | }
30 | xlog.Debug("aliRsp:", *aliRsp)
31 | // 同步返回验签
32 | ok, err := alipay.VerifySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
33 | if err != nil {
34 | xlog.Debug("VerifySign-err:", err)
35 | return
36 | }
37 | xlog.Debug("ok:", ok)
38 | }
39 |
--------------------------------------------------------------------------------
/examples/alipay/alipay_ZhimaCreditEpSceneRatingInitialize.go:
--------------------------------------------------------------------------------
1 | package alipay
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/alipay"
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func ZhimaCreditEpSceneRatingInitialize() {
10 | 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="
11 | //初始化支付宝客户端
12 | // appId:应用ID
13 | // privateKey:应用私钥,支持PKCS1和PKCS8
14 | // isProd:是否是正式环境
15 | client, err := alipay.NewClient("2014072300007148", privateKey, false)
16 | if err != nil {
17 | xlog.Error(err)
18 | return
19 | }
20 | //配置公共参数
21 | client.SetCharset("utf-8").
22 | SetSignType(alipay.RSA2)
23 |
24 | //请求参数
25 | bm := make(gopay.BodyMap)
26 | bm.Set("credit_category", "ZMSCCO_5_1_1")
27 | bm.Set("product_code", "w1010100100000000001")
28 | bm.Set("out_order_no", "201805301527674106562F0000954216")
29 | bm.Set("user_id", "2088302248028263")
30 |
31 | aliRsp, err := client.ZhimaCreditEpSceneRatingInitialize(ctx, bm)
32 | if err != nil {
33 | xlog.Error("err:", err)
34 | return
35 | }
36 | xlog.Debug("aliRsp:", *aliRsp)
37 | }
38 |
--------------------------------------------------------------------------------
/examples/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/gopay/alipay"
8 | "github.com/go-pay/xlog"
9 | )
10 |
11 | func main() {
12 | privateKey := "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCRbpW2f4M7ciRpfcEwnE4QQsoLMN4LiINSgOxhS6cguO2g7GzKWn8Vj5pyE1Px3NJ0ymlBl0sQBnpid1v/CnEjd9erz4YWs+AplljDwvhAzD1S7BY4zSYOi/KZaQnLpSAFhp7B3L1az2uMB07pezzn6aaQr5E3qpusLNzvtiVUX+V21LZh7aga33qTe6ovbDh9b/SNb2l/cDDJ0oWVbi663173RfCo0LRG0caGUl8jRQ2X+Um3yI/S0BRMHxkr97NuPt+oH2JSrwLy1ueJz+OXxiVK7cvxwX94PhqvGD9rL5VQBkcnuM+d5jbzwQDaGu99ofFGA5gr8zIOpM3R1fzfAgMBAAECggEBAJB//Td4mQ8OyYkbj0HafGIByri11FpHSJxIRxYhUizcMhfL8ghZRJ5Ksh2YgLb3PxEWMOEgD1Ab76w4hmrxmBqyr9Mhfky+awNHRGk2Ju5TQLdMpoPHqoGXofO1/yqdpiR3bvSWfHpnT6exd0Hb1ldju8FVAIf793NqnBd9treOlPAsSI2lr+2Nxs56yCIZUIrD4iNbkkQCq9ZDZAxlf5hW/u8QS7ZsCu7KfK9NL+dhYPQzoI/Avtbkle2CI1A2pW9QyIDh8OhM2bqfFbw/uoxSp0QH6fPtgeoq5kEH/QX7WeVcYeroa9nTEpoKLlXaujss8aBzRLGFA5gScGgBqNkCgYEAy9N2Hp57Lb+i/kJTORc0a6TzixV5b7i2tR5QDwLS9c2H9hnytCtz6kq26IA1U7cTRYg6whiQEXpVLcW7bezDrED+phrImbWQ06KyWRuPvirpyDEsM4U56Q0U+zZ18x1wYYS5LNE4uC8lx9bSAZ3iPW1DS5liqABAGNusaIqsjtsCgYEAtqic9Bqm97EiXzdFfAQ2nEHhfP+vaKeeouHBBKVaW8WIqjU220ODWb6QuXJ1gQARhu+SSnO4/hHj8J/TPAbQxxVi8pB8fYoAIxqwQLe471NDQ+7hPTtuxPSnWKRGe/nNbzXWMXAEhGriLesdrUMEwfiAaCB/sJvg/zVYP68vn00CgYBxP2uotYthLtHkDXvqA4+Xo43BoEvZnDq/xTjcLkiCVBEP1vj3zBDag2q/IcT/X3/wqTFkeHtLirna9bse52cMxQv3xHfil3QBcqs/QUYLdhJwrYmOkp5Lc35N2cONMbUoKbMtSI4IIAIQ17XVOiDi2luCnJWpHIKAjUVszGf18wKBgQCgJ9GOuzvBHGBN6lGTfsI/WgiTKEEt2yLeIGG0aCOFKfs9enFB6b1m2A9fevuKg3vau36ipzsCEr+wwQJetH8kwBzFIGj3TiP2o7T82dpehbwJ+Y8muFDUgsukjk168LnvE95d9KERVgJBTtDzlTq7tN8p7azoNpUeUDCzjjCMVQKBgGH9tkNeEZ2Tcfuh8QKEQewZYNc+c3w/E1L/uFOuganmQUeLWbdXpFk0fAyJLEsfJoYeJK7OjmNG7mcwSQLbiqrtlGlT6n22pc+AhaToSZuM1Z7ExkzKIIVm/ijCLploIHW16SWe8qecax1xPK2XElIAhcGCe8sRH8Z+fiv2B9Vp"
13 | client, err := alipay.NewClient("2021002103640726", privateKey, false)
14 | if err != nil {
15 | xlog.Error(err)
16 | return
17 | }
18 | //配置公共参数
19 | client.SetCharset("utf-8").
20 | SetSignType(alipay.RSA2).
21 | SetNotifyUrl("http://crm.deepic.cn/ali/pay/notify")
22 | client.SetCertSnByPath("./appPublicCert.crt", "./alipayRootCert.crt", "./alipayPublicCert.crt")
23 |
24 | //请求参数
25 | bm := gopay.BodyMap{}
26 | bm.Set("out_order_no", "202104021339585117785701")
27 | bm.Set("out_request_no", "20210402133958511778570101")
28 | bm.Set("remark", "测试取消")
29 | rs, err := client.FundAuthOperationCancel(context.Background(), bm)
30 | xlog.Infof("rs:%v, err:%+v", rs, err)
31 | }
32 |
--------------------------------------------------------------------------------
/examples/wechat/wx_BatchQueryComment.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func BatchQueryComment() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境
17 | // 好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
18 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
19 |
20 | // 初始化参数结构体
21 | bm := make(gopay.BodyMap)
22 | bm.Set("nonce_str", util.RandomString(32)).
23 | Set("sign_type", wechat.SignType_HMAC_SHA256).
24 | Set("begin_time", "20190120000000").
25 | Set("end_time", "20190122174000").
26 | Set("offset", "0")
27 |
28 | // 请求拉取订单评价数据,成功后得到结果,沙箱环境下,证书路径参数可传空
29 | wxRsp, err := client.BatchQueryComment(ctx, bm)
30 | if err != nil {
31 | xlog.Error(err)
32 | return
33 | }
34 | xlog.Debug("Response:", wxRsp)
35 | }
36 |
--------------------------------------------------------------------------------
/examples/wechat/wx_CloseOrder.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func CloseOrder() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境
17 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
18 |
19 | // 初始化参数结构体
20 | bm := make(gopay.BodyMap)
21 | bm.Set("out_trade_no", "MfZC2segKxh0bnJSELbvKNeH3d9oWvvQ").
22 | Set("nonce_str", util.RandomString(32)).
23 | Set("sign_type", wechat.SignType_MD5)
24 |
25 | // 请求关闭订单,成功后得到结果
26 | wxRsp, err := client.CloseOrder(ctx, bm)
27 | if err != nil {
28 | xlog.Error(err)
29 | return
30 | }
31 | xlog.Debug("Response:", wxRsp)
32 | }
33 |
--------------------------------------------------------------------------------
/examples/wechat/wx_DownloadBill.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func DownloadBill() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境
17 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
18 |
19 | // 初始化参数结构体
20 | bm := make(gopay.BodyMap)
21 | bm.Set("nonce_str", util.RandomString(32)).
22 | Set("sign_type", wechat.SignType_MD5).
23 | Set("bill_date", "20190722").
24 | Set("bill_type", "ALL")
25 |
26 | //请求下载对账单,成功后得到结果(string类型字符串)
27 | wxRsp, err := client.DownloadBill(ctx, bm)
28 | if err != nil {
29 | xlog.Error(err)
30 | return
31 | }
32 | xlog.Debug("Response:", wxRsp)
33 | }
34 |
--------------------------------------------------------------------------------
/examples/wechat/wx_DownloadFundFlow.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func DownloadFundFlow() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境
17 | // 好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
18 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
19 |
20 | // 初始化参数结构体
21 | bm := make(gopay.BodyMap)
22 | bm.Set("nonce_str", util.RandomString(32)).
23 | Set("sign_type", wechat.SignType_HMAC_SHA256).
24 | Set("bill_date", "20190122").
25 | Set("account_type", "Basic")
26 |
27 | // 请求下载资金账单,成功后得到结果,沙箱环境下,证书路径参数可传空
28 | wxRsp, err := client.DownloadFundFlow(ctx, bm)
29 | if err != nil {
30 | xlog.Error(err)
31 | return
32 | }
33 | xlog.Debug("Response:", wxRsp)
34 | }
35 |
--------------------------------------------------------------------------------
/examples/wechat/wx_Micropay.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func Micropay() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境
17 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
18 |
19 | number := util.RandomString(32)
20 | xlog.Debug("out_trade_no:", number)
21 | // 初始化参数Map
22 | bm := make(gopay.BodyMap)
23 | bm.Set("nonce_str", util.RandomString(32)).
24 | Set("body", "扫用户付款码支付").
25 | Set("out_trade_no", number).
26 | Set("total_fee", 1).
27 | Set("spbill_create_ip", "127.0.0.1").
28 | Set("auth_code", "134595229789828537").
29 | Set("sign_type", wechat.SignType_MD5)
30 |
31 | //请求支付,成功后得到结果
32 | wxRsp, err := client.Micropay(ctx, bm)
33 | if err != nil {
34 | xlog.Error(err)
35 | return
36 | }
37 | xlog.Debug("Response:", wxRsp)
38 |
39 | ok, err := wechat.VerifySign("GFDS8j98rewnmgl45wHTt980jg543abc", wechat.SignType_MD5, wxRsp)
40 | if err != nil {
41 | xlog.Error(err)
42 | return
43 | }
44 | xlog.Debug("SignOk?:", ok)
45 | }
46 |
--------------------------------------------------------------------------------
/examples/wechat/wx_QueryOrder.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func QueryOrder() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // apiKey:API秘钥值
16 | // isProd:是否是正式环境
17 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
18 |
19 | // 初始化参数结构体
20 | bm := make(gopay.BodyMap)
21 | bm.Set("out_trade_no", "GW201908091551421156").
22 | Set("nonce_str", util.RandomString(32)).
23 | Set("sign_type", wechat.SignType_MD5)
24 |
25 | // 请求订单查询,成功后得到结果
26 | wxRsp, resBm, err := client.QueryOrder(ctx, bm)
27 | if err != nil {
28 | xlog.Error(err)
29 | return
30 | }
31 | xlog.Debug("wxRsp:", wxRsp)
32 | xlog.Debug("resBm:", resBm)
33 | }
34 |
--------------------------------------------------------------------------------
/examples/wechat/wx_QueryRefund.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func QueryRefund() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境
17 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
18 |
19 | // 初始化参数结构体
20 | bm := make(gopay.BodyMap)
21 | bm.Set("out_trade_no", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk").
22 | //Set("out_refund_no", "vk4264I1UQ3Hm3E4AKsavK8npylGSgQA092f9ckUxp8A2gXmnsLEdsupURVTcaC7").
23 | //Set("transaction_id", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk").
24 | //Set("refund_id", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk").
25 | Set("nonce_str", util.RandomString(32)).
26 | Set("sign_type", wechat.SignType_MD5)
27 |
28 | //请求申请退款
29 | wxRsp, resBm, err := client.QueryRefund(ctx, bm)
30 | if err != nil {
31 | xlog.Error(err)
32 | return
33 | }
34 | xlog.Debug("wxRsp:", wxRsp)
35 | xlog.Debug("resBm:", resBm)
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/examples/wechat/wx_Refund.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/go-pay/gopay"
7 | "github.com/go-pay/gopay/wechat"
8 | "github.com/go-pay/util"
9 | "github.com/go-pay/xlog"
10 | )
11 |
12 | var ctx = context.Background()
13 |
14 | func Refund() {
15 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
16 | // 初始化微信客户端
17 | // appId:应用ID
18 | // MchID:商户ID
19 | // ApiKey:Key值
20 | // isProd:是否是正式环境
21 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
22 |
23 | s := util.RandomString(64)
24 | xlog.Debug("out_refund_no:", s)
25 | // 初始化参数结构体
26 | bm := make(gopay.BodyMap)
27 | bm.Set("out_trade_no", "SdZBAqJHBQGKVwb7aMR2mUwC588NG2Sd").
28 | Set("nonce_str", util.RandomString(32)).
29 | Set("sign_type", wechat.SignType_MD5).
30 | Set("out_refund_no", s).
31 | Set("total_fee", 1).
32 | Set("refund_fee", 1).
33 | Set("notify_url", "https://www.fmm.ink")
34 |
35 | //请求申请退款(沙箱环境下,证书路径参数可传空)
36 | // body:参数Body
37 | wxRsp, resBm, err := client.Refund(ctx, bm)
38 | if err != nil {
39 | xlog.Error(err)
40 | return
41 | }
42 | xlog.Debug("wxRsp:", wxRsp)
43 | xlog.Debug("resBm:", resBm)
44 | }
45 |
--------------------------------------------------------------------------------
/examples/wechat/wx_Reverse.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func Reverse() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境
17 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
18 |
19 | // 初始化参数Map
20 | bm := make(gopay.BodyMap)
21 | bm.Set("nonce_str", util.RandomString(32)).
22 | Set("out_trade_no", "6aDCor1nUcAihrV5JBlI09tLvXbUp02B").
23 | Set("sign_type", wechat.SignType_MD5)
24 |
25 | //请求撤销订单,成功后得到结果,沙箱环境下,证书路径参数可传空
26 | wxRsp, err := client.Reverse(ctx, bm)
27 | if err != nil {
28 | xlog.Error(err)
29 | return
30 | }
31 | xlog.Debug("wxRsp:", wxRsp)
32 | }
33 |
--------------------------------------------------------------------------------
/examples/wechat/wx_Transfer.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "github.com/go-pay/gopay"
5 | "github.com/go-pay/gopay/wechat"
6 | "github.com/go-pay/util"
7 | "github.com/go-pay/xlog"
8 | )
9 |
10 | func Transfer() {
11 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
12 | // 初始化微信客户端
13 | // appId:应用ID
14 | // MchID:商户ID
15 | // ApiKey:Key值
16 | // isProd:是否是正式环境(企业转账到个人账户,默认正式环境)
17 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
18 |
19 | err := client.AddCertPkcs12FileContent([]byte("apiclient_cert.p12 content"))
20 | if err != nil {
21 | xlog.Error(err)
22 | return
23 | }
24 |
25 | // 初始化参数结构体
26 | bm := make(gopay.BodyMap)
27 | bm.Set("nonce_str", util.RandomString(32)).
28 | Set("partner_trade_no", util.RandomString(32)).
29 | Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8").
30 | Set("check_name", "FORCE_CHECK"). // NO_CHECK:不校验真实姓名 , FORCE_CHECK:强校验真实姓名
31 | Set("re_user_name", "付明明"). // 收款用户真实姓名。 如果check_name设置为FORCE_CHECK,则必填用户真实姓名
32 | Set("amount", 30). // 企业付款金额,单位为分
33 | Set("desc", "测试转账"). // 企业付款备注,必填。注意:备注中的敏感词会被转成字符*
34 | Set("spbill_create_ip", "127.0.0.1")
35 |
36 | // 企业向微信用户个人付款(不支持沙箱环境)
37 | // body:参数Body
38 | wxRsp, err := client.Transfer(ctx, bm)
39 | if err != nil {
40 | xlog.Error(err)
41 | return
42 | }
43 | xlog.Debug("Response:", wxRsp)
44 | }
45 |
--------------------------------------------------------------------------------
/examples/wechat/wx_UnifiedOrder.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "strconv"
5 | "time"
6 |
7 | "github.com/go-pay/gopay"
8 | "github.com/go-pay/gopay/wechat"
9 | "github.com/go-pay/util"
10 | "github.com/go-pay/xlog"
11 | )
12 |
13 | func UnifiedOrder() {
14 | // client只需要初始化一个,此处为了演示,每个方法都做了初始化
15 | // 初始化微信客户端
16 | // appId:应用ID
17 | // mchId:商户ID
18 | // apiKey:API秘钥值
19 | // isProd:是否是正式环境
20 | client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
21 |
22 | //设置国家
23 | client.SetCountry(wechat.China)
24 |
25 | number := util.RandomString(32)
26 | xlog.Debug("out_trade_no:", number)
27 |
28 | //初始化参数Map
29 | bm := make(gopay.BodyMap)
30 | bm.Set("nonce_str", util.RandomString(32)).
31 | Set("body", "H5支付").
32 | Set("out_trade_no", number).
33 | Set("total_fee", 1).
34 | Set("spbill_create_ip", "127.0.0.1").
35 | Set("notify_url", "https://www.fmm.ink").
36 | Set("trade_type", wechat.TradeType_H5).
37 | Set("device_info", "WEB").
38 | Set("sign_type", wechat.SignType_MD5).
39 | SetBodyMap("scene_info", func(bm gopay.BodyMap) {
40 | bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
41 | bm.Set("type", "Wap")
42 | bm.Set("wap_url", "https://www.fmm.ink")
43 | bm.Set("wap_name", "H5测试支付")
44 | })
45 | }) /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
46 |
47 | //请求支付下单,成功后得到结果
48 | wxRsp, err := client.UnifiedOrder(ctx, bm)
49 | if err != nil {
50 | xlog.Error(err)
51 | return
52 | }
53 | xlog.Debug("Response:", wxRsp)
54 | //xlog.Debug("wxRsp.MwebUrl:", wxRsp.MwebUrl)
55 |
56 | timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
57 |
58 | //获取小程序支付需要的paySign
59 | //pac := "prepay_id=" + wxRsp.PrepayId
60 | //paySign := wechat.GetMiniPaySign("wxdaa2ab9ef87b5497", wxRsp.NonceStr, pac, wechat.SignType_MD5, timeStamp, "GFDS8j98rewnmgl45wHTt980jg543abc")
61 | //xlog.Debug("paySign:", paySign)
62 |
63 | //获取Jsapi支付需要的paySign
64 | pac := "prepay_id=" + wxRsp.PrepayId
65 | paySign := wechat.GetJsapiPaySign("wxdaa2ab9ef87b5497", wxRsp.NonceStr, pac, wechat.SignType_MD5, timeStamp, "GFDS8j98rewnmgl45wHTt980jg543abc")
66 | xlog.Debug("paySign:", paySign)
67 |
68 | //获取App支付需要的paySign
69 | //paySign := wechat.GetAppPaySign("wxdaa2ab9ef87b5497","", wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, "GFDS8j98rewnmgl45wHTt980jg543abc")
70 | //xlog.Debug("paySign:", paySign)
71 | }
72 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/go-pay/gopay
2 |
3 | go 1.23.0
4 |
5 | require (
6 | github.com/go-pay/crypto v0.0.1
7 | github.com/go-pay/errgroup v0.0.3
8 | github.com/go-pay/smap v0.0.2
9 | github.com/go-pay/util v0.0.4
10 | github.com/go-pay/xlog v0.0.3
11 | github.com/go-pay/xtime v0.0.2
12 | golang.org/x/crypto v0.38.0
13 | )
14 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/go-pay/crypto v0.0.1 h1:B6InT8CLfSLc6nGRVx9VMJRBBazFMjr293+jl0lLXUY=
2 | github.com/go-pay/crypto v0.0.1/go.mod h1:41oEIvHMKbNcYlWUlRWtsnC6+ASgh7u29z0gJXe5bes=
3 | github.com/go-pay/errgroup v0.0.3 h1:DB4s8e8oWYDyETKQ1y1riMJ7y29zE1uIsMCSjEOFSbU=
4 | github.com/go-pay/errgroup v0.0.3/go.mod h1:0+4b8mvFMS71MIzsaC+gVvB4x37I93lRb2dqrwuU8x8=
5 | github.com/go-pay/smap v0.0.2 h1:kKflYor5T5FgZltPFBMTFfjJvqYMHr5VnIFSEyhVTcA=
6 | github.com/go-pay/smap v0.0.2/go.mod h1:HW9oAo0okuyDYsbpbj5fJFxnNj/BZorRGFw26SxrNWw=
7 | github.com/go-pay/util v0.0.4 h1:TuwSU9o3Qd7m9v1PbzFuIA/8uO9FJnA6P7neG/NwPyk=
8 | github.com/go-pay/util v0.0.4/go.mod h1:Tsdhs8Ib9J9b4+NKNO1PHh5hWHhlg98PthsX0ckq6PM=
9 | github.com/go-pay/xlog v0.0.3 h1:avyMhCL/JgBHreoGx/am/kHxfs1udDOAeVqbmzP/Yes=
10 | github.com/go-pay/xlog v0.0.3/go.mod h1:mH47xbobrdsSHWsmFtSF5agWbMHFP+tK0ZbVCk5OAEw=
11 | github.com/go-pay/xtime v0.0.2 h1:7YR4/iuELsEHpJ6LUO0SVK80hQxDO9MLCfuVYIiTCRM=
12 | github.com/go-pay/xtime v0.0.2/go.mod h1:W1yRbJaSt4CSBcdAtLBQ8xajiN/Pl5hquGczUcUE9xE=
13 | golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
14 | golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
15 |
--------------------------------------------------------------------------------
/lakala/client_test.go:
--------------------------------------------------------------------------------
1 | package lakala
2 |
3 | import (
4 | "os"
5 | "testing"
6 |
7 | "github.com/go-pay/gopay"
8 | "github.com/go-pay/xlog"
9 | )
10 |
11 | var (
12 | client *Client
13 | err error
14 | partnerCode = "xxxxxxx"
15 | credentialCode = "xxxxxxx"
16 | )
17 |
18 | func TestMain(m *testing.M) {
19 | // 初始化lakala户端
20 | // PartnerCode: 商户编码,由4~6位大写字母或数字构成
21 | // credentialCode: 系统为商户分配的开发校验码,请妥善保管,不要在公开场合泄露
22 | // isProd: 是否生产环境
23 | client, err = NewClient(partnerCode, credentialCode, false)
24 | if err != nil {
25 | xlog.Error(err)
26 | return
27 | }
28 | // 打开Debug开关,输出日志
29 | client.DebugSwitch = gopay.DebugOn
30 |
31 | os.Exit(m.Run())
32 | }
33 |
--------------------------------------------------------------------------------
/lakala/h5.go:
--------------------------------------------------------------------------------
1 | package lakala
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "errors"
7 | "fmt"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // 创建H5支付单
13 | // 文档:https://payjp.lakala.com/docs/cn/#api-MobileH5-NewMobileH5Pay
14 | func (c *Client) CreateH5PayOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *PaymentRsp, err error) {
15 | if orderId == gopay.NULL {
16 | return nil, fmt.Errorf("orderId is empty")
17 | }
18 | if err = bm.CheckEmptyError("description", "price", "channel"); err != nil {
19 | return nil, err
20 | }
21 | url := fmt.Sprintf(newH5Order, c.PartnerCode, orderId)
22 | bs, err := c.doPut(ctx, url, bm)
23 | if err != nil {
24 | return nil, err
25 | }
26 | rsp = new(PaymentRsp)
27 | err = json.Unmarshal(bs, rsp)
28 | if err != nil {
29 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
30 | }
31 | return rsp, nil
32 | }
33 |
34 | // H5支付跳转页
35 | // 文档:https://payjp.lakala.com/docs/cn/#api-MobileH5-MobileH5Pay
36 | func (c *Client) H5Pay(ctx context.Context, orderId, redirect string) (rsp *ErrorCode, err error) {
37 | if orderId == gopay.NULL {
38 | return nil, errors.New("order_id is empty")
39 | }
40 | if redirect == gopay.NULL {
41 | return nil, fmt.Errorf("redirect is empty")
42 | }
43 | url := fmt.Sprintf(h5Pay, c.PartnerCode, orderId)
44 | bs, err := c.doGet(ctx, url, "redirect="+redirect)
45 | if err != nil {
46 | return nil, err
47 | }
48 | rsp = new(ErrorCode)
49 | err = json.Unmarshal(bs, rsp)
50 | if err != nil {
51 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
52 | }
53 | return rsp, nil
54 | }
55 |
56 | // H5支付跳转页(Alipay+)
57 | // 文档:https://payjp.lakala.com/docs/cn/#api-MobileH5-MobileH5PayAlipayPlus
58 | func (c *Client) H5AlipayPlusPay(ctx context.Context, orderId, redirect string) (rsp *ErrorCode, err error) {
59 | if orderId == gopay.NULL {
60 | return nil, errors.New("order_id is empty")
61 | }
62 | if redirect == gopay.NULL {
63 | return nil, fmt.Errorf("redirect is empty")
64 | }
65 | url := fmt.Sprintf(alipayPlusH5Pay, c.PartnerCode, orderId)
66 | bs, err := c.doGet(ctx, url, "redirect="+redirect)
67 | if err != nil {
68 | return nil, err
69 | }
70 | rsp = new(ErrorCode)
71 | err = json.Unmarshal(bs, rsp)
72 | if err != nil {
73 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
74 | }
75 | return rsp, nil
76 | }
77 |
--------------------------------------------------------------------------------
/lakala/mini_program.go:
--------------------------------------------------------------------------------
1 | package lakala
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // 创建小程序订单
12 | // 文档:https://payjp.lakala.com/docs/cn/#api-Miniprogram_Payment-microapp
13 | func (c *Client) CreateMiniProgramOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *PaymentRsp, err error) {
14 | if orderId == gopay.NULL {
15 | return nil, fmt.Errorf("orderId is empty")
16 | }
17 | if err = bm.CheckEmptyError("description", "price", "channel"); err != nil {
18 | return nil, err
19 | }
20 | url := fmt.Sprintf(newMiniProgramOrder, c.PartnerCode, orderId)
21 | bs, err := c.doPut(ctx, url, bm)
22 | if err != nil {
23 | return nil, err
24 | }
25 | rsp = new(PaymentRsp)
26 | err = json.Unmarshal(bs, rsp)
27 | if err != nil {
28 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
29 | }
30 | return rsp, nil
31 | }
32 |
--------------------------------------------------------------------------------
/lakala/qr_code.go:
--------------------------------------------------------------------------------
1 | package lakala
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // 创建QRCode支付单
12 | // 文档:https://payjp.lakala.com/docs/cn/#api-QRCode-NewQRCode
13 | func (c *Client) CreateQRCodeOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *PaymentRsp, err error) {
14 | if orderId == gopay.NULL {
15 | return nil, fmt.Errorf("orderId is empty")
16 | }
17 | if err = bm.CheckEmptyError("description", "price", "channel"); err != nil {
18 | return nil, err
19 | }
20 | url := fmt.Sprintf(newQrcodeOrder, c.PartnerCode, orderId)
21 | bs, err := c.doPut(ctx, url, bm)
22 | if err != nil {
23 | return nil, err
24 | }
25 | rsp = new(PaymentRsp)
26 | err = json.Unmarshal(bs, rsp)
27 | if err != nil {
28 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
29 | }
30 | return rsp, nil
31 | }
32 |
33 | // 创建Native QRCode支付单
34 | // 文档:https://payjp.lakala.com/docs/cn/#api-QRCode-NativeQRCode
35 | func (c *Client) CreateNativeQRCodeOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *PaymentRsp, err error) {
36 | if orderId == gopay.NULL {
37 | return nil, fmt.Errorf("orderId is empty")
38 | }
39 | if err = bm.CheckEmptyError("description", "price", "channel"); err != nil {
40 | return nil, err
41 | }
42 | url := fmt.Sprintf(newNativeQrcodeOrder, c.PartnerCode, orderId)
43 | bs, err := c.doPut(ctx, url, bm)
44 | if err != nil {
45 | return nil, err
46 | }
47 | rsp = new(PaymentRsp)
48 | err = json.Unmarshal(bs, rsp)
49 | if err != nil {
50 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
51 | }
52 | return rsp, nil
53 | }
54 |
55 | // QRCode支付跳转页
56 | // 文档:https://payjp.lakala.com/docs/cn/#api-QRCode-QRCodePay
57 | func (c *Client) QRCodePay(ctx context.Context, orderId, redirect string) (rsp *ErrorCode, err error) {
58 | if orderId == gopay.NULL {
59 | return nil, fmt.Errorf("orderId is empty")
60 | }
61 | if redirect == gopay.NULL {
62 | return nil, fmt.Errorf("redirect is empty")
63 | }
64 | url := fmt.Sprintf(qrcodePay, c.PartnerCode, orderId)
65 | bs, err := c.doGet(ctx, url, "redirect="+redirect)
66 | if err != nil {
67 | return nil, err
68 | }
69 | rsp = new(ErrorCode)
70 | err = json.Unmarshal(bs, rsp)
71 | if err != nil {
72 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
73 | }
74 | return rsp, nil
75 | }
76 |
--------------------------------------------------------------------------------
/lakala/retail_pay.go:
--------------------------------------------------------------------------------
1 | package lakala
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // 创建线下支付订单
12 | // 文档:https://payjp.lakala.com/docs/cn/#api-RetailPay-RetailMicroPay
13 | func (c *Client) CreateRetailOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *RetailPayRsp, err error) {
14 | if orderId == gopay.NULL {
15 | return nil, fmt.Errorf("orderId is empty")
16 | }
17 | if err = bm.CheckEmptyError("description", "price"); err != nil {
18 | return nil, err
19 | }
20 | url := fmt.Sprintf(newRetailOrder, c.PartnerCode, orderId)
21 | bs, err := c.doPut(ctx, url, bm)
22 | if err != nil {
23 | return nil, err
24 | }
25 | rsp = new(RetailPayRsp)
26 | err = json.Unmarshal(bs, rsp)
27 | if err != nil {
28 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
29 | }
30 | return rsp, nil
31 | }
32 |
33 | // 创建线下QRCode支付单
34 | // 文档:https://payjp.lakala.com/docs/cn/#api-RetailPay-RetailQRCode
35 | func (c *Client) CreateRetailQRCodeOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *PaymentRsp, err error) {
36 | if orderId == gopay.NULL {
37 | return nil, fmt.Errorf("orderId is empty")
38 | }
39 | if err = bm.CheckEmptyError("description", "price"); err != nil {
40 | return nil, err
41 | }
42 | url := fmt.Sprintf(newRetailQrcodeOrder, c.PartnerCode, orderId)
43 | bs, err := c.doPut(ctx, url, bm)
44 | if err != nil {
45 | return nil, err
46 | }
47 | rsp = new(PaymentRsp)
48 | err = json.Unmarshal(bs, rsp)
49 | if err != nil {
50 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
51 | }
52 | return rsp, nil
53 | }
54 |
--------------------------------------------------------------------------------
/lakala/sdk_payment.go:
--------------------------------------------------------------------------------
1 | package lakala
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // 创建SDK订单(Online)
12 | // 文档:https://payjp.lakala.com/docs/cn/#api-SDKPayment-SDK
13 | func (c *Client) CreateSDKPaymentOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *PaymentRsp, err error) {
14 | if orderId == gopay.NULL {
15 | return nil, fmt.Errorf("orderId is empty")
16 | }
17 | if err = bm.CheckEmptyError("description", "price", "channel"); err != nil {
18 | return nil, err
19 | }
20 | if bm.Get("channel") == "Wechat" && bm.Get("appid") == "" {
21 | return nil, fmt.Errorf("wechat appid is empty")
22 | }
23 | url := fmt.Sprintf(newSDKPaymentOrder, c.PartnerCode, orderId)
24 | bs, err := c.doPut(ctx, url, bm)
25 | if err != nil {
26 | return nil, err
27 | }
28 | rsp = new(PaymentRsp)
29 | err = json.Unmarshal(bs, rsp)
30 | if err != nil {
31 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
32 | }
33 | return rsp, nil
34 | }
35 |
--------------------------------------------------------------------------------
/lakala/web_gateway.go:
--------------------------------------------------------------------------------
1 | package lakala
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // 创建渠道Web网关订单
12 | // 文档:https://payjp.lakala.com/docs/cn/#api-Channel_Web_Gateway-WebGateway
13 | func (c *Client) CreateWebGatewayOrder(ctx context.Context, orderId string, bm gopay.BodyMap) (rsp *PaymentRsp, err error) {
14 | if orderId == gopay.NULL {
15 | return nil, fmt.Errorf("orderId is empty")
16 | }
17 | if err = bm.CheckEmptyError("description", "price", "channel"); err != nil {
18 | return nil, err
19 | }
20 | url := fmt.Sprintf(newWebGatewayOrder, c.PartnerCode, orderId)
21 | bs, err := c.doPut(ctx, url, bm)
22 | if err != nil {
23 | return nil, err
24 | }
25 | rsp = new(PaymentRsp)
26 | err = json.Unmarshal(bs, rsp)
27 | if err != nil {
28 | return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
29 | }
30 | return rsp, nil
31 | }
32 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/go-pay/gopay/bb8f8ce9105aa793b9b0f1b122bb2917c4e421de/logo.png
--------------------------------------------------------------------------------
/paypal/access_token.go:
--------------------------------------------------------------------------------
1 | package paypal
2 |
3 | import (
4 | "encoding/base64"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 | "runtime"
9 | "time"
10 |
11 | "github.com/go-pay/gopay"
12 | "github.com/go-pay/gopay/pkg/xhttp"
13 | "github.com/go-pay/util/retry"
14 | )
15 |
16 | func (c *Client) goAuthRefreshToken() {
17 | defer func() {
18 | if r := recover(); r != nil {
19 | buf := make([]byte, 64<<10)
20 | buf = buf[:runtime.Stack(buf, false)]
21 | c.logger.Errorf("paypal_goAuthRefreshToken: panic recovered: %s\n%s", r, buf)
22 | }
23 | }()
24 | for {
25 | time.Sleep(time.Duration(c.ExpiresIn/2) * time.Second)
26 | err := retry.Retry(func() error {
27 | _, err := c.GetAccessToken()
28 | if err != nil {
29 | return err
30 | }
31 | return nil
32 | }, 3, time.Second)
33 | if err != nil {
34 | c.logger.Errorf("PayPal GetAccessToken Error: %s", err.Error())
35 | }
36 | }
37 | }
38 |
39 | // =====================================================================================================================
40 |
41 | // 获取AccessToken(Get an access token)
42 | // 文档:https://developer.paypal.com/docs/api/reference/get-an-access-token
43 | func (c *Client) GetAccessToken() (token *AccessToken, err error) {
44 | var (
45 | baseUrl = c.baseUrlProd
46 | url string
47 | )
48 | if !c.IsProd {
49 | baseUrl = c.baseUrlSandbox
50 | }
51 | url = baseUrl + getAccessToken
52 | // Authorization
53 | authHeader := AuthorizationPrefixBasic + base64.StdEncoding.EncodeToString([]byte(c.Clientid+":"+c.Secret))
54 | req := c.hc.Req(xhttp.TypeFormData)
55 | req.Header.Add(HeaderAuthorization, authHeader)
56 | req.Header.Add("Accept", "*/*")
57 | // Body
58 | bm := make(gopay.BodyMap)
59 | bm.Set("grant_type", "client_credentials")
60 | if c.DebugSwitch == gopay.DebugOn {
61 | c.logger.Debugf("PayPal_Url: %s", url)
62 | c.logger.Debugf("PayPal_Req_Body: %s", bm.JsonBody())
63 | c.logger.Debugf("PayPal_Req_Headers: %#v", req.Header)
64 | }
65 | res, bs, err := req.Post(url).SendBodyMap(bm).EndBytes(c.ctx)
66 | if err != nil {
67 | return nil, err
68 | }
69 | if c.DebugSwitch == gopay.DebugOn {
70 | c.logger.Debugf("PayPal_Response: %d > %s", res.StatusCode, string(bs))
71 | c.logger.Debugf("PayPal_Rsp_Headers: %#v", res.Header)
72 | }
73 | if res.StatusCode != http.StatusOK {
74 | return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
75 | }
76 | token = new(AccessToken)
77 | if err = json.Unmarshal(bs, token); err != nil {
78 | return nil, fmt.Errorf("json.Unmarshal(%s): %w", string(bs), err)
79 | }
80 | c.Appid = token.Appid
81 | c.AccessToken = token.AccessToken
82 | c.ExpiresIn = token.ExpiresIn
83 | return token, nil
84 | }
85 |
--------------------------------------------------------------------------------
/paypal/client_test.go:
--------------------------------------------------------------------------------
1 | package paypal
2 |
3 | import (
4 | "context"
5 | "encoding/base64"
6 | "os"
7 | "testing"
8 |
9 | "github.com/go-pay/gopay"
10 | "github.com/go-pay/xlog"
11 | )
12 |
13 | var (
14 | client *Client
15 | ctx = context.Background()
16 | err error
17 | Clientid = ""
18 | Secret = ""
19 | )
20 |
21 | func TestMain(m *testing.M) {
22 | xlog.SetLevel(xlog.DebugLevel)
23 | client, err = NewClient(Clientid, Secret, false)
24 | if err != nil {
25 | xlog.Error(err)
26 | return
27 | }
28 | // 打开Debug开关,输出日志
29 | client.DebugSwitch = gopay.DebugOn
30 |
31 | xlog.Debugf("Appid: %s", client.Appid)
32 | xlog.Debugf("AccessToken: %s", client.AccessToken)
33 | xlog.Debugf("ExpiresIn: %d", client.ExpiresIn)
34 | os.Exit(m.Run())
35 | }
36 |
37 | func TestBasicAuth(t *testing.T) {
38 | uname := "jerry"
39 | passwd := "12346"
40 | auth := base64.StdEncoding.EncodeToString([]byte(uname + ":" + passwd))
41 | xlog.Debugf("Basic %s", auth)
42 | }
43 |
--------------------------------------------------------------------------------
/paypal/model_product.go:
--------------------------------------------------------------------------------
1 | package paypal
2 |
3 | type ProductCreateRep struct {
4 | Code int `json:"-"`
5 | Error string `json:"-"`
6 | ErrorResponse *ErrorResponse `json:"-"`
7 | Response *Product `json:"response,omitempty"`
8 | }
9 |
10 | type Product struct {
11 | ID string `json:"id"`
12 | Name string `json:"name"`
13 | Description string `json:"description"`
14 | Type string `json:"type"`
15 | Category string `json:"category"`
16 | ImageURL string `json:"image_url"`
17 | HomeURL string `json:"home_url"`
18 | CreateTime string `json:"create_time"`
19 | UpdateTime string `json:"update_time"`
20 | Links []struct {
21 | Href string `json:"href"`
22 | Rel string `json:"rel"`
23 | Method string `json:"method"`
24 | } `json:"links"`
25 | }
26 |
27 | type ProductsListRsp struct {
28 | Code int `json:"-"`
29 | Error string `json:"-"`
30 | ErrorResponse *ErrorResponse `json:"-"`
31 | Response *ProductsList `json:"response,omitempty"`
32 | }
33 |
34 | type ProductsList struct {
35 | TotalItems int `json:"total_items"`
36 | TotalPages int `json:"total_pages"`
37 | Items []*ProductDetail `json:"products"`
38 | Links []*Link `json:"links,omitempty"`
39 | }
40 |
41 | type ProductDetailsRsp struct {
42 | Code int `json:"-"`
43 | Error string `json:"-"`
44 | ErrorResponse *ErrorResponse `json:"-"`
45 | Response *ProductDetail `json:"response,omitempty"`
46 | }
47 |
48 | type ProductDetail struct {
49 | ID string `json:"id"`
50 | Name string `json:"name"`
51 | Description string `json:"description"`
52 | Type string `json:"type,omitempty"`
53 | Category string `json:"category,omitempty"`
54 | ImageURL string `json:"image_url,omitempty"`
55 | HomeURL string `json:"home_url,omitempty"`
56 | CreateTime string `json:"create_time"`
57 | UpdateTime string `json:"update_time,omitempty"`
58 | Links []struct {
59 | Href string `json:"href"`
60 | Rel string `json:"rel"`
61 | Method string `json:"method"`
62 | } `json:"links"`
63 | }
64 |
--------------------------------------------------------------------------------
/paypal/tracking.go:
--------------------------------------------------------------------------------
1 | package paypal
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // AddTrackingNumber 添加物流单号
13 | // Code = 0 is success
14 | // 文档:https://developer.paypal.com/docs/api/orders/v2/#orders_track_create
15 | func (c *Client) AddTrackingNumber(ctx context.Context, orderId string, bm gopay.BodyMap) (ppRsp *AddTrackingNumberRsp, err error) {
16 | if err = bm.CheckEmptyError("tracking_number", "carrier", "capture_id"); err != nil {
17 | return nil, err
18 | }
19 |
20 | url := fmt.Sprintf(addTrackingNumber, orderId)
21 | res, bs, err := c.doPayPalPost(ctx, bm, url)
22 | if err != nil {
23 | return nil, err
24 | }
25 | ppRsp = &AddTrackingNumberRsp{Code: Success}
26 | ppRsp.Response = new(OrderDetail)
27 | if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
28 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
29 | }
30 | if res.StatusCode != http.StatusCreated {
31 | ppRsp.Code = res.StatusCode
32 | ppRsp.Error = string(bs)
33 | ppRsp.ErrorResponse = new(ErrorResponse)
34 | _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
35 | }
36 | return ppRsp, nil
37 | }
38 |
--------------------------------------------------------------------------------
/paypal/tracking_test.go:
--------------------------------------------------------------------------------
1 | package paypal
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/xlog"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | func TestAddTrackingNumber(t *testing.T) {
12 | var items []*ShipItem
13 | var item = &ShipItem{
14 | Name: "T-Shirt",
15 | Quantity: 1,
16 | Sku: "sku02",
17 | Url: "https://www.example.com/example.jpg",
18 | ImageUrl: "https://www.example.com/example",
19 | }
20 | items = append(items, item)
21 |
22 | bm := make(gopay.BodyMap)
23 | bm.Set("capture_id", "1DW71051X94135205").
24 | Set("tracking_number", "UJ639398620YP").
25 | Set("carrier", "YANWEN").
26 | Set("items", items)
27 |
28 | xlog.Debug("bm:", bm.JsonBody())
29 |
30 | ppRsp, err := client.AddTrackingNumber(ctx, "3TH70640XJ5862H", bm)
31 | if err != nil {
32 | xlog.Error(err)
33 | return
34 | }
35 | if ppRsp.Code != Success {
36 | xlog.Debugf("ppRsp.Code: %+v", ppRsp.Code)
37 | xlog.Debugf("ppRsp.Error: %+v", ppRsp.Error)
38 | xlog.Debugf("ppRsp.ErrorResponse: %+v", ppRsp.ErrorResponse)
39 | return
40 | }
41 | xlog.Debugf("ppRsp.Response: %+v", ppRsp.Response)
42 | for _, v := range ppRsp.Response.Links {
43 | xlog.Debugf("ppRsp.Response.Links: %+v", v)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pkg/jwt/errors.go:
--------------------------------------------------------------------------------
1 | package jwt
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | // Error constants
8 | var (
9 | ErrInvalidKey = errors.New("key is invalid")
10 | ErrInvalidKeyType = errors.New("key is of invalid type")
11 | ErrHashUnavailable = errors.New("the requested hash function is unavailable")
12 | )
13 |
14 | // The errors that might occur when parsing and validating a token
15 | const (
16 | ValidationErrorMalformed uint32 = 1 << iota // Token is malformed
17 | ValidationErrorUnverifiable // Token could not be verified because of signing problems
18 | ValidationErrorSignatureInvalid // Signature validation failed
19 |
20 | // Standard Claim validation errors
21 | ValidationErrorAudience // AUD validation failed
22 | ValidationErrorExpired // EXP validation failed
23 | ValidationErrorIssuedAt // IAT validation failed
24 | ValidationErrorIssuer // ISS validation failed
25 | ValidationErrorNotValidYet // NBF validation failed
26 | ValidationErrorId // JTI validation failed
27 | ValidationErrorClaimsInvalid // Generic claims validation error
28 | )
29 |
30 | // Helper for constructing a ValidationError with a string error message
31 | func NewValidationError(errorText string, errorFlags uint32) *ValidationError {
32 | return &ValidationError{
33 | text: errorText,
34 | Errors: errorFlags,
35 | }
36 | }
37 |
38 | // The error from Parse if token is not valid
39 | type ValidationError struct {
40 | Inner error // stores the error returned by external dependencies, i.e.: KeyFunc
41 | Errors uint32 // bitfield. see ValidationError... constants
42 | text string // errors that do not have a valid error just have text
43 | }
44 |
45 | // Validation error is an error type
46 | func (e ValidationError) Error() string {
47 | if e.Inner != nil {
48 | return e.Inner.Error()
49 | } else if e.text != "" {
50 | return e.text
51 | } else {
52 | return "token is invalid"
53 | }
54 | }
55 |
56 | // No errors
57 | func (e *ValidationError) valid() bool {
58 | return e.Errors == 0
59 | }
60 |
--------------------------------------------------------------------------------
/pkg/jwt/hmac.go:
--------------------------------------------------------------------------------
1 | package jwt
2 |
3 | import (
4 | "crypto"
5 | "crypto/hmac"
6 | "errors"
7 | )
8 |
9 | // Implements the HMAC-SHA family of signing methods signing methods
10 | // Expects key type of []byte for both signing and validation
11 | type SigningMethodHMAC struct {
12 | Name string
13 | Hash crypto.Hash
14 | }
15 |
16 | // Specific instances for HS256 and company
17 | var (
18 | SigningMethodHS256 *SigningMethodHMAC
19 | SigningMethodHS384 *SigningMethodHMAC
20 | SigningMethodHS512 *SigningMethodHMAC
21 | ErrSignatureInvalid = errors.New("signature is invalid")
22 | )
23 |
24 | func init() {
25 | // HS256
26 | SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256}
27 | RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod {
28 | return SigningMethodHS256
29 | })
30 |
31 | // HS384
32 | SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384}
33 | RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod {
34 | return SigningMethodHS384
35 | })
36 |
37 | // HS512
38 | SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512}
39 | RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod {
40 | return SigningMethodHS512
41 | })
42 | }
43 |
44 | func (m *SigningMethodHMAC) Alg() string {
45 | return m.Name
46 | }
47 |
48 | // Verify the signature of HSXXX tokens. Returns nil if the signature is valid.
49 | func (m *SigningMethodHMAC) Verify(signingString, signature string, key any) error {
50 | // Verify the key is the right type
51 | keyBytes, ok := key.([]byte)
52 | if !ok {
53 | return ErrInvalidKeyType
54 | }
55 |
56 | // Decode signature, for comparison
57 | sig, err := DecodeSegment(signature)
58 | if err != nil {
59 | return err
60 | }
61 |
62 | // Can we use the specified hashing method?
63 | if !m.Hash.Available() {
64 | return ErrHashUnavailable
65 | }
66 |
67 | // This signing method is symmetric, so we validate the signature
68 | // by reproducing the signature from the signing string and key, then
69 | // comparing that against the provided signature.
70 | hasher := hmac.New(m.Hash.New, keyBytes)
71 | hasher.Write([]byte(signingString))
72 | if !hmac.Equal(sig, hasher.Sum(nil)) {
73 | return ErrSignatureInvalid
74 | }
75 |
76 | // No validation errors. Signature is good.
77 | return nil
78 | }
79 |
80 | // Implements the Sign method from SigningMethod for this signing method.
81 | // Key must be []byte
82 | func (m *SigningMethodHMAC) Sign(signingString string, key any) (string, error) {
83 | if keyBytes, ok := key.([]byte); ok {
84 | if !m.Hash.Available() {
85 | return "", ErrHashUnavailable
86 | }
87 |
88 | hasher := hmac.New(m.Hash.New, keyBytes)
89 | hasher.Write([]byte(signingString))
90 |
91 | return EncodeSegment(hasher.Sum(nil)), nil
92 | }
93 |
94 | return "", ErrInvalidKeyType
95 | }
96 |
--------------------------------------------------------------------------------
/pkg/jwt/rsa.go:
--------------------------------------------------------------------------------
1 | package jwt
2 |
3 | import (
4 | "crypto"
5 | "crypto/rand"
6 | "crypto/rsa"
7 | "fmt"
8 |
9 | "github.com/go-pay/gopay"
10 | )
11 |
12 | // Implements the RSA family of signing methods signing methods
13 | // Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation
14 | type SigningMethodRSA struct {
15 | Name string
16 | Hash crypto.Hash
17 | }
18 |
19 | // Specific instances for RS256 and company
20 | var (
21 | SigningMethodRS256 *SigningMethodRSA
22 | SigningMethodRS384 *SigningMethodRSA
23 | SigningMethodRS512 *SigningMethodRSA
24 | )
25 |
26 | func init() {
27 | // RS256
28 | SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256}
29 | RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod {
30 | return SigningMethodRS256
31 | })
32 |
33 | // RS384
34 | SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384}
35 | RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod {
36 | return SigningMethodRS384
37 | })
38 |
39 | // RS512
40 | SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512}
41 | RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod {
42 | return SigningMethodRS512
43 | })
44 | }
45 |
46 | func (m *SigningMethodRSA) Alg() string {
47 | return m.Name
48 | }
49 |
50 | // Implements the Verify method from SigningMethod
51 | // For this signing method, must be an *rsa.PublicKey structure.
52 | func (m *SigningMethodRSA) Verify(signingString, signature string, key any) error {
53 | var err error
54 |
55 | // Decode the signature
56 | var sig []byte
57 | if sig, err = DecodeSegment(signature); err != nil {
58 | return err
59 | }
60 |
61 | var rsaKey *rsa.PublicKey
62 | var ok bool
63 |
64 | if rsaKey, ok = key.(*rsa.PublicKey); !ok {
65 | return ErrInvalidKeyType
66 | }
67 |
68 | // Create h
69 | if !m.Hash.Available() {
70 | return ErrHashUnavailable
71 | }
72 | h := m.Hash.New()
73 | h.Write([]byte(signingString))
74 |
75 | // Verify the signature
76 | if err = rsa.VerifyPKCS1v15(rsaKey, crypto.SHA256, h.Sum(nil), sig); err != nil {
77 | return fmt.Errorf("[%w]: %v", gopay.VerifySignatureErr, err)
78 | }
79 | return nil
80 | }
81 |
82 | // Implements the Sign method from SigningMethod
83 | // For this signing method, must be an *rsa.PrivateKey structure.
84 | func (m *SigningMethodRSA) Sign(signingString string, key any) (string, error) {
85 | var rsaKey *rsa.PrivateKey
86 | var ok bool
87 |
88 | // Validate type of key
89 | if rsaKey, ok = key.(*rsa.PrivateKey); !ok {
90 | return "", ErrInvalidKey
91 | }
92 |
93 | // Create the hasher
94 | if !m.Hash.Available() {
95 | return "", ErrHashUnavailable
96 | }
97 |
98 | hasher := m.Hash.New()
99 | hasher.Write([]byte(signingString))
100 |
101 | // Sign the string and return the encoded bytes
102 | sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil))
103 | if err == nil {
104 | return EncodeSegment(sigBytes), nil
105 | }
106 | return "", err
107 | }
108 |
--------------------------------------------------------------------------------
/pkg/jwt/signing_method.go:
--------------------------------------------------------------------------------
1 | package jwt
2 |
3 | import (
4 | "sync"
5 | )
6 |
7 | var signingMethods = map[string]func() SigningMethod{}
8 | var signingMethodLock = new(sync.RWMutex)
9 |
10 | // Implement SigningMethod to add new methods for signing or verifying tokens.
11 | type SigningMethod interface {
12 | Verify(signingString, signature string, key any) error // Returns nil if signature is valid
13 | Sign(signingString string, key any) (string, error) // Returns encoded signature or error
14 | Alg() string // returns the alg identifier for this method (example: 'HS256')
15 | }
16 |
17 | // Register the "alg" name and a factory function for signing method.
18 | // This is typically done during init() in the method's implementation
19 | func RegisterSigningMethod(alg string, f func() SigningMethod) {
20 | signingMethodLock.Lock()
21 | defer signingMethodLock.Unlock()
22 |
23 | signingMethods[alg] = f
24 | }
25 |
26 | // Get a signing method from an "alg" string
27 | func GetSigningMethod(alg string) (method SigningMethod) {
28 | signingMethodLock.RLock()
29 | defer signingMethodLock.RUnlock()
30 |
31 | if methodF, ok := signingMethods[alg]; ok {
32 | method = methodF()
33 | }
34 | return
35 | }
36 |
--------------------------------------------------------------------------------
/pkg/xhttp/README.md:
--------------------------------------------------------------------------------
1 | ## xhttp
2 |
3 | http request library for Go
--------------------------------------------------------------------------------
/pkg/xhttp/model.go:
--------------------------------------------------------------------------------
1 | package xhttp
2 |
3 | import (
4 | "encoding/json"
5 | "strings"
6 | )
7 |
8 | const (
9 | GET = "GET"
10 | POST = "POST"
11 | PUT = "PUT"
12 | DELETE = "DELETE"
13 | PATCH = "PATCH"
14 |
15 | ResTypeJSON = "json"
16 | ResTypeXML = "xml"
17 |
18 | TypeJSON = "json"
19 | TypeXML = "xml"
20 | TypeFormData = "form-data"
21 | TypeMultipartFormData = "multipart-form-data"
22 | )
23 |
24 | var (
25 | _ReqContentTypeMap = map[string]string{
26 | TypeJSON: "application/json",
27 | TypeXML: "application/xml",
28 | TypeFormData: "application/x-www-form-urlencoded",
29 | TypeMultipartFormData: "multipart/form-data",
30 | }
31 |
32 | _ResTypeMap = map[string]string{
33 | ResTypeJSON: "application/json",
34 | ResTypeXML: "application/xml",
35 | }
36 | )
37 |
38 | func ConvertToString(v any) (str string) {
39 | if v == nil {
40 | return ""
41 | }
42 | var (
43 | bs []byte
44 | err error
45 | )
46 | if bs, err = json.Marshal(v); err != nil {
47 | return ""
48 | }
49 | str = string(bs)
50 | return
51 | }
52 |
53 | var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
54 |
55 | func escapeQuotes(s string) string {
56 | return quoteEscaper.Replace(s)
57 | }
58 |
--------------------------------------------------------------------------------
/pkg/xhttp/transport_default_js.go:
--------------------------------------------------------------------------------
1 | // Copyright 2021 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | //go:build js && wasm
6 | // +build js,wasm
7 |
8 | package xhttp
9 |
10 | import (
11 | "context"
12 | "net"
13 | )
14 |
15 | func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
16 | return nil
17 | }
18 |
--------------------------------------------------------------------------------
/pkg/xhttp/transport_default_other.go:
--------------------------------------------------------------------------------
1 | // Copyright 2021 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | //go:build !(js && wasm)
6 | // +build !js !wasm
7 |
8 | package xhttp
9 |
10 | import (
11 | "context"
12 | "net"
13 | )
14 |
15 | func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
16 | return dialer.DialContext
17 | }
18 |
--------------------------------------------------------------------------------
/qq/client_test.go:
--------------------------------------------------------------------------------
1 | package qq
2 |
3 | import (
4 | "context"
5 | "os"
6 | "testing"
7 |
8 | "github.com/go-pay/gopay"
9 | "github.com/go-pay/util"
10 | "github.com/go-pay/xlog"
11 | )
12 |
13 | var (
14 | ctx = context.Background()
15 | client *Client
16 | mchId = "1368139502"
17 | apiKey = "GFDS8j98rewnmgl45wHTt980jg543abc"
18 | )
19 |
20 | func TestMain(m *testing.M) {
21 |
22 | // 初始化QQ客户端
23 | // mchId:商户ID
24 | // apiKey:API秘钥值
25 | client = NewClient(mchId, apiKey)
26 |
27 | // 打开Debug开关,输出日志
28 | client.DebugSwitch = gopay.DebugOn
29 |
30 | //err := client.AddCertFilePath(nil, nil, nil)
31 | //if err != nil {
32 | // panic(err)
33 | //}
34 | os.Exit(m.Run())
35 | }
36 |
37 | func TestClient_MicroPay(t *testing.T) {
38 | bm := make(gopay.BodyMap)
39 | bm.Set("nonce_str", util.RandomString(32))
40 |
41 | qqRsp, err := client.MicroPay(ctx, bm)
42 | if err != nil {
43 | xlog.Errorf("client.Micropay(%+v),error:%+v", bm, err)
44 | return
45 | }
46 | xlog.Debug("qqRsp:", *qqRsp)
47 | }
48 |
49 | func TestNotifyResponse_ToXmlString(t *testing.T) {
50 | n := new(NotifyResponse)
51 | n.ReturnCode = "SUCCESS"
52 | xlog.Info(n.ToXmlString())
53 |
54 | n.ReturnCode = "FAIL"
55 | n.ReturnMsg = "abc"
56 | xlog.Info(n.ToXmlString())
57 | }
58 |
59 | func TestClient_DownloadRedListFile(t *testing.T) {
60 | bm := make(gopay.BodyMap)
61 | bm.Set("date", 20160803)
62 | file, err := client.DownloadRedListFile(ctx, bm)
63 | if err != nil {
64 | xlog.Errorf("client.DownloadRedListFile(%+v),error:%+v", bm, err)
65 | return
66 | }
67 | xlog.Debug("qqRsp:", file)
68 | }
69 |
--------------------------------------------------------------------------------
/qq/red.go:
--------------------------------------------------------------------------------
1 | /*
2 | QQ 现金红包
3 | 文档:https://qpay.qq.com/buss/wiki/221/1219
4 | */
5 |
6 | package qq
7 |
8 | import (
9 | "context"
10 | "encoding/xml"
11 | "fmt"
12 |
13 | "github.com/go-pay/gopay"
14 | )
15 |
16 | // SendCashRed 创建现金红包
17 | // 注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传 nil,否则,3证书Path均不可空
18 | // 文档:https://qpay.qq.com/buss/wiki/221/1220
19 | func (q *Client) SendCashRed(ctx context.Context, bm gopay.BodyMap) (qqRsp *SendCashRedResponse, err error) {
20 | err = bm.CheckEmptyError("charset", "nonce_str", "mch_billno", "mch_name", "re_openid",
21 | "total_amount", "total_num", "wishing", "act_name", "icon_id", "min_value", "max_value")
22 | if err != nil {
23 | return nil, err
24 | }
25 | bs, err := q.doQQRed(ctx, bm, createCashRed)
26 | if err != nil {
27 | return nil, err
28 | }
29 | qqRsp = new(SendCashRedResponse)
30 | if err = xml.Unmarshal(bs, qqRsp); err != nil {
31 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
32 | }
33 | return qqRsp, nil
34 | }
35 |
36 | // DownloadRedListFile 对账单下载
37 | //
38 | // 注意:data类型为int类型,例如:date=20200909,2020年9月9日
39 | // 文档:https://qpay.qq.com/buss/wiki/221/1224
40 | func (q *Client) DownloadRedListFile(ctx context.Context, bm gopay.BodyMap) (qqRsp string, err error) {
41 | err = bm.CheckEmptyError("date")
42 | if err != nil {
43 | return gopay.NULL, err
44 | }
45 | bs, err := q.doQQGet(ctx, bm, redFileDown, SignType_MD5)
46 | if err != nil {
47 | return gopay.NULL, err
48 | }
49 | return string(bs), nil
50 | }
51 |
52 | // QueryRedInfo 查询红包详情
53 | //
54 | // 文档:https://qpay.qq.com/buss/wiki/221/2174
55 | func (q *Client) QueryRedInfo(ctx context.Context, bm gopay.BodyMap) (qqRsp *QueryRedInfoResponse, err error) {
56 | err = bm.CheckEmptyError("nonce_str", "listid")
57 | if err != nil {
58 | return nil, err
59 | }
60 | bs, err := q.doQQRed(ctx, bm, queryRedInfo)
61 | if err != nil {
62 | return nil, err
63 | }
64 | qqRsp = new(QueryRedInfoResponse)
65 | if err = xml.Unmarshal(bs, qqRsp); err != nil {
66 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
67 | }
68 | return qqRsp, nil
69 | }
70 |
--------------------------------------------------------------------------------
/saobei/account.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
3 | //CBK企业钱包分账
4 |
--------------------------------------------------------------------------------
/saobei/api.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
3 | const (
4 | // payPath 小程序支付接口
5 | miniPayPath = "/pay/open/minipay"
6 | // barcodePayPath 付款码支付(扫码支付)
7 | barcodePayPath = "/pay/open/barcodepay"
8 | // queryPath 支付查询
9 | queryPath = "/pay/open/query"
10 | // refundPath 退款申请
11 | refundPath = "/pay/open/refund"
12 | // queryRefundPath 退款订单查询
13 | queryRefundPath = "/pay/open/queryrefund"
14 | )
15 |
--------------------------------------------------------------------------------
/saobei/cert/cert.go:
--------------------------------------------------------------------------------
1 | package cert
2 |
3 | const (
4 | Key = "" // 机构秘钥,扫呗分配
5 | AccessToken = "8ee19b194b504b9c89b88a68b4cdf623" // 支付秘钥,扫呗分配
6 | InstNo = "" // 机构号,扫呗分配
7 | MerchantNo = "858104816000177" // 商户号,扫呗分配
8 | TerminalId = "44350591" // 终端号,扫呗分配
9 | )
10 |
--------------------------------------------------------------------------------
/saobei/client.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
3 | import (
4 | "context"
5 | "crypto/md5"
6 | "fmt"
7 | "hash"
8 | "sync"
9 |
10 | "github.com/go-pay/gopay"
11 | "github.com/go-pay/gopay/pkg/xhttp"
12 | "github.com/go-pay/xlog"
13 | )
14 |
15 | type Client struct {
16 | instNo string //商户系统机构号inst_no
17 | key string // 商户系统令牌
18 | merchantNo string // 支付系统:商户号
19 | terminalId string // 支付系统:商户号终端号
20 | accessToken string // 支付系统: 令牌
21 | isProd bool // 是否正式环境
22 | payVer string //版本号 当前201
23 | serviceId string //接口类型,当前类型015
24 | hc *xhttp.Client
25 | mu sync.Mutex
26 | md5Hash hash.Hash
27 | }
28 |
29 | // NewClient 初始化扫呗客户端
30 | // instNo string //商户系统机构号inst_no
31 | // key string // 商户系统令牌
32 | // merchantNo string // 支付系统:商户号
33 | // terminalId string // 支付系统:商户号终端号
34 | // accessToken string // 支付系统: 令牌
35 | // isProd:是否是正式环境
36 | func NewClient(instNo, key, merchantNo, terminalId, accessToken string, isProd bool) (*Client, error) {
37 | return &Client{
38 | instNo: instNo,
39 | key: key,
40 | merchantNo: merchantNo,
41 | terminalId: terminalId,
42 | accessToken: accessToken,
43 | isProd: isProd,
44 | hc: xhttp.NewClient(),
45 | md5Hash: md5.New(),
46 | payVer: "201",
47 | serviceId: "015",
48 | }, nil
49 | }
50 |
51 | // pubParamsHandle 公共参数处理
52 | func (c *Client) pubParamsHandle(bm gopay.BodyMap) gopay.BodyMap {
53 | if ver := bm.GetString("pay_ver"); ver == gopay.NULL {
54 | bm.Set("pay_ver", c.payVer)
55 | }
56 | if v := bm.GetString("service_id"); v == gopay.NULL {
57 | bm.Set("service_id", c.serviceId)
58 | }
59 | if v := bm.GetString("merchant_no"); v == gopay.NULL {
60 | bm.Set("merchant_no", c.merchantNo)
61 | }
62 | if v := bm.GetString("terminal_id"); v == gopay.NULL {
63 | bm.Set("terminal_id", c.terminalId)
64 | }
65 | sign := c.getRsaSign(bm)
66 | bm.Set("key_sign", sign)
67 | return bm
68 | }
69 |
70 | // doPost 发起请求
71 | func (c *Client) doPost(ctx context.Context, path string, bm gopay.BodyMap) (bs []byte, err error) {
72 | param := c.pubParamsHandle(bm)
73 | xlog.Debugf("saobeiParam:%+v", param.JsonBody())
74 | url := baseUrl
75 | if !c.isProd {
76 | url = sandboxBaseUrl
77 | }
78 | res, bs, err := c.hc.Req(xhttp.TypeJSON).Post(url + path).SendBodyMap(param).EndBytes(ctx)
79 | if err != nil {
80 | return nil, err
81 | }
82 | if res.StatusCode != 200 {
83 | return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
84 | }
85 | return bs, nil
86 | }
87 |
--------------------------------------------------------------------------------
/saobei/client_test.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
3 | import (
4 | "context"
5 | "os"
6 | "testing"
7 |
8 | "github.com/go-pay/gopay/saobei/cert"
9 | "github.com/go-pay/xlog"
10 | )
11 |
12 | var (
13 | ctx = context.Background()
14 | client *Client
15 | err error
16 | )
17 |
18 | func TestMain(m *testing.M) {
19 | // 初始化通联客户端
20 | // instNo string //商户系统机构号inst_no
21 | // key string // 商户系统令牌
22 | // merchantNo string // 支付系统:商户号
23 | // terminalId string // 支付系统:商户号终端号
24 | // accessToken string // 支付系统: 令牌
25 | // isProd:是否是正式环境
26 | client, err = NewClient(cert.InstNo, cert.Key, cert.MerchantNo, cert.TerminalId, cert.AccessToken, false)
27 | if err != nil {
28 | xlog.Error(err)
29 | return
30 | }
31 |
32 | os.Exit(m.Run())
33 | }
34 |
--------------------------------------------------------------------------------
/saobei/consts.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
3 | const (
4 | baseUrl = "https://pay.lcsw.cn/lcsw"
5 | sandboxBaseUrl = "http://test2.lcsw.cn:8117/lcsw"
6 |
7 | //PayTypeWX 支付方式:微信
8 | PayTypeWX = "010"
9 | //PayTypeAli 支付方式:支付宝
10 | PayTypeAli = "020"
11 | //PayTypeQQ 支付方式:QQ钱包
12 | PayTypeQQ = "060"
13 | //PayTypeYi 支付方式:翼支付
14 | PayTypeYi = "100"
15 | //PayTypeYL 支付方式:银联二维码
16 | PayTypeYL = "110"
17 |
18 | //ResultCodeSuccess 业务结果:01 成功
19 | ResultCodeSuccess = "01"
20 | //ResultCodeFail 业务结果:02 失败
21 | ResultCodeFail = "02"
22 | //ResultCodePaying 业务结果:03 支付中
23 | ResultCodePaying = "03"
24 |
25 | //TradeStatusSuccess 交易订单状态:支付成功
26 | TradeStatusSuccess = "SUCCESS"
27 | //TradeStatusRefund 交易订单状态:转入退款
28 | TradeStatusRefund = "REFUND"
29 | //TradeStatusNotPay 交易订单状态:未支付
30 | TradeStatusNotPay = "NOTPAY"
31 | //TradeStatusClosed 交易订单状态:已关闭
32 | TradeStatusClosed = "CLOSED"
33 | //TradeStatusUserPaying 交易订单状态:用户支付中
34 | TradeStatusUserPaying = "USERPAYING"
35 | //TradeStatusRevoked 交易订单状态:已撤销
36 | TradeStatusRevoked = "REVOKED"
37 | //TradeStatusNoPay 交易订单状态:未支付支付超时
38 | TradeStatusNoPay = "NOPAY"
39 | //TradeStatusPayError 交易订单状态:支付失败
40 | TradeStatusPayError = "PAYERROR"
41 | )
42 |
--------------------------------------------------------------------------------
/saobei/error.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | // BizErr 用于判断通联的业务逻辑是否有错误
8 | type BizErr struct {
9 | Code string `json:"code"`
10 | Msg string `json:"msg"`
11 | }
12 |
13 | // bizErrCheck 检查返回码是否为SUCCESS 否则返回一个BizErr
14 | func bizErrCheck(resp RspBase) error {
15 | if resp.ReturnCode != "01" {
16 | return &BizErr{
17 | Code: resp.ReturnCode,
18 | Msg: resp.ReturnMsg,
19 | }
20 | }
21 | //if resp.ResultCode != "01" {
22 | // return &BizErr{
23 | // Code: resp.ResultCode,
24 | // Msg: resp.ReturnMsg,
25 | // }
26 | //}
27 | return nil
28 | }
29 |
30 | func (e *BizErr) Error() string {
31 | return fmt.Sprintf(`[%s]%s`, e.Code, e.Msg)
32 | }
33 |
--------------------------------------------------------------------------------
/saobei/merchant.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
--------------------------------------------------------------------------------
/saobei/sign.go:
--------------------------------------------------------------------------------
1 | package saobei
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 |
7 | "github.com/go-pay/gopay"
8 | )
9 |
10 | // getRsaSign 获取签名字符串
11 | func (c *Client) getRsaSign(bm gopay.BodyMap) (sign string) {
12 | signParams := bm.EncodeAliPaySignParams()
13 | c.mu.Lock()
14 | defer func() {
15 | c.md5Hash.Reset()
16 | c.mu.Unlock()
17 | }()
18 | c.md5Hash.Write([]byte(signParams + "&access_token=" + c.accessToken))
19 | return fmt.Sprintf("%x", c.md5Hash.Sum(nil))
20 | }
21 |
22 | // verifySign 验证响应签名
23 | func (c *Client) verifySign(bs []byte) (err error) {
24 | bm := gopay.BodyMap{}
25 | if err = json.Unmarshal(bs, &bm); err != nil {
26 | return err
27 | }
28 | sign := bm.Get("key_sign")
29 | bm.Remove("key_sign")
30 | s := c.getRsaSign(bm)
31 | if s != sign {
32 | return fmt.Errorf("[%w]: %v", gopay.VerifySignatureErr, "验签失败")
33 | }
34 | return nil
35 | }
36 |
--------------------------------------------------------------------------------
/support_note.txt:
--------------------------------------------------------------------------------
1 | 赞助者皆为 微信 或 支付宝 用户名
2 |
3 | 平台 ---- 用户 ---- 金额
4 |
5 | 微信 ---- 燃烧的发丝 ---- 50
6 | 微信 ---- 三五五七ᴳᴼ ---- 100
7 | 微信 ---- 沐修 ---- 50
8 | 微信 ---- 深度学习 ---- 100
9 | 支付宝 ---- **旺 ---- 50
10 | 微信 ---- 开博黄工 ---- 88
11 | 微信 ---- 每天都有新旋律 ---- 100
12 | 微信 ---- *冉 ---- 50
13 | 微信 ---- *萧 ---- 80
--------------------------------------------------------------------------------
/wechat/applet_api.go:
--------------------------------------------------------------------------------
1 | /*
2 | 微信小程序
3 | 文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend
4 | */
5 |
6 | package wechat
7 |
--------------------------------------------------------------------------------
/wechat/customs.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "context"
5 | "encoding/xml"
6 | "fmt"
7 |
8 | "github.com/go-pay/gopay"
9 | )
10 |
11 | // 订单附加信息提交(正式环境)
12 | // 文档地址:https://pay.weixin.qq.com/doc/v2/merchant/4011985151
13 | func (w *Client) CustomsDeclareOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *CustomsDeclareOrderResponse, err error) {
14 | err = bm.CheckEmptyError("out_trade_no", "transaction_id", "customs", "mch_customs_no")
15 | if err != nil {
16 | return nil, err
17 | }
18 | bm.Set("sign_type", SignType_MD5)
19 | bs, err := w.doProdPost(ctx, bm, customsDeclareOrder)
20 | if err != nil {
21 | return nil, err
22 | }
23 | wxRsp = new(CustomsDeclareOrderResponse)
24 | if err = xml.Unmarshal(bs, wxRsp); err != nil {
25 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
26 | }
27 | return wxRsp, nil
28 | }
29 |
30 | // 订单附加信息查询(正式环境)
31 | // 文档地址:https://pay.weixin.qq.com/doc/v2/merchant/4011985273
32 | func (w *Client) CustomsDeclareQuery(ctx context.Context, bm gopay.BodyMap) (wxRsp *CustomsDeclareQueryResponse, err error) {
33 | err = bm.CheckEmptyError("customs")
34 | if err != nil {
35 | return nil, err
36 | }
37 | bm.Set("sign_type", SignType_MD5)
38 | bs, err := w.doProdPost(ctx, bm, customsDeclareQuery)
39 | if err != nil {
40 | return nil, err
41 | }
42 | wxRsp = new(CustomsDeclareQueryResponse)
43 | if err = xml.Unmarshal(bs, wxRsp); err != nil {
44 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
45 | }
46 | return wxRsp, nil
47 | }
48 |
49 | // 订单附加信息重推(正式环境)
50 | // 文档地址:https://pay.weixin.qq.com/doc/v2/merchant/4011985318
51 | func (w *Client) CustomsReDeclareOrder(ctx context.Context, bm gopay.BodyMap) (wxRsp *CustomsReDeclareOrderResponse, err error) {
52 | err = bm.CheckEmptyError("customs", "mch_customs_no")
53 | if err != nil {
54 | return nil, err
55 | }
56 | bm.Set("sign_type", SignType_MD5)
57 | bs, err := w.doProdPost(ctx, bm, customsReDeclareOrder)
58 | if err != nil {
59 | return nil, err
60 | }
61 | wxRsp = new(CustomsReDeclareOrderResponse)
62 | if err = xml.Unmarshal(bs, wxRsp); err != nil {
63 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
64 | }
65 | return wxRsp, nil
66 | }
67 |
--------------------------------------------------------------------------------
/wechat/notify_test.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TestDecryptRefundNotifyReqInfo(t *testing.T) {
10 | key := "ziR0QKsTUfMOuochC9RfCdmfHECorQAP"
11 | data := "YYwp8C48th0wnQzTqeI+41pflB26v+smFj9z6h9RPBgxTyZyxc+4YNEz7QEgZNWj/6rIb2MfyWMZmCc41CfjKSssoSZPXxOhUayb6KvNSZ1p6frOX1PDWzhyruXK7ouNND+gDsG4yZ0XXzsL4/pYNwLLba/71QrnkJ/BHcByk4EXnglju5DLup9pJQSnTxjomI9Rxu57m9jg5lLQFxMWXyeASZJNvof0ulnHlWJswS4OxKOkmW7VEyKyLGV6npoOm03Qsx2wkRxLsSa9gPpg4hdaReeUqh1FMbm7aWjyrVYT/MEZWg98p4GomEIYvz34XfDncTezX4bf/ZiSLXt79aE1/YTZrYfymXeCrGjlbe0rg/T2ezJHAC870u2vsVbY1/KcE2A443N+DEnAziXlBQ1AeWq3Rqk/O6/TMM0lomzgctAOiAMg+bh5+Gu1ubA9O3E+vehULydD5qx2o6i3+qA9ORbH415NyRrQdeFq5vmCiRikp5xYptWiGZA0tkoaLKMPQ4ndE5gWHqiBbGPfULZWokI+QjjhhBmwgbd6J0VqpRorwOuzC/BHdkP72DCdNcm7IDUpggnzBIy0+seWIkcHEryKjge3YDHpJeQCqrAH0CgxXHDt1xtbQbST1VqFyuhPhUjDXMXrknrGPN/oE1t0rLRq+78cI+k8xe5E6seeUXQsEe8r3358mpcDYSmXWSXVZxK6er9EF98APqHwcndyEJD2YyCh/mMVhERuX+7kjlRXSiNUWa/Cv/XAKFQuvUYA5ea2eYWtPRHa4DpyuF1SNsaqVKfgqKXZrJHfAgslVpSVqUpX4zkKszHF4kwMZO3M7J1P94Mxa7Tm9mTOJePOoHPXeEB+m9rX6pSfoi3mJDQ5inJ+Vc4gOkg/Wd/lqiy6TTyP/dHDN6/v+AuJx5AXBo/2NDD3fWhHjkqEKIuARr2ClZt9ZRQO4HkXdZo7CN06sGCHk48Tg8PmxnxKcMZm7Aoquv5yMIM2gWSWIRJhwJ8cUpafIHc+GesDlbF6Zbt+/KXkafJAQq2RklEN+WvZ/zFz113EPgWPjp16TwBoziq96MMekvWKY/vdhjol8VFtGH9F61Oy1Xwf6DJtPw=="
12 | refundNotify, err := DecryptRefundNotifyReqInfo(data, key)
13 | if err != nil {
14 | xlog.Error(err)
15 | return
16 | }
17 | xlog.Debug("refundNotify:", *refundNotify)
18 | }
19 |
--------------------------------------------------------------------------------
/wechat/oplatform_api.go:
--------------------------------------------------------------------------------
1 | /*
2 | 微信开放平台
3 | 移动应用文档:https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/iOS.html
4 | 网站应用文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
5 | 第三方平台文档:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/product/Third_party_platform_appid.html
6 | */
7 |
8 | package wechat
9 |
10 | import (
11 | "context"
12 |
13 | "github.com/go-pay/gopay/pkg/xhttp"
14 | )
15 |
16 | // GetOauth2AccessToken 微信第三方登录,code 换取 access_token
17 | // appId:应用唯一标识,在微信开放平台提交应用审核通过后获得
18 | // appSecret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
19 | // code:App用户换取access_token的code
20 | func GetOauth2AccessToken(ctx context.Context, appId, appSecret, code string) (accessToken *Oauth2AccessToken, err error) {
21 | accessToken = new(Oauth2AccessToken)
22 | url := "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code"
23 | _, err = xhttp.NewClient().Req().Get(url).EndStruct(ctx, accessToken)
24 | if err != nil {
25 | return nil, err
26 | }
27 | return accessToken, nil
28 | }
29 |
30 | // RefreshOauth2AccessToken 刷新微信第三方登录后,获取到的 access_token
31 | // appId:应用唯一标识,在微信开放平台提交应用审核通过后获得
32 | // refreshToken:填写通过获取 access_token 获取到的 refresh_token 参数
33 | func RefreshOauth2AccessToken(ctx context.Context, appId, refreshToken string) (accessToken *Oauth2AccessToken, err error) {
34 | accessToken = new(Oauth2AccessToken)
35 | url := "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + appId + "&grant_type=refresh_token&refresh_token=" + refreshToken
36 | _, err = xhttp.NewClient().Req().Get(url).EndStruct(ctx, accessToken)
37 | if err != nil {
38 | return nil, err
39 | }
40 | return accessToken, nil
41 | }
42 |
43 | // CheckOauth2AccessToken 检验授权凭证(access_token)是否有效
44 | // accessToken:调用接口凭证
45 | // openid:普通用户标识,对该公众帐号唯一,获取 access_token 是获取的
46 | func CheckOauth2AccessToken(ctx context.Context, accessToken, openid string) (result *CheckAccessTokenRsp, err error) {
47 | result = new(CheckAccessTokenRsp)
48 | url := "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + openid
49 | _, err = xhttp.NewClient().Req().Get(url).EndStruct(ctx, result)
50 | if err != nil {
51 | return nil, err
52 | }
53 | return result, nil
54 | }
55 |
56 | // GetOauth2UserInfo 微信开放平台:获取用户个人信息
57 | // accessToken:接口调用凭据
58 | // openId:用户的OpenID
59 | // lang:默认为 zh_CN ,可选填 zh_CN 简体,zh_TW 繁体,en 英语
60 | func GetOauth2UserInfo(ctx context.Context, accessToken, openId string, lang ...string) (userInfo *Oauth2UserInfo, err error) {
61 | userInfo = new(Oauth2UserInfo)
62 | url := "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId
63 | if len(lang) == 1 {
64 | url += "&lang=" + lang[0]
65 | }
66 | _, err = xhttp.NewClient().Req().Get(url).EndStruct(ctx, userInfo)
67 | if err != nil {
68 | return nil, err
69 | }
70 | return userInfo, nil
71 | }
72 |
--------------------------------------------------------------------------------
/wechat/v3/discount_card.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | "github.com/go-pay/util/js"
11 | )
12 |
13 | // 预受理领卡请求API
14 | // Code = 0 is success
15 | func (c *ClientV3) V3DiscountCardApply(ctx context.Context, bm gopay.BodyMap) (wxRsp *DiscountCardApplyRsp, err error) {
16 | authorization, err := c.authorization(MethodPost, v3CardPre, bm)
17 | if err != nil {
18 | return nil, err
19 | }
20 | res, si, bs, err := c.doProdPost(ctx, bm, v3CardPre, authorization)
21 | if err != nil {
22 | return nil, err
23 | }
24 | wxRsp = &DiscountCardApplyRsp{Code: Success, SignInfo: si, Response: &DiscountCardApply{}}
25 | if res.StatusCode != http.StatusOK {
26 | wxRsp.Code = res.StatusCode
27 | wxRsp.Error = string(bs)
28 | _ = js.UnmarshalBytes(bs, &wxRsp.ErrResponse)
29 | return wxRsp, nil
30 | }
31 | if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
32 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
33 | }
34 | return wxRsp, c.verifySyncSign(si)
35 | }
36 |
37 | // 增加用户记录API
38 | // Code = 0 is success
39 | func (c *ClientV3) V3DiscountCardAddUser(ctx context.Context, bm gopay.BodyMap) (wxRsp *EmptyRsp, err error) {
40 | if err = bm.CheckEmptyError("out_card_code"); err != nil {
41 | return nil, err
42 | }
43 | uri := fmt.Sprintf(v3CardAddUser, bm.GetString("out_card_code"))
44 | bm.Remove("out_card_code")
45 | authorization, err := c.authorization(MethodPost, uri, bm)
46 | if err != nil {
47 | return nil, err
48 | }
49 | res, si, bs, err := c.doProdPost(ctx, bm, uri, authorization)
50 | if err != nil {
51 | return nil, err
52 | }
53 | wxRsp = &EmptyRsp{Code: Success, SignInfo: si}
54 | if res.StatusCode != http.StatusNoContent {
55 | wxRsp.Code = res.StatusCode
56 | wxRsp.Error = string(bs)
57 | _ = js.UnmarshalBytes(bs, &wxRsp.ErrResponse)
58 | return wxRsp, nil
59 | }
60 | return wxRsp, c.verifySyncSign(si)
61 | }
62 |
63 | // 查询先享卡订单API
64 | // Code = 0 is success
65 | func (c *ClientV3) V3DiscountCardQuery(ctx context.Context, outCardCode string) (wxRsp *DiscountCardQueryRsp, err error) {
66 | url := fmt.Sprintf(v3CardQuery, outCardCode)
67 | authorization, err := c.authorization(MethodGet, url, nil)
68 | if err != nil {
69 | return nil, err
70 | }
71 | res, si, bs, err := c.doProdGet(ctx, url, authorization)
72 | if err != nil {
73 | return nil, err
74 | }
75 | wxRsp = &DiscountCardQueryRsp{Code: Success, SignInfo: si, Response: &DiscountCardQuery{}}
76 | if res.StatusCode != http.StatusOK {
77 | wxRsp.Code = res.StatusCode
78 | wxRsp.Error = string(bs)
79 | _ = js.UnmarshalBytes(bs, &wxRsp.ErrResponse)
80 | return wxRsp, nil
81 | }
82 | if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
83 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
84 | }
85 | return wxRsp, c.verifySyncSign(si)
86 | }
87 |
--------------------------------------------------------------------------------
/wechat/v3/encrypt_decrypt_test.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | var (
10 | publicPKCS1 = `
11 | -----BEGIN RSA PUBLIC KEY-----
12 | MIIBCgKCAQEA4//8F2TVtGTU18XAdbJ4O+S8D+YrtQOepDnAyRMli52NQPbf4e41
13 | XprsIQYZ8qkbRjmLCTXI+Pz5g5AZZXVXQ284OY0OUyS5L28SlEXxTyFuv/jHtvt1
14 | WvHOtMPXL6epyenvo2OAIEP7fAVQjyftWE9w+x1A01J5QOlWruc4M15ewkp5Dsyj
15 | fjNF5MG51wSmcWsGCAIZ0POPNrvf/pYtaWq/4eK6GJAlJ+oytaaZBE0T+MpYoL2j
16 | k6ranOYqPK7LVLMy3txRIJMtpjjb+Dc2SwV3tIeYKwuYu64gf6FiQjHwpSEFQ+CF
17 | MdHYYEoxIgt8W1xB3SGInV6d5HZ9f/wLWwIDAQAB
18 | -----END RSA PUBLIC KEY-----`
19 |
20 | privatePKCS1 = `-----BEGIN RSA PRIVATE KEY-----
21 | MIIEpAIBAAKCAQEA4//8F2TVtGTU18XAdbJ4O+S8D+YrtQOepDnAyRMli52NQPbf
22 | 4e41XprsIQYZ8qkbRjmLCTXI+Pz5g5AZZXVXQ284OY0OUyS5L28SlEXxTyFuv/jH
23 | tvt1WvHOtMPXL6epyenvo2OAIEP7fAVQjyftWE9w+x1A01J5QOlWruc4M15ewkp5
24 | DsyjfjNF5MG51wSmcWsGCAIZ0POPNrvf/pYtaWq/4eK6GJAlJ+oytaaZBE0T+MpY
25 | oL2jk6ranOYqPK7LVLMy3txRIJMtpjjb+Dc2SwV3tIeYKwuYu64gf6FiQjHwpSEF
26 | Q+CFMdHYYEoxIgt8W1xB3SGInV6d5HZ9f/wLWwIDAQABAoIBAQCAE9m6DoPaDVZf
27 | S5Aczb+q7YgTalodGkZwvJyml6HctwmVd9k2YokKdv60YmgLH6HZphOLffJCpGFJ
28 | 3ZXWn78Ae6ba9XkZjaSVl9CZCF1Q9VfwcUFHciRvjSxv8R+dfpLrgQWEBC4Ccg4A
29 | kj+521UB6cZu2fUDgO3qX+m44Nx6RbYW0FXfH84h8J/92X5192YnFw7n1BHZ3uIk
30 | TkMr0+a7e1VqyjgfyoDrW0c8qEN5/UN0DzShXQuJtXfvZ17z61Rv8qXYzIVPHFTA
31 | rKCqtC5ke/R5OQ6Zz3yxGb5grgapDgn9WJX03k9NSPGk6Wvv1c+2ukgbOOSmB3of
32 | 2tjj5lepAoGBAP/TaBEbkT3jvisIh8x0NjssWcF0IOWv5FECv4iIeEcychbSGftU
33 | /xY6gb2Hki+AkCjHTID0hG1MRBC+pXcBlFaNAPecJiyPV5WQVxPyTq/AEcYevk0y
34 | ojugQmPA0YO8P3VuigETjg0Ph67XyHO8hjtlrFhAdy4P0Ge+mqskMsFPAoGBAOQn
35 | ulPCp+LzyUQQg77Xe7Q+zsNJ3WUuTRwfKd7+vgnu45IQoMo1qlK0uF9Ra/4wi706
36 | KkoD5dhO+VqYncsp16K99BkmT2FoXlQl3afKWdzwDl5K58IYSyrT7xUIi8wWpECD
37 | tZGaTStccRGQm32KAFZPjLiZUFNCUpxCrpGiqBo1AoGBAOdmwms3FFl29zzVqoA1
38 | XhiINWfXMyqPv2XHpphJWQKNjsU1pmrApzvkEBbv2js9fyhjnb/HbUGwCqFa0TCk
39 | LRlc0dMnWyBTSFXxCdLxClvO0ET06g3KDxUAEQ1KDDmsvXnrUslGduc5dPGiHZ8S
40 | mBiCDzKEnUj85PXyYtULGR3hAoGAfkuXkwIv2SvF/818gEncClyyK9xZl8bXnHeL
41 | wAsXu3vnsVVPDGBEll+/p9P0idLpp6fo/OvHccPVuFa/ElVpLocj9kAEtREHFmGX
42 | n2gd8nVYHs4sGH9GLMEAmY4PhLwL1EKUYbMegKA9XtHDoOyhXyXN6enEUzJldGZd
43 | J/T4RPkCgYBn3fqFtxOfV7ZxMxbivbz15RDaZ0k7k6c7Sf/HafDOL+VTrCi6lIXf
44 | /dGjW0FdbTxmIQSMAe5fVEqzFaNWz//gPNWrHRDikzfy9jIKDe/nxV0lEOYXPmGj
45 | bdz/NH6klplarq02xmXk6pwxd11bfq3AvckrUdjywiRfGw6C1+bO+w==
46 | -----END RSA PRIVATE KEY-----`
47 | )
48 |
49 | func TestV3EncryptTextAndV3DecryptText(t *testing.T) {
50 | text := "I love GoPay"
51 | cipherText, err := V3EncryptText(text, []byte(publicPKCS1))
52 | if err != nil {
53 | xlog.Errorf("V3EncryptText.Err:", err)
54 | return
55 | }
56 | xlog.Debugf("encrypt text: %s", cipherText)
57 |
58 | originText, err := V3DecryptText(cipherText, []byte(privatePKCS1))
59 | if err != nil {
60 | xlog.Errorf("V3DecryptText.Err:", err)
61 | return
62 | }
63 | xlog.Debugf("decrypt text: %s", originText)
64 | }
65 |
--------------------------------------------------------------------------------
/wechat/v3/market_activity.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | // 支付有礼
4 |
--------------------------------------------------------------------------------
/wechat/v3/market_media.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | "github.com/go-pay/util/js"
11 | )
12 |
13 | // 图片上传(营销专用)
14 | // 注意:图片不能超过2MB
15 | // Code = 0 is success
16 | func (c *ClientV3) V3FavorMediaUploadImage(ctx context.Context, fileName, fileSha256 string, img *gopay.File) (wxRsp *MarketMediaUploadRsp, err error) {
17 | bmFile := make(gopay.BodyMap)
18 | bmFile.Set("filename", fileName).Set("sha256", fileSha256)
19 | authorization, err := c.authorization(MethodPost, v3FavorMediaUploadImage, bmFile)
20 | if err != nil {
21 | return nil, err
22 | }
23 |
24 | bm := make(gopay.BodyMap)
25 | bm.SetBodyMap("meta", func(bm gopay.BodyMap) {
26 | bm.Set("filename", fileName).Set("sha256", fileSha256)
27 | }).SetFormFile("file", img)
28 | res, si, bs, err := c.doProdPostFile(ctx, bm, v3FavorMediaUploadImage, authorization)
29 | if err != nil {
30 | return nil, err
31 | }
32 | wxRsp = &MarketMediaUploadRsp{Code: Success, SignInfo: si, Response: new(MarketMediaUpload)}
33 | if res.StatusCode != http.StatusOK {
34 | wxRsp.Code = res.StatusCode
35 | wxRsp.Error = string(bs)
36 | _ = js.UnmarshalBytes(bs, &wxRsp.ErrResponse)
37 | return wxRsp, nil
38 | }
39 | if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
40 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
41 | }
42 | return wxRsp, c.verifySyncSign(si)
43 | }
44 |
--------------------------------------------------------------------------------
/wechat/v3/model_bill.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | // 交易、资金账单 Rsp
4 | type BillRsp struct {
5 | Code int `json:"-"`
6 | SignInfo *SignInfo `json:"-"`
7 | Response *TradeBill `json:"response,omitempty"`
8 | ErrResponse ErrResponse `json:"err_response,omitempty"`
9 | Error string `json:"-"`
10 | }
11 |
12 | // 二级商户资金账单 Rsp
13 | type EcommerceFundFlowBillRsp struct {
14 | Code int `json:"-"`
15 | SignInfo *SignInfo `json:"-"`
16 | Response *DownloadBill `json:"response,omitempty"`
17 | ErrResponse ErrResponse `json:"err_response,omitempty"`
18 | Error string `json:"-"`
19 | }
20 |
21 | // =========================================================分割=========================================================
22 |
23 | type TradeBill struct {
24 | HashType string `json:"hash_type"`
25 | HashValue string `json:"hash_value"`
26 | DownloadUrl string `json:"download_url"`
27 | }
28 |
29 | type BillDetail struct {
30 | BillSequence int `json:"bill_sequence"` // 商户将多个文件按账单文件序号的顺序合并为完整的资金账单文件,起始值为1
31 | HashType string `json:"hash_type"`
32 | HashValue string `json:"hash_value"`
33 | DownloadUrl string `json:"download_url"`
34 | EncryptKey string `json:"encrypt_key"` // 加密账单文件使用的加密密钥。密钥用商户证书的公钥进行加密,然后进行Base64编码
35 | Nonce string `json:"nonce"` // 加密账单文件使用的随机字符串
36 | }
37 |
38 | type DownloadBill struct {
39 | DownloadBillCount int `json:"download_bill_count"`
40 | DownloadBillList []*BillDetail `json:"download_bill_list"`
41 | }
42 |
--------------------------------------------------------------------------------
/wechat/v3/model_business.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | // 商圈积分授权查询 Rsp
4 | type BusinessAuthPointsQueryRsp struct {
5 | Code int `json:"-"`
6 | SignInfo *SignInfo `json:"-"`
7 | Response *BusinessAuthPointsQuery `json:"response,omitempty"`
8 | ErrResponse ErrResponse `json:"err_response,omitempty"`
9 | Error string `json:"-"`
10 | }
11 |
12 | // 商圈会员待积分状态查询 Rsp
13 | type BusinessPointsStatusQueryRsp struct {
14 | Code int `json:"-"`
15 | SignInfo *SignInfo `json:"-"`
16 | Response *BusinessPointsStatusQuery `json:"response,omitempty"`
17 | ErrResponse ErrResponse `json:"err_response,omitempty"`
18 | Error string `json:"-"`
19 | }
20 |
21 | // =========================================================分割=========================================================
22 |
23 | type BusinessAuthPointsQuery struct {
24 | Openid string `json:"openid"` // 顾客授权时使用的小程序上的openid
25 | AuthorizeState string `json:"authorize_state"` // 顾客授权商圈积分结果:UNAUTHORIZED:未授权,AUTHORIZED:已授权,DEAUTHORIZED:已取消授权
26 | AuthorizeTime string `json:"authorize_time,omitempty"` // 顾客成功授权商圈积分的时间
27 | DeauthorizeTime string `json:"deauthorize_time,omitempty"` // 顾客关闭授权商圈积分的时间
28 | }
29 |
30 | type BusinessPointsStatusQuery struct {
31 | PointsCommitStatus string `json:"points_commit_status"` // 顾客关闭授权商圈积分的时间
32 | }
33 |
--------------------------------------------------------------------------------
/wechat/v3/model_discount.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | // 预受理领卡请求 Rsp
4 | type DiscountCardApplyRsp struct {
5 | Code int `json:"-"`
6 | SignInfo *SignInfo `json:"-"`
7 | Response *DiscountCardApply `json:"response,omitempty"`
8 | ErrResponse ErrResponse `json:"err_response,omitempty"`
9 | Error string `json:"-"`
10 | }
11 |
12 | // 查询先享卡订单 Rsp
13 | type DiscountCardQueryRsp struct {
14 | Code int `json:"-"`
15 | SignInfo *SignInfo `json:"-"`
16 | Response *DiscountCardQuery `json:"response,omitempty"`
17 | ErrResponse ErrResponse `json:"err_response,omitempty"`
18 | Error string `json:"-"`
19 | }
20 |
21 | // =========================================================分割=========================================================
22 |
23 | type DiscountCardApply struct {
24 | PrepareCardToken string `json:"prepare_card_token"` // 预领卡请求token,在引导用户进入先享卡领卡时,需要传入prepare_card_token
25 | }
26 |
27 | type DiscountCardQuery struct {
28 | CardId string `json:"card_id"` // 先享卡Id,唯一标识一个先享卡。
29 | CardTemplateId string `json:"card_template_id"` // 先享卡卡模板Id,唯一定义此资源的标识。
30 | Openid string `json:"openid"` // 微信用户在商户对应appid下的唯一标识
31 | OutCardCode string `json:"out_card_code"` // 商户领卡号
32 | Appid string `json:"appid"` // 公众账号Id
33 | Mchid string `json:"mchid"` // 商户号
34 | TimeRange *struct {
35 | BeginTime string `json:"begin_time"` // 约定开始时间
36 | EndTime string `json:"end_time"` // 约定结束时间
37 | } `json:"time_range"` // 用户领取先享卡之后,约定的生效时间和到期时间。
38 | State string `json:"state"` // 先享卡的守约状态:ONGOING:约定进行中,SETTLING:约定到期核对中,FINISHED:已完成约定,UNFINISHED:未完成约定
39 | UnfinishedReason string `json:"unfinished_reason,omitempty"` // 用户未完成约定的原因
40 | TotalAmount int `json:"total_amount,omitempty"` // 享受优惠总金额
41 | PayInformation *PayInformation `json:"pay_information,omitempty"` // 用户退回优惠的付款信息
42 | CreateTime string `json:"create_time"` // 创卡时间
43 | Objectives []*Objective `json:"objectives"` // 用户先享卡目标列表
44 | Rewards []*Reward `json:"rewards"` // 用户先享卡优惠列表
45 | SharerOpenid string `json:"sharer_openid,omitempty"` // 邀请者用户标识
46 | }
47 |
--------------------------------------------------------------------------------
/wechat/v3/model_media.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | // 商户上传(营销专用)反馈图片 Rsp
4 | type MarketMediaUploadRsp struct {
5 | Code int `json:"-"`
6 | SignInfo *SignInfo `json:"-"`
7 | Response *MarketMediaUpload `json:"response,omitempty"`
8 | ErrResponse ErrResponse `json:"err_response,omitempty"`
9 | Error string `json:"-"`
10 | }
11 |
12 | // 商户上传反馈图片 Rsp
13 | type MediaUploadRsp struct {
14 | Code int `json:"-"`
15 | SignInfo *SignInfo `json:"-"`
16 | Response *MediaUpload `json:"response,omitempty"`
17 | ErrResponse ErrResponse `json:"err_response,omitempty"`
18 | Error string `json:"-"`
19 | }
20 |
21 | type ComplaintImageRsp struct {
22 | Code int `json:"-"`
23 | SignInfo *SignInfo `json:"-"`
24 | Response *ComplaintImage `json:"response,omitempty"`
25 | ImageData []byte // 🔥 新增:如果是图片流,放到这里
26 | ErrResponse ErrResponse `json:"err_response,omitempty"`
27 | Error string `json:"-"`
28 | }
29 |
30 | // =========================================================分割=========================================================
31 |
32 | type MarketMediaUpload struct {
33 | MediaUrl string `json:"media_url"` // 微信返回的媒体文件URL地址
34 | }
35 |
36 | type MediaUpload struct {
37 | MediaId string `json:"media_id"` // 微信返回的媒体文件标识Id。
38 | }
39 |
40 | type ComplaintImage struct {
41 | MediaData *MediaData `json:"media_data"`
42 | }
43 |
44 | type MediaData struct {
45 | Filename string `json:"filename"`
46 | ContentType string `json:"content_type"`
47 | TotalSize int `json:"total_size"`
48 | FirstPos int `json:"first_pos"`
49 | Chunk string `json:"chunk"`
50 | Etag string `json:"etag"`
51 | SupportPartialContent bool `json:"support_partial_content"`
52 | }
53 |
--------------------------------------------------------------------------------
/wechat/v3/model_partner.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | // 建立合作关系 Rsp
4 | type PartnershipsBuildRsp struct {
5 | Code int `json:"-"`
6 | SignInfo *SignInfo `json:"-"`
7 | Response *PartnershipsBuild `json:"response,omitempty"`
8 | ErrResponse ErrResponse `json:"err_response,omitempty"`
9 | Error string `json:"-"`
10 | }
11 |
12 | // 终止合作关系 Rsp
13 | type PartnershipsTerminateRsp struct {
14 | Code int `json:"-"`
15 | SignInfo *SignInfo `json:"-"`
16 | Response *PartnershipsTerminate `json:"response,omitempty"`
17 | ErrResponse ErrResponse `json:"err_response,omitempty"`
18 | Error string `json:"-"`
19 | }
20 |
21 | // 查询合作关系列表 Rsp
22 | type PartnershipsListRsp struct {
23 | Code int `json:"-"`
24 | SignInfo *SignInfo `json:"-"`
25 | Response *PartnershipsList `json:"response,omitempty"`
26 | ErrResponse ErrResponse `json:"err_response,omitempty"`
27 | Error string `json:"-"`
28 | }
29 |
30 | // =========================================================分割=========================================================
31 |
32 | type PartnershipsBuild struct {
33 | Partner *Partner `json:"partner"` // 合作方相关的信息
34 | AuthorizedData *AuthorizedData `json:"authorized_data"` // 被授权的数据
35 | State string `json:"state"` // 合作状态,ESTABLISHED:已建立,TERMINATED:已终止
36 | BuildTime string `json:"build_time"` // 建立合作关系时间
37 | CreateTime string `json:"create_time"` // 创建时间
38 | UpdateTime string `json:"update_time"` // 更新时间
39 | }
40 |
41 | type Partner struct {
42 | Appid string `json:"appid"` // 合作方APPID
43 | Type string `json:"type"` // 合作方类别
44 | MerchantId string `json:"merchant_id"` // 合作方商户Id
45 | }
46 |
47 | type AuthorizedData struct {
48 | BusinessType string `json:"business_type"` // 授权业务类别
49 | Scenarios []string `json:"scenarios"` // 授权场景
50 | StockId string `json:"stock_id"` // 授权批次Id
51 | }
52 |
53 | type PartnershipsTerminate struct {
54 | TerminateTime string `json:"terminate_time"` // 终止合作关系时间
55 | }
56 |
57 | type PartnershipsList struct {
58 | Data []*Partnerships `json:"data,omitempty"` // 合作关系结果集
59 | TotalCount int `json:"total_count"` // 批次总数
60 | Offset int `json:"offset"` // 分页页码
61 | Limit int `json:"limit"` // 分页大小
62 | }
63 |
64 | type Partnerships struct {
65 | Partner *Partner `json:"partner"` // 合作方相关的信息
66 | AuthorizedData *AuthorizedData `json:"authorized_data"` // 被授权的数据
67 | BuildTime string `json:"build_time"` // 建立合作关系时间
68 | TerminateTime string `json:"terminate_time"` // 终止合作关系时间
69 | CreateTime string `json:"create_time"` // 创建时间
70 | UpdateTime string `json:"update_time"` // 更新时间
71 | }
72 |
--------------------------------------------------------------------------------
/wechat/v3/model_violation.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | // 创建、查询、更新投诉通知回调地址 Rsp
4 | type ViolationNotifyUrlRsp struct {
5 | Code int `json:"-"`
6 | SignInfo *SignInfo `json:"-"`
7 | Response *ViolationNotifyUrl `json:"response,omitempty"`
8 | ErrResponse ErrResponse `json:"err_response,omitempty"`
9 | Error string `json:"-"`
10 | }
11 |
12 | type ViolationNotifyUrl struct {
13 | NotifyUrl string `json:"notify_url"` // 通知地址,仅支持https。
14 | }
15 |
--------------------------------------------------------------------------------
/wechat/v3/palm.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "net/http"
8 |
9 | "github.com/go-pay/gopay"
10 | "github.com/go-pay/util/js"
11 | )
12 |
13 | // 用户自主录掌&预授权
14 | // Code = 0 is success
15 | func (c *ClientV3) V3PalmServicePreAuthorize(ctx context.Context, bm gopay.BodyMap) (wxRsp *PalmServicePreAuthorizeRsp, err error) {
16 | authorization, err := c.authorization(MethodPost, v3PalmServicePreAuthorize, bm)
17 | if err != nil {
18 | return nil, err
19 | }
20 | res, si, bs, err := c.doProdPost(ctx, bm, v3PalmServicePreAuthorize, authorization)
21 | if err != nil {
22 | return nil, err
23 | }
24 | wxRsp = &PalmServicePreAuthorizeRsp{Code: Success, SignInfo: si, Response: &PalmServicePreAuthorize{}}
25 | if res.StatusCode != http.StatusOK {
26 | wxRsp.Code = res.StatusCode
27 | wxRsp.Error = string(bs)
28 | _ = js.UnmarshalBytes(bs, &wxRsp.ErrResponse)
29 | return wxRsp, nil
30 | }
31 | if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
32 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
33 | }
34 | return wxRsp, c.verifySyncSign(si)
35 | }
36 |
37 | // 预授权状态查询
38 | // Code = 0 is success
39 | func (c *ClientV3) V3PalmServiceOpenidQuery(ctx context.Context, openid string, bm gopay.BodyMap) (wxRsp *PalmServiceOpenidQueryRsp, err error) {
40 | uri := fmt.Sprintf(v3PalmServiceOpenidQuery, openid) + "?" + bm.EncodeURLParams()
41 | authorization, err := c.authorization(MethodGet, uri, nil)
42 | if err != nil {
43 | return nil, err
44 | }
45 | res, si, bs, err := c.doProdGet(ctx, uri, authorization)
46 | if err != nil {
47 | return nil, err
48 | }
49 | wxRsp = &PalmServiceOpenidQueryRsp{Code: Success, SignInfo: si, Response: &PalmServiceOpenidQuery{}}
50 | if res.StatusCode != http.StatusOK {
51 | wxRsp.Code = res.StatusCode
52 | wxRsp.Error = string(bs)
53 | _ = js.UnmarshalBytes(bs, &wxRsp.ErrResponse)
54 | return wxRsp, nil
55 | }
56 | if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
57 | return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
58 | }
59 | return wxRsp, c.verifySyncSign(si)
60 | }
61 |
--------------------------------------------------------------------------------
/wechat/v3/papay.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "net/http"
7 |
8 | "github.com/go-pay/gopay"
9 | "github.com/go-pay/util/js"
10 | )
11 |
12 | // 预扣费通知API
13 | // Code = 0 is success
14 | func (c *ClientV3) V3EntrustPayNotify(ctx context.Context, contractId string, bm gopay.BodyMap) (wxRsp *EmptyRsp, err error) {
15 | url := fmt.Sprintf(v3EntrustPayNotify, contractId)
16 | authorization, err := c.authorization(MethodPost, url, bm)
17 | if err != nil {
18 | return nil, err
19 | }
20 | res, si, bs, err := c.doProdPost(ctx, bm, url, authorization)
21 | if err != nil {
22 | return nil, err
23 | }
24 | wxRsp = &EmptyRsp{Code: Success, SignInfo: si}
25 | if res.StatusCode != http.StatusNoContent {
26 | wxRsp.Code = res.StatusCode
27 | wxRsp.Error = string(bs)
28 | _ = js.UnmarshalBytes(bs, &wxRsp.ErrResponse)
29 | return wxRsp, nil
30 | }
31 | return wxRsp, c.verifySyncSign(si)
32 | }
33 |
--------------------------------------------------------------------------------
/wechat/v3/sign_test.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/go-pay/xlog"
7 | )
8 |
9 | func TestPaySignOfJSAPIp(t *testing.T) {
10 | jsapi, err := client.PaySignOfJSAPI("appid", "prepayid")
11 | if err != nil {
12 | xlog.Error(err)
13 | return
14 | }
15 | xlog.Debugf("jsapi:%#v", jsapi)
16 | }
17 |
18 | func TestPaySignOfApp(t *testing.T) {
19 | app, err := client.PaySignOfApp("appid", "prepayid")
20 | if err != nil {
21 | xlog.Error(err)
22 | return
23 | }
24 | xlog.Debugf("app:%#v", app)
25 | }
26 |
27 | func TestPaySignOfApplet(t *testing.T) {
28 | applet, err := client.PaySignOfApplet("appid", "prepayid")
29 | if err != nil {
30 | xlog.Error(err)
31 | return
32 | }
33 | xlog.Debugf("applet:%#v", applet)
34 | }
35 |
--------------------------------------------------------------------------------