赞
踩
java1.8
springboot 2.7.5
本文是以JSAPI支付为例子,其他支付完全可以以此参考
JSAPI支付适用于线下场所、公众号场景和PC网站场景。
商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程。
1、登陆已认证企业服务号,开通微信支付
注册微信商户号请参考官方文档,参考地址如下:
https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal#none
商户到公众平台开通JSAPI支付
同时配置JSAPI回调域,授权目录为公网IP,本地测试要使用内网穿透
JSAPI支付时必要传入openid
前提配置
openid获取是在微信登录授权时获取的,他和access_token一同获取到,分为两步。
相关文档参考:
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#0
第一步:根据appid获取code()访问地址为:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
注意在公众号中配置回调接受code的地址:redirect_uri
注意scope的类型
第二步:根据code,appid,appsecret获取openid,访问地址为:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
正确访问后返回结果
1,后端向微信第三方发送预支付(其中包括支付详细信息),
2,将预支付的返回结果返回给前端,前端拉起支付界面
3,支付状态进入后端回调接口中,后端记录数据持久到数据库
导入maven
<!--微信支付依赖-->
<dependency>
<groupId>com.github.tedzhdz</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>3.0.10</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>3.4.0</version>
</dependency>
接口参考文档:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
使用微信统一下单接口
@Controller public class WxPayController { String appID = "xxxxxxx"; //公众号id String mchID = "xxxxxxx"; //商户号 String appSecret = "xxxxxxx";//公众号idSecret String key = "xxxxxxx"; //商户key,用于sign验证 //申请授权码地址 String notify_url = "xxxxxxx/jsapiPayback"; //授权回调地址 String state=""; //统一下单,接收openid @GetMapping("/wxjspay") public ModelAndView wxjspay(HttpServletRequest request,HttpServletResponse response) throws Exception { //创建sdk客户端 WXPay wxPay = new WXPay(new WXPayConfigCustom()); //构造请求的参数 Map<String,String> requestParam = new HashMap<>(); requestParam.put("out_trade_no","10029293889");//订单号 requestParam.put("body", "iphone8");//订单描述 requestParam.put("fee_type", "CNY");//人民币 requestParam.put("total_fee", String.valueOf(1)); //金额 requestParam.put("spbill_create_ip", "");//客户端ip requestParam.put("notify_url", "xxxxx/payback");//微信异步通知支付结果接口, requestParam.put("trade_type", "JSAPI"); //从之前的步骤中拿到openid String openid = ; requestParam.put("openid",openid); //调用统一下单接口 Map<String, String> resp = wxPay.unifiedOrder(requestParam); //准备h5网页需要的数据 Map<String,String> jsapiPayParam = new HashMap<>(); jsapiPayParam.put("appId",appID); jsapiPayParam.put("timeStamp",System.currentTimeMillis()/1000+""); jsapiPayParam.put("nonceStr", UUID.randomUUID().toString());//随机字符串 jsapiPayParam.put("package","prepay_id="+resp.get("prepay_id")); jsapiPayParam.put("signType","HMAC-SHA256"); jsapiPayParam.put("paySign", WXPayUtil.generateSignature(jsapiPayParam,key,WXPayConstants.SignType.HMACSHA256)); //将h5网页响应给前端 return new ModelAndView("wxpay",jsapiPayParam); } // 支付功能 @GetMapping("xxxxxxx/jsapiPayback") public void h5payBack(HttpServletRequest request, HttpServletResponse response) throws Exception { // 读取回调数据 InputStream inputStream = request.getInputStream(); StringBuffer sb = new StringBuffer(); String s; BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); while ((s = in.readLine()) != null) { sb.append(s); } in.close(); inputStream.close(); // 解析xml成map Map<String, Object> m = XmlUtil.xmlToMap(sb.toString()); // 过滤空 设置 TreeMap SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>(); Iterator<String> it = m.keySet().iterator(); while (it.hasNext()) { String parameter = it.next(); Object parameterValue = m.get(parameter); String v = ""; if (null != parameterValue) { v = parameterValue.toString().trim(); } packageParams.put(parameter, v); } System.out.println("packageParams=" + packageParams); // 微信支付的API密钥 String key = environment.getProperty("wechat.pay.apiKey"); // 判断签名是否正确 if (WechatUtils.isTenpaySign(packageParams, key)) { String resXml = ""; if ("SUCCESS".equals((String) packageParams.get("result_code"))) { log.info("已支付, packageParams:{}", packageParams.toString()); //开始自己的逻辑 } // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了. resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; } else { log.info("支付失败,错误信息:" + packageParams.get("err_code")); log.info("支付失败"); resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> "; } response.getWriter().write(resXml); } else { log.info("通知签名验证失败"); } }
前置条件
导入maven,这个maven是官方推荐maven,里面很多需要填写的已经封装好,非常推荐
<!--微信支付依赖-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.7</version>
</dependency>
v3接口文档参考
https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
@GetMapping("/wxjspay") public ModelAndView wxjspay(HttpServletRequest request,HttpServletResponse response) throws Exception { /** 商户号 */ public static String merchantId = ""; /** 商户API私钥路径 */ public static String privateKeyPath = ""; /** 商户证书序列号 */ public static String merchantSerialNumber = ""; /** 商户APIV3密钥 */ public static String apiV3key = ""; RSAConfig config = new RSAConfig.Builder() .merchantId(merchantId) // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(merchantSerialNumber) .wechatPayCertificatesFromPath(wechatPayCertificatePath) .build(); // 初始化服务 service = new JsapiServiceExtension.Builder() .config(config) .signType("RSA") // 不填默认为RSA .build(); try { // ... 调用接口 PrepayWithRequestPaymentResponse response = prepayWithRequestPayment(); System.out.println(response); Map<String,String> jsapiPayParam = new HashMap<>(); jsapiPayParam.put("appId",appID); jsapiPayParam.put("timeStamp",System.currentTimeMillis()/1000+""); jsapiPayParam.put("nonceStr", UUID.randomUUID().toString());//随机字符串 jsapiPayParam.put("package","prepay_id="+resp.get("prepay_id")); jsapiPayParam.put("signType","HMAC-SHA256"); jsapiPayParam.put("paySign", WXPayUtil.generateSignature(jsapiPayParam,key,WXPayConstants.SignType.HMACSHA256)); //将h5网页响应给前端 return new ModelAndView("wxpay",jsapiPayParam); } catch (HttpException e) { // 发送HTTP请求失败 // 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义 } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500 // 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义 } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败 // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义 } } /** 关闭订单 */ public static void closeOrder() { CloseOrderRequest request = new CloseOrderRequest(); // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义 // 调用接口 service.closeOrder(request); } /** JSAPI支付下单,并返回JSAPI调起支付数据 */ public static PrepayWithRequestPaymentResponse prepayWithRequestPayment() { PrepayRequest request = new PrepayRequest(); // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义 // 调用接口 return service.prepayWithRequestPayment(request); } /** 微信支付订单号查询订单 */ public static Transaction queryOrderById() { QueryOrderByIdRequest request = new QueryOrderByIdRequest(); // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义 // 调用接口 return service.queryOrderById(request); } /** 商户订单号查询订单 */ public static Transaction queryOrderByOutTradeNo() { QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest(); // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义 // 调用接口 return service.queryOrderByOutTradeNo(request); } }
回调处理见v2后面的**“xxxxxxx/jsapiPayback”**接口,v3与其一致
此文章包含部分参考
原文链接:https://blog.csdn.net/weixin_45865428/article/details/117807648
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。