admin 管理员组

文章数量: 1184232

微信支付

一、JDK版本需要1.8u162+以上版本

<!--微信支付 V3--><dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-java</artifactId><version>0.2.7</version></dependency><dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-apache-httpclient</artifactId><version>0.4.9</version></dependency>

二、前期准备

官网引导:接入前准备-小程序支付 | 微信支付商户平台文档中心

①appid:小程序appid-登录小程序后台获取

②secret:小程序密钥-登录小程序后台获取

登录小程序后台:

③appV3Secret:商户apiV3密钥-登录商户后台获取

④mchid:商户号-登录商户后台获取(商户号要绑定小程序)

⑤certpath:微信平台证书-登录商户后台获取

⑥privateKeyPath:商户私钥证书-登录商户后台获取

⑦merchantSerialNumber:商户证书序列化-登录商户后台获取

登录商户后台:

三、证书存放地

四、配置与加载

# application-dev.ymlwx:miniapp:configs:- appid: wx1fcxxxxxxxxsecret: 1exxxxxxxxxxxxxxxxxxxxxxxxxxxxxtoken:  #微信小程序消息服务器配置的tokenaesKey:  #微信小程序消息服务器配置的EncodingAESKeymsgDataFormat: JSONappV3Secret: ADxxxAas654xxxxxxxxxxxxxxxxxx # V3密钥mchid: 12345678 # 商户号certpath: D:/workspace/hxj-miniprogram-java/src/main/resources/wxpay/apiclient_cert.pem # 微信平台证书(发布时换成linux地址)privateKeyPath: D:/workspace/hxj-miniprogram-java/src/main/resources/wxpay/apiclient_key.pem # 商户私钥证书(发布时换成linux地址)payCallBackUrl: https://xxxxxxxxxxxxx/wechatPay/payCallback # 支付结束回调地址timeExpire: 1200000 # 交易过期时间(单位毫秒)merchantSerialNumber: 37ABCD098765ADCBF124656099AB # 商户证书序列号

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;/*** @author xuhj*/
@Slf4j
@Data
@ConfigurationProperties(prefix = "wx.miniapp")
public class WxMaProperties {private List<Config> configs;@Datapublic static class Config {/*** 设置微信小程序的appid*/private String appid;/*** 设置微信小程序的Secret*/private String secret;/*** 设置微信小程序消息服务器配置的token*/private String token;/*** 设置微信小程序消息服务器配置的EncodingAESKey*/private String aesKey;/*** 消息格式,XML或者JSON*/private String msgDataFormat;/*** appV3Secret V3密钥*/private String appV3Secret;/*** mchid 商户号*/private String mchid;/*** 微信支付平台证书地址,注意 windows地址与linux地址不同*/private String certpath;/*** 商户API证书的路径(一般和上边的certpath在一起下载)*/private String privateKeyPath;/*** 支付回调地址*/private String payCallBackUrl;/*** 交易过期时间(单位毫秒)*/private Long timeExpire;/*** 商户证书序列号*/private String merchantSerialNumber;}
}

五、证书自动更新

import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class WxPayConfig {@Autowiredprivate WxMaProperties properties;/*** 初始化商户配置(只能加载一次)* 确保是单例** @return*/@Beanpublic RSAAutoCertificateConfig rsaAutoCertificateConfig() {RSAAutoCertificateConfig config = new RSAAutoCertificateConfig.Builder().merchantId(properties.getConfigs().get(0).getMchid()).privateKeyFromPath(properties.getConfigs().get(0).getPrivateKeyPath()).merchantSerialNumber(properties.getConfigs().get(0).getMerchantSerialNumber()).apiV3Key(properties.getConfigs().get(0).getAppV3Secret()).build();return config;}
}

六、预支付和回调

import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE;
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_NONCE;
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_TIMESTAMP;/*** <p>* 微信支付 前端控制器* </p>** @author sunziwen* @since 2023-03-23*/
@Api(tags = {"微信支付"})
@Slf4j
@RestController
@RequestMapping("/wechatPay")
@Validated
public class PayController extends BaseController {/*** 配置文件*/@Autowiredprivate WxMaProperties properties;@Autowiredprivate RSAAutoCertificateConfig rsaAutoCertificateConfig;@Autowiredprivate IOrderMasterService iOrderMasterService;@ApiOperation(value = "预支付-委托")@PostMapping("preparePayment")@ApiImplicitParams({@ApiImplicitParam(name = "openid", value = "openid"),@ApiImplicitParam(name = "description", value = "商品描述"),@ApiImplicitParam(name = "outTradeNo", value = "商户订单号"),@ApiImplicitParam(name = "total", value = "订单总金额,单位为分")})public ServiceResult<?> preparePayment(String openid, String description, String outTradeNo, Integer total) {// 初始化服务JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();PrepayRequest request = new PrepayRequest();// 应用IDrequest.setAppid(properties.getConfigs().get(0).getAppid());// 直连商户号request.setMchid(properties.getConfigs().get(0).getMchid());// 商品描述request.setDescription(description);// 商户订单号request.setOutTradeNo(outTradeNo);// 交易结束时间:2018-06-08T10:34:56+08:00request.setTimeExpire(timeStampToRfc3339(System.currentTimeMillis() + properties.getConfigs().get(0).getTimeExpire()));// 附加数据:在查询API和支付通知中原样返回,可作为自定义参数使用request.setAttach("");// 回调地址:异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 公网域名必须为httpsrequest.setNotifyUrl(properties.getConfigs().get(0).getPayCallBackUrl());// 商品标记,代金券或立减优惠功能的参数request.setGoodsTag("");// 限制支付类型
//        request.setLimitPay(LimitPayEnum.);// 电子发票入口开放标识:传入true时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效request.setSupportFapiao(true);Amount amount = new Amount();amount.setTotal(total);amount.setCurrency("CNY");// 订单金额信息request.setAmount(amount);Payer payer = new Payer();payer.setOpenid(openid);// 支付者信息request.setPayer(payer);// 优惠功能request.setDetail(null);// 支付场景描述request.setSceneInfo(null);// 结算信息request.setSettleInfo(null);PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);//重复支付判断TODO// 存储预付订单信息 TODOlog.info("发起预支付成功-" + response.toString());return success(response);}@ApiOperation(value = "预支付-回调(或退款)")@RequestMapping("payCallback")public synchronized String payCallback(HttpServletRequest request) throws IOException {log.info("收到支付回调-------------");// 请求头Wechatpay-nonceString nonce = request.getHeader(WECHAT_PAY_NONCE);// 请求头Wechatpay-TimestampString timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);// 请求头Wechatpay-SignatureString signature = request.getHeader(WECHAT_PAY_SIGNATURE);// 微信支付证书序列号 TODO 这里千万不能搞错,不能是商家证书序列号!!!String serial = request.getHeader("Wechatpay-Serial");// 签名方式String signType = request.getHeader("Wechatpay-Signature-Type");// 构造 RequestParamRequestParam requestParam = new RequestParam.Builder().serialNumber(serial) // TODO 不能搞错!!!.nonce(nonce).signature(signature).timestamp(timestamp).signType(signType).body(getRequestBody()).build();// 初始化 NotificationParserNotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);// 以支付通知回调为例,验签、解密并转换成 Transactionlog.info("验签参数:" + requestParam);Transaction transaction = parser.parse(requestParam, Transaction.class);log.info("验签成功!-支付回调结果:" + transaction.toString());
//        RefundNotification refundNotification = parser.parse(requestParam, RefundNotification.class);// 修改订单之前,主动去微信支付主动查询订单是否已经支付成功,这一步不能少,防止有人假冒主动post接口。/*** 收到支付成功的回调:这里进行处理业务*/
//        List<OrderMaster> orderMasters = iOrderMasterService.lambdaQuery().eq(OrderMaster::getOrderNo, transaction.getOutTradeNo()).list();
//        Assert.isTrue(orderMasters.size() == 1, "根据订单编号未查到订单OR查到了多个订单!!!");
//        if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
//            //支付成功 0待付款1待发货2待收货3已完成4已取消
//            orderMasters.get(0).setBuyStatus(1);
//            // 1待送仓2待打款3已完成4已取消
//            orderMasters.get(0).setSaleStatus(1);
//            // 1现金,2余额,3网银,4支付宝,5微信
//            orderMasters.get(0).setPaymentMethod(5);
//            return "{\"code\": \"FAIL\",\"message\": \"失败\"}";
//        } else {
//            log.info("支付未成功:" + transaction.getTradeState());
//        }
//        // TODO 存储支付流水return "{\"code\": \"FAIL\",\"message\": \"失败\"}";}}

本文标签: 微信支付