草庐IT

java微信支付v3系列——6.微信支付查询订单API

CV大魔王 2023-08-06 原文

目录

java微信支付v3系列——1.微信支付准备工作
java微信支付v3系列——2.微信支付基本配置
java微信支付v3系列——3.订单创建准备操作
java微信支付v3系列——4.创建订单的封装及使用
java微信支付v3系列——5.微信支付成功回调
java微信支付v3系列——6.微信支付查询订单API
java微信支付v3系列——7.微信支付之申请退款
java微信支付v3系列——8.微信支付之退款成功回调
java微信支付v3系列——9.微信支付之商家转账API

正文

什么时候会用到这个API?常规情况下,回调接口已经足够我们使用,用户支付成功后,微信会自动调用我们的回调接口进行回调,那么还需要这个API吗?

使用场景:微信服务器故障,我们的服务器故障,服务器端正在进行更新导致用户付款后端没有及时接收到微信的回调请求,那么此时我们就可以让用户点击按钮“更新支付状态”,此时再来调用这个API。

来看一下下面的java对象,是不是很熟悉?没错,这个接口的返回数据和回调接口是一样的,我们直接拿来复用一下。

@Data
@Slf4j
public class WxchatCallbackSuccessData {

    /**
     * 商户订单号
     */
    private String orderId;

    /**
     * 微信支付系统生成的订单号
     */
    private String transactionId;

    /**
     * 交易状态
     * SUCCESS:支付成功
     * REFUND:转入退款
     * NOTPAY:未支付
     * CLOSED:已关闭
     * REVOKED:已撤销(付款码支付)
     * USERPAYING:用户支付中(付款码支付)
     * PAYERROR:支付失败(其他原因,如银行返回失败)
     */
    private String tradestate;

    /**
     * 支付完成时间
     */
    private Date successTime;

    /**
     * 交易类型
     * JSAPI:公众号支付
     * NATIVE:扫码支付
     * APP:APP支付
     * MICROPAY:付款码支付
     * MWEB:H5支付
     * FACEPAY:刷脸支付
     */
    private String 	tradetype;

    /**
     * 订单总金额
     */
    private BigDecimal totalMoney;


    public Date getSuccessTime() {
        return successTime;
    }

    public void setSuccessTime(String successTime) {
        // Hutool工具包的方法,自动识别一些常用格式的日期字符串
        this.successTime = DateUtil.parse(successTime);
    }
}

解析响应数据

和回调接口不同的是,我们的解析响应数据返回的不是Map集合,而是一个直接的对象,请求和创建微信订单的请求一样,我们往后放一放。

@Slf4j
public class WxPayRefundUtil {

	/**
	  * 解析响应数据
	  * @param response 发送请求成功后,返回的数据
	  * @return 微信返回的参数
	  */
	private static WxchatCallbackSuccessData resolverResponse(CloseableHttpResponse response) {
	    try {
	        // 1.获取请求码
	        int statusCode = response.getStatusLine().getStatusCode();
	        // 2.获取返回值 String 格式
	        final String bodyAsString = EntityUtils.toString(response.getEntity());
	
	        Gson gson = new Gson();
	        if (statusCode == 200) {
	            // 3.如果请求成功则解析成Map对象返回
	            HashMap<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
	
	            // 4.封装成我们需要的数据
	            WxchatCallbackSuccessData callbackData = new WxchatCallbackSuccessData();
	            callbackData.setSuccessTime(String.valueOf(resultMap.get("success_time")));
	            callbackData.setOrderId(String.valueOf(resultMap.get("out_trade_no")));
	            callbackData.setTransactionId(String.valueOf(resultMap.get("transaction_id")));
	            callbackData.setTradestate(String.valueOf(resultMap.get("trade_state")));
	            callbackData.setTradetype(String.valueOf(resultMap.get("trade_type")));
	            String amount = String.valueOf(resultMap.get("amount"));
	            HashMap<String,Object> amountMap = gson.fromJson(amount, HashMap.class);
	            String total = String.valueOf(amountMap.get("total"));
	            callbackData.setTotalMoney(new BigDecimal(total).movePointLeft(2));
	            return callbackData;
	        } else {
	            if (StringUtils.isNoneBlank(bodyAsString)) {
	                log.error("微信支付请求失败,提示信息:{}", bodyAsString);
	                // 4.请求码显示失败,则尝试获取提示信息
	                HashMap<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
	                throw new DefaultException(resultMap.get("message"));
	            }
	            log.error("微信支付请求失败,未查询到原因,提示信息:{}", response);
	            // 其他异常,微信也没有返回数据,这就需要具体排查了
	            throw new IOException("request failed");
	        }
	    } catch (Exception e) {
	        e.printStackTrace();
	        throw new DefaultException(e.getMessage());
	    } finally {
	        try {
	            response.close();
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	    }
	}
}

发送查询微信订单请求

这样有两个请求,只是url不同,其余部分是一样的,一个是根据微信支付订单号查询,另一个是根据商户订单号查询。

@Slf4j
public class WxPaySearchOrderUtil {


    /**
     * 根据微信支付系统生成的订单号查询订单详情
     * @param wxPayConfig 微信支付配置信息
     * @param transactionId 微信支付系统生成的订单号
     * @param wxPayClient 微信支付客户端请求对象
     * @return 微信订单对象
     */
    public static WxchatCallbackSuccessData searchByTransactionId(WxPayConfig wxPayConfig, String transactionId, CloseableHttpClient wxPayClient) {
        // 1.请求路径和对象
        String url = wxPayConfig.getDomain().concat("/v3/pay/transactions/id/").concat(transactionId).concat("?mchid=").concat(wxPayConfig.getMchId());
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");

        // 2.完成签名并执行请求
        CloseableHttpResponse response = null;
        try {
            response = wxPayClient.execute(httpGet);
        } catch (IOException e) {
            e.printStackTrace();
            throw new DefaultException("微信支付请求失败");
        }

        // 3.解析返回的数据
        WxchatCallbackSuccessData callbackData = resolverResponse(response);
        log.info("callbackData:{}",callbackData);
        return callbackData;
    }

    /**
     * 根据微信支付系统生成的订单号查询订单详情
     * @param wxPayConfig 微信支付配置信息
     * @param orderId 我们自己的订单id
     * @param wxPayClient 微信支付客户端请求对象
     * @return 微信订单对象
     */
    public static WxchatCallbackSuccessData searchByOrderId(WxPayConfig wxPayConfig, String orderId, CloseableHttpClient wxPayClient) {
        // 1.请求路径和对象
        String url = wxPayConfig.getDomain().concat("/v3/pay/transactions/out-trade-no/").concat(orderId).concat("?mchid=").concat(wxPayConfig.getMchId());
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");

        // 2.完成签名并执行请求
        CloseableHttpResponse response = null;
        try {
            response = wxPayClient.execute(httpGet);
        } catch (IOException e) {
            e.printStackTrace();
            throw new DefaultException("微信支付请求失败");
        }

        // 3.解析返回的数据
        WxchatCallbackSuccessData callbackData = resolverResponse(response);
        log.info("callbackData:{}",callbackData);
        return callbackData;
    }


    /**
     * 解析响应数据
     * @param response 发送请求成功后,返回的数据
     * @return 微信返回的参数
     */
    private static WxchatCallbackSuccessData resolverResponse(CloseableHttpResponse response) {
        try {
            // 1.获取请求码
            int statusCode = response.getStatusLine().getStatusCode();
            // 2.获取返回值 String 格式
            final String bodyAsString = EntityUtils.toString(response.getEntity());

            Gson gson = new Gson();
            if (statusCode == 200) {
                // 3.如果请求成功则解析成Map对象返回
                HashMap<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);

                // 4.封装成我们需要的数据
                WxchatCallbackSuccessData callbackData = new WxchatCallbackSuccessData();
                callbackData.setSuccessTime(String.valueOf(resultMap.get("success_time")));
                callbackData.setOrderId(String.valueOf(resultMap.get("out_trade_no")));
                callbackData.setTransactionId(String.valueOf(resultMap.get("transaction_id")));
                callbackData.setTradestate(String.valueOf(resultMap.get("trade_state")));
                callbackData.setTradetype(String.valueOf(resultMap.get("trade_type")));
                String amount = String.valueOf(resultMap.get("amount"));
                HashMap<String,Object> amountMap = gson.fromJson(amount, HashMap.class);
                String total = String.valueOf(amountMap.get("total"));
                callbackData.setTotalMoney(new BigDecimal(total).movePointLeft(2));
                return callbackData;
            } else {
                if (StringUtils.isNoneBlank(bodyAsString)) {
                    log.error("微信支付请求失败,提示信息:{}", bodyAsString);
                    // 4.请求码显示失败,则尝试获取提示信息
                    HashMap<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
                    throw new DefaultException(resultMap.get("message"));
                }
                log.error("微信支付请求失败,未查询到原因,提示信息:{}", response);
                // 其他异常,微信也没有返回数据,这就需要具体排查了
                throw new IOException("request failed");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new DefaultException(e.getMessage());
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

使用方法

使用方法就更简单了,基本上是无脑使用。

@Autowired
private WxPayConfig wxPayConfig;

@Autowired
private CloseableHttpClient wxPayClient;  

@ApiOperation("根据微信订单号查询订单")
@PostMapping("/search/order/transaction/{transactionId}")
public WxchatCallbackSuccessData searchByTransactionId(@PathVariable String transactionId) {
    return  WxPaySearchOrderUtil.searchByTransactionId(wxPayConfig,transactionId,wxPayClient);
}

@ApiOperation("根据商户订单号查询")
@PostMapping("/search/order/{orderId}")
public WxchatCallbackSuccessData searchByOrderId(@PathVariable String orderId) {
    return  WxPaySearchOrderUtil.searchByOrderId(wxPayConfig,orderId,wxPayClient);
}

有关java微信支付v3系列——6.微信支付查询订单API的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  3. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  6. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  7. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  8. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  9. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  10. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

随机推荐