Springboot 微信页面H5wap商家支付

在这里介绍的是使用SpringBoot 来完成对微信页面wap商家支付

前提:使用了springboot框架技术来整合,实现了微信授权拉去用户信息,

开通了微信认证的公众号以及申请了商家支付以及域名备案。

商家支付需要开通微信认证后的公众号才能申请,个人的话目前不能申请。

参考下方官方微信公众号支付开发文档,本次是用了wap网页支付。

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1

自己看了文档说实话还是有点蒙蒙的,还是有结合一些相关视频进行学习,并简单实现微信支付。

wap支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。

主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。


一、在项目导入相关支付pom依赖

用的是在github上别人写的一个封装包,可能版本有点旧,有兴趣的同学可以去github搜best-pay。

cn.springboot

best-pay-sdk

1.2.0

二、上微信支付商家平台

下方为官方微信支付商家网页

https://pay.weixin.qq.com/index.php/core/home/login

2.1 登录微信支付书,并点击产品中心,选中支付产品,JSAPI支付,里面会有相关支付展示

图1

2.2 开发配置

在使用JSAPI支付和Native支付需要配置开发需要的域名

在此需要点击添加,并注意右边的问号的提示


图2


2.3 添加备好案的域名

添加的时候看下提示,可以选择http和https

举例你的项目是   

www.xxxx.com/项目名/映射地址/

www.xxxx.com/demo/pay/

注意:配置上面的地址后,只要在pay地址的目录都可以。

例如    /pay/demo/           /pay/demo/demo2

图3

2.4 商户信息

第一步:需要微信支付商户号和密钥

第二步:点击商户信息和API设置密码


图4

第三步:设置商户的key密码并安装证书

按步骤申请证书下载和密钥设置

图5

三、项目配置

由于项目是使用springboot整合三大框架,所以在yml下配置已知的微信公众号appid、密钥、商户账号、密钥、证书目录以及需要用到的回调地址等。

图6

3.1 商户账户实体类

@Data

@Component

@ConfigurationProperties(prefix ="wechat")

public class WechatAccounConfig {

private StringmpAppId;

private StringmpAppSecret;

/**

* 商户号

*/

    private  StringmchId;

/**

* 商户密钥

*/

    private StringmchKey;

/**

* 商户证书路径

*/

    private StringkeyPath;

/**

* 微信支付异步通知地址

*

*/

    private StringnotifyUrl;

}

3.2 支付环境配置实体类

@Component

public class WechatPayConfig {

@Autowired

    private WechatAccounConfigaccounConfig;

@Bean

    public BestPayServiceImpl bestPayService(){

BestPayServiceImpl bestPayService =new BestPayServiceImpl();

bestPayService.setWxPayH5Config(wxPayH5Config());

return bestPayService;

}

@Bean

    public WxPayH5Config wxPayH5Config(){

WxPayH5Config wxPayH5Config =new WxPayH5Config();

wxPayH5Config.setAppId(accounConfig.getMpAppId());

wxPayH5Config.setAppSecret(accounConfig.getMpAppSecret());

wxPayH5Config.setMchId(accounConfig.getMchId());

wxPayH5Config.setMchKey(accounConfig.getMchKey());

wxPayH5Config.setKeyPath(accounConfig.getKeyPath());

wxPayH5Config.setNotifyUrl(accounConfig.getNotifyUrl());

return wxPayH5Config;

}

}

3.3 写一个支付接口的类并且实现

public interface PayService {

/**

* 创建支付订单

    * @param orderDTO

    */

    PayResponse create(OrderDTO orderDTO);

/**

* 异步通知

    * @param notify

    */

    PayResponse notify(String notify);

}

3.4 支付接口实现类

@Service("payService")

@Slf4j

public class PayServiceImplimplements PayService {

private static final StringORDER_NAME ="微信预约";

@Autowired

    private BestPayServiceImplbestPayService;

@Autowired

    private AppointOrderServiceorderService;

@Autowired

    private AppointmentMapperappointmentMapper;

@Override

    public PayResponse create(OrderDTO orderDTO) {

Appointment appointment =appointmentMapper.selectByPrimaryKey(orderDTO.getAppointId());

PayRequest payRequest =new PayRequest();

payRequest.setOpenid(orderDTO.getCustomerOpenid());

payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());

payRequest.setOrderId(orderDTO.getOrderId());

payRequest.setOrderName(ORDER_NAME);

payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);

log.info("[微信支付]发起支付,request={}", JsonUtil.toJson(payRequest));

PayResponse payResponse =bestPayService.pay(payRequest);

log.info("[微信支付]发起支付,response ={}",JsonUtil.toJson(payRequest));

return payResponse;

}

@Override

    public PayResponse notify(String notify) {

//1.验证签名

//2.支付的状态

//3.支付金额

//4.支付人(下单人 == 支付人)

        PayResponse payResponse =bestPayService.asyncNotify(notify);

log.info("[微信支付]异步通知,payResponse={}",JsonUtil.toJson(payResponse));

//查询订单

        OrderDTO orderDTO =orderService.findOne(payResponse.getOrderId());

//判断订单是否存在

        if (orderDTO ==null){

log.error("[微信支付]异步通知,订单不存在,orderId={}",payResponse.getOrderId());

throw new AppointException(ResultEnum.ORDER_NOT_EXIST);

}

//判断金额是否一致(考虑 0.10 0.1)  注意比较类型

        if (!MathUtil.equals(payResponse.getOrderAmount(),orderDTO.getOrderAmount().doubleValue())){

log.error("[微信支付]异步通知,订单金额不一致,orderId={},微信通知金额={},系统金额={}"

                    ,payResponse.getOrderId(),payResponse.getOrderAmount(),orderDTO.getOrderAmount());

throw new AppointException(ResultEnum.WXPAY_NOTIFY_MONEY_ERROR);

}

//修改订单支付状态

        orderService.paid(orderDTO);

return payResponse;

}

}

3.5 前端页面传值给下单接口,并返回数据给回调地址

在之前必须实现一个下单接口,并通过回调地址实现对支付的发起

wechatPayUrl: www.xxx.com/项目名/pay/create  的接口

returnUrl: 是你支付完后返回的地址

图7

3.6  location.href 接口Controller代码实现以及微信异步通知

@RestController

@RequestMapping("/pay")

public class PayController {

@Autowired

    private AppointOrderServiceorderService;

@Autowired

    private PayServicepayService;

@GetMapping("/create")

public ModelAndView create(@RequestParam("orderId")String orderId,

@RequestParam("returnUrl")String returnUrl,

Map map){

//1.查询订单

        OrderDTO orderDTO =orderService.findOne(orderId);

if (orderDTO ==null){

throw new AppointException(ResultEnum.ORDER_NOT_EXIST);

}

//2.发起支付

        PayResponse payResponse =payService.create(orderDTO);

map.put("payResponse",payResponse);

map.put("returnUrl",returnUrl);

return new ModelAndView("pay/create",map);

}

/**

* 微信异步通知

* 需要配置

*/

    @PostMapping("/notify")

public ModelAndView notify(@RequestBody String notifyData){

payService.notify(notifyData);

//返回给微信处理

        return new ModelAndView("pay/success");

}

}

3.7 需要写js和xml调起微信支付窗口和返回结果

可以通过API列表了解一下

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1

项目是用freemarker

create.ftl

success.ftl

 

四、实现支付功能

点击提交按钮,调用下单接口,前端用图7那样方式进行跳转发起支付接口


图8

调起支付窗口并输入支付密码

注:本图为真机操作

图9

注:该文章主要为个人学习内容

你可能感兴趣的:(Springboot 微信页面H5wap商家支付)