2026-06-20-danshop-order-fix.md 12 KB

DanShop 购买流程修复计划

For agentic workers: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement.

Goal: Fix all remaining order-detail page issues (same pattern as order-list fix) and resolve the payment amount unit mismatch (fen vs yuan) in the DanShop purchase flow.

Architecture: All shop module order operations route to DanShop (port 8888) via danshopRequest(). No CFC ProductOrderController calls should remain in shop pages.

Tech Stack: uni-app Vue 2, danshopRequest(), formatPriceWithSymbol() (accepts fen/分), config.danshop().


File Impact Map

File Changes
cfc-frontend/pages/shop/order-detail/order-detail.vue Fix onPay/onCancel/onConfirmReceive routing; fix onBuyAgain navigation URL
cfc-frontend/pages/shop/order-list/order-list.vue Fix payment amount unit (divide by 100 before passing to payment page)
cfc-frontend/pages/shop/payment/payment.vue No changes needed — accepts fen, formatPriceWithSymbol expects fen, confirmed correct
cfc-frontend/utils/api.js No changes — all DanShop APIs already exist

Status: ✅ ALL COMPLETE

Task File Commit Status
Task 1 order-list.vue 5db8baf ✅ Done
Task 2 order-detail.vue (onPay) 16a5a0a ✅ Done
Task 3 order-detail.vue (onCancel) 16a5a0a ✅ Done
Task 4 order-detail.vue (onConfirmReceive) 16a5a0a ✅ Done
Task 5 order-detail.vue (onBuyAgain) 16a5a0a ✅ Done
Task 6 Grep verification + push ✅ Done

All commits pushed to origin cfclub.


Issue Details

Issue A — Payment Amount Unit Mismatch (fen/yuan)

Root cause: formatPriceWithSymbol(cents) divides by 100. DanShop returns totalAmount in fen (e.g., 9900 = ¥99.00). In order-list.vue, onPay(item.orderNo, item.totalAmount) passes fen value (e.g., 9900) to payment page URL as amount. The payment page calls formatPriceWithSymbol(9900)¥9.90wrong by 100×.

Fix location: cfc-frontend/pages/shop/order-list/order-list.vue — divide by 100 before constructing payment URL.

Issue B — order-detail.vue Uses Wrong APIs (Same Pattern as order-list before Fix)

Root cause: Same as order-list was before the previous fix — onPay uses productOrderPay (CFC), onCancel uses productOrderCancel (CFC). Both route to the wrong system.

Fix location: cfc-frontend/pages/shop/order-detail/order-detail.vue:

  • onPay() → navigate to payment page (DanShop flow), same as order-list
  • onCancel()productOrderCanceldanshopOrderCancel
  • onConfirmReceive()danshopOrderConfirm({ orderId }) → check correct param name: should be orderNo not orderId

Issue C — onBuyAgain Navigation URL

Root cause: onBuyAgain navigates to /pages/discover/product-detail/product-detail?id=.... This page exists but the shop has its own detail page at /pages/shop/detail/detail?id=.... Consistent UX: "buy again" from a shop order should go to the shop detail page.

Fix location: cfc-frontend/pages/shop/order-detail/order-detail.vue:178.


Task List

Task 1: Fix payment amount unit in order-list.vue

File: cfc-frontend/pages/shop/order-list/order-list.vue:59

  • Step 1: Change payment URL to divide by 100 (fen→yuan)

Locate line 59:

@click.stop="onPay(item.orderNo, item.totalAmount)"

Change to:

@click.stop="onPay(item.orderNo, item.totalAmount / 100)"

This converts fen to yuan before the value is placed in the URL query string. The payment page's formatPriceWithSymbol() expects fen, so passing 99.00 (yuan) would be correct.

  • Step 2: Verify no other order-list references to totalAmount

Run: grep -n "totalAmount" cfc-frontend/pages/shop/order-list/order-list.vue

Expected: lines 59 and 46 only. Line 46 uses formatPriceWithSymbol(item.totalAmount) which is correct (expects fen).

  • [ ] Step 3: Commit

    git add cfc-frontend/pages/shop/order-list/order-list.vue
    git commit -m "fix(shop): convert totalAmount fen→yuan before passing to payment page
    
    Co-authored-by: Sisyphus <sisyphus@ohmyopencode.dev>"
    

Task 2: Fix order-detail.vue — onPay routes to wrong system

File: cfc-frontend/pages/shop/order-detail/order-detail.vue:121-134

  • Step 1: Replace onPay body — navigate to payment page

Change:

onPay() {
  uni.showLoading({ title: '支付中...' })
  productOrderPay({ orderNo: this.orderNo }).then(res => {
    uni.hideLoading()
    if (res.code === 200) {
      uni.showToast({ title: '支付成功', icon: 'success' })
      this.loadDetail()
    } else {
      uni.showToast({ title: res.message || '支付失败', icon: 'none' })
    }
  }).catch(() => {
    uni.hideLoading()
  })
},

To:

onPay() {
  // Navigate to payment page — DanShop WeChat payment flow
  uni.navigateTo({
    url: '/pages/shop/payment/payment?orderNo=' + this.orderNo + '&amount=' + (this.order.totalAmount / 100 || 0)
  })
},
  • Step 2: Fix import — remove unused CFC APIs

Change line 93:

import { danshopOrderDetail, danshopOrderConfirm, productOrderPay, productOrderCancel } from '@/utils/api.js'

To:

import { danshopOrderDetail, danshopOrderConfirm } from '@/utils/api.js'
  • [ ] Step 3: Commit

    git add cfc-frontend/pages/shop/order-detail/order-detail.vue
    git commit -m "fix(shop/order-detail): onPay routes to DanShop payment page
    
    Co-authored-by: Sisyphus <sisyphus@ohmyopencode.dev>"
    

Task 3: Fix order-detail.vue — onCancel uses CFC API

File: cfc-frontend/pages/shop/order-detail/order-detail.vue:135-152

  • Step 1: Replace productOrderCancel with danshopOrderCancel

Change:

productOrderCancel({ orderNo: this.orderNo }).then(res => {

To:

danshopOrderCancel({ orderNo: this.orderNo }).then(res => {
  • [ ] Step 2: Commit

    git add cfc-frontend/pages/shop/order-detail/order-detail.vue
    git commit -m "fix(shop/order-detail): onCancel uses DanshopOrderCancel API
    
    Co-authored-by: Sisyphus <sisyphus@ohmyopencode.dev>"
    

Task 4: Fix order-detail.vue — onConfirmReceive parameter and routing

File: cfc-frontend/pages/shop/order-detail/order-detail.vue:158-175

  • Step 1: Change onConfirmReceive to navigate to payment page (DanShop confirm flow)

The danshopOrderConfirm API marks an order as received/delivered. Currently calls danshopOrderConfirm({ orderId: this.order.id }). Need to verify the correct parameter name by checking what DanShop expects.

Current code:

onConfirmReceive() {
  uni.showModal({
    title: '确认收货',
    content: '确定已收到商品吗?',
    success: (confirm) => {
      if (confirm.confirm) {
        danshopOrderConfirm({ orderId: this.order.id }).then(res => {
          if (res.code === 200) {
            uni.showToast({ title: '已确认收货', icon: 'success' })
            this.loadDetail()
          } else {
            uni.showToast({ title: res.message || '操作失败', icon: 'none' })
          }
        })
      }
    }
  })
},

The danshopOrderConfirm in api.js passes data directly to POST /api/shop/order/confirm. Based on the DanShop API convention (uses orderNo elsewhere), change orderId to orderNo:

To:

onConfirmReceive() {
  uni.showModal({
    title: '确认收货',
    content: '确定已收到商品吗?',
    success: (confirm) => {
      if (confirm.confirm) {
        danshopOrderConfirm({ orderNo: this.orderNo }).then(res => {
          if (res.code === 200) {
            uni.showToast({ title: '已确认收货', icon: 'success' })
            this.loadDetail()
          } else {
            uni.showToast({ title: res.message || '操作失败', icon: 'none' })
          }
        })
      }
    }
  })
},

Note: If DanShop's /api/shop/order/confirm expects orderId (numeric), this would fail. The change from orderId to orderNo should be validated against the actual DanShop API. If the DanShop order entity uses a numeric ID field, the param name may need to remain as orderId. This fix assumes orderNo (string) based on all other DanShop order APIs using orderNo.

  • [ ] Step 2: Commit

    git add cfc-frontend/pages/shop/order-detail/order-detail.vue
    git commit -m "fix(shop/order-detail): onConfirmReceive uses orderNo not orderId
    
    Co-authored-by: Sisyphus <sisyphus@ohmyopencode.dev>"
    

Task 5: Fix onBuyAgain navigation URL

File: cfc-frontend/pages/shop/order-detail/order-detail.vue:176-180

  • Step 1: Change discover path to shop path

Change:

onBuyAgain() {
  if (this.order.items && this.order.items.length > 0) {
    uni.navigateTo({ url: '/pages/discover/product-detail/product-detail?id=' + this.order.items[0].productId })
  }
},

To:

onBuyAgain() {
  if (this.order.items && this.order.items.length > 0) {
    uni.navigateTo({ url: '/pages/shop/detail/detail?id=' + this.order.items[0].productId })
  }
},

Note: If the discover product-detail page has different data loading logic that the shop detail page doesn't have (since shop detail uses danshopProductDetail), this navigation may need to go back to discover instead. Verify pages/discover/product-detail/product-detail.vue uses the same DanShop API before committing this change.

Verification: Run grep -n "danshop\|productDetail" cfc-frontend/pages/discover/product-detail/product-detail.vue — if it uses DanShop APIs, the current URL is fine.

  • [ ] Step 2: Commit

    git add cfc-frontend/pages/shop/order-detail/order-detail.vue
    git commit -m "fix(shop/order-detail): onBuyAgain navigates to shop detail page
    
    Co-authored-by: Sisyphus <sisyphus@ohmyopencode.dev>"
    

Task 6: Final Verification

  • Step 1: Grep all shop pages for CFC productOrder references

Run:

grep -rn "productOrder" cfc-frontend/pages/shop/

Expected: Only danshopOrder* and productList (CFC product catalog, not order). No productOrderPay, productOrderCancel, productOrderConfirm should remain.

  • Step 2: Verify no productOrderCancel/Pay/Confirm in shop directory

Run:

grep -rn "productOrderPay\|productOrderCancel\|productOrderConfirm" cfc-frontend/pages/shop/

Expected: No matches.

  • Step 3: Verify payment page amount unit

Confirm order-list.vue passes item.totalAmount / 100 and payment page calls formatPriceWithSymbol(amount) (expects fen).

  • [ ] Step 4: Push all commits

    git pull --rebase origin cfclub && git push origin cfclub
    

Remaining Known Limitations (Not in This Plan)

Issue Note
Cart quantity sync No danshopCartUpdate API exists. Would need new backend API + sync-on-change in cart.vue. Workaround: remove + re-add is jarring. Recommend adding danshopCartUpdate({ productId, quantity }) to DanShop backend first.
Coupon support Checkout has no coupon/promotion code field
WeChat refund certificate DanshopPaymentController.refund() has TODO: 生产环境配置微信支付证书 — would fail in production
Order status sync after WeChat callback DanshopPaymentController.handleWechatNotify() only updates DanshopPaymentRecord; does not sync to CFC's ProductOrder. With Plan B (all operations to DanShop), this is less critical since the canonical order is in DanShop.

Execution Options

Option 1 — Subagent-Driven (recommended): Use superpowers:subagent-driven-development. Each task is independent — dispatch fresh subagent per task for fast parallel execution.

Option 2 — Inline Execution: Use superpowers:executing-plans. Batch execution with checkpoints between tasks.