From 621b15079e07c5d9113afad8276aaa7347280496 Mon Sep 17 00:00:00 2001 From: hy001 Date: Sat, 18 Apr 2026 18:53:09 +0800 Subject: [PATCH] feat: wire lucky gift go flow and reward config updates --- nacos_config/common/external.yml | 16 +- nacos_config/common/framework-config.yml | 40 ++-- nacos_config/common/mongo-config.yml | 2 +- nacos_config/common/rds-config.yml | 9 +- nacos_config/common/redis-config.yml | 8 +- nacos_config/common/rocketmq.yml | 7 +- nacos_config/rc-gateway/application.yml | 47 ++-- .../rc-service-external/application.yml | 100 ++++---- nacos_config/rc-service-order/application.yml | 90 +++---- nacos_config/rc-service-other/application.yml | 71 +++--- .../rc-service-wallet/sharding-config.yml | 6 +- nacos_config/visual-monitor/application.yml | 4 +- .../gift/GameLuckyGiftBusinessEvent.java | 51 ++-- .../service/impl/AuthEndpointServiceImpl.java | 87 ++++--- .../ResidentRegisterRewardServiceImpl.java | 10 + .../ResidentRegisterRewardConfigCO.java | 5 + .../ResidentRegisterRewardConfigSaveCmd.java | 5 + .../ResidentRegisterRewardConfig.java | 3 + .../debug/LuckyGiftLocalDebugController.java | 52 ++++ .../app/command/gift/LuckyGiftGiveCmdExe.java | 98 +++++--- .../app/common/gift/GameLuckyGiftCommon.java | 54 ++++- .../app/common/gift/LuckyGiftGoClient.java | 111 +++++++++ .../common/gift/LuckyGiftResultProcessor.java | 224 ++++++++++++++++++ .../GameLuckyGiftBusinessListener.java | 198 ++++++++++------ .../other/infra/config/LuckyGiftGoConfig.java | 21 ++ .../impl/RegionConfigClientServiceImpl.java | 18 +- .../src/main/resources/application-local.yml | 16 +- .../driver/NacosDriverURLProvider.java | 93 +++++++- 28 files changed, 1067 insertions(+), 379 deletions(-) create mode 100644 rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/debug/LuckyGiftLocalDebugController.java create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftGoClient.java create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftResultProcessor.java create mode 100644 rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/config/LuckyGiftGoConfig.java diff --git a/nacos_config/common/external.yml b/nacos_config/common/external.yml index a2be6be..e0f469c 100644 --- a/nacos_config/common/external.yml +++ b/nacos_config/common/external.yml @@ -10,12 +10,12 @@ spring: red-circle: log: tencent-cls: - secret-id: IKID1pNfgOmrc4G8frlNfcEWU7PMkrd4AwNU - secret-key: oISIp41i7F6fwvby1kCLBivsWqrZ07vV - endpoint: ap-singapore.cls.tencentcs.com - region: ap-singapore + secret-id: ${LIKEI_TENCENT_CLS_SECRET_ID} + secret-key: ${LIKEI_TENCENT_CLS_SECRET_KEY} + endpoint: ${LIKEI_TENCENT_CLS_ENDPOINT} + region: ${LIKEI_TENCENT_CLS_REGION} rtc: - appId: 4b5e5cea3b86476caf7f7a57d05b82d1 - certificate: a6feb209de6448148a926f59634807bb - killRoom: https://api.sd-rtn.com/dev/v1/kicking-rule - authKey: Basic ZTA0MTVjMzYwZjBmNDNhZGFhNTdjZDZmNjgwYTFiZWQ6MWIyYmNjZDU0NGQzNDRhYmJhMTNiNDliZjUyMGY4MTI= + appId: ${LIKEI_RTC_APP_ID} + certificate: ${LIKEI_RTC_CERTIFICATE} + killRoom: ${LIKEI_RTC_KILL_ROOM_URL} + authKey: ${LIKEI_RTC_AUTH_KEY} diff --git a/nacos_config/common/framework-config.yml b/nacos_config/common/framework-config.yml index 016104b..e0b4d48 100644 --- a/nacos_config/common/framework-config.yml +++ b/nacos_config/common/framework-config.yml @@ -1,19 +1,21 @@ -framework: - nacos: - subscribeServices: - - rc-auth - - rc-service-console - - rc-service-external - - rc-service-order - - rc-service-other - - rc-service-team - - rc-service-user - - rc-service-wallet - - rc-service-live - healthEndpoint: /actuator/health - healthStatus: UP - healthCheckSleepTime: 5000 - healthSuccessWaitTime: 5000 - instanceDownWaitTime: 15000 - stopAfterWaitTime: 5000 - stopKey: CxILm9hA1b9hF3Hl \ No newline at end of file +framework: + nacos: + subscribeServices: + - rc-auth + - rc-gateway + - rc-service-console + - rc-service-external + - rc-service-order + - rc-service-other + - rc-service-wallet + - rc-service-live + - rc-scheduling + - game-fruit + - visual-monitor + healthEndpoint: /actuator/health + healthStatus: UP + healthCheckSleepTime: 5000 + healthSuccessWaitTime: 5000 + instanceDownWaitTime: 15000 + stopAfterWaitTime: 5000 + stopKey: ${LIKEI_FRAMEWORK_NACOS_STOP_KEY} diff --git a/nacos_config/common/mongo-config.yml b/nacos_config/common/mongo-config.yml index 36a5e39..05e7d63 100644 --- a/nacos_config/common/mongo-config.yml +++ b/nacos_config/common/mongo-config.yml @@ -1,7 +1,7 @@ spring: data: mongodb: - uri: mongodb://root:123456@localhost:27017/tarab_all?authSource=admin&readPreference=secondaryPreferred&retryWrites=false&maxPoolSize=50&minPoolSize=5&maxIdleTimeMS=6000 + uri: ${LIKEI_MONGO_URI} logging: diff --git a/nacos_config/common/rds-config.yml b/nacos_config/common/rds-config.yml index 94d2e14..172fcd2 100644 --- a/nacos_config/common/rds-config.yml +++ b/nacos_config/common/rds-config.yml @@ -3,10 +3,9 @@ spring: datasource: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.p6spy.engine.spy.P6SpyDriver - url: jdbc:p6spy:mysql://localhost:3306/likei?characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&autoReconnect=true - # url: jdbc:p6spy:mysql://10.0.17.81:3306/likei?characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&autoReconnect=true - username: root - password: 123456 + url: ${LIKEI_MYSQL_JDBC_URL} + username: ${LIKEI_MYSQL_USERNAME} + password: ${LIKEI_MYSQL_PASSWORD} hikari: # 连接池名称 @@ -22,4 +21,4 @@ spring: # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟 max-lifetime: 1800000 # 数据库连接超时时间,默认30秒,即30000 - connection-timeout: 30000 \ No newline at end of file + connection-timeout: 30000 diff --git a/nacos_config/common/redis-config.yml b/nacos_config/common/redis-config.yml index bd7406f..522d5f3 100644 --- a/nacos_config/common/redis-config.yml +++ b/nacos_config/common/redis-config.yml @@ -1,13 +1,13 @@ spring: data: redis: - port: 6379 - host: localhost + port: ${LIKEI_REDIS_PORT} + host: ${LIKEI_REDIS_HOST} # username: prod ssl: enabled: false - database: 0 + database: ${LIKEI_REDIS_DATABASE} timeout: 120000 lettuce: pool: @@ -16,4 +16,4 @@ spring: min-idle: 2 max-active: 8 max-wait: 120000ms - time-between-eviction-runs: 60000ms \ No newline at end of file + time-between-eviction-runs: 60000ms diff --git a/nacos_config/common/rocketmq.yml b/nacos_config/common/rocketmq.yml index dae3b57..c1fedd0 100644 --- a/nacos_config/common/rocketmq.yml +++ b/nacos_config/common/rocketmq.yml @@ -1,4 +1,5 @@ rocketmq: - accessKey: ak9ogoaw3zm5b5d2b2e4f05 - secretKey: sk0caf0e8a8b5a9109 - endpoints: rmq-9ogoaw3zm.rocketmq.sg.qcloud.tencenttdmq.com:8080 + accessKey: ${LIKEI_ROCKETMQ_ACCESS_KEY} + secretKey: ${LIKEI_ROCKETMQ_SECRET_KEY} + endpoints: ${LIKEI_ROCKETMQ_ENDPOINT} + local-disable: ${LIKEI_ROCKETMQ_LOCAL_DISABLE} diff --git a/nacos_config/rc-gateway/application.yml b/nacos_config/rc-gateway/application.yml index c28a874..91ce085 100644 --- a/nacos_config/rc-gateway/application.yml +++ b/nacos_config/rc-gateway/application.yml @@ -11,81 +11,93 @@ spring: maxAge: 360000 routes: - id: service-auth - uri: lb://rc-auth + uri: ${LIKEI_GATEWAY_ROUTE_AUTH_URI} predicates: - Path=/auth/** filters: - StripPrefix=1 - id: service-external - uri: lb://rc-service-external + uri: ${LIKEI_GATEWAY_ROUTE_EXTERNAL_URI} predicates: - Path=/external/** filters: - StripPrefix=1 - id: service-order - uri: lb://rc-service-order + uri: ${LIKEI_GATEWAY_ROUTE_ORDER_URI} predicates: - Path=/order/** filters: - StripPrefix=1 - id: service-wallet - uri: lb://rc-service-wallet + uri: ${LIKEI_GATEWAY_ROUTE_WALLET_URI} predicates: - Path=/wallet/** filters: - StripPrefix=1 - id: service-live - uri: lb://rc-service-live + uri: ${LIKEI_GATEWAY_ROUTE_LIVE_URI} predicates: - Path=/live/** filters: - StripPrefix=1 - id: invite-campaign-public - uri: http://10.2.1.16:2900 + uri: ${LIKEI_GATEWAY_ROUTE_INVITE_PUBLIC_URI} predicates: - Path=/public/h5/invite-campaign/** - id: invite-campaign-app - uri: http://10.2.1.16:2900 + uri: ${LIKEI_GATEWAY_ROUTE_INVITE_APP_URI} predicates: - Path=/app/h5/invite-campaign/** + - id: register-reward-app + uri: ${LIKEI_GATEWAY_ROUTE_REGISTER_REWARD_APP_URI} + predicates: + - Path=/app/register-reward/** + + - id: go-service + uri: ${LIKEI_GATEWAY_ROUTE_GO_URI} + predicates: + - Path=/go/** + filters: + - StripPrefix=1 + - id: invite-campaign-internal - uri: http://10.2.1.16:2900 + uri: ${LIKEI_GATEWAY_ROUTE_INVITE_INTERNAL_URI} predicates: - Path=/internal/invite-campaign/** - id: game-app - uri: http://10.2.1.16:2900 + uri: ${LIKEI_GATEWAY_ROUTE_GAME_APP_URI} predicates: - Path=/app/game/** - id: game-internal - uri: http://10.2.1.16:2900 + uri: ${LIKEI_GATEWAY_ROUTE_GAME_INTERNAL_URI} predicates: - Path=/internal/game/baishun/** - id: game-baishun-callback - uri: http://10.2.1.16:2900 + uri: ${LIKEI_GATEWAY_ROUTE_GAME_BAISHUN_URI} predicates: - Path=/game/baishun/** - id: service-gateway - uri: lb://rc-service-gateway + uri: ${LIKEI_GATEWAY_ROUTE_FORWARD_URI} predicates: - Header=Req-Likei, true filters: - name: ForwardRoute args: - aesKey: 7NcAa111UGiRlRiR + aesKey: ${LIKEI_GATEWAY_FORWARD_ROUTE_AES_KEY} - id: service-other - uri: lb://rc-service-other + uri: ${LIKEI_GATEWAY_ROUTE_OTHER_URI} predicates: - Path=/** gateway: @@ -139,6 +151,11 @@ gateway: - /activity/king-queen/** # week-star - /activity/week-star/** + - /go/public/** + - /public/h5/week-star/** + - /go/resident-activity/register-reward/** + - /go/resident-activity/specified-gift-weekly-rank/** + - /go/resident-activity/week-star/** # leaderboard - /activity/leaderboard/gifts-send - /activity/leaderboard/gifts-received @@ -147,4 +164,4 @@ gateway: - /sys/version/manage/latest/review - /game/yomi/** - /public/h5/invite-campaign/** - forward-aes-key: 8NcSaTt8EHjRlRuG + forward-aes-key: ${LIKEI_GATEWAY_FORWARD_AES_KEY} diff --git a/nacos_config/rc-service-external/application.yml b/nacos_config/rc-service-external/application.yml index ad250fa..3ef8ee2 100644 --- a/nacos_config/rc-service-external/application.yml +++ b/nacos_config/rc-service-external/application.yml @@ -1,72 +1,72 @@ red-circle: ai: minimax: - url: https://api.minimax.io/v1/text/chatcompletion_v2 - authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiJ0b255IGxpdSIsIlVzZXJOYW1lIjoidG9ueSBsaXUiLCJBY2NvdW50IjoiIiwiU3ViamVjdElEIjoiMTkzMDg0MzI0Nzg4NjczMzY4NCIsIlBob25lIjoiIiwiR3JvdXBJRCI6IjE5MzA4NDMyNDc4ODI1MzkzODAiLCJQYWdlTmFtZSI6IiIsIk1haWwiOiJsaXV0YW90b255M0BpY2xvdWQuY29tIiwiQ3JlYXRlVGltZSI6IjIwMjUtMDYtMjUgMTQ6MzA6MjYiLCJUb2tlblR5cGUiOjEsImlzcyI6Im1pbmltYXgifQ.TAHcSE-3YSSLWC9z9424GVF6twqi3Po5LkpGENtLF25397IvEV-CiXDFzBE5F-H6w9yG-YAROwGy0jFxwoDWPF4IsC2emKp5Qan5geavx7YqTEUQ4vJzhu7TJgDrvvUcUanVPQRBo5IyqpPuDagNPHhmPca7wgOrVHQfahUs7Q5VwOUiUDguHdwXcl6h4Yk32Ufv7rHDuS_sZnuAXxG_dY_XfIkJGwdMz7O7c9uWICnnMFXAL7GEyhy50MKJoEiCFLWnIC6Tu20oTnd2QBDlp1JCzdphA9FpBqo0SVCSmR2CZK1Uo4oXioxizkfv4EgPpCZUkOVSqT2f74l1zbFe-g - model: MiniMax-Text-01 + url: ${LIKEI_AI_MINIMAX_URL} + authorization: ${LIKEI_AI_MINIMAX_AUTHORIZATION} + model: ${LIKEI_AI_MINIMAX_MODEL} qian-fan: - url: https://qianfan.baidubce.com/v2/chat/completions - appId: '' - authorization: Bearer bce-v3/ALTAK-DjBrg6HP36lGomporE2iT/3a509ddcafca5e22cea75c85f5bd9b9e11f8d192 - model: c0jkrl3v_dt24b + url: ${LIKEI_AI_QIANFAN_URL} + appId: ${LIKEI_AI_QIANFAN_APP_ID:} + authorization: ${LIKEI_AI_QIANFAN_AUTHORIZATION} + model: ${LIKEI_AI_QIANFAN_MODEL} tts: - url: http://128.168.134.215:9001/tts/stream - model: cloudsway_tts + url: ${LIKEI_AI_TTS_URL} + model: ${LIKEI_AI_TTS_MODEL} oss: aliYun: - endpoint: http://oss-accelerate.aliyuncs.com - bucketName: tkm-likei - accessUrl: https://media.haiyihy.com - access-key-id: LTAI5 - access-key-secret: v2Z31d + endpoint: ${LIKEI_ALIYUN_OSS_ENDPOINT} + bucketName: ${LIKEI_ALIYUN_OSS_BUCKET_NAME} + accessUrl: ${LIKEI_ALIYUN_OSS_ACCESS_URL} + access-key-id: ${LIKEI_ALIYUN_OSS_ACCESS_KEY_ID} + access-key-secret: ${LIKEI_ALIYUN_OSS_ACCESS_KEY_SECRET} sts: - endpoint: sts.us-west-1.aliyuncs.com - role-arn: acs:ram::124470563:role/stsoss + endpoint: ${LIKEI_ALIYUN_STS_ENDPOINT} + role-arn: ${LIKEI_ALIYUN_STS_ROLE_ARN} # 有效时间是900 ~ 3600 token-expire-time: 3600 # policy-file: policy/bucket_write_policy.txt tencent-cos: - enabled: true - secret-id: IKIDMchhZEfrsiNo472DAtTpzzmLjttkOnyu - secret-key: nMkbLsGRO6ZqulSyJQJ0UjjU0KSKxOgl - bucket-name: yumi-assets-1420526837 - region: me-saudi-arabia - access-url: https://media.haiyihy.com + enabled: ${LIKEI_TENCENT_COS_ENABLED} + secret-id: ${LIKEI_TENCENT_COS_SECRET_ID} + secret-key: ${LIKEI_TENCENT_COS_SECRET_KEY} + bucket-name: ${LIKEI_TENCENT_COS_BUCKET} + region: ${LIKEI_TENCENT_COS_REGION} + access-url: ${LIKEI_TENCENT_COS_ACCESS_URL} instant-message: broadcast-group: - LOTFUN: "@TGS#a3C" - LIKEI: "@TGS#2RUK4PK5C2" + LOTFUN: ${LIKEI_IM_BROADCAST_GROUP_LOTFUN} + LIKEI: ${LIKEI_IM_BROADCAST_GROUP_LIKEI} tencet-trtc: - secretId: IKIDMchhZEfrsiNo472DAtTpzzmLjttkOnyu - secretKey: nMkbLsGRO6ZqulSyJQJ0UjjU0KSKxOgl - endpoint: trtc.tencentcloudapi.com - sdkAppId: 20036101 + secretId: ${LIKEI_TRTC_SECRET_ID} + secretKey: ${LIKEI_TRTC_SECRET_KEY} + endpoint: ${LIKEI_TRTC_ENDPOINT} + sdkAppId: ${LIKEI_TRTC_SDK_APP_ID} tencet-im: - appId: 20036101 - key: dcdf53135f27e7cf8541c4ae9798fb0cb2f0e4d6c5c20022dbaea053f35cbb8c - identifier: yumiadmin - baseEndpoint: https://adminapisgp.im.qcloud.com - noticeAccount: yuminotice - newsletterAccount: yuminotice + appId: ${LIKEI_IM_APP_ID} + key: ${LIKEI_IM_KEY} + identifier: ${LIKEI_IM_IDENTIFIER} + baseEndpoint: ${LIKEI_IM_BASE_ENDPOINT} + noticeAccount: ${LIKEI_IM_NOTICE_ACCOUNT} + newsletterAccount: ${LIKEI_IM_NEWSLETTER_ACCOUNT} agora: - appId: 4b5e5cea3b86476caf7f7a57d05b82d1 - appCertificate: a6feb209de6448148a926f59634807bb - tokenExpireSecond: 86400 - privilegeExpireSecond: 86400 - authKey: Basic ZTA0MTVjMzYwZjBmNDNhZGFhNTdjZDZmNjgwYTFiZWQ6MWIyYmNjZDU0NGQzNDRhYmJhMTNiNDliZjUyMGY4MTI= + appId: ${LIKEI_AGORA_APP_ID} + appCertificate: ${LIKEI_AGORA_APP_CERTIFICATE} + tokenExpireSecond: ${LIKEI_AGORA_TOKEN_EXPIRE_SECOND} + privilegeExpireSecond: ${LIKEI_AGORA_PRIVILEGE_EXPIRE_SECOND} + authKey: ${LIKEI_AGORA_AUTH_KEY} sms: aliYun: - enabled: true - sign-name: Tarab - access-key-id: LTAI4xxxxxxU8JQ6Xf - access-key-secret: hh2DrAxxxxxxW5bQTA7s1 - endpoint: dysmsapi.aliyuncs.com + enabled: ${LIKEI_SMS_ALIYUN_ENABLED} + sign-name: ${LIKEI_SMS_ALIYUN_SIGN_NAME} + access-key-id: ${LIKEI_SMS_ALIYUN_ACCESS_KEY_ID} + access-key-secret: ${LIKEI_SMS_ALIYUN_ACCESS_KEY_SECRET} + endpoint: ${LIKEI_SMS_ALIYUN_ENDPOINT} censor: - active: qcloud + active: ${LIKEI_CENSOR_ACTIVE} tupu: - enabled: false + enabled: ${LIKEI_CENSOR_TUPU_ENABLED} tencent-cloud: - secret-id: AKIDGMNDrNk - secret-key: 71h9dv41lU - endpoint: ims.tencentcloudapi.com - region: ap-guangzhou + secret-id: ${LIKEI_TENCENT_CLOUD_IMS_SECRET_ID} + secret-key: ${LIKEI_TENCENT_CLOUD_IMS_SECRET_KEY} + endpoint: ${LIKEI_TENCENT_CLOUD_IMS_ENDPOINT} + region: ${LIKEI_TENCENT_CLOUD_IMS_REGION} diff --git a/nacos_config/rc-service-order/application.yml b/nacos_config/rc-service-order/application.yml index 00a8aeb..9aa1ebf 100644 --- a/nacos_config/rc-service-order/application.yml +++ b/nacos_config/rc-service-order/application.yml @@ -1,28 +1,28 @@ red-circle: pay: - web-pay-base-url: 'https://h5.likeichat.com/#/' - web-pay-result-page: pay-result - web-pay-recharge-page: recharge - web-pay-collection-page: collection-receipt + web-pay-base-url: ${LIKEI_PAY_WEB_PAY_BASE_URL} + web-pay-result-page: ${LIKEI_PAY_WEB_PAY_RESULT_PAGE} + web-pay-recharge-page: ${LIKEI_PAY_WEB_PAY_RECHARGE_PAGE} + web-pay-collection-page: ${LIKEI_PAY_WEB_PAY_COLLECTION_PAGE} googlePayGlobal: - serverAccount: server-api@api-5499404589076025365-781142.iam.gserviceaccount.com - classPatchServiceAccountJson: payfile/google_pay.json + serverAccount: ${LIKEI_GOOGLE_PAY_GLOBAL_SERVER_ACCOUNT} + classPatchServiceAccountJson: ${LIKEI_GOOGLE_PAY_GLOBAL_PATCH_JSON} googlePay: TAXAB: - serverAccount: tarab-server@tarab-427706.iam.gserviceaccount.com - publicKey: MIIBIjANxxxxxxxxTjmAO68rmnKr2gYJ3isuepCZsaX0wIDAQAB - classPatchServiceAccountJson: payfile/tarab-427706-04fe535b024a.json + serverAccount: ${LIKEI_GOOGLE_PAY_TAXAB_SERVER_ACCOUNT} + publicKey: ${LIKEI_GOOGLE_PAY_TAXAB_PUBLIC_KEY} + classPatchServiceAccountJson: ${LIKEI_GOOGLE_PAY_TAXAB_PATCH_JSON} paypal: - merchantId: 'AZm9zUAxxxxx8kiGKL6D4l0elx2' - secretKey: 'EJuYA6cSud6xxxxx4_Fj9rbBh1yYnr97btui2ocuR' - devMerchantId: 'Ac2aB2KFgz3xxxxxGmbS7dcPedRf2_eg23D' - devSecretKey: 'ECjyOP4nxxxxxxB0JEAH9P7im' + merchantId: ${LIKEI_PAYPAL_MERCHANT_ID} + secretKey: ${LIKEI_PAYPAL_SECRET_KEY} + devMerchantId: ${LIKEI_PAYPAL_DEV_MERCHANT_ID} + devSecretKey: ${LIKEI_PAYPAL_DEV_SECRET_KEY} huawei: access-token: - grant-type: 'client_credentials' - client-secret: 'dff36e68xxxx30da9c7240ae0bc96' - client-id: '11xx93' - oauth-login-url: https://oauth-login.cloud.huawei.com/oauth2/v3/token + grant-type: ${LIKEI_HUAWEI_GRANT_TYPE} + client-secret: ${LIKEI_HUAWEI_CLIENT_SECRET} + client-id: ${LIKEI_HUAWEI_CLIENT_ID} + oauth-login-url: ${LIKEI_HUAWEI_OAUTH_LOGIN_URL} host: CHINA: https://orders-drcn.iap.hicloud.com GERMANY: https://orders-dre.iap.hicloud.com @@ -33,45 +33,45 @@ red-circle: PURCHASES_TOKENS_VERIFY: /applications/purchases/tokens/verify PURCHASES_CONFIRM: /applications/v2/purchases/confirm PURCHASES_CANCELLED_LIST: /applications/v2/purchases/cancelledList - iap-public-key: MIIBojANBgkqhkiG9w0Bxxxxx7cdmApDJfpAlKeLZ9fy7d3VIWyqZiLYtxxxxj3t+sFuC4lEJBVrw5MgDE7bmpjidOm0rxxxxUYC1hSI8xXagbJ0sOcYXSunxxxx1NaupT2+ILoZPfIQVF4RThlQmphuOif4uMMlYvYosiueCKlv6MYQi0fVcLKEjWVc/XslowtLS4w0EV/eAVpFq7kTvy04LNYVscSjZop7AHEMVVoNgzg+mLC0UGsftYRfEBeKHkNppTg931qodgJSkIM582ZTK0eujAJR43On3z1gc8+UvSKW+9w+tAqw099VYrFY3sXySUfVJ6SoejiHeKlAgMBAAE= + iap-public-key: ${LIKEI_HUAWEI_IAP_PUBLIC_KEY} # uat环境 payer-max: - secret-key: 8aexx98f - merchant-id: SDP01010 - rsa-private-key: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCQU2JiAdSO8M3CQft5nZEGLO9/TPFArQCffVzWoaz3niIacJ/B3dOePJyXMljuKByoRC+1ApW+9ucVXoulkLkqUAve0q7xKMFaxCw4OAEkRC6JhjYgEJyJXLEA9KRT6EklvvomqfUwuddCKtTNLL2hFtG5+2P+BioYrekaIiZh9lIel1msn4WKoBp3LgyStcZBQOPzhD7NcKsbo+ppjT4JBSQyVZrcJ3mYe+YSV/Qnw/KY2v3OzPeLApeZhLh5wVsfcmyz04IHFogLIjRVFGU6Xbvfz8ujRtpoBD+3RSz5GKiBLPjoSgGLSIxCWc10VphKwOlvR0bi3ssKYG9HsHw5AgMBAAECggEADzebgfXrcX7WUwsd9r60UdBfGC8GqOkUzbwsE71MPXeA5QTG82vuKhr977sxQTsdemhmF1HEdDQYPVqQos5Vl66E8eOI6oh/ipBwkSTmiepedcWe41adCqapSw6AXRB61e4C9hypa4/MsH9PnKqA/AEp79AfxOLlgWCk2UqMfXuPuYhKD9SSlYVoJ5x/W48B+NBaRuSiCV3agPfnpRtMuTZ9Vs4IOL4riIyE9ABBgFinL0h/D5qSX6JnrO+N1miORSiM+2e/Sh/xs6nrCIuh9pSBcXjAeO/l4/BKCfj3TPH9hcYWWWRVgbX0WV6MDZFz/au5o9LZ7m9kUltP4dH7AQKBgQDvyrKh7BKIrwEwvt0eWBfCNdwLctb0GbsEoYVsQaiS/cLfje5289DLTTYc18fy/G8dRMGftME6qAiidtQaEb/mfSWPhHYfTayWJ0At8TvX2qbUS2b46or3lRgUBWOgpNkmLSEy7ae0I1UTStI3UN9rJNvjZ7Jntc7KGeZMfivCqQKBgQCaFMN2xBV00KerElFp0XZRaCZEyLz3MkTOwSlcs4c9cA7TTV0sZlxNRsA11WCaFIEV8TGCjZMJfmZihmB+LRXOhb45lXD+xi/JTOPs9UVOPJNpeFHuABL93/TqL0ma7d/VntKkIv2g+/CUoSzXQ6QrLg4/BpmfevZDtW/A8Gx3EQKBgQCe/TmVjM35HHfglxxLK0ONfGKKoLkPHiRW/LVXQu1/kItt6FBNRHmS4n3Xf+bOIDuYH2d1+cYImzMmbT1Sj6Q6MY3+62fad4jQAfRWwdTY2Nu2dMwwjGpZn9xYIf6dm89ytYeGmfaQxMB6yyg4jwGjq8uzqqSqiOw0Khn9a8aeCQKBgArX0zmUav4hgOslCt2rg+wOrELC7alnvDfgmAySBb5pGGH+W8Q4H97AT955+aZeMwdcReOuGt7cKlBcrIW0nog+GTjsL1t+jvZXluKiEBKFaMpPUVSyZKPBEvc4BLIGc24REznBzJ97m16aSRGNDQyM3SvKRx1WBeaV6htlz/xBAoGAbi5IvOQMCbUvtrD/lJ3xkVaoEQL6dlCVBK7Ldf5+6g/Rc9j6d5B2UVb3v9+BOpAHHFa2fIPNI8y22TmCjgIGi6O8Rm60KqFDQIQnzcmPQg9HsTIG5u0V2b/0saUj2txHRzIC+cZ4b+/xms7OHu1OKZeVIZhNdT/+CWmO2wVgA/s= - rsa-public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkFNiYgHUjvDNwkH7eZ2RBizvf0zxQK0An31c1qGs954iGnCfwd3TnjyclzJY7igcqEQvtQKVvvbnFV6LpZC5KlAL3tKu8SjBWsQsODgBJEQuiYY2IBCciVyxAPSkU+hJJb76Jqn1MLnXQirUzSy9oRbRuftj/gYqGK3pGiImYfZSHpdZrJ+FiqAady4MkrXGQUDj84Q+zXCrG6PqaY0+CQUkMlWa3Cd5mHvmElf0J8PymNr9zsz3iwKXmYS4ecFbH3Jss9OCBxaICyI0VRRlOl2738/Lo0baaAQ/t0Us+RiogSz46EoBi0iMQlnNdFaYSsDpb0dG4t7LCmBvR7B8OQIDAQAB - platform-rsa-public-key: MIIBIjANBgkqhkiG9w0BAQEFAACBAQ8AMIIBCgKCAQEAi4+8n/BEFhWKzWs1SMdD+1gzK3xiI/wGGTS330yKSxQMM5Ec39AFQjKFTvcjIZegt2vTQYnA/AL0l0O5C98BWSBuM20/pUXd1+i/Ew/lvLYoeKDD4ARkCzJfXQcDgvm4gTZvnVJwerCN+E2rziNZoLTdTo468IArzBVFzWGa/YmQvi7brCbTlzp5EpVeZMNLNpM04I0uJIiqGpEp0PDPbbn/ZVzZLoLKO+LXWxXx1nFPVlL+X1yk1TyJVfPv7Au3mv9UXNGSF6EP21n97aaU1j29+PXNy3Yze8pmkdWmcOqGnORSLPk0Acl6gklBGyvFiSk/QsL1ocecqD8cJk1JbQIDAQAB - app-id: d6afddeb3ca447448 - gateway-base-url: https://pay-gate-uat.payermax.com - enable-real-time-exchange-rate: false + secret-key: ${LIKEI_PAYERMAX_SECRET_KEY} + merchant-id: ${LIKEI_PAYERMAX_MERCHANT_ID} + rsa-private-key: ${LIKEI_PAYERMAX_RSA_PRIVATE_KEY} + rsa-public-key: ${LIKEI_PAYERMAX_RSA_PUBLIC_KEY} + platform-rsa-public-key: ${LIKEI_PAYERMAX_PLATFORM_RSA_PUBLIC_KEY} + app-id: ${LIKEI_PAYERMAX_APP_ID} + gateway-base-url: ${LIKEI_PAYERMAX_GATEWAY_BASE_URL} + enable-real-time-exchange-rate: ${LIKEI_PAYERMAX_ENABLE_REAL_TIME_EXCHANGE_RATE} mifa-pay: - mer-account: 4dab789b6c8 - mer-no: 1000 - gateway-base-url: https://platformtest.xqdmipay.com - rsa-private-key: MIIEvgIBADANBgkqhkiG9w0BAQGFCASCBKgwggSkAgEAAoIBAQC2DZell5v2A/bfR1lTuvHsPFnzQDl8apqM72WKlRf8/AFCTLsDK2si2iKFHcf/JTL+BqKAReVwYbG0GxapleaouO95YPqH7br6J+mdpTxFVzI9AObuVybdEmrO1vE4+OqLX1EXzh88oeqkuU/lJNow12HIZABDXkj1SilAwEbgusFpZn8cZ6eTRqYYcr5bfq2uIyq1s5Hj2I6q2NwogyV12a8pkPX5y/667Kmgsg8bb+cdpFGLpLltEbm0rk7z0Dv5SWuZxKOowPfxz+ISl53RjxY+yCXks5D1Kw1EwEB0c7N8ADkbO+1BDQM1MM8IGKdTQgGUwEbT/AdhVPK39kvLAgMBAAECggEAOqQKMuaw7/+655Td6yCOiJ+wAbCwU6kq+zapqIf54B10clyw6IZ1zhYhhGthXogm8rhEY7kf/KEbUn5fQGTulW5shNZ+HIaw8Z8lmwf8cAF0Rz4hJKih9hfWm6WUsdtMAXTEdDyKx0cIg+LFH3RNa+oUry22//xA1/H5c8f7jKtQRu5rIePaRsAvMYpfTzmKXjVq0WkD9jMFgYowHWuwBc+HTvN5SI/3Ag+pXhI5dot3BMLXrLqrM7fPIH1cqi1u1jyYZIpIAEM1ZqRWJCfNmXn0YYGjswqpluqNbSgTmwMGuqhMPe1hOYJwwtXwXXSFkyO/lX8iziUbvsq5b4J6wQKBgQDamnLZc7ymnOjzg3yrm9n7SqgBsgk7pYHwl/HVdaopKm6YcsW9uTr80zYXGbTSSE65/pFCN45mkHpyyFdCoCb+FMpMyn1I6bDbDTwQPEdCo9i9uVOZM692/I/8kb9czvCqiG22Uosx3AzY/lem+XjoudDIUBha8P7cwxL64Ie/UQKBgQDVMnUERQVfLnWvdNq0W3bi2de/ynPSXDtDPHP+ezYmyyUUEIYX33BLTBFWYX9jxGVumqyOvUvmweAHTTRHPsDHrtqS/xMztxfOMNW7eBaP5Btp3pBaq/FMCUpqtYH1lMsSfLEC6iQePiAtQThvfgLuNsLm73F3vlFtBs+C3LIqWwKBgQDSn+ey3xHQkvTc1D7F9kdkGT2hTJIa11BIqY4INvP57/lZh5RBRfyw5yyBu3H+/k5kZQQ+gdsBtYlVmPSCrF6FhzCYJq3qF8ggdzL9Dac3bTkDLFKBFUyl35k4KJHx8S3vkb3r4sJdCwGR/hYkOtClo4unxYyB6xwVRxu9f6Mr0QKBgQDLa+2DOWg6vVXFKDZVyL/TDBB0C3Qfz6ksKk5zDpVIxqSGVI3d0XCQJ/CS/0xRoV82/ZaQS8ZUU8CyttOe9x1yakBb6c4klhq8vpPw4FCG0xvlFFugaFdAOc0rrCxoaqSo6xjqswXrZVPGWmjC2PVq3g1x1B3sJ0gCQ3FUZ8gH6QKBgDu+g2Adn3sF7NZKWW/sHcWhhtfx05PuFLdmA7J9LJ6TTQFW1snMp2GjkAvDx6KfwmqTT8TYZmnA0nPgz9bSgdpvCaBAdhbU6EjEcBpc3+gFwDnF4Qen8qAbXVnOE7pOrQ/F6kKaL+Xuu3dTKzJR2v6kFJRTywt+kuo3INAbN86c - platform-rsa-public-key: MIIBIjANBgkqhkiG9w1BAQEFAAOCAQ8AMIIBCgKCAQEAtjRr7TpawlzKYDFwzpUwCK+twx/0KS3W0ZVCPdOAoaVxhEDfacHkgHMUJ7MXd6raqce++k2XHFoYyD4d8fJPkjNrzQ7PPoFm774XfGxz85oemfK88AI6+3PlxEwdf0VBZXmrraJvOdD3dPv4Uq/J15PzKGSh8edYTZgeNSCD/gMRcZoZhacd0WIiaJFf/P4AEa7g+JnefatinayQXAl1n7O5kAiU7jryCzBbno7R5X96riGxUpu/Rxome/tBSBf0644jzQFU7eLA4mJ6aFchArFZ1SvMBVjpYWEgLFgQxyUbJewXRYCPU5uDvzYhFUzF/4bIdhR5swPvAPokavijKwIDAQAB + mer-account: ${LIKEI_MIFA_PAY_MER_ACCOUNT} + mer-no: ${LIKEI_MIFA_PAY_MER_NO} + gateway-base-url: ${LIKEI_MIFA_PAY_GATEWAY_BASE_URL} + rsa-private-key: ${LIKEI_MIFA_PAY_RSA_PRIVATE_KEY} + platform-rsa-public-key: ${LIKEI_MIFA_PAY_PLATFORM_RSA_PUBLIC_KEY} airwallex: - client-id: j5v_C5xxg - api-key: e397fa14297xxxxxxxx6d3dff3e92c63c338 - base-url: https://api-demo.airwallex.com + client-id: ${LIKEI_AIRWALLEX_CLIENT_ID} + api-key: ${LIKEI_AIRWALLEX_API_KEY} + base-url: ${LIKEI_AIRWALLEX_BASE_URL} api-url: AUTHENTICATION_LOGIN: /api/v1/authentication/login PAYMENT_INTENTS_CREATE: /api/v1/pa/payment_intents/create paynicorn: - app-key: 79xx58 - merchant-secret: 704a8xxx50b + app-key: ${LIKEI_PAYNICORN_APP_KEY} + merchant-secret: ${LIKEI_PAYNICORN_MERCHANT_SECRET} clipspay: - merchantNo: 800xx2370 - md5SecretKey: 18455c7xxxxx4a48fb7fe - terminalNo: 10xxx6 - terminalKey: NzMyNGRxxxxxYThiMmE4ODA - notifyUrl: https://dexxxxx.com/play/server/notice/clipspay - placeAnOrderApi: http://uat.card.api.clipspay.com/payment/gateway/api/backTransReq - redirectResult: https://dev.xxxxine.com/clipspay/redirect + merchantNo: ${LIKEI_CLIPSPAY_MERCHANT_NO} + md5SecretKey: ${LIKEI_CLIPSPAY_MD5_SECRET_KEY} + terminalNo: ${LIKEI_CLIPSPAY_TERMINAL_NO} + terminalKey: ${LIKEI_CLIPSPAY_TERMINAL_KEY} + notifyUrl: ${LIKEI_CLIPSPAY_NOTIFY_URL} + placeAnOrderApi: ${LIKEI_CLIPSPAY_PLACE_ORDER_API} + redirectResult: ${LIKEI_CLIPSPAY_REDIRECT_RESULT} telegram: - bot-token: 72649:AAE7gZj0 - webhook-url: https://local.api.yuyinfang168.com/order/telegram/webhook \ No newline at end of file + bot-token: ${LIKEI_ORDER_TELEGRAM_BOT_TOKEN} + webhook-url: ${LIKEI_ORDER_TELEGRAM_WEBHOOK_URL} diff --git a/nacos_config/rc-service-other/application.yml b/nacos_config/rc-service-other/application.yml index b5f6648..115cf44 100644 --- a/nacos_config/rc-service-other/application.yml +++ b/nacos_config/rc-service-other/application.yml @@ -24,22 +24,22 @@ red-circle: templateId: 1994334094730010626 game: hkys: - signKey: svO + signKey: ${LIKEI_GAME_HKYS_SIGN_KEY} hotgame: - signKey: qFO + signKey: ${LIKEI_GAME_HOTGAME_SIGN_KEY} baishun: - app-id: 1704692112 - app-key: 6EllbAruJDfw - app-channel: lotfun + app-id: ${LIKEI_GAME_BAISHUN_APP_ID} + app-key: ${LIKEI_GAME_BAISHUN_APP_KEY} + app-channel: ${LIKEI_GAME_BAISHUN_APP_CHANNEL} baishun2fun: - app-id: 26xxxx65 - app-key: OWq58W1XDxxxxxxxzAfHqNr0l - app-channel: 2xxxxxn + app-id: ${LIKEI_GAME_BAISHUN2FUN_APP_ID} + app-key: ${LIKEI_GAME_BAISHUN2FUN_APP_KEY} + app-channel: ${LIKEI_GAME_BAISHUN2FUN_APP_CHANNEL} sud: - app-id: 178xxxx00130 - app-key: kAdoDDw6xxxxOphybk3G4 - app-secret: Psw9s7nOnxxxxxxxS97y4uf0vW - app-channel: axxxxt,TxxxxN + app-id: ${LIKEI_GAME_SUD_APP_ID} + app-key: ${LIKEI_GAME_SUD_APP_KEY} + app-secret: ${LIKEI_GAME_SUD_APP_SECRET} + app-channel: ${LIKEI_GAME_SUD_APP_CHANNEL} static-resources: levelStyle: wealth: @@ -82,25 +82,30 @@ red-circle: # 测试 lucky: gift: + go: + enabled: ${LUCKY_GIFT_GO_ENABLED} + base-url: ${GAME_LUCKY_GIFT_GO_URL} + internal-token: ${GAME_INTERNAL_CALLBACK_SECRET} + timeout-millis: ${LUCKY_GIFT_GO_TIMEOUT_MILLIS} api: - enabled: true + enabled: ${LUCKY_GIFT_API_ENABLED} # 多账号配置 configs: - - standardId: 18816 - url: https://game-cn-test.jieyou.shop/lucky_gift/start_game - app_key: w0GoEN4hg - app_id: 929 - app_channel: likei - - standardId: 19102 - url: https://game-cn-test.jieyou.shop/lucky_gift/start_game - app_key: bXdpzw94i - app_id: 261 - app_channel: likei + - standardId: ${LUCKY_GIFT_API_CONFIG_1_STANDARD_ID} + url: ${LUCKY_GIFT_API_CONFIG_1_URL} + app_key: ${LIKEI_GAME_BAISHUN_APP_KEY} + app_id: ${LIKEI_GAME_BAISHUN_APP_ID} + app_channel: ${LIKEI_GAME_BAISHUN_APP_CHANNEL} + - standardId: ${LUCKY_GIFT_API_CONFIG_2_STANDARD_ID} + url: ${LUCKY_GIFT_API_CONFIG_2_URL} + app_key: ${LIKEI_GAME_BAISHUN_APP_KEY} + app_id: ${LIKEI_GAME_BAISHUN_APP_ID} + app_channel: ${LIKEI_GAME_BAISHUN_APP_CHANNEL} # 默认配置(向后兼容) - url: https://game-cn-test.jieyou.shop/lucky_gift/start_game - app_key: w0GoEN4hg6G - app_id: 9291 - app_channel: likei + url: ${LUCKY_GIFT_API_DEFAULT_URL} + app_key: ${LIKEI_GAME_BAISHUN_APP_KEY} + app_id: ${LIKEI_GAME_BAISHUN_APP_ID} + app_channel: ${LIKEI_GAME_BAISHUN_APP_CHANNEL} activity: ranking: @@ -120,13 +125,13 @@ scheduler: telegram: bot: - token: 8350:AAGwh1O + token: ${LIKEI_TELEGRAM_BOT_TOKEN} monitor: chat-ids: - - '-5081' - alert-limit-seconds: 60 - proxy-host: 127.0.0.1 - proxy-port: 7897 + - '${LIKEI_TELEGRAM_MONITOR_CHAT_ID_1}' + alert-limit-seconds: ${LIKEI_TELEGRAM_MONITOR_ALERT_LIMIT_SECONDS} + proxy-host: ${LIKEI_TELEGRAM_MONITOR_PROXY_HOST} + proxy-port: ${LIKEI_TELEGRAM_MONITOR_PROXY_PORT} yomi: - aes_key: Lt2tYDHewn6U4 + aes_key: ${LIKEI_YOMI_AES_KEY} diff --git a/nacos_config/rc-service-wallet/sharding-config.yml b/nacos_config/rc-service-wallet/sharding-config.yml index c527672..02ae87a 100644 --- a/nacos_config/rc-service-wallet/sharding-config.yml +++ b/nacos_config/rc-service-wallet/sharding-config.yml @@ -2,9 +2,9 @@ dataSources: wallet: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.jdbc.Driver - jdbcUrl: jdbc:p6spy:mysql://mysql:3306/likei_wallet?characterEncoding=utf8&useUnicode=true&useSSL=false&allowMultiQueries=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&autoReconnect=true - username: root - password: 123456 + jdbcUrl: ${LIKEI_WALLET_MYSQL_JDBC_URL} + username: ${LIKEI_MYSQL_USERNAME} + password: ${LIKEI_MYSQL_PASSWORD} #hikari: # 连接池名称 diff --git a/nacos_config/visual-monitor/application.yml b/nacos_config/visual-monitor/application.yml index f7b214c..0fd842a 100644 --- a/nacos_config/visual-monitor/application.yml +++ b/nacos_config/visual-monitor/application.yml @@ -1,5 +1,5 @@ spring: security: user: - name: dxxop - password: devxx23 \ No newline at end of file + name: ${LIKEI_VISUAL_MONITOR_USERNAME} + password: ${LIKEI_VISUAL_MONITOR_PASSWORD} diff --git a/rc-common-business/common-business-mq/business-mq-model/src/main/java/com/red/circle/mq/business/model/event/gift/GameLuckyGiftBusinessEvent.java b/rc-common-business/common-business-mq/business-mq-model/src/main/java/com/red/circle/mq/business/model/event/gift/GameLuckyGiftBusinessEvent.java index f2861a1..a96ddef 100644 --- a/rc-common-business/common-business-mq/business-mq-model/src/main/java/com/red/circle/mq/business/model/event/gift/GameLuckyGiftBusinessEvent.java +++ b/rc-common-business/common-business-mq/business-mq-model/src/main/java/com/red/circle/mq/business/model/event/gift/GameLuckyGiftBusinessEvent.java @@ -1,13 +1,14 @@ package com.red.circle.mq.business.model.event.gift; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import java.io.Serial; -import java.io.Serializable; -import java.util.List; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; /** * 游戏幸运礼物抽奖. @@ -42,13 +43,33 @@ public class GameLuckyGiftBusinessEvent implements Serializable { /** * 来源系统. */ - private String sysOrigin; - - /** - * 礼物id. - */ - @JsonSerialize(using = ToStringSerializer.class) - private Long giftId; + private String sysOrigin; + + /** + * 整个送礼动作业务id. + */ + private String businessId; + + /** + * 扣款资产流水id. + */ + private String consumeAssetRecordId; + + /** + * 礼物id. + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long giftId; + + /** + * 礼物单价. + */ + private BigDecimal giftPrice; + + /** + * 是否免费礼物. + */ + private Boolean giftIsFree; /** * 选的礼物数量. diff --git a/rc-gateway/src/main/java/com/red/circle/gateway/service/impl/AuthEndpointServiceImpl.java b/rc-gateway/src/main/java/com/red/circle/gateway/service/impl/AuthEndpointServiceImpl.java index df96e3b..2fd25b2 100644 --- a/rc-gateway/src/main/java/com/red/circle/gateway/service/impl/AuthEndpointServiceImpl.java +++ b/rc-gateway/src/main/java/com/red/circle/gateway/service/impl/AuthEndpointServiceImpl.java @@ -1,34 +1,53 @@ -package com.red.circle.gateway.service.impl; - -import com.red.circle.framework.core.request.RequestHeaderConstant; -import com.red.circle.framework.dto.ResultResponse; -import com.red.circle.gateway.constant.ApiConstant; -import com.red.circle.gateway.service.AuthEndpointService; -import com.red.circle.gateway.service.UserCredential; -import lombok.RequiredArgsConstructor; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; - -/** - * @author pengliang on 2023/5/5 - */ -@Service -@RequiredArgsConstructor -public class AuthEndpointServiceImpl implements AuthEndpointService { - - private final WebClient.Builder webClientBuilder; - - @Override - public Mono> getTokenCredential( - String authorization) { - return webClientBuilder.build().get() - .uri(ApiConstant.AUTH_FULL_URL) - .header(RequestHeaderConstant.AUTHORIZATION, authorization) - .retrieve() - .bodyToMono(new ParameterizedTypeReference<>() { - }); - } - -} +package com.red.circle.gateway.service.impl; + +import com.red.circle.framework.core.request.RequestHeaderConstant; +import com.red.circle.framework.dto.ResultResponse; +import com.red.circle.gateway.constant.ApiConstant; +import com.red.circle.gateway.service.AuthEndpointService; +import com.red.circle.gateway.service.UserCredential; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Mono; + +/** + * @author pengliang on 2023/5/5 + */ +@Service +@RequiredArgsConstructor +public class AuthEndpointServiceImpl implements AuthEndpointService { + + private final WebClient.Builder webClientBuilder; + + @Value("${FEIGN_AUTH_URL:}") + private String authBaseUrl; + + @Override + public Mono> getTokenCredential( + String authorization) { + return webClientBuilder.build().get() + .uri(buildTokenCheckUrl()) + .header(RequestHeaderConstant.AUTHORIZATION, authorization) + .retrieve() + .bodyToMono(new ParameterizedTypeReference<>() { + }); + } + + private String buildTokenCheckUrl() { + String normalizedBaseUrl = authBaseUrl == null ? "" : authBaseUrl.trim(); + if (normalizedBaseUrl.isEmpty()) { + return ApiConstant.AUTH_FULL_URL; + } + if (normalizedBaseUrl.endsWith("/")) { + normalizedBaseUrl = normalizedBaseUrl.substring(0, normalizedBaseUrl.length() - 1); + } + return UriComponentsBuilder.fromUriString(normalizedBaseUrl) + .path("/token/check") + .build(true) + .toUriString(); + } + +} diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentRegisterRewardServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentRegisterRewardServiceImpl.java index b174cda..5394c8b 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentRegisterRewardServiceImpl.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentRegisterRewardServiceImpl.java @@ -42,6 +42,7 @@ public class ResidentRegisterRewardServiceImpl implements ResidentRegisterReward return result.setConfigured(Boolean.TRUE) .setEnabled(Boolean.TRUE.equals(config.getEnabled())) .setGoldAmount(defaultGoldAmount(config.getGoldAmount())) + .setDailyLimit(defaultDailyLimit(config.getDailyLimit())) .setRewardGroupId(config.getRewardGroupId()) .setRewardGroupName(getRewardGroupName(config.getRewardGroupId())); } @@ -62,6 +63,7 @@ public class ResidentRegisterRewardServiceImpl implements ResidentRegisterReward config.setSysOrigin(normalizedSysOrigin) .setEnabled(Boolean.TRUE.equals(cmd.getEnabled())) .setGoldAmount(defaultGoldAmount(cmd.getGoldAmount())) + .setDailyLimit(defaultDailyLimit(cmd.getDailyLimit())) .setRewardGroupId(cmd.getRewardGroupId()); if (exists) { @@ -84,6 +86,7 @@ public class ResidentRegisterRewardServiceImpl implements ResidentRegisterReward private void validateConfig(ResidentRegisterRewardConfigSaveCmd cmd) { long goldAmount = defaultGoldAmount(cmd.getGoldAmount()); + long dailyLimit = defaultDailyLimit(cmd.getDailyLimit()); if (Boolean.TRUE.equals(cmd.getEnabled())) { ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, "At least one reward is required when enabled.", @@ -92,6 +95,9 @@ public class ResidentRegisterRewardServiceImpl implements ResidentRegisterReward ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, "goldAmount must be greater than or equal to zero.", goldAmount >= 0); + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + "dailyLimit must be greater than or equal to zero.", + dailyLimit >= 0); } private String normalizeSysOrigin(String sysOrigin) { @@ -102,6 +108,10 @@ public class ResidentRegisterRewardServiceImpl implements ResidentRegisterReward return goldAmount == null ? 0L : goldAmount; } + private Long defaultDailyLimit(Long dailyLimit) { + return dailyLimit == null ? 0L : dailyLimit; + } + private String getRewardGroupName(Long rewardGroupId) { if (rewardGroupId == null) { return null; diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/register/ResidentRegisterRewardConfigCO.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/register/ResidentRegisterRewardConfigCO.java index cc882fc..2d0a433 100644 --- a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/register/ResidentRegisterRewardConfigCO.java +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/register/ResidentRegisterRewardConfigCO.java @@ -28,4 +28,9 @@ public class ResidentRegisterRewardConfigCO extends ClientObject { private Long rewardGroupId; private String rewardGroupName; + + /** + * 每日奖励份数上限,0 表示不限。 + */ + private Long dailyLimit = 0L; } diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/register/ResidentRegisterRewardConfigSaveCmd.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/register/ResidentRegisterRewardConfigSaveCmd.java index 0cbf637..5a07396 100644 --- a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/register/ResidentRegisterRewardConfigSaveCmd.java +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/register/ResidentRegisterRewardConfigSaveCmd.java @@ -26,4 +26,9 @@ public class ResidentRegisterRewardConfigSaveCmd implements Serializable { private Long goldAmount; private Long rewardGroupId; + + /** + * 每日奖励份数上限,0 表示不限。 + */ + private Long dailyLimit; } diff --git a/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/entity/app/register/ResidentRegisterRewardConfig.java b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/entity/app/register/ResidentRegisterRewardConfig.java index 652c631..55512e4 100644 --- a/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/entity/app/register/ResidentRegisterRewardConfig.java +++ b/rc-service/rc-service-console/console-infrastructure/src/main/java/com/red/circle/console/infra/database/rds/entity/app/register/ResidentRegisterRewardConfig.java @@ -36,4 +36,7 @@ public class ResidentRegisterRewardConfig extends TimestampBaseEntity { @TableField("reward_group_id") private Long rewardGroupId; + + @TableField("daily_limit") + private Long dailyLimit; } diff --git a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/debug/LuckyGiftLocalDebugController.java b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/debug/LuckyGiftLocalDebugController.java new file mode 100644 index 0000000..b531ae1 --- /dev/null +++ b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/debug/LuckyGiftLocalDebugController.java @@ -0,0 +1,52 @@ +package com.red.circle.other.adapter.app.debug; + +import com.red.circle.mq.business.model.event.gift.GameLuckyGiftBusinessEvent; +import com.red.circle.other.app.common.gift.LuckyGiftGoClient; +import com.red.circle.other.app.listener.GameLuckyGiftBusinessListener; +import com.red.circle.tool.core.text.StringUtils; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Profile("local") +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/internal/debug/lucky-gift", produces = MediaType.APPLICATION_JSON_VALUE) +public class LuckyGiftLocalDebugController { + + private final GameLuckyGiftBusinessListener gameLuckyGiftBusinessListener; + + @PostMapping("/business-event") + public LuckyGiftGoClient.LuckyGiftGoDrawResponse replayBusinessEvent( + @RequestBody GameLuckyGiftBusinessEvent event) { + validateEvent(event); + + LuckyGiftGoClient.LuckyGiftGoDrawResponse response = + gameLuckyGiftBusinessListener.processLotteryEvent(event); + if (response == null) { + throw new IllegalStateException("Lucky gift business event returned empty response"); + } + return response; + } + + @PostMapping("/go-draw") + public LuckyGiftGoClient.LuckyGiftGoDrawResponse replayGoDrawOnly( + @RequestBody GameLuckyGiftBusinessEvent event) { + validateEvent(event); + return gameLuckyGiftBusinessListener.drawWithGo(event); + } + + private void validateEvent(GameLuckyGiftBusinessEvent event) { + if (StringUtils.isBlank(event.getBusinessId())) { + throw new IllegalArgumentException("businessId required"); + } + if (Objects.isNull(event.getUsers()) || event.getUsers().isEmpty()) { + throw new IllegalArgumentException("users required"); + } + } +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/gift/LuckyGiftGiveCmdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/gift/LuckyGiftGiveCmdExe.java index a588c76..b52523c 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/gift/LuckyGiftGiveCmdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/gift/LuckyGiftGiveCmdExe.java @@ -15,15 +15,16 @@ import com.red.circle.other.infra.database.cache.service.other.GiftCacheService; import com.red.circle.other.inner.asserts.GiftErrorCode; import com.red.circle.other.inner.asserts.OtherErrorCode; import com.red.circle.other.inner.asserts.RoomErrorCode; -import com.red.circle.other.inner.enums.material.GiftCurrencyType; -import com.red.circle.other.inner.enums.material.GiftTabEnum; -import com.red.circle.other.inner.model.dto.material.GiftConfigDTO; -import com.red.circle.tool.core.collection.CollectionUtils; -import com.red.circle.tool.core.date.LocalDateTimeUtils; -import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient; -import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd; -import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO; -import com.red.circle.wallet.inner.model.enums.GoldOrigin; +import com.red.circle.other.inner.enums.material.GiftCurrencyType; +import com.red.circle.other.inner.enums.material.GiftTabEnum; +import com.red.circle.other.inner.model.dto.material.GiftConfigDTO; +import com.red.circle.tool.core.collection.CollectionUtils; +import com.red.circle.tool.core.date.LocalDateTimeUtils; +import com.red.circle.tool.core.sequence.IdWorkerUtils; +import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient; +import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd; +import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO; +import com.red.circle.wallet.inner.model.enums.GoldOrigin; import java.math.BigDecimal; import java.util.Objects; import lombok.RequiredArgsConstructor; @@ -63,32 +64,55 @@ public class LuckyGiftGiveCmdExe { Objects.equals(giftConfig.getGiftTab(), GiftTabEnum.MAGIC.name())); // 过滤赠送人非法值 - ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, - CollectionUtils.isNotEmpty(cmd.filterAcceptUserId())); - - if (giftConfig.getGiftCandy().equals(new BigDecimal("0.00"))) { - BigDecimal dollarAmount = walletGoldClient.getBalance(cmd.requiredReqUserId()).getBody().getDollarAmount(); - log.info("赠送幸运礼物金额为0,余额为 {}", dollarAmount); - return dollarAmount; - } - - if (GiftTabEnum.MAGIC.name().equals(giftConfig.getGiftTab())) { - ResponseAssert.isFalse(GiftErrorCode.MAGIC_GIFT_QUANTITY_ERROR, cmd.getQuantity() > 1); - } - - // 付钱 - WalletReceiptResDTO receipt = consumeCandy(cmd, giftConfig); - - // 礼物处理mq 魔法礼物不处理,放到中奖后处理 - if (!GiftTabEnum.MAGIC.name().equals(giftConfig.getGiftTab())) { - giftMqMessage.sendGift(receipt.getAssetRecordId().toString(), - giftAppConvertor.toGiveAwayGiftBatchEvent(cmd, giftConfig, receipt.getAssetRecordId())); - } - - // 抽奖mq - gameLuckyGiftCommon.sendMq(cmd, giftConfig.getStandardId()); - - userProfileGateway.removeCache(cmd.requiredReqUserId()); + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + CollectionUtils.isNotEmpty(cmd.filterAcceptUserId())); + + boolean luckyGift = GiftTabEnum.LUCKY_GIFT.name().equals(giftConfig.getGiftTab()); + boolean magicGift = GiftTabEnum.MAGIC.name().equals(giftConfig.getGiftTab()); + boolean freeGift = giftConfig.getGiftCandy().compareTo(BigDecimal.ZERO) == 0; + String businessId = IdWorkerUtils.getIdStr(); + + if (magicGift) { + ResponseAssert.isFalse(GiftErrorCode.MAGIC_GIFT_QUANTITY_ERROR, cmd.getQuantity() > 1); + } + + WalletReceiptResDTO receipt = null; + BigDecimal balance; + if (freeGift) { + balance = walletGoldClient.getBalance(cmd.requiredReqUserId()).getBody().getDollarAmount(); + log.info("赠送幸运礼物金额为0,余额为 {}", balance); + if (!luckyGift) { + return balance; + } + } else { + receipt = consumeCandy(cmd, giftConfig); + balance = receipt.getBalance().getDollarAmount(); + } + + // 礼物处理mq 魔法礼物不处理,放到中奖后处理 + if (!magicGift) { + Long trackId = Objects.nonNull(receipt) ? receipt.getAssetRecordId() : Long.parseLong(businessId); + giftMqMessage.sendGift( + Objects.toString(trackId), + giftAppConvertor.toGiveAwayGiftBatchEvent(cmd, giftConfig, trackId) + ); + } + + // 抽奖mq + if (luckyGift) { + gameLuckyGiftCommon.sendMq( + cmd, + giftConfig.getStandardId(), + businessId, + Objects.nonNull(receipt) ? Objects.toString(receipt.getAssetRecordId()) : null, + giftConfig.getGiftCandy(), + freeGift + ); + } else { + gameLuckyGiftCommon.sendMq(cmd, giftConfig.getStandardId()); + } + + userProfileGateway.removeCache(cmd.requiredReqUserId()); // 检查是否未完成任务 Boolean taskStatus = taskService.checkTaskStatus(cmd.getReqUserId(), 8L, null); @@ -100,8 +124,8 @@ public class LuckyGiftGiveCmdExe { .build()); } - return receipt.getBalance().getDollarAmount(); - } + return balance; + } /** * 付钱. diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/GameLuckyGiftCommon.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/GameLuckyGiftCommon.java index 8467c85..5ff03dd 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/GameLuckyGiftCommon.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/GameLuckyGiftCommon.java @@ -133,11 +133,11 @@ public class GameLuckyGiftCommon { /** * 发送幸运礼物抽奖mq. */ - public void sendMq(GiveAwayGiftBatchCmd cmd, Long standardId) { - - GameLuckyGiftBusinessEvent event = buildLuckyGiftBusinessEvent(cmd, standardId); - if (Objects.isNull(event)) { - return; + public void sendMq(GiveAwayGiftBatchCmd cmd, Long standardId) { + + GameLuckyGiftBusinessEvent event = buildLuckyGiftBusinessEvent(cmd, standardId); + if (Objects.isNull(event)) { + return; } event.setUsers(cmd.filterAcceptUserId().stream().map(acceptUserId -> @@ -154,9 +154,47 @@ public class GameLuckyGiftCommon { .topic(FixedTopic.RC_DEFAULT_APP_ORDINARY) .tag(GameLuckyGiftBusinessSink.TAG) .body(event) - .build()); - - } + .build()); + + } + + public void sendMq( + GiveAwayGiftBatchCmd cmd, + Long standardId, + String businessId, + String consumeAssetRecordId, + BigDecimal giftPrice, + Boolean giftIsFree + ) { + + GameLuckyGiftBusinessEvent event = new GameLuckyGiftBusinessEvent() + .setBusinessId(businessId) + .setConsumeAssetRecordId(consumeAssetRecordId) + .setUserId(cmd.requiredReqUserId()) + .setRoomId(cmd.getRoomId()) + .setSysOrigin(cmd.requireReqSysOrigin()) + .setGiftId(cmd.getGiftId()) + .setGiftPrice(giftPrice) + .setGiftIsFree(Boolean.TRUE.equals(giftIsFree)) + .setQuantity(cmd.getQuantity()) + .setCheckCombo(cmd.getCheckCombo()) + .setGiftCombos(0) + .setStandardId(standardId) + .setUsers(cmd.filterAcceptUserId().stream().map(acceptUserId -> + new GameLuckyGiftUser() + .setId(IdWorkerUtils.getId()) + .setAcceptUserId(acceptUserId) + .setGiftsCount(0) + .setComboLossCount(0) + ).collect(Collectors.toList())); + + senderService.sendEventMessage(MessageEvent.builder() + .consumeId(businessId) + .topic(FixedTopic.RC_DEFAULT_APP_ORDINARY) + .tag(GameLuckyGiftBusinessSink.TAG) + .body(event) + .build()); + } private Integer getComboLossCount(GameLuckyGiftBusinessEvent event) { diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftGoClient.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftGoClient.java new file mode 100644 index 0000000..d07515e --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftGoClient.java @@ -0,0 +1,111 @@ +package com.red.circle.other.app.common.gift; + +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.red.circle.other.infra.config.LuckyGiftGoConfig; +import java.util.List; +import java.util.Objects; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class LuckyGiftGoClient { + + private final LuckyGiftGoConfig luckyGiftGoConfig; + + public LuckyGiftGoDrawResponse draw(LuckyGiftGoDrawRequest request) { + if (!luckyGiftGoConfig.isEnabled()) { + throw new IllegalStateException("Lucky gift go client is disabled"); + } + + String baseUrl = Objects.toString(luckyGiftGoConfig.getBaseUrl(), "").trim(); + if (baseUrl.isEmpty()) { + throw new IllegalStateException("Lucky gift go baseUrl is blank"); + } + + HttpResponse response = HttpUtil.createPost(baseUrl + "/internal/lucky-gift/draw") + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .header("X-Internal-Token", Objects.toString(luckyGiftGoConfig.getInternalToken(), "")) + .timeout(Objects.requireNonNullElse(luckyGiftGoConfig.getTimeoutMillis(), 10000)) + .body(JSON.toJSONString(request)) + .execute(); + + String responseBody = response.body(); + if (response.getStatus() < 200 || response.getStatus() >= 300) { + throw new IllegalStateException("Lucky gift go http error, status=" + response.getStatus() + + ", body=" + responseBody); + } + if (responseBody == null || responseBody.trim().isEmpty()) { + throw new IllegalStateException("Lucky gift go response is empty"); + } + + JSONObject root = JSON.parseObject(responseBody); + if (root == null) { + throw new IllegalStateException("Lucky gift go response is invalid"); + } + if (root.containsKey("status") && !root.getBooleanValue("status")) { + throw new IllegalStateException("Lucky gift go business error: " + root.getString("message")); + } + + JSONObject body = root.getJSONObject("body"); + LuckyGiftGoDrawResponse result = Objects.nonNull(body) + ? body.toJavaObject(LuckyGiftGoDrawResponse.class) + : root.toJavaObject(LuckyGiftGoDrawResponse.class); + + if (result == null || result.getBusinessId() == null || result.getResults() == null) { + throw new IllegalStateException("Lucky gift go response body is invalid: " + responseBody); + } + return result; + } + + @Data + @Accessors(chain = true) + public static class LuckyGiftGoDrawRequest { + private String businessId; + private String consumeAssetRecordId; + private String sysOrigin; + private Long standardId; + private Long roomId; + private Long sendUserId; + private Long giftId; + private Long giftPrice; + private Long giftNum; + private Boolean giftIsFree; + private List orders; + } + + @Data + @Accessors(chain = true) + public static class LuckyGiftGoDrawOrder { + private String id; + private Long acceptUserId; + } + + @Data + @Accessors(chain = true) + public static class LuckyGiftGoDrawResponse { + private String businessId; + private Integer providerCode; + private Long rewardTotal; + private Long balanceAfter; + private List results; + } + + @Data + @Accessors(chain = true) + public static class LuckyGiftGoDrawResult { + private String id; + private String orderId; + private Long acceptUserId; + private Boolean isWin; + private Long rewardNum; + } +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftResultProcessor.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftResultProcessor.java new file mode 100644 index 0000000..54d175d --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/common/gift/LuckyGiftResultProcessor.java @@ -0,0 +1,224 @@ +package com.red.circle.other.app.common.gift; + +import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; +import com.red.circle.component.redis.service.RedisService; +import com.red.circle.external.inner.endpoint.message.ImGroupClient; +import com.red.circle.external.inner.model.cmd.message.BroadcastGroupMsgBodyCmd; +import com.red.circle.external.inner.model.cmd.message.CustomGroupMsgBodyCmd; +import com.red.circle.external.inner.model.enums.message.GroupMessageTypeEnum; +import com.red.circle.mq.business.model.event.gift.GameLuckyGiftBusinessEvent; +import com.red.circle.mq.business.model.event.gift.GameLuckyGiftUser; +import com.red.circle.other.app.convertor.user.UserProfileAppConvertor; +import com.red.circle.other.app.dto.clientobject.game.GameLuckyGiftMsgCO; +import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskProgressUpdateCmd; +import com.red.circle.other.app.service.task.RoomDailyTaskProgressService; +import com.red.circle.other.app.util.DateTimeAsiaRiyadhUtils; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.infra.database.cache.service.other.GiftCacheService; +import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager; +import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService; +import com.red.circle.other.infra.database.rds.entity.game.GameLuckyGiftCount; +import com.red.circle.other.infra.database.rds.entity.live.RoomMember; +import com.red.circle.other.infra.database.rds.service.game.GameLuckyGiftCountService; +import com.red.circle.other.infra.database.rds.service.live.RoomMemberService; +import com.red.circle.other.inner.enums.material.PropsCommodityType; +import com.red.circle.other.inner.enums.task.RoomDailyTaskCode; +import com.red.circle.other.inner.model.dto.material.GiftConfigDTO; +import com.red.circle.other.inner.model.dto.user.UserProfileDTO; +import com.red.circle.other.inner.model.dto.user.props.UserPropsResourcesDTO; +import com.red.circle.other.inner.model.dto.user.props.UserUsePropsDTO; +import com.red.circle.tool.core.collection.CollectionUtils; +import com.red.circle.tool.core.date.TimestampUtils; +import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; +import com.red.circle.tool.core.text.StringUtils; +import java.math.BigDecimal; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class LuckyGiftResultProcessor { + + private final GameLuckyGiftCountService gameLuckyGiftCountService; + private final GiftCacheService giftCacheService; + private final UserProfileGateway userProfileGateway; + private final UserProfileAppConvertor userProfileAppConvertor; + private final ImGroupClient imGroupClient; + private final RoomDailyTaskProgressService roomDailyTaskProgressService; + private final RoomMemberService roomMemberService; + private final RedisService redisService; + private final RoomProfileManagerService roomProfileManagerService; + private final GameLuckyGiftCommon gameLuckyGiftCommon; + + public void process(GameLuckyGiftBusinessEvent event, LuckyGiftGoClient.LuckyGiftGoDrawResponse response) { + GiftConfigDTO giftConfig = giftCacheService.getById(event.getGiftId()); + if (giftConfig == null) { + throw new IllegalStateException("Lucky gift config not found, giftId=" + event.getGiftId()); + } + + UserProfileDTO sendUserProfile = userProfileAppConvertor.toUserProfileDTO( + userProfileGateway.getByUserId(event.getUserId())); + if (sendUserProfile == null) { + throw new IllegalStateException("Lucky gift sender profile not found, userId=" + event.getUserId()); + } + + Map userMap = Optional.ofNullable(event.getUsers()) + .orElse(Collections.emptyList()) + .stream() + .collect(Collectors.toMap(user -> Objects.toString(user.getId()), Function.identity())); + + if (userMap.size() != Optional.ofNullable(response.getResults()).orElse(Collections.emptyList()).size()) { + throw new IllegalStateException("Lucky gift result size mismatch, businessId=" + event.getBusinessId()); + } + + UserPropsResourcesDTO avatarFrame = getUserAvatarFrameProps(sendUserProfile); + long payAmount = resolvePayAmount(event, giftConfig); + BigDecimal balanceAfter = BigDecimal.valueOf(Objects.requireNonNullElse(response.getBalanceAfter(), 0L)); + + for (LuckyGiftGoClient.LuckyGiftGoDrawResult result : response.getResults()) { + GameLuckyGiftUser user = userMap.get(result.getId()); + if (user == null) { + throw new IllegalStateException("Lucky gift user mapping missing, resultId=" + result.getId()); + } + + long rewardNum = Objects.requireNonNullElse(result.getRewardNum(), 0L); + int multiple = payAmount > 0 && rewardNum > 0 ? (int) (rewardNum / payAmount) : 0; + + gameLuckyGiftCountService.saveOrUpdate(new GameLuckyGiftCount() + .setId(Long.valueOf(result.getId())) + .setGiftId(event.getGiftId()) + .setRoomId(event.getRoomId()) + .setQuantity(event.getQuantity()) + .setUserId(event.getUserId()) + .setSysOrigin(event.getSysOrigin()) + .setGiftIncCount(0) + .setGiftCombos(Objects.requireNonNullElse(event.getGiftCombos(), 0)) + .setGiftCover(giftConfig.getGiftPhoto()) + .setPayAmount(payAmount) + .setMultiple(multiple) + .setChangeInventory(false) + .setSysGiftIncCount(0) + .setAwardAmount(rewardNum) + .setRegionCode(event.getRegionCode()) + .setDateNumber(ZonedDateTimeAsiaRiyadhUtils.nowDateToInt()) + ); + + if (rewardNum <= 0) { + continue; + } + + sendLuckyGiftMessage(event, giftConfig, sendUserProfile, avatarFrame, result, multiple, balanceAfter); + updateRoomDailyTask(event.getUserId(), event.getRoomId(), rewardNum, RoomDailyTaskCode.PERSONAL_LUCKY_GIFT_GOLD); + } + } + + private long resolvePayAmount(GameLuckyGiftBusinessEvent event, GiftConfigDTO giftConfig) { + BigDecimal giftPrice = Objects.nonNull(event.getGiftPrice()) ? event.getGiftPrice() : giftConfig.getGiftCandy(); + return giftPrice.multiply(BigDecimal.valueOf(Objects.requireNonNullElse(event.getQuantity(), 0))).longValue(); + } + + private void sendLuckyGiftMessage( + GameLuckyGiftBusinessEvent event, + GiftConfigDTO giftConfig, + UserProfileDTO sendUserProfile, + UserPropsResourcesDTO avatarFrame, + LuckyGiftGoClient.LuckyGiftGoDrawResult result, + Integer multiple, + BigDecimal balanceAfter + ) { + GameLuckyGiftMsgCO giftMsg = new GameLuckyGiftMsgCO() + .setSysOrigin(event.getSysOrigin()) + .setRoomId(event.getRoomId()) + .setRoomAccount(event.getRoomAccount()) + .setSendUserId(event.getUserId()) + .setAccount(sendUserProfile.actualAccount()) + .setNickname(sendUserProfile.getUserNickname()) + .setUserAvatar(sendUserProfile.getUserAvatar()) + .setAvatarFrameCover(avatarFrame.getCover()) + .setAvatarFrameSvg(avatarFrame.getSourceUrl()) + .setMultiple(multiple) + .setAwardAmount(result.getRewardNum()) + .setGiftId(event.getGiftId()) + .setMultipleType(gameLuckyGiftCommon.getRewardMultipleType(multiple)) + .setGiftCover(giftConfig.getGiftPhoto()) + .setRegionCode(event.getRegionCode()) + .setGiftQuantity(event.getQuantity()) + .setAcceptUserId(result.getAcceptUserId()) + .setAcceptNickname(resolveAcceptNickname(result.getAcceptUserId())) + .setBalance(balanceAfter) + .setGiftCandy(Objects.nonNull(event.getGiftPrice()) ? event.getGiftPrice() : giftConfig.getGiftCandy()) + .setGlobalNews(Boolean.TRUE); + + imGroupClient.sendMessageBroadcast( + BroadcastGroupMsgBodyCmd.builder() + .toPlatform(SysOriginPlatformEnum.toEnum(giftMsg.getSysOrigin())) + .type(GroupMessageTypeEnum.GAME_LUCKY_GIFT) + .data(giftMsg) + .build() + ); + + if (StringUtils.isBlank(giftMsg.getRoomAccount())) { + return; + } + imGroupClient.sendCustomMessage(giftMsg.getRoomAccount(), + CustomGroupMsgBodyCmd.builder() + .type(GroupMessageTypeEnum.GAME_LUCKY_GIFT) + .data(giftMsg) + .build()); + } + + private String resolveAcceptNickname(Long acceptUserId) { + if (acceptUserId == null) { + return null; + } + return Optional.ofNullable(userProfileGateway.getByUserId(acceptUserId)) + .map(profile -> profile.getUserNickname()) + .orElse(null); + } + + private void updateRoomDailyTask(Long userId, Long roomId, Long rewardAmount, RoomDailyTaskCode taskType) { + RoomMember roomMember = roomMemberService.getRoomMember(roomId, userId); + if (roomMember == null) { + return; + } + + RoomProfileManager profileManager = roomProfileManagerService.getByUserId(userId); + if (profileManager == null || Objects.equals(profileManager.getId(), roomMember.getRoomId())) { + return; + } + + String redisKey = "room:daily:task:progress:" + taskType.name() + ":" + userId + ":" + + ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate(); + Long total = redisService.increment(redisKey, rewardAmount); + redisService.expire(redisKey, DateTimeAsiaRiyadhUtils.getSecondsUntilMidnight(), TimeUnit.SECONDS); + + roomDailyTaskProgressService.updateTaskProgress( + new RoomDailyTaskProgressUpdateCmd() + .setUserId(userId) + .setTaskCode(taskType.name()) + .setProgressValue(total.intValue()) + ); + } + + private UserPropsResourcesDTO getUserAvatarFrameProps(UserProfileDTO sendUserProfile) { + if (CollectionUtils.isEmpty(sendUserProfile.getUseProps())) { + return new UserPropsResourcesDTO(); + } + + return Optional.ofNullable(sendUserProfile.getUseProps().stream() + .filter(props -> Objects.nonNull(props.getPropsResources()) + && !Objects.equals(props.getPropsResources().getType(), PropsCommodityType.AVATAR_FRAME.name()) + && props.getExpireTime() > TimestampUtils.now().getTime()) + .findFirst().orElse(new UserUsePropsDTO()) + .getPropsResources()).orElse(new UserPropsResourcesDTO()); + } +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/GameLuckyGiftBusinessListener.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/GameLuckyGiftBusinessListener.java index 24314b5..3d93600 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/GameLuckyGiftBusinessListener.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/GameLuckyGiftBusinessListener.java @@ -1,23 +1,27 @@ package com.red.circle.other.app.listener; - - -import com.red.circle.component.mq.MessageEventProcess; -import com.red.circle.component.mq.MessageEventProcessDescribe; -import com.red.circle.component.mq.config.RocketMqMessageListener; + + +import com.red.circle.component.mq.MessageEventProcess; +import com.red.circle.component.mq.MessageEventProcessDescribe; +import com.red.circle.component.mq.config.RocketMqMessageListener; import com.red.circle.component.mq.service.Action; -import com.red.circle.component.mq.service.ConsumerMessage; -import com.red.circle.component.mq.service.MessageListener; -import com.red.circle.mq.business.model.event.gift.GameLuckyGiftBusinessEvent; -import com.red.circle.mq.rocket.business.streams.GameLuckyGiftBusinessSink; -import com.red.circle.other.app.common.gift.GameLuckyGiftCommon; -import com.red.circle.other.app.common.gift.GameLuckyGiftParamCmd; -import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway; -import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile; -import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService; -import com.red.circle.tool.core.date.LocalDateTimeUtils; -import java.util.Objects; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; +import com.red.circle.component.mq.service.ConsumerMessage; +import com.red.circle.component.mq.service.MessageListener; +import com.red.circle.mq.business.model.event.gift.GameLuckyGiftBusinessEvent; +import com.red.circle.mq.rocket.business.streams.GameLuckyGiftBusinessSink; +import com.red.circle.other.app.common.gift.GameLuckyGiftCommon; +import com.red.circle.other.app.common.gift.LuckyGiftGoClient; +import com.red.circle.other.app.common.gift.LuckyGiftResultProcessor; +import com.red.circle.other.app.common.gift.GameLuckyGiftParamCmd; +import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway; +import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile; +import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService; +import com.red.circle.tool.core.text.StringUtils; +import com.red.circle.tool.core.date.LocalDateTimeUtils; +import java.util.stream.Collectors; +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; /** * 游戏幸运礼物抽奖. @@ -29,13 +33,15 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor public class GameLuckyGiftBusinessListener implements MessageListener { - private final UserRegionGateway userRegionGateway; - private final MessageEventProcess messageEventProcess; - private final GameLuckyGiftCommon gameLuckyGiftManager; - private final RoomProfileManagerService roomProfileManagerService; + private final UserRegionGateway userRegionGateway; + private final MessageEventProcess messageEventProcess; + private final GameLuckyGiftCommon gameLuckyGiftManager; + private final RoomProfileManagerService roomProfileManagerService; + private final LuckyGiftGoClient luckyGiftGoClient; + private final LuckyGiftResultProcessor luckyGiftResultProcessor; - @Override - public Action consume(ConsumerMessage message) { + @Override + public Action consume(ConsumerMessage message) { return messageEventProcess.consume( MessageEventProcessDescribe.builder() @@ -47,48 +53,77 @@ public class GameLuckyGiftBusinessListener implements MessageListener { .message(message) .build(), GameLuckyGiftBusinessEvent.class, - this::processLottery); - } - - /** - * 保存幸运礼物流水. - */ - private void processLottery(GameLuckyGiftBusinessEvent event) { - - if (Objects.isNull(event.getRoomId())) { - return; - } - - long startTime = LocalDateTimeUtils.nowEpochMilli(); - - try { - RoomProfile roomProfile = roomProfileManagerService.getProfileById(event.getRoomId()); - if (Objects.isNull(roomProfile)) { - return; - } - - GameLuckyGiftParamCmd cmd = buildLuckyGiftRunParam(event, roomProfile); - - event.getUsers().forEach(user -> { - - cmd.setId(user.getId()); - cmd.setGiftsCount(user.getGiftsCount()); - cmd.setAcceptUserId(user.getAcceptUserId()); - cmd.setComboLossCount(user.getComboLossCount()); - gameLuckyGiftManager.run(cmd); - }); - } finally { - long endTime = LocalDateTimeUtils.nowEpochMilli() - startTime; - if (endTime > (1000 * 20)) { - log.warn("[游戏幸运礼物抽奖] 队列处理耗时:{}", endTime); - } - } - - } - - private GameLuckyGiftParamCmd buildLuckyGiftRunParam(GameLuckyGiftBusinessEvent event, - RoomProfile roomProfile) { - return new GameLuckyGiftParamCmd() + this::processLottery); + } + + /** + * 保存幸运礼物流水. + */ + private void processLottery(GameLuckyGiftBusinessEvent event) { + processLotteryEvent(event); + } + + public LuckyGiftGoClient.LuckyGiftGoDrawResponse processLotteryEvent(GameLuckyGiftBusinessEvent event) { + if (Objects.isNull(event.getRoomId())) { + log.warn("Lucky gift event missing roomId, businessId={}", event.getBusinessId()); + return null; + } + + long startTime = LocalDateTimeUtils.nowEpochMilli(); + + try { + RoomProfile roomProfile = roomProfileManagerService.getProfileById(event.getRoomId()); + if (Objects.nonNull(roomProfile)) { + event.setRoomAccount(roomProfile.getRoomAccount()); + } else if (StringUtils.isBlank(event.getBusinessId())) { + log.warn("Lucky gift room profile missing for legacy flow, roomId={}", event.getRoomId()); + return null; + } else { + log.warn("Lucky gift room profile missing, continue go draw with fallback roomAccount, businessId={}, roomId={}", + event.getBusinessId(), event.getRoomId()); + } + + if (StringUtils.isBlank(event.getRegionCode())) { + event.setRegionCode(userRegionGateway.getRegionCode(event.getUserId())); + } + + if (StringUtils.isBlank(event.getBusinessId())) { + GameLuckyGiftParamCmd cmd = buildLuckyGiftRunParam(event, roomProfile); + event.getUsers().forEach(user -> { + cmd.setId(user.getId()); + cmd.setGiftsCount(user.getGiftsCount()); + cmd.setAcceptUserId(user.getAcceptUserId()); + cmd.setComboLossCount(user.getComboLossCount()); + gameLuckyGiftManager.run(cmd); + }); + return null; + } + + LuckyGiftGoClient.LuckyGiftGoDrawResponse response = drawWithGo(event); + luckyGiftResultProcessor.process(event, response); + return response; + } finally { + long endTime = LocalDateTimeUtils.nowEpochMilli() - startTime; + if (endTime > (1000 * 20)) { + log.warn("[游戏幸运礼物抽奖] 队列处理耗时:{}", endTime); + } + } + } + + public LuckyGiftGoClient.LuckyGiftGoDrawResponse drawWithGo(GameLuckyGiftBusinessEvent event) { + LuckyGiftGoClient.LuckyGiftGoDrawResponse response = luckyGiftGoClient.draw(buildGoRequest(event)); + if (!Objects.equals(event.getBusinessId(), response.getBusinessId())) { + throw new IllegalStateException("Lucky gift businessId mismatch, request=" + event.getBusinessId() + + ", response=" + response.getBusinessId()); + } + log.info("Lucky gift go draw success businessId={}, standardId={}, providerCode={}, rewardTotal={}", + event.getBusinessId(), event.getStandardId(), response.getProviderCode(), response.getRewardTotal()); + return response; + } + + private GameLuckyGiftParamCmd buildLuckyGiftRunParam(GameLuckyGiftBusinessEvent event, + RoomProfile roomProfile) { + return new GameLuckyGiftParamCmd() .setUserId(event.getUserId()) .setRoomId(event.getRoomId()) .setRoomAccount(roomProfile.getRoomAccount()) @@ -101,9 +136,28 @@ public class GameLuckyGiftBusinessListener implements MessageListener { .setSysComboLoss(event.getSysComboLoss()) .setOpenGiftGiveTotal(event.getOpenGiftGiveTotal()) .setSysGiftGiveTotal(event.getSysGiftGiveTotal()) - .setRegionCode(userRegionGateway.getRegionCode(event.getUserId())) - .setStandardId(event.getStandardId()); - } - - -} + .setRegionCode(userRegionGateway.getRegionCode(event.getUserId())) + .setStandardId(event.getStandardId()); + } + + private LuckyGiftGoClient.LuckyGiftGoDrawRequest buildGoRequest(GameLuckyGiftBusinessEvent event) { + return new LuckyGiftGoClient.LuckyGiftGoDrawRequest() + .setBusinessId(event.getBusinessId()) + .setConsumeAssetRecordId(event.getConsumeAssetRecordId()) + .setSysOrigin(event.getSysOrigin()) + .setStandardId(event.getStandardId()) + .setRoomId(event.getRoomId()) + .setSendUserId(event.getUserId()) + .setGiftId(event.getGiftId()) + .setGiftPrice(Objects.nonNull(event.getGiftPrice()) ? event.getGiftPrice().longValue() : 0L) + .setGiftNum(Objects.nonNull(event.getQuantity()) ? Long.valueOf(event.getQuantity()) : 0L) + .setGiftIsFree(Boolean.TRUE.equals(event.getGiftIsFree())) + .setOrders(event.getUsers().stream().map(user -> + new LuckyGiftGoClient.LuckyGiftGoDrawOrder() + .setId(Objects.toString(user.getId(), null)) + .setAcceptUserId(user.getAcceptUserId()) + ).collect(Collectors.toList())); + } + + +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/config/LuckyGiftGoConfig.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/config/LuckyGiftGoConfig.java new file mode 100644 index 0000000..3948ba7 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/config/LuckyGiftGoConfig.java @@ -0,0 +1,21 @@ +package com.red.circle.other.infra.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; + +@Data +@Component +@RefreshScope +@ConfigurationProperties(prefix = "lucky.gift.go") +public class LuckyGiftGoConfig { + + private boolean enabled = true; + + private String baseUrl; + + private String internalToken; + + private Integer timeoutMillis = 10000; +} diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/user/region/impl/RegionConfigClientServiceImpl.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/user/region/impl/RegionConfigClientServiceImpl.java index 699534c..234847d 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/user/region/impl/RegionConfigClientServiceImpl.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/user/region/impl/RegionConfigClientServiceImpl.java @@ -80,14 +80,16 @@ public class RegionConfigClientServiceImpl implements RegionConfigClientService } @Override - public void add(SysRegionCmd config) { - - config.setId(IdWorkerUtils.getIdStr()); - ResponseAssert.isFalse(UserErrorCode.CODE_ALREADY_EXISTS, - sysRegionConfigService.existRegionCode(config.getRegionCode(), config.getId(), config.getSysOrigin())); - sysRegionConfigService.add(regionConfigInnerConvertor.toSysRegionConfig(config)); - regionCacheService.remove(config.getSysOrigin()); - } + public void add(SysRegionCmd config) { + + config.setId(IdWorkerUtils.getIdStr()); + ResponseAssert.isFalse(UserErrorCode.CODE_ALREADY_EXISTS, + sysRegionConfigService.existRegionCode(config.getRegionCode(), config.getId(), config.getSysOrigin())); + SysRegionConfig regionConfig = regionConfigInnerConvertor.toSysRegionConfig(config); + regionConfig.setWithdrawalWays(StringUtils.join(config.getWithdrawalWaysList(), ",")); + sysRegionConfigService.add(regionConfig); + regionCacheService.remove(config.getSysOrigin()); + } @Override public void update(SysRegionCmd config) { diff --git a/rc-service/rc-service-other/other-start/src/main/resources/application-local.yml b/rc-service/rc-service-other/other-start/src/main/resources/application-local.yml index 9b6bb87..750f6c7 100644 --- a/rc-service/rc-service-other/other-start/src/main/resources/application-local.yml +++ b/rc-service/rc-service-other/other-start/src/main/resources/application-local.yml @@ -3,13 +3,13 @@ logging: com.red.circle.*: debug com.alibaba.cloud.nacos.*: debug -feign: - gateway: - url: http://127.0.0.1:1100 - wallet: - url: http://127.0.0.1:2000 - other: - url: http://127.0.0.1:2400 +feign: + gateway: + url: http://127.0.0.1:1100 + wallet: + url: http://wallet:2000 + other: + url: http://127.0.0.1:2400 live: url: http://127.0.0.1:2500 console: @@ -19,4 +19,4 @@ feign: order: url: http://127.0.0.1:2600 external: - url: http://127.0.0.1:3000 \ No newline at end of file + url: http://127.0.0.1:3000 diff --git a/rc-service/rc-service-wallet/wallet-start/src/main/java/com/red/circle/framework/shardingsphere/driver/NacosDriverURLProvider.java b/rc-service/rc-service-wallet/wallet-start/src/main/java/com/red/circle/framework/shardingsphere/driver/NacosDriverURLProvider.java index 1cfeed4..e4cfcad 100644 --- a/rc-service/rc-service-wallet/wallet-start/src/main/java/com/red/circle/framework/shardingsphere/driver/NacosDriverURLProvider.java +++ b/rc-service/rc-service-wallet/wallet-start/src/main/java/com/red/circle/framework/shardingsphere/driver/NacosDriverURLProvider.java @@ -3,6 +3,11 @@ package com.red.circle.framework.shardingsphere.driver; import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.exception.NacosException; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; @@ -40,12 +45,6 @@ public class NacosDriverURLProvider implements ShardingSphereDriverURLProvider { } Map queryParams = parseQuery(url); - Properties properties = new Properties(); - setIfHasText(properties, "serverAddr", queryParams.get("serverAddr")); - setIfHasText(properties, "namespace", queryParams.get("namespace")); - setIfHasText(properties, "username", queryParams.get("username")); - setIfHasText(properties, "password", queryParams.get("password")); - String group = Optional.ofNullable(queryParams.get(GROUP)) .filter(NacosDriverURLProvider::hasText) .orElse("DEFAULT_GROUP"); @@ -57,19 +56,95 @@ public class NacosDriverURLProvider implements ShardingSphereDriverURLProvider { shardingConfigFilename, group, queryParams); - ConfigService configService = NacosFactory.createConfigService(properties); - String content = configService.getConfig(shardingConfigFilename, group, TIMEOUT_MILLIS); + String content = ""; + try { + content = loadConfig(queryParams, shardingConfigFilename, group, true); + } catch (NacosException ex) { + LOGGER.warn( + "Load sharding config via nacos client failed, fallback to HTTP. dataId={}, group={}", + shardingConfigFilename, + group, + ex); + } + if (!hasText(content)) { + LOGGER.warn( + "Empty sharding config via nacos client, fallback to HTTP. dataId={}, group={}", + shardingConfigFilename, + group); + content = loadConfigViaHTTP(queryParams, shardingConfigFilename, group); + } if (!hasText(content)) { throw new RuntimeException( "Empty Nacos sharding config: dataId=" + shardingConfigFilename + ", group=" + group); } LOGGER.info(content); return content.getBytes(StandardCharsets.UTF_8); - } catch (NacosException ex) { + } catch (IOException ex) { throw new RuntimeException(ex); } } + private String loadConfig(Map queryParams, String dataID, String group, + boolean includeAuth) throws NacosException { + ConfigService configService = NacosFactory.createConfigService( + buildProperties(queryParams, includeAuth)); + return configService.getConfig(dataID, group, TIMEOUT_MILLIS); + } + + private String loadConfigViaHTTP(Map queryParams, String dataID, String group) + throws IOException { + String serverAddr = queryParams.get("serverAddr"); + if (!hasText(serverAddr)) { + return ""; + } + + StringBuilder urlBuilder = new StringBuilder("http://") + .append(serverAddr) + .append("/nacos/v1/cs/configs?dataId=") + .append(encode(dataID)) + .append("&group=") + .append(encode(group)); + String namespace = queryParams.get("namespace"); + if (hasText(namespace) && !"public".equalsIgnoreCase(namespace.trim())) { + urlBuilder.append("&tenant=").append(encode(namespace)); + } + + HttpURLConnection connection = (HttpURLConnection) new URL(urlBuilder.toString()).openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout((int) TIMEOUT_MILLIS); + connection.setReadTimeout((int) TIMEOUT_MILLIS); + int status = connection.getResponseCode(); + if (status != HttpURLConnection.HTTP_OK) { + LOGGER.warn( + "Load sharding config via HTTP failed. status={}, dataId={}, group={}, url={}", + status, + dataID, + group, + urlBuilder); + return ""; + } + try (InputStream inputStream = connection.getInputStream()) { + return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + } finally { + connection.disconnect(); + } + } + + private Properties buildProperties(Map queryParams, boolean includeAuth) { + Properties properties = new Properties(); + setIfHasText(properties, "serverAddr", queryParams.get("serverAddr")); + setIfHasText(properties, "namespace", queryParams.get("namespace")); + if (includeAuth) { + setIfHasText(properties, "username", queryParams.get("username")); + setIfHasText(properties, "password", queryParams.get("password")); + } + return properties; + } + + private static String encode(String value) { + return URLEncoder.encode(value, StandardCharsets.UTF_8); + } + private static void setIfHasText(Properties properties, String key, String value) { if (hasText(value)) { properties.setProperty(key, value);