Java 实现微信支付

图解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

扫码支付开发者文档

模式二与模式一相比,流程更为简单,不依赖设置的回调支付URL。商户后台系统先调用微信支付的统一下单接口,微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。注意:code_url有效期为2小时,过期后扫码不能再发起支付。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1·下载微信支付demo

在这里插入图片描述

2.提取微信支付工具类

新建trade模块 弄好依赖关系 建包如下
在这里插入图片描述
并且trade模块pom.xml在增加个依赖

<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
</dependency>

微信支付开发文档之参数含义及写法
在这里插入图片描述
3.编写微信支付调用接口
4.生成微信支付二维码
5.编写微信异步通知接口
6.编写定时程序检测微信支付结果

订单号必须填对
在这里插入图片描述
下面通过草料二维码生成二维码 用手机扫一扫
在这里插入图片描述
在这里插入图片描述
用浏览器来测试
在这里插入图片描述
效果一样
在这里插入图片描述
在这里插入图片描述

微信支付异步通知链接

在这里插入图片描述

微信支付通知

在这里插入图片描述
整体模块如下
在这里插入图片描述
在这里插入图片描述

WXPaymentController

package cn.itrip.trade.controller;

import cn.itrip.beans.dto.Dto;
import cn.itrip.beans.pojo.ItripHotelOrder;

import cn.itrip.trade.config.WXPayConfig;
import cn.itrip.trade.service.OrderService;
import cn.itrip.trade.wx.MyWXPayRequest;
import cn.itrip.trade.wx.WXPayConstants;
import cn.itrip.trade.wx.WXPayUtil;
import cn.itrip.util.common.DtoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/api/wxpay")

public class WXPaymentController {
    static Logger logger = LoggerFactory.getLogger(WXPaymentController.class);

    @Resource
    private OrderService orderService;
    @Resource
    private WXPayConfig wxPayConfig;

    /**文档参数地址   https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
     * get
     * http://localhost:8080/wx//api/wxpay/createcode/D100000120200602144804b01129
     * 生成微信支付二维码的方法
     */
    @RequestMapping(value = "/createcode/{orderNo}", method = RequestMethod.GET)
    @ResponseBody
    public Dto createCode(@PathVariable String orderNo) throws Exception {
        try {
            //根据订单编号查询订单信息
            ItripHotelOrder order = orderService.loadItripHotelOrder(orderNo);

            //1、构造参数
            Map<String, String> data = new HashMap<String, String>();
            //商品描述	body

            data.put("body", "爱旅行项目订单支付");
            //商户订单号	out_trade_no
            data.put("out_trade_no", orderNo);
            //设备号	device_info
            data.put("device_info", "");
        //标价币种	  fee_type  示例值  CNY(默认人民币)
            data.put("fee_type", "CNY");
            //下面测试 用1分钱来测试(订单总金额,单位为分)标价金额	total_fee
            //data.put("total_fee", "1");//不能这么写 竟然postman测试报错下面可以
            data.put("total_fee", order.getPayAmount().multiply(new BigDecimal(100)).toBigInteger().toString());
            // 终端IP	spbill_create_ip
            data.put("spbill_create_ip", "47.92.146.135");
//            data.put("notify_url", wxPayConfig.getNotifyUrl());
            //不知道我的为啥得用官方文档这块给的这个值才行 按理说上面可以的吧毕竟弄到配置文件里了
            data.put("notify_url", "http://www.weixin.qq.com/wxpay/pay.php");
          //交易类型	trade_type JSAPI -JSAPI支付NATIVE -Native支付//APP -APP支付
            data.put("trade_type", "NATIVE");
            //商品ID	product_id trade_type=NATIVE时,此参数必传。此参数为二维码中包含的商品ID,商户自行定义。
            data.put("product_id", "12");
            //公众账号ID	appid   微信支付分配的公众账号ID(企业号corpid即为此appId)
            data.put("appid", wxPayConfig.getAppID());
            //商户号	mch_id   微信支付分配的商户号
            data.put("mch_id", wxPayConfig.getMchID());
            //签名类型	sign_type   签名类型,默认为MD5,支持HMAC-SHA256和MD5。
            data.put("sign_type", "HMAC-SHA256");
            //随机字符串	nonce_str   微信返回的随机字符串
            data.put("nonce_str", WXPayUtil.generateNonceStr());
// todo 注:参数值用XML转义即可,CDATA标签用于说明数据不被XML解析器解析。
            //2、把参数转换成XML格式,请求微信支付平台
            //生成签名
            String reqXml = WXPayUtil.generateSignedXml(
                    data, wxPayConfig.getKey(),
                    WXPayConstants.SignType.HMACSHA256);

            //3、请求微信支付平台,获取与支付交易链接
            //支付 接口链接
            //URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder
            //URL地址:https://api2.mch.weixin.qq.com/pay/unifiedorder(备用域名)见跨城冗灾方案  比上面多个s  https
            String respXML = MyWXPayRequest.requestWX("https://api.mch.weixin.qq.com/pay/unifiedorder", reqXml);
            //xml转换为map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(respXML);
            //判断是否请求成功
            //以下字段在return_code为SUCCESS的时候有返回
            //公众账号ID 商户号 设备号 随机字符串 签名 业务结果 错误代码 错误代码描述
            //以下字段在return_code 和result_code都为SUCCESS的时候有返回
            //交易类型	trade_type     预支付交易会话标识	prepay_id    二维码链接	code_url
            if (resultMap.get("return_code").equals("SUCCESS")
                    && resultMap.get("result_code").equals("SUCCESS")) {
                Map<String, String> result = new HashMap<>();
                //trade_type=NATIVE时有返回,此url用于生成支付二维码,然后提供给用户进行扫码支付。
                //注意:code_url的值并非固定,使用时按照URL格式转成二维码即可
                result.put("code_url", resultMap.get("code_url"));
                return DtoUtil.returnDataSuccess(result);
            } else {
                return DtoUtil.returnFail(resultMap.get("return_msg"), "110002");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return DtoUtil.returnFail("订单运行异常", "110003");
        }

    }

//回调函数
    @RequestMapping("/notify")
    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.info("成功被调用");
        try {
            //1、从request获取XML流
            StringBuffer dataBuf = new StringBuffer();
            InputStream is = request.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
            //
            String temp;
            while ((temp = reader.readLine()) != null) {
                dataBuf.append(temp);
            }
            reader.close();
            is.close();

            //2、 识别是否成功,修改订单状态
            //xml-->map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(dataBuf.toString());
            boolean valid = WXPayUtil.isSignatureValid(
                    resultMap,
                    wxPayConfig.getKey(),
                    WXPayConstants.SignType.HMACSHA256);
            //数据合法化验证:是否是微信返回的
            if (valid) {
                logger.info("签名验证通过");
                //判断是否请求成功
                if (resultMap.get("return_code").equals("SUCCESS")
                        && resultMap.get("result_code").equals("SUCCESS")) {
                    logger.info("订单支付成功");
                    //
                    String out_trade_no = resultMap.get("out_trade_no");
                    String trade_no = resultMap.get("prepay_id");

                    //订单状态
                    if (!orderService.processed(out_trade_no)) {
                        //订单未处理,则进行支付
                        orderService.paySuccess(out_trade_no, 2, trade_no);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            logger.info("成功返回数据");
            //3、给微信返回结果
            Map<String, String> returnMap = new HashMap<String, String>();
            returnMap.put("return_code", "SUCCESS");
            returnMap.put("return_msg", "SUCCESS");
            try {
                String respXml = WXPayUtil.generateSignedXml(returnMap, "2ab9071b06b9f739b950ddb41db2690d");
                response.getWriter().write(respXml);
                response.getWriter().flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 定时查询订单状态,刷新订单
     */
    @RequestMapping(value = "/queryorderstatus/{orderNo}", method = RequestMethod.GET)
    @ResponseBody
    public Dto queryOrderStatus(@PathVariable String orderNo) throws Exception {
        try {
            ItripHotelOrder order = orderService.loadItripHotelOrder(orderNo);
            return DtoUtil.returnDataSuccess(order);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return DtoUtil.returnFail("查询失败", "100003");
    }
}

WXPayConfig

package cn.itrip.trade.config;

public class WXPayConfig {
    private String appID;
    private String mchID;
    private String key;
    private String notifyUrl;
    private String successUrl;
    private String failUrl;

    public String getAppID() {
        return appID;
    }

    public void setAppID(String appID) {
        this.appID = appID;
    }

    public String getMchID() {
        return mchID;
    }

    public void setMchID(String mchID) {
        this.mchID = mchID;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getNotifyUrl() {
        return notifyUrl;
    }

    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }

    public String getSuccessUrl() {
        return successUrl;
    }

    public void setSuccessUrl(String successUrl) {
        this.successUrl = successUrl;
    }

    public String getFailUrl() {
        return failUrl;
    }

    public void setFailUrl(String failUrl) {
        this.failUrl = failUrl;
    }
}

MyWXPayRequest

package cn.itrip.trade.wx;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.util.Map;

public class MyWXPayRequest {

    public static String requestWX(String url,String data) throws Exception{
        BasicHttpClientConnectionManager connManager;

            connManager = new BasicHttpClientConnectionManager(
                    RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.getSocketFactory())
                            .register("https", SSLConnectionSocketFactory.getSocketFactory())
                            .build(),
                    null,
                    null,
                    null
            );

        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        HttpPost httpPost = new HttpPost(url);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(1000).setConnectTimeout(1000)
                .build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(data, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);

        try {
            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            return EntityUtils.toString(httpEntity, "UTF-8");
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

service

package cn.itrip.trade.service;

import cn.itrip.beans.pojo.ItripHotelOrder;
public interface OrderService {
    /**
     * 加载酒店订单
     * @param orderNo
     * @return
     * @throws Exception
     */
    public ItripHotelOrder loadItripHotelOrder(String orderNo) throws Exception;
    /**
     * 判断该订单是否已被处理过(被更新为已支付状态)
     * @param orderNo
     * @return
     * @throws Exception
     */
    public boolean processed(String orderNo) throws Exception;
    /**
     * 支付成功
     * @param orderNo 订单编号
     * @param payType 支付方式:1:支付宝 2:微信 3:到店付
     * @param tradeNo 支付平台返回的交易码
     * @throws Exception
     */
    public void paySuccess(String orderNo, int payType, String tradeNo) throws Exception;
}

package cn.itrip.trade.service;

import cn.itrip.beans.pojo.ItripHotelOrder;
import cn.itrip.beans.pojo.ItripTradeEnds;

import cn.itrip.dao.hotelorder.ItripHotelOrderMapper;
import cn.itrip.dao.tradeends.ItripTradeEndsMapper;
import cn.itrip.util.common.EmptyUtils;
import cn.itrip.util.common.SystemConfig;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service("orderService")
public class OrderServiceImpl implements OrderService {
    @Resource
    private ItripHotelOrderMapper itripHotelOrderMapper;
    @Resource
    private SystemConfig systemConfig;
    @Resource
    private ItripTradeEndsMapper itripTradeEndsMapper;

    @Override
    public ItripHotelOrder loadItripHotelOrder(String orderNo) throws Exception {
        Map<String, Object> param = new HashMap<>();
        param.put("orderNo", orderNo);
        List<ItripHotelOrder> orders = itripHotelOrderMapper.getItripHotelOrderListByMap(param);
        if (orders.size() == 1) {
            return orders.get(0);
        } else {
            return null;
        }
    }

    @Override
    public boolean processed(String orderNo) throws Exception {
        ItripHotelOrder order = this.loadItripHotelOrder(orderNo);
        return order.getOrderStatus().equals(2)&& EmptyUtils.isNotEmpty(order.getTradeNo());
    }

    @Override
    public void paySuccess(String orderNo, int payType, String tradeNo) throws Exception {
        //更新订单状态、支付宝交易号
        ItripHotelOrder itripHotelOrder=this.loadItripHotelOrder(orderNo);
        itripHotelOrder.setOrderStatus(2);//支付成功
        itripHotelOrder.setPayType(payType);
        itripHotelOrder.setTradeNo(tradeNo);//交易号(如支付宝交易号)
        itripHotelOrderMapper.updateItripHotelOrder(itripHotelOrder);

        //增加订单后续待处理记录
        ItripTradeEnds itripTradeEnds=new ItripTradeEnds();
        itripTradeEnds.setId(itripHotelOrder.getId());
        itripTradeEnds.setOrderNo(itripHotelOrder.getOrderNo());
        itripTradeEndsMapper.insertItripTradeEnds(itripTradeEnds);
        //通知业务模块后续处理
        sendGet(systemConfig.getTradeEndsUrl(),"orderNo="+orderNo);
    }

    public void sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection;
            if(systemConfig.getTradeUseProxy()){//代理环境
                Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(
                        systemConfig.getTradeProxyHost(),
                        systemConfig.getTradeProxyPort()));
                connection= realUrl.openConnection(proxy);
            }
            else{
                connection= realUrl.openConnection();
            }
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            System.out.println(connection.getContentLength());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

### 回答1: 在 Java实现微信支付需要使用微信支付 SDK。您可以在微信支付官方网站上下载最新版本的 SDK,并在您的 Java 项目中使用它。 使用微信支付 SDK 的具体步骤如下: 1. 注册微信支付商户并获取商户 ID 和密钥。 2. 下载并导入微信支付 SDK。 3. 创建支付订单并获取支付二维。 4. 使用扫支付或者 JSAPI 支付接口调用微信支付。 5. 接收微信支付的异步通知并进行订单状态的更新。 有关微信支付的更多信息,您可以参考微信支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 希望这些信息对您有帮助! ### 回答2: 要实现微信支付功能,可以使用Java编程语言结合微信支付开放平台提供的API来实现。 首先,需要在微信支付开放平台注册并创建一个应用,获取到应用的AppID、商户号、AppSecret等信息。 接下来,在Java项目中引入微信支付SDK,可以使用第三方库,如"wechatpay-api"来简化开发流程。然后,通过使用SDK提供的相关方法,可以实现以下功能: 1. 获取access_token:通过获取 access_token 接口,获取微信支付接口调用凭证,用于后续接口调用的身份验证。 2. 统一下单:使用统一下单接口,将用户提交的支付信息传给微信支付平台,生成预支付订单,并返回预付款二维链接或者支付ID。 3. 生成支付链接或二维:将预付款二维链接或支付ID返回给前端,通过生成支付链接或者二维的方式,提供给用户进行支付。 4. 微信支付回调:在用户支付成功后,微信支付平台会异步调用开发者设置的支付结果通知地址,向该地址发送支付结果信息。开发者需要在接收到回调时,验证回调的合法性,并及时处理支付结果。 5. 查询订单状态:通过订单查询接口,可以查询用户支付订单的当前状态,如支付成功、支付失败等。 6. 退款:使用退款接口,可以实现订单退款操作,退还用户支付的金额。 以上是使用Java实现微信支付的基本步骤。在具体实现过程中,还需注意接口调用的参数传递、异常处理、数据加密等问题。为确保支付安全,建议使用HTTPS协议进行数据传输,并加强对接口的签名验证。 ### 回答3: Java 实现微信支付可以通过微信支付开放平台提供的开发工具包来完成。首先,需要在微信支付开放平台注册一个开发者账号,并创建一个应用获取对应的应用ID和应用密钥。 接下来,可以使用Java语言进行开发。首先,需要引入微信支付Java SDK,例如官方提供的weixin-java-pay SDK。通过在项目的pom.xml文件中添加相关依赖,即可将SDK集成到项目中。 然后,通过在代中进行配置,将应用ID和应用密钥等信息设置到SDK中。可以使用SDK提供的配置类进行设置,例如WxPayConfig。 接下来,可以使用SDK提供的API进行微信支付的相关操作。例如,使用SDK提供的统一下单API可以生成一个支付链接,通过该链接用户可以进行支付操作。可以通过创建对应的请求对象,并调用SDK提供的发送请求的方法来实现支付结果通知可以使用SDK提供的回调接口来处理,当支付完成后,微信支付平台会向预先设置的回调URL发送通知。可以在代中编写对应的处理逻辑,接收并解析微信支付平台发送的通知,校验数据的正确性,并进行相应的业务处理。 最后,可以使用SDK提供的查询订单API来查询订单的支付结果。可以根据订单号或其他查询条件,调用SDK提供的查询订单接口来获取订单的最新支付状态。 通过以上步骤,就可以使用Java实现微信支付功能。需要注意的是,开发过程中需要仔细阅读微信支付开放平台提供的文档和SDK的使用指南,并按照实际需求进行相关配置和操作。同时,为了确保支付过程的安全性,建议使用SSL证书进行加密传输。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值