Compare commits

..

3 Commits

Author SHA1 Message Date
zhuzihao acdb10b516 feat(ad): 提现看视频广告后端支持(withdrawal_ad 场景 + 开关下发) (#74)
Co-authored-by: zzhyyyyy <2685922758@qq.com>
Reviewed-on: #74
Co-authored-by: zhuzihao <zhuzihao@wonderable.ai>
Co-committed-by: zhuzihao <zhuzihao@wonderable.ai>
2026-06-24 22:38:06 +08:00
marco b1849834f7 fix(alembic): merge meituan_coupon_image_meta 与 comparison/ad 双 head 2026-06-24 20:50:21 +08:00
guke 8008366abc fix(wx-cps): 修复 微信cps分发时淘宝落地页授权刷新导致click_value 重复入库问题 0624 (#73)
通过authed=1判断当前请求是否是微信授权回填,如果是授权回填,不再insert cps_click

---------

Co-authored-by: guke <guke@autohome.com.cn>
Reviewed-on: #73
Co-authored-by: guke <guke@wonderable.ai>
Co-committed-by: guke <guke@wonderable.ai>
2026-06-24 18:15:44 +08:00
7 changed files with 54 additions and 3 deletions
@@ -0,0 +1,26 @@
"""merge meituan_coupon_image_meta and comparison/ad heads
Revision ID: bcfcaf07152b
Revises: 4dc2af7ebe74, meituan_coupon_image_meta
Create Date: 2026-06-24 20:34:09.475641
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = 'bcfcaf07152b'
down_revision: Union[str, Sequence[str], None] = ('4dc2af7ebe74', 'meituan_coupon_image_meta')
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
pass
def downgrade() -> None:
pass
+2
View File
@@ -15,6 +15,7 @@ class AdConfigOut(BaseModel):
reward_enabled: bool
compare_ad_enabled: bool
coupon_ad_enabled: bool
withdrawal_ad_enabled: bool
class AdConfigUpdate(BaseModel):
@@ -28,3 +29,4 @@ class AdConfigUpdate(BaseModel):
reward_enabled: bool | None = None
compare_ad_enabled: bool | None = None
coupon_ad_enabled: bool | None = None
withdrawal_ad_enabled: bool | None = None
+16
View File
@@ -53,6 +53,9 @@ REASON_UNKNOWN_USER = 2 # user_id 不存在(可能伪造)
REWARD_SCENE_REWARD_VIDEO = "reward_video"
REWARD_SCENE_SIGNIN_BOOST = "signin_boost"
# 提现看视频:看完才能提现的「硬门槛」广告,**不发金币**,只记一条幂等记录(收益由 eCPM 上报口径
# ad_type="withdrawal_video" 单独统计)。故意不放进 SUPPORTED_REWARD_SCENES——它不走发币分支。
REWARD_SCENE_WITHDRAWAL_AD = "withdrawal_ad"
SUPPORTED_REWARD_SCENES = {REWARD_SCENE_REWARD_VIDEO, REWARD_SCENE_SIGNIN_BOOST}
@@ -126,6 +129,19 @@ def pangle_callback(request: Request, db: DbSession) -> PangleCallbackOut:
return PangleCallbackOut(is_verify=True, reason=REASON_OK)
try:
if reward_scene == REWARD_SCENE_WITHDRAWAL_AD:
# 提现看视频:已知合法场景,只记一条幂等记录、**不动钱包**(发不发币由 reward_scene 决定)。
# is_verify=true 让穿山甲不重试(区别于 unknown_scene 的 false)。
crud_ad.record_external_reward(
db, user_id, trans_id, coin=0, reward_scene=REWARD_SCENE_WITHDRAWAL_AD,
ad_session_id=ad_session_id, ecpm=ecpm,
reward_name=params.get("reward_name"), raw=raw[:1024],
status="withdrawal_ad",
)
logger.info(
"pangle callback withdrawal_ad user_id=%d trans_id=%s", user_id, trans_id,
)
return PangleCallbackOut(is_verify=True, reason=REASON_OK)
if reward_scene not in SUPPORTED_REWARD_SCENES:
rec = crud_ad.record_external_reward(
db, user_id, trans_id, coin=0, reward_scene=reward_scene[:32],
+7 -3
View File
@@ -83,7 +83,10 @@ def cps_landing(code: str, request: Request, db: Session = Depends(get_db)):
redirect_uri = f"{settings.CPS_REDIRECT_BASE.rstrip('/')}/wx/oauth/cb"
auth_url = wx_oauth.build_authorize_url(redirect_uri, "snsapi_base", f"base:{code}")
return RedirectResponse(auth_url, status_code=302)
_record(db, link, request, "visit", openid=openid)
# ?authed=1 是 userinfo 授权后的自动回跳重载,不是用户主动打开:visit 已在授权前那次
# 落地(base 静默授权回来那次)记过,这里再记会让每个走"领券授权"的用户 visit 虚增 1。
if request.query_params.get("authed") != "1":
_record(db, link, request, "visit", openid=openid)
if link.platform == "taobao":
activity = db.get(CpsActivity, link.activity_id)
image_url = (activity.image_url if activity else None) or _DEFAULT_TAOBAO_IMAGE
@@ -201,8 +204,9 @@ function copyToken(){
if(UINFO_URL){location.href=UINFO_URL;return}
doCopy();
}
// userinfo 授权回流(?authed=1):自动复制,把"点领券→授权→复制"衔接成一步无感
if(location.search.indexOf('authed=1')>=0){doCopy()}
// userinfo 授权回流(?authed=1):自动复制,把"点领券→授权→复制"衔接成一步无感;
// 复制后用 replaceState 清掉 authed=1,避免刷新/微信返回(BFCache)重载时重复触发复制上报。
if(location.search.indexOf('authed=1')>=0){doCopy();history.replaceState(null,'',location.pathname)}
</script>
</body>
</html>"""
+1
View File
@@ -68,6 +68,7 @@ def ad_config(db: DbSession) -> AdConfigPublicOut:
reward_enabled=c["reward_enabled"],
compare_ad_enabled=c["compare_ad_enabled"],
coupon_ad_enabled=c["coupon_ad_enabled"],
withdrawal_ad_enabled=c["withdrawal_ad_enabled"],
)
+1
View File
@@ -109,6 +109,7 @@ _AD_CONFIG_DEFAULTS: dict[str, Any] = {
"reward_enabled": True, # 福利激励视频开关
"compare_ad_enabled": True, # 比价广告开关
"coupon_ad_enabled": True, # 领券广告开关
"withdrawal_ad_enabled": True, # 提现激励视频开关(关=直接放行提现,不挡用户的钱)
}
+1
View File
@@ -43,6 +43,7 @@ class AdConfigPublicOut(BaseModel):
reward_enabled: bool # 福利激励视频开关
compare_ad_enabled: bool # 比价广告开关
coupon_ad_enabled: bool # 领券广告开关
withdrawal_ad_enabled: bool # 提现激励视频开关(关=客户端直接放行提现)
class AppVersionOut(BaseModel):