• Springboot+mybatis-plus微信支付


    一、根据订单生成付款二维码

    1.导入依赖和配置文件的配置

    1. <dependency>
    2. <groupId>com.github.wxpaygroupId>
    3. <artifactId>wxpay-sdkartifactId>
    4. <version>0.0.3version>
    5. dependency>
    6. <dependency>
    7. <groupId>org.apache.httpcomponentsgroupId>
    8. <artifactId>httpclientartifactId>
    9. <version>4.5.3version>
    10. dependency>
    11. <dependency>
    12. <groupId>com.baomidougroupId>
    13. <artifactId>mybatis-plus-boot-starterartifactId>
    14. <version>3.5.2version>
    15. dependency>
    16. <dependency>
    17. <groupId>com.baomidougroupId>
    18. <artifactId>mybatis-plus-generatorartifactId>
    19. <version>3.5.2version>
    20. dependency>

     配置文件:

    1. server.port=9000
    2. #数据库连接的信息
    3. spring.datasource.password=
    4. spring.datasource.username=
    5. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    6. spring.datasource.url=jdbc:mysql://localhost:3306/weixin?serverTimezone=Asia/Shanghai
    7. # 微信的appid 商家id 密钥---申请你无法申请因为需要营业执照--
    8. weixin.appid=
    9. weixin.mch_id=
    10. weixin.api_key=

     2.导入发送网络请求配置类

    1. package com.gsh.system.utils;
    2. import org.apache.http.Consts;
    3. import org.apache.http.HttpEntity;
    4. import org.apache.http.NameValuePair;
    5. import org.apache.http.client.ClientProtocolException;
    6. import org.apache.http.client.entity.UrlEncodedFormEntity;
    7. import org.apache.http.client.methods.*;
    8. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    9. import org.apache.http.conn.ssl.SSLContextBuilder;
    10. import org.apache.http.conn.ssl.TrustStrategy;
    11. import org.apache.http.entity.StringEntity;
    12. import org.apache.http.impl.client.CloseableHttpClient;
    13. import org.apache.http.impl.client.HttpClients;
    14. import org.apache.http.message.BasicNameValuePair;
    15. import org.apache.http.util.EntityUtils;
    16. import javax.net.ssl.SSLContext;
    17. import java.io.IOException;
    18. import java.security.cert.CertificateException;
    19. import java.security.cert.X509Certificate;
    20. import java.text.ParseException;
    21. import java.util.HashMap;
    22. import java.util.LinkedList;
    23. import java.util.List;
    24. import java.util.Map;
    25. /**
    26. * http请求客户端
    27. *
    28. * @author 必须引入httpclient的依赖:在java端模拟浏览器的效果。
    29. *
    30. */
    31. public class HttpClient {
    32. private String url;
    33. private Map param;
    34. private int statusCode;
    35. private String content;
    36. private String xmlParam;
    37. private boolean isHttps;
    38. public boolean isHttps() {
    39. return isHttps;
    40. }
    41. public void setHttps(boolean isHttps) {
    42. this.isHttps = isHttps;
    43. }
    44. public String getXmlParam() {
    45. return xmlParam;
    46. }
    47. public void setXmlParam(String xmlParam) {
    48. this.xmlParam = xmlParam;
    49. }
    50. public HttpClient(String url, Map param) {
    51. this.url = url;
    52. this.param = param;
    53. }
    54. public HttpClient(String url) {
    55. this.url = url;
    56. }
    57. public void setParameter(Map map) {
    58. param = map;
    59. }
    60. public void addParameter(String key, String value) {
    61. if (param == null)
    62. param = new HashMap();
    63. param.put(key, value);
    64. }
    65. public void post() throws ClientProtocolException, IOException {
    66. HttpPost http = new HttpPost(url);
    67. setEntity(http);
    68. execute(http);
    69. }
    70. public void put() throws ClientProtocolException, IOException {
    71. HttpPut http = new HttpPut(url);
    72. setEntity(http);
    73. execute(http);
    74. }
    75. public void get() throws ClientProtocolException, IOException {
    76. if (param != null) {
    77. StringBuilder url = new StringBuilder(this.url);
    78. boolean isFirst = true;
    79. for (String key : param.keySet()) {
    80. if (isFirst)
    81. url.append("?");
    82. else
    83. url.append("&");
    84. url.append(key).append("=").append(param.get(key));
    85. }
    86. this.url = url.toString();
    87. }
    88. HttpGet http = new HttpGet(url);
    89. execute(http);
    90. }
    91. /**
    92. * set http post,put param
    93. */
    94. private void setEntity(HttpEntityEnclosingRequestBase http) {
    95. if (param != null) {
    96. List nvps = new LinkedList();
    97. for (String key : param.keySet())
    98. nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
    99. http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
    100. }
    101. if (xmlParam != null) {
    102. http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
    103. }
    104. }
    105. private void execute(HttpUriRequest http) throws ClientProtocolException,
    106. IOException {
    107. CloseableHttpClient httpClient = null;
    108. try {
    109. if (isHttps) {
    110. SSLContext sslContext = new SSLContextBuilder()
    111. .loadTrustMaterial(null, new TrustStrategy() {
    112. // 信任所有
    113. public boolean isTrusted(X509Certificate[] chain,
    114. String authType)
    115. throws CertificateException {
    116. return true;
    117. }
    118. }).build();
    119. SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
    120. sslContext);
    121. httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
    122. .build();
    123. } else {
    124. httpClient = HttpClients.createDefault();
    125. }
    126. CloseableHttpResponse response = httpClient.execute(http);
    127. try {
    128. if (response != null) {
    129. if (response.getStatusLine() != null)
    130. statusCode = response.getStatusLine().getStatusCode();
    131. HttpEntity entity = response.getEntity();
    132. // 响应内容
    133. content = EntityUtils.toString(entity, Consts.UTF_8);
    134. }
    135. } finally {
    136. response.close();
    137. }
    138. } catch (Exception e) {
    139. e.printStackTrace();
    140. } finally {
    141. httpClient.close();
    142. }
    143. }
    144. public int getStatusCode() {
    145. return statusCode;
    146. }
    147. public String getContent() throws ParseException, IOException {
    148. return content;
    149. }
    150. }

    3.controller 层

    1. @PostMapping("/createNative/{orderNo}")
    2. public CommonResult createNative(@PathVariable String orderNo){
    3. return orderService.createNative(orderNo);
    4. }

    4.Service层业务代码

    获取配置文件的信息

    1. //获取配置文件里的appid
    2. @Value("${weixin.appid}")
    3. private String appId;
    4. //获取配置文件里的mch_id
    5. @Value("${weixin.mch_id}")
    6. private String mchId;
    7. //获取配置文件里的apiKey
    8. @Value("${weixin.api_key}")
    9. private String apiKey;

     

    1. public CommonResult createNative(String orderNo) {
    2. QueryWrapperwrapper=new QueryWrapper<>();
    3. wrapper.eq("order_no",orderNo);
    4. wrapper.eq("status",0);
    5. Order order = orderMapper.selectOne(wrapper);
    6. System.out.println(order);
    7. if(order!=null){
    8. try{
    9. //设置请求参数----需要的格式为.xml格式
    10. //我们使用map存放再转为xml
    11. Map params=new HashMap<>();//请求参数
    12. params.put("appid",appId);
    13. params.put("mch_id",mchId);
    14. params.put("nonce_str", WXPayUtil.generateNonceStr());
    15. params.put("body",order.getCourseTitle());
    16. params.put("out_trade_no",orderNo);
    17. BigDecimal totalFee = order.getTotalFee();
    18. //double会丢失精度所以我们选择BigDecimal
    19. //params.put("total_fee",totalFee.multiply(new BigDecimal(100)).longValue()+"");
    20. //0.01将来要缓存真实的金额
    21. params.put("total_fee",new BigDecimal(0.01).multiply(new BigDecimal(100)).longValue()+"");
    22. params.put("spbill_create_ip","127.0.0.1");//未来写成项目部署的ip
    23. params.put("notify_url","http://localhost:9000/pay/back");
    24. params.put("trade_type","NATIVE");
    25. //创建HttpClient对象 远程调用
    26. HttpClient client=new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
    27. //支持https协议
    28. client.setHttps(true);
    29. client.setXmlParam(WXPayUtil.generateSignedXml(params,apiKey));
    30. //设置请求方式
    31. client.post();
    32. String content = client.getContent();
    33. System.out.println(content);
    34. //将返回结果的xml转换为Map
    35. Map map = WXPayUtil.xmlToMap(content);
    36. if(map.get("result_code").equals("SUCCESS")){
    37. Map result=new HashMap<>();
    38. result.put("codeUrl",map.get("code_url"));//获取生成二维码地址
    39. result.put("price",totalFee);//获取商品价格
    40. result.put("orderNo",orderNo);//获取订单编号
    41. return new CommonResult(2000,"生成二维码",result);
    42. }
    43. }catch (Exception e){
    44. e.printStackTrace();
    45. }
    46. }
    47. return new CommonResult(5000,"订单失效",null);
    48. }

    5.前端二维码的展示

    1. <el-button type="primary" @click="pay">支付el-button>
    2. <el-dialog
    3. title="收银台"
    4. :visible.sync="dialogVisible"
    5. width="30%">
    6. <div style="text-align: center">
    7. <p>微信支付{{payResult.price}}元p>
    8. <div style="border: 1px solid #f3f3f3;width: 220px;padding: 10px;margin: 0px auto">
    9. <vue-qr
    10. :text="payResult.codeUrl"
    11. :margin="0"
    12. colorDark="green"
    13. :logoSrc="require('@/assets/logo.png')"
    14. colorLight="#fff"
    15. :size="200">
    16. vue-qr>
    17. div>
    18. div>
    19. <el-divider>el-divider>
    20. <div style="font-size: 13px">
    21. 提示:<br>
    22. 支付成功前请勿手动关闭页面<br>
    23. 二维码两小时有效,请及时扫码支付<br>
    24. div>
    25. el-dialog>

    6.data数据的存放

    1. data(){
    2. return{
    3. orderNo:"e334ce2a6b1d4bc6949",
    4. dialogVisible:false,
    5. payResult:{
    6. price:0,
    7. codeUrl:"",
    8. orderNo:"",
    9. },
    10. timer1:""
    11. }
    12. },

    7.前端发送的请求方法

    1. pay(){
    2. this.dialogVisible=true;
    3. this.$http.post("/order/createNative/"+this.orderNo).then(result=>{
    4. if (result.data.code===2000) {
    5. this.payResult = result.data.data
    6. //设置一个定时任务,每隔3秒调用一次
    7. this.timer1=setInterval(()=>{
    8. this.queryPayStatus(this.payResult.orderNo)
    9. },3000)
    10. }
    11. })
    12. },

    二、前端调用订单状态查询的方法

    1. //根据订单号查询支付状态
    2. queryPayStatus(orderNo){
    3. this.$http.post("/order/queryPayStatus/"+this.orderNo).then(result=>{
    4. console.log(result.data.code)
    5. if(result.data.code===2000){
    6. console.log("****************************")
    7. //消除定时器
    8. clearInterval(this.timer1)
    9. this.timer1=null;
    10. this.$message.success("支付成功!")
    11. this.dialogVisible=false;
    12. }
    13. })
    14. },

    三、后台查询订单状态

    1.controller层

    1. @PostMapping("/queryPayStatus/{orderNo}")
    2. public CommonResult queryPayStatus(@PathVariable String orderNo){
    3. return orderService.queryPayStatus(orderNo);
    4. }

    2.Service业务层

    1. public CommonResult queryPayStatus(String orderNo) {
    2. try {
    3. HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
    4. Map params=new HashMap<>();
    5. params.put("appid",appId);
    6. params.put("mch_id",mchId);
    7. params.put("out_trade_no",orderNo);
    8. params.put("nonce_str",WXPayUtil.generateNonceStr());
    9. client.setHttps(true);
    10. //根据订单状态查询微信的支付情况
    11. client.setXmlParam(WXPayUtil.generateSignedXml(params,apiKey));
    12. client.post();
    13. String content = client.getContent();
    14. System.out.println(content);
    15. //将返回的xml内容转为map内容
    16. Map map = WXPayUtil.xmlToMap(content);
    17. //修改订单状态
    18. if(map.get("trade_state").equals("SUCCESS")) {
    19. Order order = new Order();
    20. order.setStatus(1);
    21. order.setGmtModified(LocalDateTime.now());
    22. QueryWrapper wrapper=new QueryWrapper<>();
    23. wrapper.eq("order_no",orderNo);
    24. wrapper.eq("status",0);
    25. orderMapper.update(order,wrapper);
    26. return new CommonResult(2000,"支付成功!",null);
    27. }
    28. } catch (Exception e) {
    29. }
    30. return new CommonResult(5000,"支付失败!",null);
    31. }

  • 相关阅读:
    HTTP超时时间设置
    【SLAM】 前端-视觉里程计之相对位姿估计
    网络I/O_04 IO模型
    【报错解决】java:错误:无效的源发行版:15
    第十三天到达终点数字
    “蔚来杯“2022牛客暑期多校训练营6 ABM题解
    多目标进化算法详细讲解及代码实现(样例:MOEA/D、NSGA-Ⅱ求解多目标(柔性)作业车间调度问题)
    电影大师杂记
    《神经网络与深度学习》算法伪代码汇总
    VBA根据Excel内容快速创建PPT
  • 原文地址:https://blog.csdn.net/Have_MonkeyG/article/details/126372648