<返回更多

多应用多平台支付模块-微信V2JsApi支付

2022-09-10  今日头条  三牛爱编程
加入收藏

此前,已设计过多应用多平模块的基础开篇。

本篇,准备对接微信V2JsApi支付基础模块,并基于此模块实现具体的业务功能逻辑。

开发思路如下

 

微信下单网络请求配置

定义微信统一下单网络请求配置,提供实现类进行调用获取下单数据。

package com.threeox.biz.order.config;

import com.threeox.biz.order.entity.wx.WxOrderInfo;
import com.threeox.drivenlibrary.engine.annotation.base.ParamConfig;
import com.threeox.drivenlibrary.engine.annotation.request.NETWorkRequestConfig;
import com.threeox.drivenlibrary.engine.annotation.request.RequestConfig;
import com.threeox.drivenlibrary.engine.annotation.scan.RequestScanConfig;
import com.threeox.drivenlibrary.enums.dictionary.DataType;
import com.threeox.drivenlibrary.enums.dictionary.RequestMethod;

/**
 * 支付请求配置
 *
 * @author 赵屈犇
 * @version 1.0
 * @date 创建时间: 2022/4/23 16:54
 */
@RequestScanConfig
public class PayRequestConfig {

    /**
     * 微信统一下单
     */
    @RequestConfig(requestName = "统一下单", netWorkConfig = @NetWorkRequestConfig(rootUrl = "https://api.mch.weixin.qq.com/", serverUrl = "pay/unifiedorder",
            parsingRespDataType = DataType.XML, responseClass = WxOrderInfo.class, methodType = RequestMethod.POST_XML, body = {
            @ParamConfig(paramCode = "Appid", valueCode = "appid"),
            @ParamConfig(paramCode = "mch_id", valueCode = "mch_id"),
            @ParamConfig(paramCode = "nonce_str", valueCode = "nonce_str"),
            @ParamConfig(paramCode = "sign", valueCode = "sign"),
            @ParamConfig(paramCode = "sign_type", valueCode = "sign_type"),
            @ParamConfig(paramCode = "body", valueCode = "body"),
            @ParamConfig(paramCode = "detail", valueCode = "detail"),
            @ParamConfig(paramCode = "out_trade_no", valueCode = "out_trade_no"),
            @ParamConfig(paramCode = "fee_type", valueCode = "fee_type"),
            @ParamConfig(paramCode = "openid", valueCode = "openid"),
            @ParamConfig(paramCode = "total_fee", valueCode = "total_fee"),
            @ParamConfig(paramCode = "notify_url", valueCode = "notify_url"),
            @ParamConfig(paramCode = "trade_type", valueCode = "trade_type"),
            @ParamConfig(paramCode = "product_id", valueCode = "product_id"),
            @ParamConfig(paramCode = "spbill_create_ip", valueCode = "spbill_create_ip"),
    }))
    public static final String WX_API_PLACE_ORDER = "COM.THREEOX.BIZ.ORDER.CONFIG.PAYREQUESTCONFIG.WX_API_PLACE_ORDER";

}

支付方式工厂实现

此工厂继承基础实现类,并实现下单子类函数。

package com.threeox.biz.order.factory.impl.wx;

import com.alibaba.fastjson.JSONObject;
import com.threeox.biz.order.config.OrderDictConstants;
import com.threeox.biz.order.config.PayRequestConfig;
import com.threeox.biz.order.config.extend.PaymentExtend;
import com.threeox.biz.order.entity.OrderInfo;
import com.threeox.biz.order.entity.wx.WxOrderInfo;
import com.threeox.biz.order.enums.PayWay;
import com.threeox.biz.order.factory.impl.base.BasePaymentFactory;
import com.threeox.biz.order.utils.PayUtils;
import com.threeox.biz.order.utils.wx.WXPayConstants;
import com.threeox.biz.order.utils.wx.WXPayUtil;
import com.threeox.drivenlibrary.engine.constants.config.DrivenModelDBConstants;
import com.threeox.drivenlibrary.engine.entity.driven.config.OpenPlatformConfigMessage;
import com.threeox.drivenlibrary.engine.request.execute.ExecuteRequestFactory;
import com.threeox.drivenlibrary.enums.ResponseResult;
import com.threeox.drivenlibrary.exception.ResponseException;
import com.threeox.drivenlibrary.manage.entity.UserInfoMessage;
import com.threeox.drivenlibrary.manage.factory.user.UserFactory;
import com.threeox.httplibrary.entity.HttpResponseInfo;
import com.threeox.utillibrary.date.TimeUtils;
import com.threeox.utillibrary.JAVA.IDGenerate;

import java.math.BigDecimal;

/**
 * 微信JSApi支付
 *
 * @author 赵屈犇
 * @version 1.0
 * @date 创建时间: 2022/4/23 17:38
 */
@PaymentExtend(OrderDictConstants.PayWay.WX_JS_API_V2)
public class WxJsApiV2PaymentFactory extends BasePaymentFactory {

    @Override
    protected JSONObject placeOrder(OrderInfo orderInfo, OpenPlatformConfigMessage openPlatform) throws Exception {
        UserInfoMessage userInfo = UserFactory.builder().getUser();
        JSONObject params = new JSONObject();
        params.put("fee_type", "CNY");
        params.put("openid", userInfo.getWxOpenId());
        params.put("body", orderInfo.getOrderName());
        params.put("nonce_str", IDGenerate.getUUId());
        params.put("appid", openPlatform.getWxAppId());
        params.put("mch_id", openPlatform.getWxMchId());
        params.put("detail", orderInfo.getBizSnapshot());
        params.put("product_id", orderInfo.getOrderId());
        params.put("out_trade_no", orderInfo.getOrderNum());
        params.put("trade_type", PayWay.WX_JS_API_V2.getCode());
        params.put("spbill_create_ip", orderInfo.getIpAddress());
        params.put("sign_type", WXPayConstants.SignType.MD5.name());
        params.put("total_fee", orderInfo.getPayMoney().multiply(new BigDecimal(100)).toBigInteger());
        params.put("notify_url", PayUtils.getNotifyUrl(PayWay.WX_JS_API_V2));
        params.put("sign", WXPayUtil.generateSignature(params, openPlatform.getWxMchSecret(), WXPayConstants.SignType.MD5));
        // 执行请求
        HttpResponseInfo responseInfo = ExecuteRequestFactory.builder().initConfig(DrivenModelDBConstants.DRIVEN_MANAGE_MODEL_DB_CODE, PayRequestConfig.WX_API_PLACE_ORDER)
                .requestParam(params).execute();
        if (responseInfo != null && responseInfo.isSuccess()) {
            WxOrderInfo wxOrderInfo = responseInfo.getResult();
            if ("SUCCESS".equals(wxOrderInfo.getReturn_code()) && wxOrderInfo.getReturn_code().equals(wxOrderInfo.getResult_code())) {
                JSONObject payResult = new JSONObject();
                payResult.put("appId", openPlatform.getWxAppId());
                payResult.put("nonceStr", IDGenerate.getUUId());
                payResult.put("package", "prepay_id=" + wxOrderInfo.getPrepay_id());
                payResult.put("timeStamp", String.valueOf(TimeUtils.getNowTimeMills()));
                payResult.put("signType", WXPayConstants.SignType.MD5.name());
                payResult.put("paySign", WXPayUtil.generateSignature(payResult, openPlatform.getWxMchSecret(), WXPayConstants.SignType.MD5));
                return payResult;
            }
        }
        throw new ResponseException(ResponseResult.PLACE_ORDER_FAILURE);
    }
}

回调接口

此接口继承基础回调实现类,并实现是否支付成功函数。

并,在其内部拼接签名验证是否正确。从而保证错误回调请求。

package com.threeox.biz.order.api.notify;

import com.alibaba.fastjson.JSONObject;
import com.threeox.biz.order.api.notify.base.BasePayNotifyExtend;
import com.threeox.biz.order.config.OrderResponseConfig;
import com.threeox.biz.order.entity.OrderInfo;
import com.threeox.biz.order.entity.wx.WxNotifyInfo;
import com.threeox.biz.order.utils.wx.WXPayConstants;
import com.threeox.biz.order.utils.wx.WXPayUtil;
import com.threeox.drivenlibrary.engine.annotation.api.Api;
import com.threeox.drivenlibrary.engine.entity.driven.config.OpenPlatformConfigMessage;
import com.threeox.drivenlibrary.enums.dictionary.ContentType;
import com.threeox.drivenlibrary.enums.dictionary.ResponseType;

/**
 * 微信JSApi支付回调通知
 *
 * @author 赵屈犇
 * @version 1.0
 * @date 创建时间: 2022/4/28 23:38
 */
@Api(apiUrl = "notify", apiName = "支付回调", moduleUrl = "pay/wxJsApi/v2", isVerifyToken = false, isVerifyLogin = false,
        isEncryptedResult = false, isDecryptParams = false, isStartAuth = false, requestContentType = ContentType.TEXT_XML,
        responseCode = OrderResponseConfig.WX_NOTIFY_RESPONSE, responseType = ResponseType.XML
)
public class WxJsV2PayNotifyExtend extends BasePayNotifyExtend<WxNotifyInfo> {

    @Override
    protected boolean isPaySuccess(OrderInfo orderInfo, OpenPlatformConfigMessage openPlatform) throws Exception {
        String returnCode = getRequestParams().getReturn_code();
        if ("SUCCESS".equals(returnCode)) {
            //验证签名是否正确
            // 回调验签时需要去除sign和空值参数
            JSONObject validParams = WXPayUtil.paraFilter(getParams());
            // 拼装生成服务器端验证的签名
            String sign = WXPayUtil.generateSignature(validParams, openPlatform.getWxMchSecret(), WXPayConstants.SignType.MD5);
            // 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了
            // 根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等
            if (sign.equals(getParamValue("sign"))) {
                return true;
            }
        }
        return false;
    }

}

至此的话,微信V2JsApi业已完成开发。后期会逐渐完善更多三方支付功能。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>