取订单号的程序

本文介绍了一段VBA代码,用于从Excel表格中提取特定格式的订单号,并去除非数字及顺序号部分,确保提取出的订单号符合规定格式。
Option Explicit

Sub 仓库获取客户代码()
    If Worksheets("产品入库序时簿").Range("G1").Value = "收货仓库" Then
        Columns("G:G").Select
        Selection.Insert
    End If

    getSONo "产品入库序时簿", "F", 2, "G", 2
End Sub
Private Function getSONo(xlWsh As String, strRangeIn As String, intRangeIn As Integer, strRangeOut As String, intRangeOut As Integer)
    '定义两个变量存储单元格Range位置编号
    Dim strStartRangeID As String
    Dim strOutputRangeID As String
    Dim strFinalSONo As String
    '定义一个整数变量,存编号到第几行为止
    Dim intStop As Integer
    intStop = ActiveWorkbook.Worksheets(xlWsh).UsedRange.Rows.Count

    '设置输出的那些单元格为文本格式
    ActiveWorkbook.Worksheets(xlWsh).Range(strRangeOut & ":" & strRangeOut).NumberFormatLocal = "@"

    '获取第一个订单编号的ID
    Do While intRangeIn <= intStop
        strStartRangeID = strRangeIn & intRangeIn
        strOutputRangeID = strRangeOut & intRangeOut
        strFinalSONo = ActiveWorkbook.Worksheets(xlWsh).Range(strStartRangeID).Value

        '切掉后面的订单序号
        If Not InStrRev(strFinalSONo, "-") = 0 Then
            strFinalSONo = cutEndSerialNumber(strFinalSONo)
        End If

        '切掉前面的非数字字符
        strFinalSONo = cutLeft(strFinalSONo)
        '切掉后面的
        strFinalSONo = cutRight(strFinalSONo)

        ActiveWorkbook.Worksheets(xlWsh).Range(strOutputRangeID).Value = strFinalSONo

        '继续下一行
        intRangeIn = intRangeIn + 1
        intRangeOut = intRangeOut + 1
    Loop


End Function

Private Function cutEndSerialNumber(SaleNumber As String) As String
    '-----------------截掉字符"-"后面的内容,包括"-"
    '但是如果包含多个"-"的话,每次只能截掉最后一个的
    '比方说cutEndSerialNumber("CHL0010-1-1")运行结果是CHL0010-1
    Dim intPosition As Integer
    intPosition = InStrRev(SaleNumber, "-")

    If intPosition = 0 Then
        cutEndSerialNumber = SaleNumber
        Exit Function
    End If

    Do While Not intPosition = 0
        SaleNumber = Left(SaleNumber, intPosition - 1)
        intPosition = InStrRev(SaleNumber, "-")
    Loop

    cutEndSerialNumber = SaleNumber
End Function
Private Function cutLeft(strInPut As String)
    '如果第一个就是数字的话就没必要切了
    If (Asc(Left(strInPut, 1)) >= Asc("0") And Asc(Left(strInPut, 1)) <= Asc("9")) Or Len(strInPut) = 1 Then
        cutLeft = strInPut
        Exit Function
    End If


    Do While Not (Asc(Left(strInPut, 1)) >= Asc("0") And Asc(Left(strInPut, 1)) <= Asc("9"))
        strInPut = Right(strInPut, Len(strInPut) - 1)
    Loop
    cutLeft = strInPut
End Function
Private Function cutRight(strInPut As String)
    '如果第一个就是数字的话就没必要切了
    If (Asc(Right(strInPut, 1)) >= Asc("0") And Asc(Right(strInPut, 1)) <= Asc("9")) Or Len(strInPut) = 1 Then
        cutRight = strInPut
        Exit Function
    End If



    Do While Not (Asc(Right(strInPut, 1)) >= Asc("0") And Asc(Right(strInPut, 1)) <= Asc("9"))
        strInPut = Left(strInPut, Len(strInPut) - 1)
    Loop
    cutRight = strInPut
End Function

<think>我们之前在讨论微信云开发中实现订单添加功能,现在用户询问的是“如何实现订单号功能”。从引用内容来看,用户可能关注的是在微信支付场景下如何生成和管理订单号(用于支付的商户订单号outTradeNo)。结合之前的上下文和引用材料,我们需要解释订单号的生成方式及其重要性。 订单号(通常称为商户订单号out_trade_no)是商户系统内部用于唯一标识一笔订单的字符串,在微信支付等场景中必须确保唯一性。根据微信支付官方要求,订单号必须满足: 1. 在同一个商户号下唯一 2. 长度在6到32个字符之间 3. 只能包含字母、数字或下划线(即符合正则表达式:`[a-zA-Z0-9_]{6,32}`) 在微信云开发中,生成订单号的常见方法有以下几种: 方法一:使用云数据库自动生成的_id(但注意:微信支付要求订单号只能由数字、字母、下划线组成,而云数据库默认的_id是包含特殊字符的,所以需要转换) 方法二:自定义生成规则(通常采用时间戳+随机数的方式) 下面我们具体说明两种实现方案: ### 方案一:使用云数据库自动生成的_id(推荐) 虽然云数据库的_id默认是ObjectId类型(如:"5f1c7a8e8f9a6d0001a1b1c1"),我们可以将其转换为字符串,但是微信支付要求订单号只能由字母、数字、下划线组成,而ObjectId的字符串形式恰好符合(只包含0-9和a-f的十六进制字符),所以可以直接使用。但是要注意,ObjectId的长度固定为24个字符(在微信支付要求的6-32个字符范围内),因此可以直接使用。 示例代码(在云函数中生成订单并获取_id): ```javascript // 在云函数中 const db = cloud.database() // 添加一个订单记录,此时会生成一个_id const res = await db.collection('orders').add({ data: { // 订单的其他字段... status: 'unpaid', totalFee: 100, // 单位:分 createdAt: db.serverDate() } }) // 获取生成的_id作为商户订单号 const outTradeNo = res._id ``` 然后,在调用微信支付接口时,使用这个`outTradeNo`作为商户订单号。 ### 方案二:自定义生成规则 如果我们不想使用数据库自动生成的_id,可以自己生成一个符合要求的订单号。常用的方法是: 当前时间戳(精确到毫秒) + 随机数(防止同一毫秒内重复) 示例代码: ```javascript // 生成订单号函数(云函数或小程序端) function generateOrderNo() { const date = new Date() const timePart = date.getTime().toString() // 时间戳,13位 const randomPart = Math.floor(Math.random() * 1000).toString().padStart(3, '0') // 3位随机数 return timePart + randomPart // 共16位,符合要求 } ``` 注意:这样生成的订单号长度是16位(13位时间戳+3位随机数),在6-32位之间。 但是,这种方法有可能重复(尽管概率极低),所以我们在将订单写入数据库时,可以先查询一下是否已经存在相同的订单号。为了避免重复,我们可以使用云数据库的唯一索引。 ### 为订单号字段添加唯一索引 1. 在云开发控制台,打开orders集合。 2. 在索引管理中添加索引,选择订单号字段(例如outTradeNo),设置为唯一索引。 这样,如果插入重复的订单号,数据库会报错,我们可以在代码中捕获这个错误并重新生成。 ### 在支付云函数中使用自定义订单号 结合上面的生成函数,在云函数中创建订单并调用支付: ```javascript const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() exports.main = async (event, context) => { const wxContext = cloud.getWXContext() let outTradeNo = generateOrderNo() // 生成订单号 // 先尝试写入订单,如果遇到重复则重新生成(最多尝试3次) let attempts = 0 while (attempts < 3) { try { const res = await db.collection('orders').add({ data: { outTradeNo: outTradeNo, // 使用自定义订单号 totalFee: event.totalFee, // 单位:分 status: 'unpaid', openid: wxContext.OPENID, createdAt: db.serverDate() } }) // 写入成功,跳出循环 break } catch (error) { if (error.errCode === -502 && error.errMsg.includes('duplicate key')) { // 如果是订单号重复,重新生成 attempts++ outTradeNo = generateOrderNo() } else { // 其他错误直接抛出 throw error } } } if (attempts >= 3) { throw new Error('生成订单号失败,请重试') } // 然后调用微信支付统一下单接口,使用outTradeNo作为商户订单号 // ... (支付逻辑,可参考引用[3][4]) } ``` ### 注意事项 1. **订单号的重要性**:在支付场景中,订单号用于唯一标识一笔支付交易,必须确保在商户号下唯一,否则微信支付接口会返回错误。 2. **订单状态管理**:在订单创建时初始状态设为'unpaid'(待支付),在支付成功回调中更新为'paid'(已支付)。 3. **订单号存储**:在云数据库的订单集合中,建议将订单号(outTradeNo)作为一个字段存储,以便后续查询和更新。 以上两种方法各有优劣: - 方法一(使用数据库_id)简单可靠,无需担心重复,但_id较长(24位)。 - 方法二(自定义)可以生成更短或更有业务含义的订单号,但需要处理可能的重复问题。 根据实际业务需求选择即可。 ### 支付回调处理 在支付成功后,微信支付会回调我们在统一下单时设置的回调地址(云函数URL),我们在回调云函数中需要根据商户订单号(outTradeNo)更新订单状态。 回调云函数示例: ```javascript // 支付回调云函数 const cloud = require('wx-server-sdk') cloud.init() const db = cloud.database() exports.main = async (event, context) => { // 验证微信支付回调的签名(此处省略,需要使用微信支付APIv3的验证方法) // ... // 解析回调数据,获取商户订单号 const outTradeNo = event.outTradeNo // 根据商户订单号更新订单状态 await db.collection('orders').where({ outTradeNo: outTradeNo }).update({ data: { status: 'paid', paidTime: db.serverDate() } }) return 'SUCCESS' // 返回给微信支付 } ``` 关于微信支付回调的详细处理,请参考微信支付官方文档[^3][^4]。 以上就是在微信云开发中实现订单号功能的方法。 §§相关问题§§ 1. 微信云开发中如何保证订单号的唯一性? 2. 微信支付回调处理需要注意哪些安全问题? 3. 如何设计订单状态流转(如待支付、已支付、已发货等)? </think>在微信云开发中实现订单号功能,确保唯一性和可追溯性是核心目标。以下是几种实用方法和实现步骤: ### 一、订单号生成策略 1. **时间戳+随机数法**(推荐) ```javascript // 云函数中生成订单号 function generateOrderNo() { const date = new Date(); const timePart = date.getTime().toString(); // 13位时间戳 const randomPart = Math.floor(Math.random() * 10000).toString().padStart(4, '0'); return `ORD${timePart}${randomPart}`; // 示例:ORD16911345678901234 } ``` 2. **数据库自增ID法** ```javascript // 使用计数器集合实现自增ID const db = cloud.database() const _ = db.command async function getAutoIncrementId() { const res = await db.collection('counters').doc('order_id') .update({ data: { seq: _.inc(1) } }) return res.updated ? `ORD${res.seq.toString().padStart(10, '0')}` : null; } ``` 3. **哈希算法生成** ```javascript // 生成唯一哈希值 const crypto = require('crypto'); function generateHashOrderNo(userId) { const hash = crypto.createHash('sha256') .update(userId + Date.now().toString()) .digest('hex'); return `HASH${hash.substring(0, 16)}`; // 前16位 } ``` ### 二、支付场景下的订单号集成 **在支付云函数中使用订单号**(参考引用[3][4]): ```javascript // 支付云函数 const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db = cloud.database() exports.main = async (event) => { const { totalFee, productInfo } = event const wxContext = cloud.getWXContext() // 生成订单号 const orderNo = generateOrderNo() // 使用上述生成方法 // 创建订单记录 await db.collection('orders').add({ data: { orderNo, // 关键字段 totalFee, productInfo, openid: wxContext.OPENID, status: 'UNPAID', createTime: db.serverDate() } }) // 调用支付API(引用[3][4]) const tenpay = require('tenpay') const config = { appid: wxContext.APPID, mchid: '商户号', partnerKey: '微信支付密钥' } const api = new tenpay(config) return api.getPayParams({ out_trade_no: orderNo, // 使用生成的订单号 body: '商品描述', total_fee: totalFee, openid: wxContext.OPENID }) } ``` ### 三、订单号使用规范 1. **字段设计原则**: | 字段名 | 类型 | 说明 | |-------------|--------|--------------------------------| | _id | String | 云数据库自动ID(非订单号) | | orderNo | String | **主业务订单号**(唯一索引) | | outTradeNo | String | 支付网关订单号(微信支付返回) | 2. **数据库优化**: ```javascript // 创建唯一索引防止重复 db.createCollection('orders', { autoIndexId: true, indexes: [{ name: 'orderNo_unique', key: { orderNo: 1 }, unique: true }] }) ``` ### 四、订单号应用场景 1. **支付回调验证**: ```javascript // 支付回调云函数 exports.main = async (event) => { const { out_trade_no } = event // 微信返回的订单号 // 根据订单号更新状态 await db.collection('orders').where({ orderNo: out_trade_no }) .update({ data: { status: 'PAID', payTime: db.serverDate() } }) } ``` 2. **订单查询优化**: ```javascript // 前端查询订单 Page({ onLoad(options) { const orderNo = options.id // 从URL参数获取订单号 db.collection('orders').where({ orderNo }).get().then(res => { this.setData({ orderDetail: res.data[0] }) }) } }) ``` ### 五、最佳实践建议 1. **长度控制**:订单号长度建议16-24位(微信限制6-32字符)[^3] 2. **前缀标识**:使用`ORD`/`PAY`等前缀区分业务类型 3. **错误处理**: ```javascript try { const orderNo = generateOrderNo() } catch(error) { // 捕获重复订单号错误 if(error.errCode === 11000) { console.error('订单号冲突', orderNo) return generateOrderNo() // 重新生成 } } ``` > 关键点:始终通过`orderNo`而非`_id`进行支付接口调用和业务流转,确保支付系统和业务系统解耦[^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值