微信支付对接 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
下班记得打卡
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!