├── .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 | --------------------------------------------------------------------------------