• JSAPI实现H5页面微信支付


    进入官网文档:> 微信支付官网文档 根据官网文档能够很详细的需要做的事

    接下来,采用的是JSAPI的方式小程序嵌入H5页面中实现微信支付,直接拉起支付页面

    一:需要在微信公众号平台和微信支付商家平台获取的配置的关键参数如下:

    1,openid:需要实现微信登录才能获取

    2,微信公众号绑定的appid

    3,微信商家号绑定对应的appid的商家号id

    4,商家号密钥

    5,商家号拉起支付的授权目录

    6,支付完成通知的回调地址:这个地址是后端自定义的回调接口地址

    准备以上参数之后,开始写代码:根据官网文档编写

    二:简单总结需要做的事儿

    1,创建sdk客户端
    .
    2,构造请求的参数
    .
    3,封装前端需要的响应参数
    .
    4,前端获取参数,直接拉起支付界面
    .
    5,支付完成完成后,请求回调地址,处理结果
    .
    注意:这里签名的类型有两种md5和HMACSHA256需要注意一下这个地方,出错概率大

    controller层如下 :
    在这里插入图片描述

    请求实体

    @Data
    @ApiModel("微信下单请求实体")
    public class WxPayOrderDTO {
    
        @ApiModelProperty(value = "用户openid")
        @NotBlank(message = "openid不能未空")
        private String openId;
    
        @ApiModelProperty(value = "收费类型")
        @NotNull(message = "商品标识标识不能未空")
        private Integer type;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    常量封装

    public class WxPayConstant {
    
         // 回调地址
        public static final String  NOTIFY_URL = "https://gpt.xiaomon.com/api2/base/wx/callback";
    
        // 商家号密钥
        public static final String  API_KEY = "Tunda123Tunda123Tunda123Tunda123";
    
        // appid
        public static final String  APP_ID = "wx27599519b337b629";
    
        // 商家号id
        public static final String  PAY_MCH_ID = "1618043632";
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    serviceImpl层:

       /**
         * 微信JSAPI支付
         * @param payDTO
         * @return
         */
        public Map<String, String> wxPayForJSAPI(WxPayOrderDTO payDTO) {
    
                // 创建订单
                SaveOrderVO order = orderService.createOrder(payDTO);
            try {
                //创建sdk客户端
                WXPay wxPay = new WXPay(new WXPayConfigCustom());
    
                //构造请求的参数
                Map<String, String> data = new HashMap<>();
                data.put("openid",payDTO.getOpenId());
                data.put("body",order.getRemark()); // 商品描述
                // 金额处理一下
                BigDecimal fee = order.getFee().multiply(new BigDecimal(100));
                log.info("金额:{}",fee.setScale(0, BigDecimal.ROUND_DOWN).toString());
                data.put("total_fee", fee.setScale(0, BigDecimal.ROUND_DOWN).toString()); // 订单金额, 单位分
                data.put("nonce_str",WXPayUtil.generateNonceStr());// 随机字符串
                data.put("spbill_create_ip", AddressUtils.getIp()); // 下单ip
                log.info("微信下单ip->{}",AddressUtils.getIp());
                data.put("notify_url", WxPayConstant.NOTIFY_URL); // 订单结果通知, 微信主动回调此接口
                data.put("out_trade_no", order.getOrderNo()); // 订单唯一编号, 不允许重复
                data.put("trade_type", "JSAPI");  // 交易类型 MWEB--H5支付、JSAPI--小程序支付-类型不同则参数不同
                String sign = WXPayUtil.generateSignature(data, WxPayConstant.API_KEY, WXPayConstants.SignType.HMACSHA256);
                data.put("sign",sign);
    
                Map<String, String> map = wxPay.unifiedOrder(data);
                log.info("微信平台下订单情况->{}",map);
                String prepayId = map.get("prepay_id");
                if(null==prepayId){
                    orderService.updateOrder(order.getOrderNo(),"", OrderStatusEnum.FAIL_PAY);
                    throw new BusinessException("获取预支付id异常");
                }
    
                // 封装前端需要的响应参数
                Map<String, String> resultMap = new HashMap<String, String>();
                resultMap.put("appId", WxPayConstant.APP_ID);
                resultMap.put("timeStamp", String.valueOf(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000));
                resultMap.put("nonceStr", WXPayUtil.generateNonceStr());
                resultMap.put("package", "prepay_id=" + prepayId);
                // 注意:下单默认的是h256方式,校验默认是MD5方式,前端默认采用MD5校验
                resultMap.put("signType", "MD5");
    
                // 将map按照ASCILL码排序
                Map<String, String> sortMap = new TreeMap<String,String>(resultMap);
                log.info("排序之后:{}",sortMap);
    
                 sign = WXPayUtil.generateSignature(sortMap, WxPayConstant.API_KEY,WXPayConstants.SignType.HMACSHA256);
    
                resultMap.put("paySign", sign);
                resultMap.put("orderNo",order.getOrderNo());
                return resultMap;
            }catch (Exception e){
                orderService.updateOrder(order.getOrderNo(),"", OrderStatusEnum.FAIL_PAY);
                throw new BusinessException("微信支付下单异常,请重试");
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    微信回调

     /**
         * 微信回调
         * @param request
         * @return
         */
        @Override
        public String wxPayCallBack(HttpServletRequest request) {
            log.info("微信支付-成功回调");
            // 校验结果、XML
            Map<String, String> back = new HashMap();
            String result = "";
            try {
                InputStream inStream = request.getInputStream();
                ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inStream.read(buffer)) != -1) {
                    outSteam.write(buffer, 0, len);
                }
                outSteam.close();
                inStream.close();
                result = new String(outSteam.toByteArray());
                //xml转map 微信SDK自带
                Map<String, String> map = WXPayUtil.xmlToMap(result);
                // 判断签名是否正确、记得指定加密方式,因为下单默认的是h256方式,校验默认是MD5方式
                if (WXPayUtil.isSignatureValid(map, WxPayConstant.API_KEY, WXPayConstants.SignType.HMACSHA256)) {
                    back.put("return_code", "SUCCESS");
                    if ("SUCCESS".equalsIgnoreCase(map.get("result_code")));{
                        log.info("支付成功,回调成功");
                        // 拿到订单号,修改订单状态
                        String orderNo = map.get("out_trade_no");
                        String  payTime = map.get("time_end");
                        orderService.updateOrder(orderNo, payTime,OrderStatusEnum.SUCESS_PAY);
                    }
                } else {
                    back.put("return_code", "FAIL");
                    back.put("return_msg", "参数格式校验错误");
                }
                // WX响应格式是xml的字符串
                result  = WXPayUtil.mapToXml(back);
            } catch (Exception e) {
               throw new BusinessException("支付回调用异常");
            }finally {
                // 必须响应给WX服务器
                return result;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
  • 相关阅读:
    爬虫--爬取自己想去的目的的车票信息
    [附源码]计算机毕业设计基于springboot框架的食品安全监督平台的设计与实现
    transformer架构中 encoder decoder self-attention cross-attention的作用
    MyBatis 查询 MySQL 实现返回 List<Map> 或 Map 类型数据操作
    haas506 2.0开发教程-sntp(仅支持2.2以上版本)
    R语言绘制矩形树状图
    自定义switch实现以下两种方式
    K_A08_002 基于 STM32等单片机驱动MAX1508模块按键控制直流电机正反转加减速启停
    ffmpeg在特定时间点插入素材
    网络安全(黑客)自学
  • 原文地址:https://blog.csdn.net/qq_45399396/article/details/133764757