标题

  • 图解
  • 扫码支付开发者文档
  • 1·下载微信支付demo
  • 2.提取微信支付工具类
  • 微信支付异步通知链接
  • 微信支付通知
  • WXPaymentController
  • WXPayConfig
  • MyWXPayRequest
  • service


图解

java 生成微信支付签名计算 java微信支付接口流程图_java


java 生成微信支付签名计算 java微信支付接口流程图_java 生成微信支付签名计算_02


java 生成微信支付签名计算 java微信支付接口流程图_java_03


java 生成微信支付签名计算 java微信支付接口流程图_java 生成微信支付签名计算_04


java 生成微信支付签名计算 java微信支付接口流程图_微信支付_05

java 生成微信支付签名计算 java微信支付接口流程图_java_06

扫码支付开发者文档

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

java 生成微信支付签名计算 java微信支付接口流程图_java_07


java 生成微信支付签名计算 java微信支付接口流程图_微信支付_08


java 生成微信支付签名计算 java微信支付接口流程图_微信支付_09


java 生成微信支付签名计算 java微信支付接口流程图_java 生成微信支付签名计算_10


java 生成微信支付签名计算 java微信支付接口流程图_java_11

1·下载微信支付demo

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_12

2.提取微信支付工具类

新建trade模块 弄好依赖关系 建包如下

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_13


并且trade模块pom.xml在增加个依赖

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

微信支付开发文档之参数含义及写法

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_14


3.编写微信支付调用接口

4.生成微信支付二维码

5.编写微信异步通知接口

6.编写定时程序检测微信支付结果订单号必须填对

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_15


下面通过草料二维码生成二维码 用手机扫一扫

java 生成微信支付签名计算 java微信支付接口流程图_java 生成微信支付签名计算_16


java 生成微信支付签名计算 java微信支付接口流程图_java_17


用浏览器来测试

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_18


效果一样

java 生成微信支付签名计算 java微信支付接口流程图_java_19


java 生成微信支付签名计算 java微信支付接口流程图_java_20

微信支付异步通知链接

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_21

微信支付通知

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_22


整体模块如下

java 生成微信支付签名计算 java微信支付接口流程图_java_23


java 生成微信支付签名计算 java微信支付接口流程图_java 生成微信支付签名计算_24

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();
        }
    }
}

java 生成微信支付签名计算 java微信支付接口流程图_微信支付_25


java 生成微信支付签名计算 java微信支付接口流程图_java_26


java 生成微信支付签名计算 java微信支付接口流程图_java 生成微信支付签名计算_27


java 生成微信支付签名计算 java微信支付接口流程图_微信支付_28