logo NodeSeekbeta

cmlink uk 小额充值

打开https://www.cmlink.com/uk/en/topup/
输入手机号,然后f12, console运行

(async function cmlinkSmallTopup() {
  'use strict';

  // 充值金额,可修改。
  const AMOUNT = '0.10';
  const RUN_KEY = '__cmlinkSmallTopupState';

  function pennies(value) {
    if (!/^(?:0|[1-9]\d*)(?:\.\d{1,2})?$/.test(String(value))) {
      return NaN;
    }
    const [whole, fraction = ''] = String(value).split('.');
    return Number(whole) * 100 +
      Number(fraction.padEnd(2, '0'));
  }

  function normalizePhone(value) {
    let phone = String(value ?? '').replace(/[\s()+-]/g, '');

    if (phone.startsWith('0044')) {
      phone = '0' + phone.slice(4);
    } else if (phone.startsWith('44')) {
      phone = '0' + phone.slice(2);
    } else if (/^7\d{9}$/.test(phone)) {
      phone = '0' + phone;
    }

    return phone;
  }

  function mustSucceed(response, label) {
    if (!response || String(response.code) !== '200') {
      throw new Error(
        `${label}失败:${response?.code ?? '未知'} ${
          response?.msg ?? response?.message ?? ''
        }`
      );
    }

    if (!response.data || typeof response.data !== 'object') {
      throw new Error(`${label}未返回有效数据。`);
    }

    return response.data;
  }

  function verifyOrder(order, expected, phone) {
    // 官网的 topupAmount 单位为便士。
    const cents = String(order.topupAmount ?? '');

    if (
      !/^\d+(?:\.0+)?$/.test(cents) ||
      Number(cents) !== expected
    ) {
      throw new Error(
        `订单充值金额不一致(返回便士数:${
          cents || '未返回'
        }),停止。`
      );
    }

    if (normalizePhone(order.phoneNum) !== phone) {
      throw new Error('订单号码未返回或不匹配,停止。');
    }
  }

  let ownsLock = false;
  let orderAttempted = false;

  try {
    if (
      location.origin !== 'https://www.cmlink.com' ||
      !/^\/uk\/(?:en|zh)\/topup\/?$/.test(location.pathname)
    ) {
      throw new Error(
        '请先打开 https://www.cmlink.com/uk/en/topup/'
      );
    }

    const expected = pennies(AMOUNT);

    if (
      !Number.isSafeInteger(expected) ||
      expected < 1 ||
      expected > 599
    ) {
      throw new Error(
        '金额应为 £0.01–£5.99,最多两位小数。'
      );
    }

    if (window[RUN_KEY]) {
      throw new Error(
        '本页已运行过或正在运行,请勿重复建单。'
      );
    }

    window[RUN_KEY] = 'running';
    ownsLock = true;

    const root =
      window.$nuxt ||
      document.querySelector('#__nuxt')?.__vue__;

    if (!root) {
      throw new Error('官网还没加载完成,请稍后再运行。');
    }

    // 查找官网充值组件。
    const queue = [root];
    const seen = new Set();
    let vm;

    while (queue.length) {
      const item = queue.shift();

      if (!item || seen.has(item)) continue;
      seen.add(item);

      if (
        item.$options?.name === 'TopupContent' &&
        item.topupForm
      ) {
        vm = item;
        break;
      }

      queue.push(...(item.$children || []));
    }

    const api = vm?.$clientApi?.topup;

    if (
      !vm ||
      !['checkMobileNum', 'placeOrder', 'queryOrder']
        .every(name => typeof api?.[name] === 'function')
    ) {
      throw new Error(
        '找不到官网充值组件或接口已变化,停止。'
      );
    }

    if (String(vm.step) !== '1') {
      throw new Error(
        '当前已有支付订单,请先完成或退出该订单。'
      );
    }

    if (vm.topupForm.couponCode || vm.couponValue) {
      throw new Error(
        '请先清空优惠码和所选优惠券,再运行。'
      );
    }

    const phone = normalizePhone(
      vm.topupForm.mobileNum ||
      prompt('请输入你自己的 CMLink UK 英国主号码:')
    );

    if (!/^07\d{9}$/.test(phone)) {
      throw new Error(
        '请输入有效的英国移动号码,例如 07 开头的 11 位号码。'
      );
    }

    // 使用官网自身的加密请求模块检查号码。
    const status = mustSucceed(
      await api.checkMobileNum({ serviceNum: phone }),
      '号码检查'
    );

    if (String(status.userStatus) === '4') {
      throw new Error('官网返回号码不可充值状态,停止。');
    }

    console.info(
      `正在尝试创建 £${AMOUNT} 未付款充值订单,不自动支付。`
    );

    orderAttempted = true;

    // 金额单位为便士:£0.10 = 10。
    const result = await api.placeOrder({
      mobileNum: phone,
      chargeAmount: String(expected),
      orgAmount: String(expected),
      operType: '3',
      chlCode: vm.chlCode || '',
      language: location.pathname.includes('/zh/')
        ? 'zh'
        : 'en'
    });

    const created = mustSucceed(result, '创建订单');

    if (!created.orderId || !created.crmOrderId) {
      throw new Error(
        '服务器未返回完整订单编号,停止。'
      );
    }

    // 独立查询服务器订单,核对实际充值金额和号码。
    const order = mustSucceed(
      await api.queryOrder({ sid: created.orderId }),
      '查询订单'
    );

    console.info('服务器订单核对:', {
      充值金额便士: order.topupAmount,
      号码是否一致:
        normalizePhone(order.phoneNum) === phone
    });

    verifyOrder(order, expected, phone);

    // 核对通过后显示官网原有支付页面。
    vm.topupForm.mobileNum = phone;
    vm.topupForm.couponCode = '';
    vm.couponValue = '';
    vm.discountFee = 0;
    vm.chargeAmountJPY = expected / 100;
    vm.isCheckPhone = true;
    vm.phoneTip = false;
    vm.amoutTip = false;
    vm.mchOrderNo = created.orderId;
    vm.payOrderNo = created.crmOrderId;
    vm.orderfee = created.orderFee;
    vm.isShowTotal = true;
    vm.step = '2';

    await vm.$nextTick();
    window.scrollTo(0, 0);

    window[RUN_KEY] = 'unpaid-order-created';

    console.info(
      `订单充值金额核对为 £${AMOUNT}。` +
      '请在官网及支付机构页面核对实际应付金额,再自行付款。'
    );
  } catch (error) {
    console.error(
      'CMLink 小额充值尝试已停止:',
      error instanceof Error
        ? error.message
        : String(error)
    );

    if (ownsLock && orderAttempted) {
      window[RUN_KEY] = 'order-attempted';
      console.info(
        '已尝试创建订单;本脚本不会自动重试。停止不代表付款成功。'
      );
    } else if (ownsLock) {
      delete window[RUN_KEY];
    }
  }
})();

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有72271位seeker

🎉欢迎新用户🎉