精华内容
下载资源
问答
  • PHP生成唯一订单号

    2020-10-23 23:17:33
    主要给大家介绍了一位网友PHP生成唯一订单号的思路和示例,感觉非常不错,需要的朋友可以参考下
  • 主要为大家详细介绍了C#如何生成唯一订单号,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 本文给大家介绍的是使用C#生成唯一不重复订单号的方法,主要用到了lock锁,有需要的小伙伴可以参考下。
  • 这里介绍的是订单号或者流水号的生成,用的方法是时间戳+随机数,如果你要严谨的算法生成的订单号,请勿下载,下载前,可以看下这篇文章介绍【https://blog.csdn.net/qq_27471405/article/details/82887786】
  • 订单号生成工具类

    2018-03-29 16:56:54
    订单号生成工具类,拿来即用,方便快捷无重复。 订单号生成工具类,拿来即用,方便快捷无重复。
  • 主要介绍了java web在高并发和分布式下实现订单号生成唯一的解决方案,需要的朋友可以参考下
  • 订单号在购物过程中起到了很好的识别作用,更方便的有利于工作人员识别商品,本文介绍利用asp.net实现生成订单号
  • 该工具类是Java编写下载即可使用,该工具类中有生成各种长度的订单号,有英文数字混合的,有数字的
  • 原理:按照一定规则生成订单号后,把订单号插入数据表后,再返回给用户,由于数据表设置了主键,也就是当数据表中存在一条一样的订单号时,是无法插入到数据表中,所以即使高并发情况下,也不会出现重复订单号
  • NULL 博文链接:https://yuhuiblog695685688425687986842568269.iteye.com/blog/2428458
  • JAVA生成订单号(日期+流水号) java按日期加流水号方式生成订单号,已经测试过,可递增方式生成。
  • 高并发订单号生成工具类,TWITTER编码方式可BAIDU
  • 银联订单号永远不会重复的生成算法分析与示例。 主要讲解了java的生成算法,其他语言原理也是一样。
  • 可以使用通配符来生成订单号、密码、随机字符串等等 用js脚本来实现的,下载解压后,打开index.html. 不要用360浏览器打开
  • 订单号随机生成器

    热门讨论 2011-12-05 00:52:59
    这个程序,我是为团购商家写的一个程序,其实,里面有一个“导出”功能,我本来想优化成导出Excel功能的,但是由于团购商家没有需求,所以,我就没有去写这个功能了。需要此功能的朋友私密我
  • 订单系统设计 —— 订单号设计

    千次阅读 2020-05-14 22:51:30
    订单号特性 唯一性:每个订单号全局唯一代表一个订单; 安全性:订单号不能透露订单量、运营规模等业务信息(数据安全性); 高性能:订单号的创建成本越低越好; 扩展性:能够较好的支撑后续业务发展变大带来的分...

    一、订单号特性

    1. 唯一性必要):每个订单号全局唯一代表一个订单;
    2. 安全性必要):订单号不能透露订单量、运营规模等业务信息(数据安全性);
    3. 高性能:订单号的创建成本越低越好;
    4. 扩展性:能够较好的支撑后续业务发展变大带来的分库分表、订单长度扩展等场景;

    二、业界方案

    方案1:数据库自增ID(不推荐)

    思路: 基于数据库主键ID自增的特性生成订单号,不推荐此方案的原因有如下几点:

    1. 不安全:订单号能够反映出系统的订单量,存在业务数据外露的风险;
    2. 性能问题:需要数据库插入一条记录获取主键ID,性能受限于数据库,且存在单点;
    3. 扩展性:不利于后续的分库分表(见方案3);

    方案2:UUID(不推荐)

    思路: JDK自带UUID工具类,生成UUID足够快速、方便,业界不使用UUID作为分布式唯一ID,或者订单号的原因在于:

    1. 性能问题:在订单表中,订单号为主键或者唯一索引,UUID是无序的(36位字符串),如果作为数据库主键,在InnoDB引擎下,UUID的无序性会引起数据位置频繁变动,严重影响数据库性能;(UUID生成是很快的,作为订单号影响的是订单表的写性能)
    2. 扩展性:不利于后续的分库分表(见方案3);

    方案3:分布式唯一ID

     分布式唯一ID生成器,主要有类snowflake方案和分库分表形式的数据库自增ID方案。目前分布式唯一ID方案已经很成熟,能做到高性能、高可用、递增等。在订单场景下,主要问题在于不利于分库分表,如下图。将分布式唯一ID作为订单号不利于分库分表原因如下:

    1. 无法满足多维护查询,当查询条件中没有订单id时,会全表扫描,性能低下;(全表扫描
    2. 为了避免全表扫描,可以通过DB或者缓存存储订单号与用户ID、商户ID的映射关系,每次在用户ID和商户ID维度查询时,先通过映射关系查询到对应的订单ID,然后路由到对应的分表;(多一次查询

    在这里插入图片描述

    三、因子分表法

    3.1 方案设计

    思路: 牺牲通用性,根据订单场景将影响分库分表的业务因子融入到订单号中,比如用户id,根据订单号分库分表路由时,通过位移对业务因子取模路由即可,实现订单号和业务因子路由的一致性,如下图所示(需要哪些因子,占用几位看实际情况)。这样做的好处是:

    1. 趋势递增:时间戳在高位,利用时间的递增性,保证订单号趋势递增;
    2. 高性能:没有第三方依赖,且基本零消耗;
    3. 分库分表:分库分表因子融入到了订单号中,避免了全表扫描或者多一次查询;
    4. 唯一性:同一用户在同一店铺的同一时间内下多个单才有可能重复,对于正常用户行为是不可能出现的;
      在这里插入图片描述

      以用户的订单库为例进行说明,订单号由三部分组成:时间戳+分库分表因子+随机数。用户因子为用户ID哈希后的某10位,这样无论是按照订单ID还是用户ID查询,最终都会用户因子分库分表,从而路由的分表也会一致,如下所示:
    在这里插入图片描述

    3.2 因子分表法 VS 分布式唯一ID

    1. 分布式唯一ID是一种通用的基础服务,为各业务系统提供唯一ID,不包含任何业务属性;(通用方案
    2. 订单号是一种特殊的分布式唯一ID,为了便于业务处理,通常会结合一些业务信息来生成;(结合业务场景的个性化方案)

    参考:

    1. Leaf——美团点评分布式ID生成系统
    2. 老司机设计了一个能扛住双11并发的订单号生成方案,同事说“666”
    3. 单KEY业务,数据库水平切分架构实践 | 架构师之路
    展开全文
  • 谈谈订单号和流水号的关系

    千次阅读 2020-06-04 10:27:15
    订单号和流水号是不同的。 首先订单号是订单唯一的编号,而且电商平台的各种子系统也是根据订单来统计业务完成的情况,订单编号经常用来被查询,所以数据类型必须是数字,而且是全局唯一,那肯定就得主键字段了。 ...

    订单号和流水号是不同的。
    首先订单号是订单唯一的编号,而且电商平台的各种子系统也是根据订单来统计业务完成的情况,订单编号经常用来被查询,所以数据类型必须是数字,而且是全局唯一,那肯定就得主键字段了。

    然后流水号是打印在一般是打印在购物单据上面的,里面一般包含了订单的相关信息,方便人员阅读,比如说有的工作人员看一眼单子就知道是线上还是线下,在哪家零售店买的,或者哪家仓库给你发的货,因为流水号是一个很长的字符串,所以注定合格字段不适合用来当主键,我们设计订单表时候是那订单号作为主键的,流水号只不过是个普通的字段,也没有设计索引,下面我们来看一个具体的流水号规则,看下图:

    在这里插入图片描述

    • 第一位代表的是线上还是线下,如果是线上购物就是E,如果是线下购物那么这个字符就是S,当然这个可以随意的规定,没有人去限制你。
    • 第二部分是零售店或者仓库编号,你要结合前面的标志位,比如说S代表的是线下,所以S后面的字符就是零售店的编号
    • 第三部分就是商品的品类编号,因为我们在品类表中设计的编号是5位字符的,所以这里我就用5位字符来表示订单的品类编号。如果订单中购买的商品很多,品类还不相同怎么办?也没有关系你把其中最贵的商品的品类作为流水的品类就好了呀,流水号只是一个标示的字符串而已,没有什么大不了的
    • 第四部分是购物日期,年月日加起来是6个字符
    • 第五部分是随机数,10位字符,这是用程序动态生成的

    这五个部分加在一起,一共是28个流水号,这是我们记的流水号规则,当然了同学们也可以根据实际的业务自己设计流水号。接下来模拟生成下流水号

    public class Demo1{
    	public static String createOrder(String type,String organizationId,String spId,String date){
    		StringBuffer buffer=new StringBuffer();
    		buffer.append(type);
    		buffer.append(organizationId);
    		buffer.append(spgId);
    		buffer.append(date);
    		//java里挺好的新的生成随机数的方法
    		ThreadLocaleRandom.current().ints(0,9).limit(10).forEach((one)->{
    			buffer.append(one);
    		});
    		return buffer.toString();
    	}
    	public static void main(String [] args){
    		String code=createOrderCode("S","000012","11002","20180514");
    		System.out.println(code);
    	}
    }
    
    展开全文
  • 探索淘宝订单号生成方案

    千次阅读 2020-05-01 22:17:15
    前10位-10位随机-剩余位数-订单号-对应的自增id 问题: 1、对于qps比较高的应用step可以设置大些,这个可以通过监控更新频率去设置。 2、本方案对数据库依赖还是比较强,所以数据库不能宕机很久。

    1、方案说明

    1.1、本方案没有使用时间戳,因为加入时间戳后长度会比较长。时间戳的方案可以参考百度和美团的。

    1.2、本方案只利用分段自增的特性,在虚拟机中自增,不依赖redis,mysql等中间件的自增属性。

     

    2、实现方案

    2.1架构图

     

    2.2 算法流程说明

    1、代码中需要配置变量bit_type。

    2、集群服务启动后,通过mysql的悲观锁(for update) 各个服务先后获取段的max_id,并更新保存新的max_id。

    3、服务把号段生成数组保存在虚拟机中。

    4、采用双号段,当前号段使用超过20%,则启动线程去更新空闲的号段。

     

    2.3 设计和实现

    数据库设计

    算法

    1、每个服务先后通过数据库锁和定义的步长计算自己的起始和结束序号。

    2、把自增序列增长转换成二进制(长度要大于10位)。

    3、使用0到1023的随机数,转换为二进制,从自增的第10位开始插入。

    示例

    java算法代码

    public void test001() {
    		
    		Long  startIndex = 460000L;
    		for(int i=0;i<800000;i++) {
    			Integer f = RandomUtils.nextInt(1024);
    			String r = full(Integer.toBinaryString(f));
    			String seqString = Long.toBinaryString(startIndex+i);
    			String seqFirString = seqString.substring(0, 10);
    			String seqSeString = seqString.substring(10);
    			
    			String zString = seqFirString+r+seqSeString;
    			if(i%5123==0) {
    				System.out.println(seqFirString+"-"+r+"-"+seqSeString+"-"+Long.parseLong(zString, 2)+"-"+startIndex+i);
    			}
    		}
    	}
    	
    	/**
    	 * 填充位10位,防止少于10位
    	 * @param src
    	 * @return
    	 */
    	public String full(String src) {
    		int n = 10-src.length();
    		for(int i=0;i<n;i++) {
    			src="0"+src;
    		}
    		return src;
    	}

    运行效果

    1110000010-1011101111-011100000-471195360-4600000
    1110001100-0101000100-011100011-476219619-4600005123
    1110010110-0011001100-011100110-481401062-46000010246
    1110100000-0100111011-011101001-486700777-46000015369
    1110101010-1001010110-011101100-492088556-46000020492
    1110110100-0100010101-011101111-497167087-46000025615
    1110111110-0010101101-011110010-502356722-46000030738
    1111001000-1111111100-011110101-508033269-46000035861
    1111010010-0101001011-011111000-512923384-46000040984
    1111011100-0100100010-011111011-518145275-46000046107
    1111100110-0001011011-011111110-523286270-46000051230
    1111110000-1101111101-100000001-528939777-46000056353
    1111111010-0010010110-100000100-533802244-46000061476
    
    //格式:前10位-10位随机-剩余位数-订单号-对应的自增id

     

    问题:

    1、对于qps比较高的应用step可以设置大些,这个可以通过监控更新频率去设置。

    2、本方案对数据库依赖还是比较强,所以数据库不能宕机很久。

    展开全文
  • wxPay 微信支付「订单号重复」错误 商家的用户在平台上下了一个订单,然后使用Native支付的方式提交过一次订单(调用微信的「统一下单接口」),但是未支付,然后再切换到APP支付/小程序支付,由于在微信支付系统中,...

    1 摘要

    在项目中使用微信、支付宝等第三方支付的时候,可能会遇到各种偶然性问题,本文将记录关于接入微信支付过程中出现的订单号重复的问题

    2 问题复现

    微信支付官方文档: https://pay.weixin.qq.com/wiki/doc/api/index.html

    常用的微信支付方式包括JSAPI支付、Native支付、APP支付、小程序支付等,对于商户而言,一般都有自己的订单系统,只是支付需要外接第三方,因此商户会有自己的订单编号,一个订单对应一个订单编号,那么会出现这样的场景,商家的用户在平台上下了一个订单,然后使用Native支付的方式提交过一次订单(调用微信的「统一下单接口」),但是未支付,然后再切换到APP支付/小程序支付,由于在微信支付系统中,一个商户的同一个订单号只能选择一种支付方式提交,当这个订单第二次使用不同的方式进行提交时便会出现「订单号重复」的错误

    此时如果依旧使用原来的支付方式进行提交,则可以成功,但是切换到其他支付方式,就会返回「订单号重复」的错误

    支付宝支付没有这种现象

    3 解决办法

    3.1 解决思路

    将微信支付的每一种支付方式使用一个常量进行标识,在调用微信「统一下单」接口时,将商户自身系统的订单号后边追加支付方式标识,即:

    微信「统一下单」订单号 = 商户订单号 + 微信支付方式标识
    

    在微信支付回调时,将获取到的微信「统一下单」订单号还原到商户系统的订单号,然后再进行操作

    这样,即使同一个订单通过不同的不同的微信支付方式进行提交,也不会再出现「订单号重复」的错误了(当然,每一次提交订单时也不要忘了校验订单是否已经支付/取消等等)

    3.2 核心代码

    支付方式标识常量

    ./src/main/java/com/ljq/demo/pay/common/constant/PayTypeConst.java
    
    package com.ljq.demo.pay.common.constant;
    
    /**
     * @Description: 支付方式常量
     * @Author: junqiang.lu
     * @Date: 2019/4/17
     */
    public class PayTypeConst{
    
        /**
         * 支付方式
         * 1 : 支付宝支付数字标识
         * 11: 支付宝电脑网站支付
         * 12: 支付宝手机网站支付
         * 13: 支付宝 APP 支付
         * AliPay: 支付宝支付文字说明
         *
         * 2: 微信支付标识
         * 21: 微信 NATIVE 支付(二维码支付)
         * 22: 微信 JSAPI 支付
         * 23: 微信 H5 支付
         * 24: 微信 APP 支付
         * WxPay: 微信支付文字说明
         */
        public static final int ORDER_PAY_TYPE_ALIPAY = 1;
        public static final int ORDER_PAY_TYPE_ALIPAY_PC = 11;
        public static final int ORDER_PAY_TYPE_ALIPAY_WAP = 12;
        public static final int ORDER_PAY_TYPE_ALIPAY_APP = 13;
        public static final String ORDER_PAY_TYPE_ALIPAY_NOTE = "AliPay";
        public static final int ORDER_PAY_TYPE_WX = 2;
        public static final int ORDER_PAY_TYPE_WX_NATIVE = 21;
        public static final int ORDER_PAY_TYPE_WX_JSAPI = 22;
        public static final int ORDER_PAY_TYPE_WX_H5 = 23;
        public static final int ORDER_PAY_TYPE_WX_APP = 24;
        public static final String ORDER_PAY_TYPE_WX_NOTE = "WxPay";
    
    }
    
    

    订单支付业务层示例

    ./src/main/java/com/ljq/demo/pay/service/impl/PayServiceImpl.java
    
    package com.ljq.demo.pay.service.impl;
    
    import com.alipay.api.AlipayApiException;
    import com.alipay.api.internal.util.AlipaySignature;
    import com.ljq.demo.pay.bean.PayBean;
    import com.ljq.demo.pay.common.api.ApiResult;
    import com.ljq.demo.pay.common.api.ResponseCode;
    import com.ljq.demo.pay.common.constant.PayTypeConst;
    import com.ljq.demo.pay.common.util.*;
    import com.ljq.demo.pay.configure.AliPayConfig;
    import com.ljq.demo.pay.configure.WxPayConfig;
    import com.ljq.demo.pay.service.PayService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Objects;
    
    /**
     * @Description: 支付业务具体实现
     * @Author: junqiang.lu
     * @Date: 2018/7/10
     */
    @Service("payService")
    @Slf4j
    public class PayServiceImpl implements PayService {
    
        @Autowired
        private WxPayConfig wxPayConfig;
        @Autowired
        private AliPayConfig aliPayConfig;
    
    
        /**
         * 创建支付订单
         *
         * @param payBean json 格式参数
         * @return
         */
        @Override
        public ApiResult createPayOrder(PayBean payBean) throws Exception {
            // 微信支付金额换算
            int amountWxPay = CalculateUtil.multiply(Double.valueOf(payBean.getAmount()), 100, 2).intValue();
            // 返回结果
            Map<String, String> resultMap = new HashMap<>(16);
            // 创建支付订单
            switch (payBean.getPayType()) {
                case PayTypeConst.ORDER_PAY_TYPE_ALIPAY_PC:
                    // 支付宝电脑网站支付
                    String aliPayPCForm = AliPayManager.createPCOrder(payBean.getOrderNo(),
                            String.valueOf(payBean.getAmount()), aliPayConfig);
                    if (!StringUtils.isEmpty(aliPayPCForm)) {
                        resultMap.put("prePayOrderInfo",aliPayPCForm);
                        return ApiResult.success(resultMap);
                    }
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_ALIPAY_WAP:
                    // 支付宝手机网站支付
                    String aliPayWapForm = AliPayManager.createWapOrder(payBean.getOrderNo(),
                            String.valueOf(payBean.getAmount()), aliPayConfig);
                    if (!StringUtils.isEmpty(aliPayWapForm)) {
                        resultMap.put("prePayOrderInfo",aliPayWapForm);
                        return ApiResult.success(resultMap);
                    }
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_ALIPAY_APP:
                    // 支付宝 APP 支付
                    String aliPayAppForm = AliPayManager.createAppOrder(payBean.getOrderNo(),
                            String.valueOf(payBean.getAmount()), aliPayConfig);
                    if (!StringUtils.isEmpty(aliPayAppForm)) {
                        resultMap.put("prePayOrderInfo",aliPayAppForm);
                        return ApiResult.success(resultMap);
                    }
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_WX_NATIVE:
                    // 微信 NATIVE 支付(二维码)
                    Map<String,String> wxPayNativeMap = WxPayManager.createNativeOrder(wxPayConfig,
                            payBean.getOrderNo() + PayTypeConst.ORDER_PAY_TYPE_WX_NATIVE,
                            amountWxPay, payBean.getIp());
                    if (wxPayNativeMap != null &&
                            Objects.equals(wxPayNativeMap.get("pre_pay_order_status"), wxPayConfig.getResponseSuccess())) {
                        resultMap.put("prePayOrderInfo",wxPayNativeMap.get("code_url"));
                        return ApiResult.success(resultMap);
                    }
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_WX_JSAPI:
                    // 微信 JsAPI 支付(公众号)
                    if (StringUtils.isEmpty(payBean.getOpenId())) {
                        return ApiResult.failure(ResponseCode.PAY_SUBMIT_ERROR);
                    }
                    Map<String, String> wxPayJsAPIMap = WxPayManager.createJsAPIOrder(wxPayConfig,
                            payBean.getOrderNo() + PayTypeConst.ORDER_PAY_TYPE_WX_JSAPI,
                            amountWxPay, payBean.getIp(), payBean.getOpenId());
                    if (wxPayJsAPIMap != null &&
                            Objects.equals(wxPayJsAPIMap.get("pre_pay_order_status"), wxPayConfig.getResponseSuccess())) {
                        return ApiResult.success(wxPayJsAPIMap);
                    }
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_WX_H5:
                    // 微信 H5 支付
                    Map<String, String> wxPayH5Map = WxPayManager.createH5Order(wxPayConfig,
                            payBean.getOrderNo() + PayTypeConst.ORDER_PAY_TYPE_WX_H5,
                            amountWxPay, payBean.getIp());
                    if (wxPayH5Map != null &&
                            Objects.equals(wxPayH5Map.get("pre_pay_order_status"), wxPayConfig.getResponseSuccess())) {
                        resultMap.put("prePayOrderInfo",wxPayH5Map.get("mweb_url"));
                        return ApiResult.success(resultMap);
                    }
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_WX_APP:
                    // 微信 APP 支付
                    Map<String, String> wxPayAppMap = WxPayManager.createAppOrder(wxPayConfig,
                            payBean.getOrderNo() + PayTypeConst.ORDER_PAY_TYPE_WX_APP,
                            amountWxPay, payBean.getIp());
                    if (wxPayAppMap != null &&
                            Objects.equals(wxPayAppMap.get("pre_pay_order_status"), wxPayConfig.getResponseSuccess())) {
                        return ApiResult.success(wxPayAppMap);
                    }
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_WX_MINI:
                    // 微信 小程序 支付
                    if (StringUtils.isEmpty(payBean.getOpenId())) {
                        return ApiResult.failure(ResponseCode.PAY_SUBMIT_ERROR);
                    }
                    Map<String, String> wxPayMiniMap = WxPayManager.createJsAPIOrder(wxPayConfig,
                            payBean.getOrderNo() + PayTypeConst.ORDER_PAY_TYPE_WX_MINI,
                            amountWxPay, payBean.getIp(), payBean.getOpenId());
                    if (wxPayMiniMap != null &&
                            Objects.equals(wxPayMiniMap.get("pre_pay_order_status"), wxPayConfig.getResponseSuccess())) {
                        return ApiResult.success(wxPayMiniMap);
                    }
                    break;
                default:
                    return ApiResult.failure(ResponseCode.PAY_TYPE_ERROR);
            }
            return ApiResult.failure(ResponseCode.PAY_SUBMIT_ERROR);
        }
    
        /**
         * (主动)获取支付结果
         *
         * @param payBean 订单信息(json 格式参数)
         * @return
         */
        @Override
        public ApiResult getPayResult(PayBean payBean) throws Exception {
            // 返回结果
            Map<String, String> resultMap;
            switch (payBean.getPayType()) {
                case PayTypeConst.ORDER_PAY_TYPE_ALIPAY_PC:
                case PayTypeConst.ORDER_PAY_TYPE_ALIPAY_WAP:
                case PayTypeConst.ORDER_PAY_TYPE_ALIPAY_APP:
                    resultMap = AliPayManager.getPayResult(aliPayConfig, payBean.getOrderNo());
                    break;
                case PayTypeConst.ORDER_PAY_TYPE_WX_NATIVE:
                case PayTypeConst.ORDER_PAY_TYPE_WX_JSAPI:
                case PayTypeConst.ORDER_PAY_TYPE_WX_H5:
                case PayTypeConst.ORDER_PAY_TYPE_WX_APP:
                case PayTypeConst.ORDER_PAY_TYPE_WX_MINI:
                    resultMap = WxPayManager.getPayResult(wxPayConfig, payBean.getOrderNo() + payBean.getPayType());
                    break;
                default:
                    return ApiResult.failure(ResponseCode.PAY_TYPE_ERROR);
            }
            if (MapUtil.isEmpty(resultMap)) {
                return ApiResult.failure(ResponseCode.PAY_STATUS_ERROR);
            }
    
            return ApiResult.success(resultMap);
        }
    
        /**
         * 微信支付结果通知
         *
         * @param request 微信支付回调请求
         * @return 支付结果
         */
        @Override
        public String wxPayNotify(HttpServletRequest request) {
    
            String result = null;
            try {
                InputStream inputStream = request.getInputStream();
                /**
                 * 读取通知参数
                 */
                String strXML = FileUtil.getStringFromStream(inputStream);
                Map<String,String> reqMap = MapUtil.xml2Map(strXML);
                if(MapUtil.isEmpty(reqMap)){
                    log.warn("request param is null");
                    return wxPayConfig.getResponseFail();
                }
                /**
                 * 校验签名
                 */
                if(!SignUtil.signValidate(reqMap, wxPayConfig.getKey(), wxPayConfig.getFieldSign())){
                    log.warn("wxPay sign is error");
                    return wxPayConfig.getResponseFail();
                }
                String orderNo = reqMap.get("out_trade_no").substring(0,reqMap.get("out_trade_no").length()-2);
                log.debug("微信支付回调,订单编号: {}", orderNo);
                // TODO 其他业务处理
    
    
                Map<String, String> resultMap = new HashMap<>(16);
                resultMap.put("return_code",wxPayConfig.getResponseSuccess());
                resultMap.put("return_msg","OK");
                result = MapUtil.map2Xml(resultMap);
            } catch (IOException e) {
                log.error("get request inputStream error",e);
                return wxPayConfig.getResponseFail();
            } catch (Exception e) {
                log.error("resolve request param error",e);
                return wxPayConfig.getResponseFail();
            }
            return result;
        }
    
        /**
         * 支付宝支付结果通知
         *
         * @param request 支付宝回调请求
         * @return
         */
        @Override
        public String aliPayNotify(HttpServletRequest request) {
            // 读取通知参数
            Map<String, String> params = AliPayManager.getNotifyParams(request.getParameterMap());
            if(MapUtil.isEmpty(params)){
                return aliPayConfig.getResponseFail();
            }
            try {
                // 签名校验
                if(!AlipaySignature.rsaCheckV1(params, aliPayConfig.getAlipayPublicKey(),
                        aliPayConfig.getCharset(), aliPayConfig.getSignType())){
                    return aliPayConfig.getResponseFail();
                }
                String orderNo = params.get("out_trade_no");
                log.debug("支付宝回调,订单编号: {}",orderNo);
                // TODO 其他业务处理
    
    
    
            } catch (AlipayApiException e) {
                log.error("支付宝回调验证失败",e);
                return aliPayConfig.getResponseFail();
            }
            return aliPayConfig.getResponseSuccess();
        }
    
        /**
         * 支付宝支付同步通知返回地址
         * @param request
         * @return
         */
        @Override
        public String aliPayReturnUrl(HttpServletRequest request) {
            // 读取通知参数
            Map<String, String> params = AliPayManager.getNotifyParams(request.getParameterMap());
            if(MapUtil.isEmpty(params)){
                return "alipay_fail_url";
            }
            try {
                // 签名校验
                if(!AlipaySignature.rsaCheckV1(params, aliPayConfig.getAlipayPublicKey(),
                        aliPayConfig.getCharset(), aliPayConfig.getSignType())){
                    return "alipay_fail_url";
                }
    
            } catch (AlipayApiException e) {
                log.error("支付宝回调验证失败",e);
                return aliPayConfig.getResponseFail();
            }
            return "alipay_success_url";
        }
    
    }
    
    

    3.3 Github项目源码

    GitHub项目源码: https://github.com/Flying9001/pay

    个人公众号:404Code,记录半个互联网人的技术与思考,感兴趣的可以关注.
    404Code

    展开全文
  • 订单号生成策略

    千次阅读 2019-07-10 11:49:45
    * 订单号生成工具列,生成20位数字编码 * 生成规则:单号类型1位 + 15位时间戳 + 用户id后4位 + 随机数4位 * @author junzhongliu * @date 2018/9/30 11:52 */ public class OrderNoUtil { /** * 取商品id...
  • 订单号的生成

    千次阅读 2019-03-21 10:44:04
    订单号生成的原则: 1.全局的唯一性 2.自增长 3.长度的要求 4.具有一定的可读性 5.保密,不可推测性 6.效率性 二.实现方案 常见的ID生成策略。 1. 数据库自增长序列或字段 2. UUID 3. UUID的变种*【UUID to ...
  • * @Title: 订单号生成 * @ClassName:OrderIdUtils.java * @Description: * * @Copyright 2016-2017 - Powered By 研发中心 * @author: 王延飞 * @date:2018年3月22日 下午7:43:30 * @version V1.0 */ ...
  • 这篇博客主要向大家介绍订单号的生成方式...订单是整个电子商务的核心。整个电子商务的流程也是围绕订单的状态执行的。这篇博客主要向大家介绍订单号的生成方式。现在大型电商网站大多都有好几种下单途径。 比如:...
  • JS生成订单号

    千次阅读 2019-09-09 10:33:02
    本文主要两种js实现订单号的生成。 一、时间戳+6位随机数的订单号 function orderCode() { var orderCode=''; for (var i = 0; i < 6; i++) //6位随机数,用以加在时间戳后面。 { orderCode += Math.floor...
  • ,并许诺给你股份若干,你想想首付也攒了好久,就差200万就够了,于是就同意了,你花了一个星期做了一个网站并上线运营,订单号格式如下:日期+6位自增数字例如:20160301000001201603010000022016...
  • Redis生成订单号

    千次阅读 2018-08-06 16:09:51
    订单号:业务类型+yyyyMMddHHmmss+ 6位流水号。 业务类型为任意2个英文字母,HHmmss为redis服务器的时间,6位流水号从1开始自增。 KEY1:包名+业务类型+yyyyMMdd,48h过期 KEY2:包名+HHmmss,这里设置KEY2是为了防止...
  • MySQL高并发生成唯一订单号的方法

    万次阅读 多人点赞 2020-06-12 09:24:59
    你还不知道怎么高并发生成唯一订单号吗?史上最直白的小白教程,你确定不来康康吗?
  • C# 生成唯一订单号

    千次阅读 2018-08-31 11:21:09
    根据GUID+DateTime.Now.Ticks生产唯一订单号。  /// &lt;summary&gt; /// 生成唯一数  /// &lt;/summary&gt;  public class UniqueData  {  private static object obj = new object();  ...
  • PHP生成订单号算法

    千次阅读 2018-08-15 16:20:45
    PHP生成订单号算法 ... 首先,订单号不适合用自增字段,因为会暴露一个网站的业务量(参见“德国坦克问题” ...另外,通常在订单在写入数据库之前,业务就需要用到订单号了。 网上多数用microtim...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 154,608
精华内容 61,843
关键字:

订单号