目录

开篇介绍

一、微信支付-Maven依赖加入和代码参数准备

二、商户私钥证书代码读取

三、微信订单支付系列接口URL配置

四、快速验证统一下单接口

五、查询订单支付状态验证

六、关闭订单状态验证

七、微信支付-SDK自动完成支付签名流程解读

八、微信支付的退款注意事项

九、微信支付退款验证

​​十、查询退款结果


开篇介绍:

本文介绍微信支付中的Native支付方式,版本是APIv3,其中Native和JSAPI的区别如下
Native支付:商家在系统中按微信支付协议生成支付二维码,用户扫码拉起微信收银台,确认并完成付款
JSAPI支付:商家张贴收款码物料,用户打开扫一扫,扫码后输入金额,完成付款
以下博文没有掺杂过多业务逻辑,对象数据都是固定写的,方便将注意力集中在微信支付的接口使用上。正式对接到项目里面,只需要改动支付的部分业务参数即可。

微信支付的文档还是很详细的,建议多看几遍,以下博文也都是根据官方文档的描述来操作的。

注意:微信支付个人无法对接操作,需要有公司商户账号,一般开发过程中是产品经理或者相关负责人提供。

微信支付接入指引 - 微信支付商户平台微信支付接入指引介绍了线下场所、公众号、小程序、PC网站、APP、企业微信等经营场景如何快速开通微信支付,实现商家在各类交易场景中用微信支付快速收款的需求。https://pay.weixin.qq.com/static/applyment_guide/applyment_index.shtml

一、微信支付-Maven依赖加入和代码参数准备

第一步application.properties:

#商户号
pay.wechat.mch-id=160164xxxx
#公众号id 需要和商户号绑定
pay.wechat.wx-pay-appid=wx5beac15xxxxx
#商户证书序列号,需要和证书对应
pay.wechat.mch-serial-no=7064ADC5FE84CA2A3Dxxxxxxxx
#api密钥
pay.wechat.api-v3-key=peYcTwRF581UOdaUqoxxxxxxx

#商户私钥路径(微信服务端会根据证书序列号,找到证书获取公钥进行解密数据)
pay.wechat.private-key-path=classpath:/cert/apiclient_key.pem
#支付成功页面跳转
pay.wechat.success-return-url=https://baidu.com
#支付成功,回调通知
pay.wechat.callback-url=http://api.xxx.com/shop-server/api/callback/order/v1/wechat

第二步:证书配置加入

 第三步:

Maven依赖加入
    微信支付API v3的Apache HttpClient扩展,实现了请求签名的生成和应答签名的验证。
    使用说明 https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient

 <!--微信支付扩展包-->
<dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-apache-httpclient</artifactId><version>0.3.0</version>
</dependency>

第四步 第一步骤的配置读取:

package net.wnn.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "pay.wechat")
public class WechatPayConfig {/*** 商户号*/private String mchId;/*** 公众号id 需要和商户号绑定*/private String wxPayAppid;/*** 商户证书序列号,需要和证书对应*/private String mchSerialNo;/*** API V3密钥*/private String apiV3Key;/*** 商户私钥路径(微信服务端会根据证书序列号,找到证书获取公钥进行解密数据)*/private String privateKeyPath;/*** 支付成功页面跳转*/private String successReturnUrl;/*** 支付成功,回调通知*/private String callbackUrl;}

二、商户私钥证书代码读取

java加载商户证书私钥 以下部分内容来自微信支付文档样例
    https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient
    商户申请商户API证书时,会生成商户私钥,并保存在本地证书文件夹的文件apiclient_key.pem中
    商户开发者可以使用方法PemUtil.loadPrivateKey()加载证书

文档中样例:

# 示例:私钥存储在文件
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
        new FileInputStream("/path/to/apiclient_key.pem"));

# 示例:私钥为String字符串
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
        new ByteArrayInputStream(privateKey.getBytes("utf-8")));

代码加载读取秘钥/定时获取微信签名验证器/获取http请求对象,会自动的处理签名和验签:

package net.wnn.config;import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.stream.Collectors;@Configuration
@Slf4j
public class PayBeanConfig {@Autowiredprivate WechatPayConfig payConfig;/*** 加载秘钥** @return* @throws IOException*/public PrivateKey getPrivateKey() throws IOException {InputStream inputStream = new ClassPathResource(payConfig.getPrivateKeyPath().replace("classpath:", "")).getInputStream();String content = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining(System.lineSeparator()));try {String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");KeyFactory kf = KeyFactory.getInstance("RSA");PrivateKey finalPrivateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));return finalPrivateKey;} catch (NoSuchAlgorithmException e) {throw new RuntimeException("当前Java环境不支持RSA", e);} catch (InvalidKeySpecException e) {throw new RuntimeException("无效的密钥格式");}}/*** 定时获取微信签名验证器,自动获取微信平台证书(证书里面包括微信平台公钥)** @return*/@Beanpublic ScheduledUpdateCertificatesVerifier getCertificatesVerifier() throws IOException {// 使用定时更新的签名验证器,不需要传入证书ScheduledUpdateCertificatesVerifier verifier = null;verifier = new ScheduledUpdateCertificatesVerifier(new WechatPay2Credentials(payConfig.getMchId(),new PrivateKeySigner(payConfig.getMchSerialNo(),getPrivateKey())),payConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));return verifier;}/*** 获取http请求对象,会自动的处理签名和验签,* 并进行证书自动更新** @return*/@Bean("wechatPayClient")public CloseableHttpClient getWechatPayClient(ScheduledUpdateCertificatesVerifier verifier) throws IOException {WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create().withMerchant(payConfig.getMchId(),payConfig.getMchSerialNo() , getPrivateKey()).withValidator(new WechatPay2Validator(verifier));// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新CloseableHttpClient httpClient = builder.build();return httpClient;}}

三、微信订单支付系列接口URL配置

package net.wnn.config;public class WechatPayApi {/*** 微信支付主机地址*/public static final String HOST = "https://api.mch.weixin.qq.com";/*** Native下单*/public static final String NATIVE_ORDER = HOST+ "/v3/pay/transactions/native";/*** Native订单状态查询, 根据商户订单号查询*/public static final String NATIVE_QUERY = HOST+ "/v3/pay/transactions/out-trade-no/%s?mchid=%s";/*** 关闭订单接口*/public static final String NATIVE_CLOSE_ORDER = HOST+ "/v3/pay/transactions/out-trade-no/%s/close";/*** 申请退款接口*/public static final String NATIVE_REFUND_ORDER = HOST+ "/v3/refund/domestic/refunds";/*** 退款状态查询接口*/public static final String NATIVE_REFUND_QUERY = HOST+ "/v3/refund/domestic/refunds/%s";}

四、快速验证统一下单接口

验证下单测试方法:

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.wnn.ShopApplication;
import net.wnn.config.PayBeanConfig;
import net.wnn.config.WechatPayApi;
import net.wnn.config.WechatPayConfig;
import net.wnn.util.CommonUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShopApplication.class)@Slf4j
public class WechatPayTest {@Autowiredprivate PayBeanConfig payBeanConfig;@Autowiredprivate WechatPayConfig payConfig;@Autowiredprivate CloseableHttpClient wechatPayClient;/*** 快速验证统一下单接口* @throws IOException*/@Testpublic void testNativeOrder() throws IOException {String outTradeNo = CommonUtil.getStringNumRandom(32);/*** {*    "mchid": "1900006XXX",*     "out_trade_no": "native12177525012014070332333",*   "appid": "wxdace645e0bc2cXXX",*     "description": "Image形象店",*     "notify_url": "https://weixin.qq.com/",*    "amount": {*      "total": 1,*      "currency": "CNY"*        }* }*/JSONObject payObj = new JSONObject();payObj.put("mchid",payConfig.getMchId());payObj.put("out_trade_no",outTradeNo);payObj.put("appid",payConfig.getWxPayAppid());payObj.put("description","王师傅的红包");payObj.put("notify_url",payConfig.getCallbackUrl());//订单总金额,单位为分。JSONObject amountObj = new JSONObject();amountObj.put("total",100);amountObj.put("currency","CNY");payObj.put("amount",amountObj);//附属参数,可以用在回调payObj.put("attach","{\"accountNo\":"+888+"}");String body = payObj.toJSONString();log.info("请求参数:{}",body);StringEntity entity = new StringEntity(body,"utf-8");entity.setContentType("application/json");HttpPost httpPost = new HttpPost(WechatPayApi.NATIVE_ORDER);httpPost.setHeader("Accept","application/json");httpPost.setEntity(entity);try(CloseableHttpResponse response = wechatPayClient.execute(httpPost)){//响应码int statusCode = response.getStatusLine().getStatusCode();//响应体String responseStr = EntityUtils.toString(response.getEntity());log.info("下单响应码:{},响应体:{}",statusCode,responseStr);}catch (Exception e){e.printStackTrace();}}}

下单参数:

请求参数:{"amount":{"total":100,"currency":"CNY"},"mchid":"1601644*****","out_trade_no":"CikYMPk*****QILoJ4Ts3mjDA",

"appid":"wx5beac15ca20******","description":"王师傅的红包","attach":"{\"accountNo\":888}","notify_url":"http://api.*****.com/shop-server/api/callback/order/v1/wechat"}

下单返回结果:

下单响应码:200,响应体:{"code_url":"weixin://wxpay/bizpayurl?pr=JGRuZXAzz"}

返回的code_url是一个二维码地址,后端自测可以直接打开cli.im网址可以进入草料二维码页面,复制code_url右侧会出现二维码图像,打开手机微信扫一扫就能看到金额标题等信息。正式环境对接的时候前端有对应js获取后端返回code_url后展示支付二维码。

手机微信扫码后的结果:二维码有效时间2小时

这样就完成下单支付的验证啦

五、查询订单支付状态验证

查询订单测试方法:

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.wnn.ShopApplication;
import net.wnn.config.PayBeanConfig;
import net.wnn.config.WechatPayApi;
import net.wnn.config.WechatPayConfig;
import net.wnn.util.CommonUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShopApplication.class)@Slf4j
public class WechatPayTest {@Autowiredprivate PayBeanConfig payBeanConfig;@Autowiredprivate WechatPayConfig payConfig;@Autowiredprivate CloseableHttpClient wechatPayClient;/*** 根据商户号订单号查询订单支付状态* 未支付的情况下返回的是如下json* {"amount":{"payer_currency":"CNY","total":100},"appid":"wx5beacxxxxx",* "mchid":"160164xxxx","out_trade_no":"fRAv2Ccpd8xxxxxx",* "promotion_detail":[],"scene_info":{"device_id":""},* "trade_state":"NOTPAY","trade_state_desc":"订单未支付"}** @throws IOException*/@Testpublic void testNativeQuery() throws IOException {String outTradeNo = "CikYMPkEmRPQILoJ4Ts3xxxxxx";String url = String.format(WechatPayApi.NATIVE_QUERY,outTradeNo,payConfig.getMchId());HttpGet httpGet = new HttpGet(url);httpGet.setHeader("Accept","application/json");try(CloseableHttpResponse response = wechatPayClient.execute(httpGet)){//响应码int statusCode = response.getStatusLine().getStatusCode();//响应体String responseStr = EntityUtils.toString(response.getEntity());log.info("查询响应码:{},响应体:{}",statusCode,responseStr);}catch (Exception e){e.printStackTrace();}}}

查询订单微信返回接口信息:

查询响应码:200,响应体:{"amount":{"currency":"CNY","payer_currency":"CNY","payer_total":100,"total":100},"appid":"wx5beac15caxxxxx",
"attach":"{\"accountNo\":888}","bank_type":"OTHERS","mchid":"1601x","outxxxx_trade_no":"CikYMPkEmRPQIxxxxxx",
"payer":{"openid":"oiNKG04YwwLSlcW_xxxxxx"},"promotion_detail":[],"success_time":"2022-02-15T22:00:35+08:00",
"trade_state":"SUCCESS","trade_state_desc":"支付成功","trade_type":"NATIVE","transaction_id":"420000139920220xxxxx"}

六、关闭订单状态验证

关闭订单测试方法:

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.wnn.ShopApplication;
import net.wnn.config.PayBeanConfig;
import net.wnn.config.WechatPayApi;
import net.wnn.config.WechatPayConfig;
import net.wnn.util.CommonUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShopApplication.class)@Slf4j
public class WechatPayTest {@Autowiredprivate PayBeanConfig payBeanConfig;@Autowiredprivate WechatPayConfig payConfig;@Autowiredprivate CloseableHttpClient wechatPayClient;@Testpublic void testNativeCloseOrder() throws IOException {String outTradeNo = "2p9tZ05bve1ZcdfcgZxxxx";JSONObject payObj = new JSONObject();payObj.put("mchid",payConfig.getMchId());String body = payObj.toJSONString();log.info("请求参数:{}",body);//将请求参数设置到请求对象中StringEntity entity = new StringEntity(body,"utf-8");entity.setContentType("application/json");String url = String.format(WechatPayApi.NATIVE_CLOSE_ORDER,outTradeNo);HttpPost httpPost = new HttpPost(url);httpPost.setHeader("Accept","application/json");httpPost.setEntity(entity);try(CloseableHttpResponse response = wechatPayClient.execute(httpPost)){//响应码int statusCode = response.getStatusLine().getStatusCode();log.info("关闭订单响应码:{},无响应体",statusCode);}catch (Exception e){e.printStackTrace();}}
}

关闭订单测试方法返回 结果:

请求参数:{"mchid":"16016xxxx"}
2022-02-15 22:16:44.085  INFO 91680 --- [           main] WechatPayTest                            : 关闭订单响应码:204,无响应体

再次使用商户订单号查询订单状态:

已成功关闭啦

查询响应码:200,响应体:{"appid":"wx5beac1xxxx","attach":"{\"accountNo\":888}","mchid":"1601644xxxx","out_trade_no":"2p9tZ05bve1Zcxxxx","payer":{},"promotion_detail":[],"trade_state":"CLOSED","trade_state_desc":"订单已关闭"}

七、微信支付-SDK自动完成支付签名流程解读

微信支付过程中包含签名验证等过程,在V3版本当中是SDK自动完成支付签名的验证操作,详情查看以下文档,本博客以下单验证接口为例子,截取部分构造签名串和设置http头信息的日志表明自动支付签名的过程。

微信支付签名规则文档
    https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml

构造签名串日志

设置Http头

日志输出:

八、微信支付的退款注意事项

1、交易时间超过一年的订单无法提交退款

2、微信支付退款支持单笔交易分多次退款(不超50次),多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号

3、错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次

4、每个支付订单的部分退款次数不能超过50次

5、如果同一个用户有多笔退款,建议分不同批次进行退款,避免并发退款导致退款失败

6、申请退款接口的返回仅代表业务的受理情况,具体退款是否成功,需要通过退款查询接口获取结果

7、一个月之前的订单申请退款频率限制为:5000/min

8、同一笔订单多次退款的请求需相隔1分钟

九、微信支付退款验证

退款验证代码:

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.wnn.ShopApplication;
import net.wnn.config.PayBeanConfig;
import net.wnn.config.WechatPayApi;
import net.wnn.config.WechatPayConfig;
import net.wnn.util.CommonUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShopApplication.class)@Slf4j
public class WechatPayTest {@Autowiredprivate PayBeanConfig payBeanConfig;@Autowiredprivate WechatPayConfig payConfig;@Autowiredprivate CloseableHttpClient wechatPayClient;/*** 订单退款操作* @throws IOException*/@Testpublic void testNativeRefundOrder() throws IOException {String outTradeNo = "CikYMPkEmRPQILoxxxxxxxxxx";String refundNo = CommonUtil.getStringNumRandom(32);// 请求body参数JSONObject refundObj = new JSONObject();//订单号refundObj.put("out_trade_no", outTradeNo);//退款单编号,商户系统内部的退款单号,商户系统内部唯一,// 只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔refundObj.put("out_refund_no", refundNo);refundObj.put("reason","商品已售完");refundObj.put("notify_url", payConfig.getCallbackUrl());JSONObject amountObj = new JSONObject();//退款金额amountObj.put("refund", 10);//实际支付的总金额amountObj.put("total", 100);amountObj.put("currency", "CNY");refundObj.put("amount", amountObj);String body = refundObj.toJSONString();log.info("请求参数:{}",body);StringEntity entity = new StringEntity(body,"utf-8");entity.setContentType("application/json");HttpPost httpPost = new HttpPost(WechatPayApi.NATIVE_REFUND_ORDER);httpPost.setHeader("Accept","application/json");httpPost.setEntity(entity);try(CloseableHttpResponse response = wechatPayClient.execute(httpPost)){//响应码int statusCode = response.getStatusLine().getStatusCode();//响应体String responseStr = EntityUtils.toString(response.getEntity());log.info("申请订单退款响应码:{},响应体:{}",statusCode,responseStr);}catch (Exception e){e.printStackTrace();}}
}

退款验证请求参数:

请求参数:{"reason":"商品已售完","amount":{"total":100,"currency":"CNY","refund":10},"out_trade_no":"CikYMPkEmRPQxxx","out_refund_no":"jKgEPCt3GtWSTsxxxx","notify_url":"http://api.open1024.com/shop-server/api/callback/order/v1/wechat"}

退款返回结果:

申请订单退款响应码:200,响应体:{"amount":{"currency":"CNY","discount_refund":0,"from":[],"payer_refund":10,"payer_total":100,"refund":10,"settlement_refund":10,"settlement_total":100,"total":100},"channel":"ORIGINAL","create_time":"2022-02-15T22:51:14+08:00","funds_account":"AVAILABLE","out_refund_no":"jKgEPCt3GtWSTsxxxxxxxx","oxxxut_trade_no":"CikYMPkEmRPQILxxxx","promotion_detail":[],"refund_id":"5030220093202xxxxxxxx","status":"PROCESSING","transaction_id":"420000139920xxxx","user_receivexxxd_account":"支付用户零钱"}

十、查询退款结果

怎么知道退款结果呢?微信回调通知和主动查询,本博客介绍主动查询

查询退款验证方法:

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.wnn.ShopApplication;
import net.wnn.config.PayBeanConfig;
import net.wnn.config.WechatPayApi;
import net.wnn.config.WechatPayConfig;
import net.wnn.util.CommonUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShopApplication.class)@Slf4j
public class WechatPayTest {@Autowiredprivate PayBeanConfig payBeanConfig;@Autowiredprivate WechatPayConfig payConfig;@Autowiredprivate CloseableHttpClient wechatPayClient;/**查询退款结果*      * @throws IOException*/@Testpublic void testNativeRefundQuery() throws IOException {String refundNo = "jKgEPCt3GtWSTssEqzFBbUDVgM235WKY";String url = String.format(WechatPayApi.NATIVE_REFUND_QUERY,refundNo);HttpGet httpGet = new HttpGet(url);httpGet.setHeader("Accept","application/json");try(CloseableHttpResponse response = wechatPayClient.execute(httpGet)){//响应码int statusCode = response.getStatusLine().getStatusCode();//响应体String responseStr = EntityUtils.toString(response.getEntity());log.info("查询订单退款 响应码:{},响应体:{}",statusCode,responseStr);}catch (Exception e){e.printStackTrace();}}

查询退款返回结果:

查询订单退款 响应码:200,响应体:{"amount":{"currency":"CNY","discount_refund":0,"from":[],"payer_refund":10,"payer_total":100,"refund":10,"settlement_refund":10,"settlement_total":100,"total":100},"channel":"ORIGINAL","create_time":"2022-02-15T22:51:14+08:00","funds_account":"AVAILABLE","out_refund_no":"jKgEPCt3GtWSTssxxxx","out_trade_no":"CikYMPkEmRPQILoJ4Txxxx","promotion_detail":[],"refund_id":"50302200932022xxxxx","status":"SUCCESS","success_time":"2022-02-15T22:51:21+08:00","transaction_id":"42000013992022xxxx","user_received_account":"支付用户零钱"}

到这微信Native支付方式的下单、查询、退款、关单操作就通过测试工具类验证完成啦,以上内容没有掺杂过多业务逻辑,对象数据都是固定写的,方便将注意力集中在微信支付的接口使用中。正式对接到项目里面,只需要改动支付的部分业务参数即可。

整合进实际项目中,加了业务逻辑和设计模式的微信支付,也就是以上内容的续集,看下下面这篇博文即可。

微信V3版本支付下单、查询支付订单状态、订单退款接入正式项目中并引入策略模式实操_8年开发工作经验的老王,积极分享工作中遇到的问题~-CSDN博客

微信回调+验签流程

微信支付V3版本回调+验签流程_8年开发工作经验的老王,积极分享工作中遇到的问题~-CSDN博客回调验签流程介绍 官方文档 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml注意: 同样的通知可能会多次发送给商户系统,商户系统必须能够正确处理重复的通知 确保回调URL是外部可正常访问的,且不能携带后缀参数https://blog.csdn.net/wnn654321/article/details/123298162

一文带你学会微信V3版本下单支付、退款、关单流程代码实操相关推荐

  1. 10分钟带你学会微信小程序的反编译

    以xxxxx小程序为例10分钟带你学会微信小程序的反编译 2019-11-28 12:59:26 以一个简单的例子介绍下小程序反编译操作流程 实验环境 前置准备 模拟器内软件安装 获取小程序包 开始解 ...

  2. 一文带你学会linux系统 史上最全linux命令大全

    一文带你学会linux系统 史上最全linux命令大全 文章目录 linux系统简介 linux命令 1.启动网络命令 2.pwd命令 2.ls命令 3.cd命令 4.mkdir命令 5.rmdir命 ...

  3. 一文带你全面了解电商在线支付

    本文由作者 书丰 发布于社区 在电商系统中,方便的在线支付功能大大推进了电商的发展,可以说没有在线支付的发展就没有今天发展完善的电商系统,本文就来讨论一下在线支付相关的内容. 01 网银支付 1. 什 ...

  4. java环境变量的配置_一文带你学会Java环境变量配置(小白向)

    很多人初学Java的时候,因为Java环境变量的配置卡的心烦意乱. 又有很多人百度上翻来翻去,得到的答案五花八门,让你头晕眼花. 你肯定也在想,不就是个环境变量的配置吗?为什么搜了那么多答案,依然不能 ...

  5. 从原理到应用,一文带你了解微信小程序插件能力

    3月13日,微信小程序插件功能上线:8月底,在时隔半年后,为进一步推广插件功能,微信在开发者社区上线了插件版块. 小程序插件是可以被开发者添加到小程序内直接使用的,能为用户提供具体服务的功能组件-- ...

  6. 一文带你学会java的jvm精华知识点

    前言 本文分为20多个问题,通过问题的方式,来逐渐理解jvm,由浅及深.希望帮助到大家. Java类实例化时,JVM执行顺序? 正确的顺序如下: 1父类静态代码块 2父类静态变量 3子类静态代码块 3 ...

  7. 变现利器!一文带你学会应用内添加「贴片广告」

    什么是贴片广告 贴片广告是一种在视频播放过程中插入的视频或图片广告.视频广告一般是15s, 可以点跳过按钮直接进入视频播放界面,也可以等广告展示结束自动进入视频播放界面. 贴片广告的优势 相较于其他形 ...

  8. 一文带你学会AB实验最佳流程

    如果你对数据分析感兴趣,希望学习更多的方法论,希望听听经验分享, 欢迎移步公众号「小火龙说数据」,更多精彩原创文章与你分享! 「经验」带你掌握AB实验最佳流程https://mp.weixin.qq. ...

  9. python绘制饼状图图例_Python图表绘制很简单,一文带你学会如何生成带图例的饼图...

    matplotlib库,作为Python数据可视化的常用库和经典库,咱们已经探讨了多次,并了解了内部多个函数的使用,上次咱们聊了如何在图表中添加各种样式的图例,今天呢,咱们接着上次的内容继续深入聊聊, ...

最新文章

  1. 搜索引擎ElasticSearchV5.4.2系列二之ElasticSearchV5.4.2+kibanaV5.4.2+x-packV5.4.2安装
  2. TCP服务端收到syn但是不回复syn ack问题分析
  3. Xen的内存布局及其启动
  4. django 业务逻辑写在view里吗?_Python Web框架Django简介
  5. 机器学习(一)梯度下降算法的实现及过程分析
  6. Java高并发入门-线程初步
  7. 【报告分享】2019年全球数字化风险调查报告-德勤.pdf(附下载链接)
  8. android.view.VelocityTracker
  9. 除了被动阅读,用户想要的更多
  10. python学习笔记-递归函数
  11. 一台机器安装两个LINUX系统的操作与经验
  12. LINUX 游戏服务器之旅1_SSH连接
  13. apex乱码_[请教]apex安装简体中文语言包的步骤
  14. 武汉大学计算机学院选考要求,武汉大学高考必选科目-考武汉大学需要选哪三科...
  15. mysql数据库迁移工具_MysqlToMsSql(数据库迁移工具)
  16. HDL4SE:软件工程师学习Verilog语言(七)
  17. 《刷新》读书笔记1-3章
  18. 3d打开无法下载star.php,下载的3dmax模型打开失败的原因及解决方法
  19. OR(odd ratios)
  20. WaWa的奇妙冒险(第二周集训自闭现场)

热门文章

  1. 用python生成和解析二维码
  2. 计算机配置怎么复制,怎么设置别人无法使用U盘复制你的电脑文件 防止拷贝操作方法...
  3. Parallels 16已可在支持Windows的M1 Mac上运行
  4. Cocos2d-x 3.2 大富翁游戏项目开发-第五部分 单机游戏-关卡选择ScrollView
  5. 如何将Excel文件中数据导入数据库
  6. oa审核费用到oracle,oa协同管理平台费用申请操作
  7. Java(十四)----Junit测试
  8. Acwing 2326:王者之剑(网格图之网络流 最大权独立集)
  9. var、let与const的区别
  10. 论文阅读-基于深度强化学习的方法解决多智能体防御和攻击问题