精华内容
下载资源
问答
  • 因为用的是第三方封装的微信支付jar,所以通过捕获其异常,如果是订单号重复,那么就重新生成订单号再次下单。 雪花算法 不过try-catch来处理,每次下单也是需要耗费时间的 于是参考了雪花算法,据说只要是时间不...

    问题

    今天系统突然出现订单号重复的问题,但通过日志观察,并没发现订单号有重复的(使用redis的incr生成),于是猜测可能是之前测试的时候用过这些订单号,但未支付的订单在商户上也查不到,所以最终只能通过代码的方式来处理。


    处理

    因为用的是第三方封装的微信支付jar,所以通过捕获其异常,如果是订单号重复,那么就重新生成订单号再次下单。


    雪花算法

    不过try-catch来处理,每次下单也是需要耗费时间的
    于是参考了雪花算法,据说只要是时间不回溯,编号就不会重复,可以看看这篇文章,感觉还不错

    • 个人理解

    一个long(64bit),由几部分组成
    1bit(符号位)
    41bit(毫秒数)
    10bit(机器标识[机房id + 机器id 或跟业务相关的id])
    12bit(序列号[如果1ms进入多个请求就根据这个来区别])
    由上可知主导还是时间,只要时间不回去的话,重复的概率还是很低的,而且这个生成不依赖于数据库(我是依赖于redis),方便

    展开全文
  • 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

    展开全文
  • 但是再次支付时,微信接口返回“201 商户订单号重复”的错误提示。 解决办法:待支付的订单号(即商户订单号,out_trade_no),再次支付时,务必保持商品描述字段和上次请求的内容完全一致。 ...

    iOS上调用微信支付,遇到了一个奇怪的问题:

    场景:使用微信支付,在微信支付界面,由于余额不足等原因,没有进行支付并关闭了支付页面,此时订单状态为“待支付”,从业务角度来说,应该允许用户继续支付。但是再次支付时,微信接口返回“201 商户订单号重复”的错误提示。

    解决办法:待支付的订单号(即商户订单号,out_trade_no),再次支付时,务必保持商品描述字段和上次请求的内容完全一致。
    另外,如果价格改变,也不能重复提交,只能重新生成订单号,重新向微信发起支付请求

    另附找到的一篇微信支付常见错误的文章
    

    这里写图片描述

    展开全文
  • 微信支付接口 订单号重复

    千次阅读 2015-09-15 20:39:47
    前面测试发送没有提示这个,但是后面,我加了个字段。然后就提示重复了。那应该是他判断附加属性不同,但是订单号一样,估计就算做重复了。如果附加属性一样,估计就没问题。瞎猜的

    前面测试发送没有提示这个,但是后面,我加了个字段。然后就提示重复了。那应该是他判断附加属性不同,但是订单号一样,估计就算做重复了。如果附加属性一样,估计就没问题。瞎猜的


    测试了一下。如果订单号不改,但是改了钱。订单号确实算作重复了。。

    展开全文
  • 用户点多次支付,提示商品订单号重复,导致同一下单失败。如何避免这样的问题。
  • 微信支付 201商户订单号重复 问题

    千次阅读 2019-12-06 10:38:53
    最近做电商项目,在用户第一次下单后,取消了支付,此时订单是待付款的状态,如果用户此时修改了订单的地址,导致订单的价格或者其他的信息变了,然后再次点击付款的话,此时微信官方会返回“201 商户订单号重复”。...
  • 微信支付报201商户订单号重复问题

    千次阅读 2019-04-12 15:34:34
    微信支付报201商户订单号重复问题 问题描述:   用户在PC端使用扫码支付(微信NATIVE支付方式)生成一个微信支付预订单后,为对该订单立即完成支付;用户打开手机APP后看到该订单状态为未支付,点击立即支付,此时...
  • 参考:微信支付出现OUT_TRADE_NO_USED:商户订单号重复 场景:使用微信支付,在微信支付界面,由于余额不足等原因,没有进行支付并关闭了支付页面,此时订单状态为“待支付”,从业务角度来说,应该允许用户继续支付...
  • 微信支付:商户订单号重复

    万次阅读 2016-06-15 14:02:10
    微信同一下单接口,返回值中有 原因是:这个订单号的金额变动之后又提交了一次,价格的不同引起的。
  • 微信支付错误:201 商户订单号重复 微信扫码支付中如果客户第一次生成了支付二维码,但是没有支付,后来再次过来点击支付,出现这个问题。 解决方法:如果你的订单号,body,detail,attach等这些都没错的情况下检查...
  • 这时,订单已经生成,订单状态为“待支付”,当用户继续支付时,微信报出了“201 商户订单号重复”错误。问题原因:第一次支付失败、取消支付,再次支付时,前端将商品描述(body)字段的值改变了,造成了该问题。像...
  • 微信支付错误:商户订单号重复

    千次阅读 2019-10-10 16:26:31
    支付订单号,是保存在单独的支付表中。每次发起支付,都是插入支付表,返回一个新的自增ID作为支付订单号。不可能存在重复的问题。 原因是测试环境。测试环境测试过支付,使用的也是自增ID。测试支付比较多,多次...
  • 微信支付有2个步骤: ...则会提醒201商户订单号重复. 如果订单号,内容总价都一样, 微信会检查是否已经成功支付,会提醒订单已支付,防止重复支付。 如果未支付,则弹出支付界面。未支付的订单可以多次预...
  • 去后台看了看报错, 是这个样子的 ...[CDATA[201 商户订单号重复]]> ...信息是从微信发过来的,就是在微信重复了 ...那么,可以得出,微信有这个订单了. ...微信就会返回这个商户订单号重复的错误  
  • 本文实例为大家分享了java微信支付之关闭订单的具体代码,供大家参考,具体内容如下一、应用场景商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付系统下单后,用户支付超时,系统...
  • 官方文档一、应用场景商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口注意:订单生成后不能马上调用关...
  • 然后请求统一下单接口,返回商城订单号重复。 我需要关闭当前订单重新生成订单吗? 已支付过或已调用关单、撤销(请见后文的API列表)的订单号不能重新发起支付。 我还看到,微信API里面有个接口。撤销订单API接口:...
  • 本文实例为大家分享了java微信支付之关闭订单的具体代码,供大家参考,具体内容如下官方文档一、应用场景商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付系统下单后,用户支付超时...
  • 本文实例为大家分享了java微信支付之关闭订单的具体代码,供大家参考,具体内容如下一、应用场景商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付系统下单后,用户支付超时,系统...
  • 微信支付踩坑记录

    2019-10-10 08:54:05
    微信支付错误:201 商户订单号重复 场景:使用微信支付,在微信支付界面,由于余额不足等原因,没有进行支付并关闭了支付页面,此时订单状态为“待支付”,从业务角度来说,应该允许用户继续支付。但是再次支付时,...
  • 一、应用场景商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口注意:订单生成后不能马上调用关单接口,...
  • 订单号是唯一的,所以可以根据订单号查找重复订单(重复订单会被标出),查重步骤 如下: 1.首先把1.xls后台的账单订单号,即为订单号1; 2.由于微信后台支付账单和自己后台的账单格式不同,先转成统一格式; ...
  • 当在微信外(H5支付)支付订单时 未支付退出后 再到微信内(JSAPI支付)支付同一订单 会支付不成功 报错:201 请勿重复下单(反之一样) 解决: 在调用统一下单接口给$out_trade_no形参时 给它加上区别字符 如 : (H5支付)...
  • 无论采取模式一还是模式二,进行预支付ID获取的时候应当确保订单号的唯一性,否则就会造成第二次扫码后的重复提醒. 解决方案: 以预支付ID处理为例: 商城: 1.创建log_id数据表如:out_trade_no,time 2.发起预...

空空如也

空空如也

1 2 3 4 5
收藏数 87
精华内容 34
关键字:

微信支付订单号重复