Micro-channel pay - H5 micro-channel pay "non-micro-channel internal browser -QQ / UC browser, etc."

Foreword

Micro-channel pay - micro letter H5 external browser payment " paper "
micro-channel pay H5 internal browser " to be written "
the PC scan code to pay " to be written ."

Been planning to write about micro-channel pay-related articles, hoping to deepen your own impression, dragged on day after day ...

Recently vacated finally time to fill in the pit, and I will essay is divided into micro-channel pay H5 external browser , micro-channel pay H5 internal browser , PC-side scan code to pay three to write.

Benpian is a micro-channel H5 external browser payment: when payment will evoke micro-channel APP payment.

Literacy added: on micro-channel H5 pay, divided into internal browser payment + external browser payment, both still a little bit different, the internal browser opens the page in the micro letter, pay, pay called by the front-end launch " JSSDK " ; and an external browser " such as QQ browser, " then returned through the background mweb_url handed over to the front evoke micro-channel APP initiate a payment operation, the official micro-channel provides a test page https://wxpay.wxutil.com/mch/pay/h5 .v2.php , you can open the mobile browser experience something.

This article development environment: Java + SpringBoot + IDEA + WxJava (open source SDK)

More few long-winded, initially did not choose WxJava open source SDK , because there is no official document to read, anyway, all kinds of error, such as: payment verification signature failure , etc. - Finally, a compromise is not repeated-create the wheel, as for the body.

1, introducing dependencies

pom.xml file introduced WxJava dependent " as used herein is version 3.3.0 ."

<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-pay</artifactId>
    <version>3.3.0</version>
</dependency>

2, Basic Configuration

WxJava provides a micro-channel pay Demo , refer https://github.com/binarywang/weixin-java-pay-demo

2.1, increasing the payment configuration information

Provided below application.yml , the application.properties two formats, as follows:

wx.pay.appId=#微信公众号或者小程序等的appid
wx.pay.mchId=#微信支付商户号
wx.pay.mchKey=#微信支付商户密钥
wx.pay.notifyUrl=#支付成功回调URL
wx.pay.keyPath=# p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)

# -----------------------------------------

wx:
  pay:
    appId: #微信公众号或者小程序等的appid
    mchId: #微信支付商户号
    mchKey: #微信支付商户密钥
    notifyUrl: #支付成功回调URL
    keyPath: # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)

Supplementary: keyPath used to specify the certification path, with respect to the use of the certificate: red envelopes / corporate payments / refunds and other operations, this does not involve, leave it blank.

2.2, the code configuration

An entity class is used to read the configuration information is used to initialize a payment SDK 's Configuration

Reads configuration class: WxProperties.java

@Data
@Configuration
@ConfigurationProperties(prefix = "wx.pay")
public class WxProperties {
    /**
     * 设置微信公众号或者小程序等的appid
     */
    private String appId;

    /**
     * 微信支付商户号
     */
    private String mchId;

    /**
     * 微信支付商户密钥
     */
    private String mchKey;

    /**
     * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
     */
    private String keyPath;

    /**
     * 微信回调接口地址
     */
    private String notifyUrl;
}

Initialization pay SDK categories: WxConfig.java

@Configuration
public class WxConfig {

    @Autowired
    private WxProperties properties;

    @Bean
    @ConditionalOnMissingBean
    public WxPayService wxService() {
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
        payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
        payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
        payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
        payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));
        // 可以指定是否使用沙箱环境
        payConfig.setUseSandboxEnv(false);
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }
}

2.3, micro-channel payment interface

微信非内部浏览器支付,比如在手机QQ浏览器中发起支付,会唤起微信APP进行支付操作,此时调用微信接口返回的是一个 URL,返回结果如下:

weixin://wxpay/bizpayurl?pr=IzX8nS

下方是获取支付URL的后端接口方法:

@RequestMapping(value = "createOrder", method = {RequestMethod.POST})
public Result<Object> createQRCode(UserModel user, HttpServletResponse response,@RequestBody WechatOrderRequest obj) {

    Orders orders = null;
    if (StringUtils.isNotBlank(obj.getOrderId())) {
        orders = ordersService.searchOrder(user, obj.getOrderId());
    } else {
        orders = ordersService.createOrder(user, obj);
    }
    WechatOrderResponse wechatOrderResponse = new WechatOrderResponse();
    wechatOrderResponse.setCodeUrl(wechatService.createOrderInfo(orders,user.getPayType()));
    wechatOrderResponse.setOrderId(orders.getOrderId());
    return ResultUtil.success(wechatOrderResponse);
}

该方法仅供参考,上方方法中对订单id进行了一个判空操作,因为我这边有可能是用户未支付订单,继续支付的操作,代码主要是 wechatService.createOrderInfo 方法,实现如下:

public String createOrderInfo(Orders orders,String payType) {
    WxPayMwebOrderResult result = null;
    try {
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setOutTradeNo(orders.getOrderId());
        orderRequest.setBody("我是商品描述");
        orderRequest.setTotalFee(orders.getAmount().multiply(new BigDecimal("100")).intValue());//金额需要扩大100倍:1代表支付时是0.01
        orderRequest.setSpbillCreateIp(DispatchParams.getInstance().getWechatSpbillCreateIp());
        orderRequest.setProductId(orders.getOrderId());
        orderRequest.setTradeType(WxPayConstants.TradeType.MWEB);// h5网页支付
        result = wxPayService.createOrder(orderRequest);
        return result.getMwebUrl();
    } catch (WxPayException e) {
        logger.error("[微信支付异常] 异常", e);
        // 抛出一个自定义全局异常「自己定义」
        throw new CommonException(微信支付异常提示信息 , 状态码 );
    }
}

具体参数就不啰嗦了,详细请看官方支付文档。

综上,当前端调用 createOrder 方法,将 weixin://wxpay/bizpayurl?pr=IzX8nS 返回给前端,那么前端怎么调用呢?

下面是我的一个测试例子,其中 res.codeUrl 为后端返回的 URL

window.open(res.codeUrl, '_blank’);

是的,就是这么简单,新窗口打开就可以了,看一下运行调起微信的截图「我手机装了两个微信」:

支付成功后会回调后端接口,具体由后端参数配置的 return_url 控制。

2.4、微信回调接口

当支付完成后,微信会自动回调该接口,我们可以根据返回的信息修改订单状态,看一下方法,代码仅供参考:

@RequestMapping(value = "/notify")
@ResponseBody
public String notify(String body) throws Exception {

        WxPayOrderNotifyResult result = null;
        try {
            result = wxPayService.parseOrderNotifyResult(body);
        } catch (WxPayException e) {
            logger.error("[微信解析回调请求] 异常", e);
            return WxPayNotifyResponse.fail(e.getMessage());
        }
        logger.info("处理微信支付平台的订单支付");
        logger.info(JSONObject.toJSONString(result));

        String appid = result.getAppid();//应用ID
        String attach = result.getAttach();//商家数据包
        String bank_type =result.getBankType();//付款银行
        Integer cash_fee = result.getCashFee();//现金支付金额
        String fee_type = result.getFeeType();//货币种类
        String is_subscribe = result.getIsSubscribe();//是否关注公众账号
        String mch_id = result.getMchId();//商户号
        String nonce_str = result.getNonceStr();//随机字符串
        String openid = result.getOpenid();//用户标识
        String out_trade_no = result.getOutTradeNo();// 获取商户订单号
        String result_code = result.getResultCode();// 业务结果
        String return_code = result.getReturnCode();// SUCCESS/FAIL
        String sign = result.getSign();// 获取签名
        String time_end = result.getTimeEnd();//支付完成时间
        Integer total_fee = result.getTotalFee();// 获取订单金额
        String trade_type = result.getTradeType();//交易类型
        String transaction_id = result.getTransactionId();//微信支付订单号

        //如果成功写入数据库
        if("SUCCESS".equals(return_code)) {// 如果微信返回的结果是success,则修改订单状态
            Orders orders = ordersDao.selectByOrderId(out_trade_no);
            // 验证签名
            if(orders != null){
                if(!"1".equals(orders.getOrderStatus())){//判断是否订单已经完成了
                    // 判断金额是否跟数据库订单金额一致,放置人为修改
                    if(orders.getAmount().multiply(new BigDecimal("100")).compareTo(new BigDecimal(total_fee)) == 0){
                        //更新订单状态
                        业务逻辑处理部分...
                        return WxPayNotifyResponse.success("订单已经处理成功!");
                    }else{
                        logger.error("微信:金额不一致!");
                        return WxPayNotifyResponse.fail("订单金额不一致");
                    }
                }else {
                    return WxPayNotifyResponse.success("订单已经处理成功!");
                }
            }else{
                return WxPayNotifyResponse.fail("商户订单号不匹配");
            }
        }
        System.out.println("回调成功");
        System.out.println("----返回给微信的xml:" + result);
        return WxPayNotifyResponse.success("支付成功!");
}

如上代码,微信返回的是 XML ,经过 wxPayService.parseOrderNotifyResult() 方法转换后得到 WxPayOrderNotifyResult 实体,具体参数我上边罗列出来了「尽管没用到」,然后就是修改数据库订单状态等操作。

最后

博客地址:https://www.cgblog.com/niceyoo

如果觉得这篇文章有丶东西,不放关注一下我,关注是对我最大的鼓励~

18年专科毕业后,期间一度迷茫,最近我创建了一个公众号用来记录自己的成长。

Guess you like

Origin www.cnblogs.com/niceyoo/p/12232215.html