微信支付对接 wxAPI 全过程

1.先说需求 是微信公众号要做 微信支付

之前没有做过的话,需要让公司财务去申请微信商户号 去微信支付官网  pay.weixin.qq.com

需要拿到的参数:

public static String WX_GX_APP_ID = "xxx"; //APPID
public static String WX_GX_AppSecret = "xxx"; //AppSecret

public static String WX_GX_MCH_ID = "xxx"; //商户号
public static String WX_GX_APIKEY_V2 = "xxx"; //apiv2密钥
// 交易类型
public static final String TRADE_TYPE = "JSAPI";  //交易类型公众号就是JSAPI

2.然后支付这一步的话需要 三个接口。这里不考虑 未支付订单 15分钟自动取消等逻辑,只考虑与微信对接需要的。

1) 下单接口  属于自己开发,生成一个订单,需要返回orderNo 是自己系统的orderNo 。参数一般是sku,商品名,金额等。

2)预支付接口  ,即微信统一下单接口,调用wxapi ,在这一步需要配置回调接口,以参数的方式传给wxPay这个接口。这个接口可以模拟测试,传入openId,totalFee 等参数,可以看到 微信返回的map。一般success 就可以了。错误会有错误信息,可以拿着去百度。

接口参数

package com.code.biz.wx.WxPaySdk;

import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * 微信:小程序支付 统一下单必要的参数
 */
@Data
public class WeChatPayDto implements Serializable {

    /**
     * 商品描述
     */
    private String body;

    /**
     * 订单号
     */
    @NotNull(message = "缺少请求参数")
    private String outTradeNo;

    /**
     * 金额
     */
    private String totalFee;

    /**
     * 终端IP
     */
    private String spbillCreateIp;

    /**
     * 支付类型
     */
    @NotBlank(message = "支付类型不能为空")
    private String payType;

    @NotBlank(message = "openID不能为空")
    private String  openId;
}

微信支付util代码,需要改成你们自己的

package com.code.biz.wx.WxPaySdk;

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

//import static com.code.biz.wx.WxPaySdk.WxHttpUtils.*;
import static com.code.biz.constant.Constant.*;
import static com.github.wxpay.sdk.WXPayUtil.*;

/**
     * 微信支付工具类
     */
@Slf4j
@Component
public class WeChatPayUtil {


    /**
     * 微信统一下单接口
     * @param miniDTO
     * @return
     * @throws Exception
     */
    public static Map<String, String> getPrePayInfo(WeChatPayDto miniDTO) throws Exception {
        Map<String, String> map = Maps.newHashMap();
        //微信分配的小程序ID
        map.put("appid", WX_GX_APP_ID);
        //微信支付分配的商户号
        map.put("mch_id", WX_GX_MCH_ID);
        //随机字符串,长度要求在32位以内
        map.put("nonce_str", generateNonceStr());
        //商品简单描述
        map.put("body", miniDTO.getBody());
        //商户系统内部订单号
        map.put("out_trade_no", miniDTO.getOutTradeNo());
        //订单总金额,单位为分
        map.put("total_fee", miniDTO.getTotalFee());
        //支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
        map.put("spbill_create_ip", getLocalIp());
        //交易类型  小程序用JSAPI
        map.put("trade_type", "JSAPI");
        //回调地址  异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数 。 这个就是上面说的配置回调接口
        map.put("notify_url", NOTIFY_URL);
        //trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
        map.put("openid", miniDTO.getOpenId());
        String unifiedorderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // 微信统一下单URL
        String sign = generateSignature(map, WX_GX_APIKEY_V2);//key是api密钥  // 生成签名 PAY_API_SECRET=微信支付相关API调用时使用的秘钥
        map.put("sign", sign);  // 参数配置 我直接写成"sign"
        String xml = mapToXml(map);
        //请求微信统一下单接口
        String xmlStr = WxHttpUtils.httpRequest(unifiedorderUrl, "POST", xml);

        //解析xml
        Map map1 = WxHttpUtils.doXMLParse(xmlStr);
        String return_code = (String) map1.get("return_code");//返回状态码
        String result_code = (String) map1.get("result_code");//返回状态码
        String err_code = (String) map1.get("err_code");//返回状态码
        String err_code_des = (String) map1.get("err_code_des");//返回状态码
        log.info(xmlStr);
        if (return_code.equals("SUCCESS") || return_code.equals(result_code)) {
            // 业务结果
            String prepay_id = (String) map1.get("prepay_id");//返回的预付单信息
            Map<String, String> payMap = new HashMap<>();
            payMap.put("appId", WX_GX_APP_ID);  // 参数配置
            payMap.put("timeStamp", WxHttpUtils.getCurrentTimestamp() + "");  //时间
            payMap.put("nonceStr", generateNonceStr());  // 获取随机字符串
            payMap.put("signType", "MD5");
            payMap.put("package", "prepay_id=" + prepay_id);
            String paySign = generateSignature(payMap, WX_GX_APIKEY_V2); //第二次生成签名
            payMap.put("paySign", paySign);
            payMap.put("prepayId", prepay_id);
            payMap.put("out_trade_no", miniDTO.getOutTradeNo());
            return payMap;   //返回给前端,让前端去调支付 ,完成后你去调支付查询接口,看支付结果,处理业务。
        } else {
            //打印失败日志
        }
        return null;

    }

    /**
     * 获取当前机器的ip
     *
     * @return String
     */
    public static String getLocalIp() {
        InetAddress ia = null;
        String localip = null;
        try {
            ia = InetAddress.getLocalHost();
            localip = ia.getHostAddress();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return localip;
    }

}

 

3)支付回调接口 更改订单状态,减库存等逻辑放在这。  属于自己开发,配置到微信统一下单接口里

    /**
     * wx支付成功回调接口.
     *
     * @param request
     * @return
     */
    @PostMapping("/notify")
    @ApiOperation(value="支付回调接口")
    public String wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        LOGGER.info("进入支付回调---------------------------------");
        System.out.println("进入支付回调---------------------------------");
        Map orderMap = new HashMap();
        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        String notityXml = sb.toString();
        String resXml = "";
        Map resPrint = new HashMap();
        Map<String, String> resultMap = WXPayUtil.xmlToMap(notityXml);
        //业务结果
        String returnCode = (String) resultMap.get("return_code");
        //订单号
        String orderNo = resultMap.get("out_trade_no");
        //获取微信签名
        String sign = resultMap.get("sign");
        //去除签名字段
        resultMap.remove("sign");
        //重新签名
        String signNew = WXPayUtil.generateSignature(resultMap, WX_GX_APIKEY_V2);
        if (signNew.equals(sign)) {
            if ("SUCCESS".equals(returnCode)) {
                System.out.println(signNew + "ppppp");
                resPrint.put("return_code", "SUCCESS");
                resPrint.put("return_msg", "ok");
                resXml = WXPayUtil.mapToXml(resPrint);
                // 自己的业务逻辑
                iCourseOrderService.updateStatus(orderNo);
                //修改订单状态为已支付
                return WxPayNotifyResponse.success("成功");
            } else {
                System.out.println("业务结果失败");
//                WxPayNotifyResponse.success("code:" + 9999 + "微信回调结果异常,异常原因:");
                return null;
            }

        } else {
            resPrint.put("return_code", "FAIL");
            resPrint.put("return_msg", "签名失败");
            resXml = WXPayUtil.mapToXml(resPrint);
        }
        LOGGER.info(resXml);
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
        br.close();
        return null;
    }

 

maven依赖

<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>

<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>3.7.8.B</version>
</dependency>

<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>2.0.2</version>
</dependency>

 

所有sdk文件

链接:https://pan.baidu.com/s/1tlKf_4FCM_SNVq39XlvRkw
提取码:g64t

 

posted @ 2022-12-08 17:59  了悟  阅读(1068)  评论(0编辑  收藏  举报