赞
踩
- <!--微信支付 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.yml wx: miniapp: configs: - appid: wx1fcxxxxxxxx secret: 1exxxxxxxxxxxxxxxxxxxxxxxxxxxxx token: #微信小程序消息服务器配置的token aesKey: #微信小程序消息服务器配置的EncodingAESKey msgDataFormat: JSON appV3Secret: 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;
-
- @Data
- public 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 {
-
- @Autowired
- private WxMaProperties properties;
-
- /**
- * 初始化商户配置(只能加载一次)
- * 确保是单例
- *
- * @return
- */
- @Bean
- public 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 {
- /**
- * 配置文件
- */
- @Autowired
- private WxMaProperties properties;
- @Autowired
- private RSAAutoCertificateConfig rsaAutoCertificateConfig;
- @Autowired
- private 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();
-
- // 应用ID
- request.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:00
- request.setTimeExpire(timeStampToRfc3339(System.currentTimeMillis() + properties.getConfigs().get(0).getTimeExpire()));
- // 附加数据:在查询API和支付通知中原样返回,可作为自定义参数使用
- request.setAttach("");
- // 回调地址:异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 公网域名必须为https
- request.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
-
- // 存储预付订单信息 TODO
- log.info("发起预支付成功-" + response.toString());
-
- return success(response);
- }
-
- @ApiOperation(value = "预支付-回调(或退款)")
- @RequestMapping("payCallback")
- public synchronized String payCallback(HttpServletRequest request) throws IOException {
- log.info("收到支付回调-------------");
-
- // 请求头Wechatpay-nonce
- String nonce = request.getHeader(WECHAT_PAY_NONCE);
- // 请求头Wechatpay-Timestamp
- String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
- // 请求头Wechatpay-Signature
- String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
- // 微信支付证书序列号 TODO 这里千万不能搞错,不能是商家证书序列号!!!
- String serial = request.getHeader("Wechatpay-Serial");
- // 签名方式
- String signType = request.getHeader("Wechatpay-Signature-Type");
-
- // 构造 RequestParam
- RequestParam requestParam = new RequestParam.Builder()
- .serialNumber(serial) // TODO 不能搞错!!!
- .nonce(nonce)
- .signature(signature)
- .timestamp(timestamp)
- .signType(signType)
- .body(getRequestBody())
- .build();
-
- // 初始化 NotificationParser
- NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);
-
- // 以支付通知回调为例,验签、解密并转换成 Transaction
- log.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\": \"失败\"}";
- }
-
- }
-

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。