微信公众号支付--2--统一下单

调用统一下单api之前,需要先获取openid,请先查看https://blog.csdn.net/hjfcgt123/article/details/104172909这篇博文。

一、配置JSAPI支付授权目录

登录企业公众号关联的商户平台https://pay.weixin.qq.com/index.php/core/info,产品中心--开发配置--支付配置--JSAPI支付--支付授权目录,配置如下

JSAPI支付在请求支付的时候会校验请求来源是否有在商户平台做了配置,所以必须确保支付目录已经正确的被配置,否则将验证失败,请求支付不成功。

二、引入依赖

这里使用一个新的sdk包

github地址:https://github.com/Pay-Group/best-pay-sdk

码云地址:https://gitee.com/liaoshixiong/best-pay-sdk 

maven依赖

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

三、主要调用api

创建预支付订单:com.lly835.bestpay.service.impl.BestPayServiceImpl.pay(PayRequest request)

四、代码实现

1、添加配置文件

在application.yml文件中添加配置

wechat:
  #公众号appId
  mpAppId: xxxxxx
  #公众号appSecret
  mpAppSecret: xxxxxx
  #商户号
  mchId: xxxxxx
  #商户秘钥
  mchKey: xxxxxx
  #商户API证书下载之后放置在服务器上的地址(退款的时候需要验证证书)
  keyPath: D:\\h5.p12
  #异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数
  notifyUrl: http://hungteshun.viphk.ngrok.org/sell/pay/notify

2、将配置文件写入对象

@Data
@Component
@ConfigurationProperties(prefix = "wechat")
public class WechatAccountConfig {

    private String mpAppId;
    private String mpAppSecret;
    /**
     * 商户id
     */
    private String mchId;
    /**
     * 商户秘钥
     */
    private String mchKey;
    /**
     * 商户证书路径
     */
    private String keyPath;
    /**
     * 微信支付异步通知地址
     */
    private String notifyUrl;
}

3、构建com.lly835.bestpay.service.impl.BestPayServiceImpl对象,并交由spring管理 

@Component
public class WechatPayConfig {

    @Autowired
    private WechatAccountConfig wechatAccountConfig;

    @Bean
    public BestPayServiceImpl bestPayService () {
        BestPayServiceImpl bestPayService = new BestPayServiceImpl();
        bestPayService.setWxPayH5Config(wxPayH5Config());
        return bestPayService;
    }

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

4、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) {
        //1、查询订单
        OrderDTO orderDTO = orderService.findOne(orderId);
        if (ObjectUtils.isEmpty(orderDTO)) {
            throw new SellException(ResultEnum.ORDER_NOT_EXIST);
        }
        //2、发起微信支付
        PayResponse payResponse = payService.create(orderDTO);
        map.put("payResponse", payResponse);
        map.put("returnUrl", returnUrl);
        return new ModelAndView("pay/create", map);
    }
}

5、controller返回的视图

使用的是freemarker模板,文件路径:src\main\resources\templates\pay\create.ftl

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

6、service实现类

@Service
@Slf4j
public class PayServiceImpl implements PayService {

    private static final String orderName = "微信点餐订单";

    @Autowired
    private BestPayServiceImpl bestPayService;

    @Override
    public PayResponse create(OrderDTO orderDTO) {
        PayRequest payRequest = new PayRequest();
        payRequest.setOpenid(orderDTO.getBuyerOpenid());
        payRequest.setOrderId(orderDTO.getOrderId());
        payRequest.setOrderAmount(orderDTO.getOrderAmount().doubleValue());
        payRequest.setOrderName(orderName);
        payRequest.setPayTypeEnum(BestPayTypeEnum.WXPAY_H5);
        return bestPayService.pay(payRequest);
    }
	
}

四、前端调用

官网链接:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6

前端调用方法

this.$http.post("/sell/buyer/order/create", {
                    'openid': getCookie('openid'),
                    'phone': this.phone,
                    'name': this.name,
                    'address': this.address,
                    'items': JSON.stringify(goods)}
                ).then((respones) => {
                    respones = respones.body;
                    if (respones.code == ERR_OK) {
                      location.href = config.wechatPayUrl +
                        '?openid=' + getCookie('openid') +
                        '&orderId=' + respones.data.orderId +
                        '&returnUrl=' + encodeURIComponent(config.sellUrl + '/#/order/' + respones.data.orderId);
                    }else {
                      alert(respones.msg);
                    }
                });

注意:WeixinJSBridge内置对象在其他浏览器中无效,所以需要在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。

其中config.wechatPayUrl 和 config.sellUrl地址为

sellUrl: 'http://sell.com',
wechatPayUrl: 'http://hungteshun.viphk.ngrok.org/sell/pay/create'

思路是:请求生成预支付订单之后跳转到订单详情页面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值