springboot整合微信支付笔记

先来看一下微信支付的流程,可见在整个支付流程中后台需要处理的事情有:
1、调用统一下单api
2、生成JSAPI页面调用的支付参数,并请求支付
3、异步通知商户支付结果
4、返回微信异步通知的处理结果
在这里插入图片描述
下面来实际编程实现以上的过程,这里面我们使用了第三方Sdk,best-pay-sdk
https://github.com/Pay-Group/best-pay-sdk
maven引入依赖

        <dependency>
            <groupId>cn.springboot</groupId>
            <artifactId>best-pay-sdk</artifactId>
            <version>1.3.0</version>
        </dependency>

支付最核心的就是要出现微信支付的界面,那么就需要在商户页面调起支付,那么如何调起支付界面呢,根据开发文档,调起支付需要执行下面的JS,JS中需要传入相应的信息
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
在这里插入图片描述
那么思路比较明确,只需要在controller层执行支付的逻辑,调用统一下单的api,并返回JSAPI页面调用的支付参数动态注入到这段JS支付模板就可以了,那么每次调用controller层的接口时,就会调起支付。

@Controller
@RequestMapping("/pay")
public class PayController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private PayService payService;
    @GetMapping("/create")
    public ModelAndView create(@RequestParam("orderId")String orderId,
                               @RequestParam("returnUrl")String returnUrl,
                               Map<String,Object> map) {
        //查询订单
        OrderDTO orderDTO=orderService.findOne(orderId);
        if(orderDTO==null){
            throw new OrderException(ResultEnum.ORDER_NOT_EXIST);
        }
        //配置创建支付所需的必要信息
        PayResponse payResponse=payService.create(orderDTO);
        //把信息放入支付模板中
        map.put("payResponse",payResponse);
        //returnUrl为支付成功之后需要跳转到的页面
        returnUrl="http://sell.com/#/order/"+orderId;
        map.put("returnUrl",returnUrl);
        return new ModelAndView("pay/create",map);
    }
}

接下来需要将后台传过来的支付参数动态注入到支付模板中,这里使用了freemarker

<script>
    function onBridgeReady(){
        WeixinJSBridge.invoke(
            'getBrandWCPayRequest', {
                "appId":"${payResponse.appId}",     //公众号名称,由商户传入
                "timeStamp":"${payResponse.timeStamp}",         //时间戳,自1970年以来的秒数
                "nonceStr":"${payResponse.nonceStr}", //随机串
                "package":"${payResponse.packAge}",
                "signType":"MD5",         //微信签名方式:
                "paySign":"${payResponse.paySign}" //微信签名
            },
            function(res){
               /* if(res.err_msg == "get_brand_wcpay_request:ok" ){
                    // 使用以上方式判断前端返回,微信团队郑重提示:
                    //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                }
                */
               location.href="${returnUrl}";
            });
    }
    if (typeof WeixinJSBridge == "undefined"){
        if( document.addEventListener ){
            document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
        }else if (document.attachEvent){
            document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
            document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
        }
    }else{
        onBridgeReady();
    }
</script>

service层中的逻辑,bestPayService.pay(payRequest)调用了统一支付的API,并返回了JSAPI页面调用的支付参数

@Service
@Slf4j
public class PayServiceImpl implements  PayService {
    @Autowired
    private OrderService orderService;
    private static final String ORDER_NAME="微信订单";

    @Autowired
    private BestPayServiceImpl bestPayService;
    @Override
    public PayResponse create(OrderDTO orderDTO) {
        PayRequest payRequest=new PayRequest();
        payRequest.setOpenid(orderDTO.getBuyerOpenid());
        payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
        payRequest.setOrderId(orderDTO.getOrderId());
        payRequest.setOrderName(ORDER_NAME);
        payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_MP);
        log.info("【微信支付】payRequest={}", JsonUtil.toJson(payRequest));
        PayResponse payResponse=bestPayService.pay(payRequest);
        log.info("【微信支付】payResponse={}",JsonUtil.toJson(payResponse));
        return payResponse;
    }
    }

配置JAVAconfig,设置商户信息

@Configuration
public class WechatPayConfig {
    @Autowired
    private  WechatAccountConfig wechatAccountConfig;

    @Bean WxPayConfig wxPayConfig(){
        WxPayConfig wxPayConfig=new WxPayConfig();
        wxPayConfig.setAppId(wechatAccountConfig.getMpAppId());
        wxPayConfig.setAppSecret(wechatAccountConfig.getMpAppSecret());
        wxPayConfig.setMchId(wechatAccountConfig.getMchId());
        wxPayConfig.setMchKey(wechatAccountConfig.getMchKey());
        wxPayConfig.setKeyPath(wechatAccountConfig.getKeyPath());
        wxPayConfig.setNotifyUrl(wechatAccountConfig.getNotifyUrl());
        return wxPayConfig;
    }
    @Bean
    public BestPayServiceImpl bestPayService(){

        BestPayServiceImpl bestPayService=new BestPayServiceImpl();
        bestPayService.setWxPayConfig(wxPayConfig());
        return  bestPayService;
    }
}
@Data
@Component
@ConfigurationProperties(prefix = "wechat")
public class WechatAccountConfig {
	//公众号ID
    private String mpAppId;
	//公众号密钥
    private String mpAppSecret;
	//商户号
    private String mchId;
    //商户密钥
    private String mchKey;
    //商户证书路径
    private String keyPath;
	//异步回调接口
    private String notifyUrl;

}

然后在yml中配置相应的信息即可
在这里插入图片描述
此时打开微信端调用controller层的支付接口就可以实现支付了

支付完成之后还需要处理微信异步返回的结果,接收到异步返回的结果后可以处理业务逻辑,比如修改支付状态等,随后将处理结果返回微信,如果不处理请求,微信会一直返回异步通知。
在这里插入图片描述
controller层

    @PostMapping("/notify")
    public ModelAndView notify(@RequestBody String notifyData)
    {
        payService.notify(notifyData);
        return new ModelAndView("pay/success");
    }

service层

    @Override
    public PayResponse notify( String notifyData)
    {
        PayResponse payResponse=bestPayService.asyncNotify(notifyData);
        log.info("【微信异步通知】,payResonse={}",JsonUtil.toJson(payResponse));
        OrderDTO orderDTO=orderService.findOne(payResponse.getOrderId());
        orderService.paid(orderDTO);
        return payResponse;
    }

在这里插入图片描述
支付成功后返回的JS代码,至此支付的所有流程结束

<xml>
    <return_code><![CDATA[SUCCESS]]></return_code>
    <return_msg><![CDATA[OK]]></return_msg>
</xml>

支付测试:
调用统一支付API之后返回的内容,可见调用了统一支付API后返回了之后生成JSAPI页面调用的所需要的支付参数

2020-02-25 03:39:22.518  INFO 22880 --- [nio-8889-exec-6] okhttp3.OkHttpClient                     : <xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wxd898fcb01713c658]]></appid>
<mch_id><![CDATA[1483469312]]></mch_id>
<nonce_str><![CDATA[g1K2MKyNdNkMkn7t]]></nonce_str>
<sign><![CDATA[61D46CFE319025CE457FC8F90B6CBADC]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx250337332209497ce17477f81982372500]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
2020-02-25 03:39:22.518  INFO 22880 --- [nio-8889-exec-6] okhttp3.OkHttpClient                     : <-- END HTTP (456-byte body)
2020-02-25 03:39:22.531  INFO 22880 --- [nio-8889-exec-6] com.pers.food.service.PayServiceImpl     : 
【微信支付】payResponse={
  "appId": "wxd898fcb01713c658",
  "timeStamp": "1582573162",
  "nonceStr": "75htValspgU82402",
  "packAge": "prepay_id\u003dwx250337332209497ce17477f81982372500",
  "signType": "MD5",
  "paySign": "855A556EBA7799B011235554A00268DB"
}

支付成功后,接收异步通知后返回的信息,可见返回了支付金额,订单号等信息

2020-02-25 03:40:24.144  INFO 22880 --- [nio-8889-exec-4] com.pers.food.service.PayServiceImpl     : 
【微信异步通知】,payResonse={
  "orderAmount": 0.01,
  "orderId": "1582573104751271126",
  "outTradeNo": "4200000512202002252531868211",
  "payPlatformEnum": "WX"
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值