|
@@ -0,0 +1,232 @@
|
|
|
+package com.llisoft.pay.service;
|
|
|
+
|
|
|
+import java.util.Objects;
|
|
|
+
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import com.llisoft.pay.util.BeanUtil;
|
|
|
+import com.llisoft.pay.util.JsonUtil;
|
|
|
+import com.llisoft.pay.vo.ApiPayWxAppResponseVo;
|
|
|
+import com.llisoft.pay.vo.ApiPayWxJsApiResponseVo;
|
|
|
+import com.wechat.pay.java.core.Config;
|
|
|
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 微信支付v3
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class PayWxV3Service {
|
|
|
+
|
|
|
+ private Logger logger = LoggerFactory.getLogger(PayWxV3Service.class);
|
|
|
+
|
|
|
+ @Value("${mta.domain}")
|
|
|
+ private String domain;
|
|
|
+ @Value("${mta.wxpay.keyPathDongke}")
|
|
|
+ private String keyPathDongke;
|
|
|
+ @Value("${mta.wxpay.keyPathQinggu}")
|
|
|
+ private String keyPathQinggu;
|
|
|
+
|
|
|
+
|
|
|
+ // 商户号
|
|
|
+ private static String mchidDongke = "1570392471";
|
|
|
+ private static String mchidQinggu = "";
|
|
|
+ // 使用自动更新平台证书的RSA配置
|
|
|
+ // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
|
|
|
+ private static Config configDongke;
|
|
|
+ private static Config configQinggu;
|
|
|
+ private Config getConfigDongke() {
|
|
|
+ return Objects.nonNull(configDongke) ? configDongke : (configDongke = new RSAAutoCertificateConfig.Builder()
|
|
|
+ .merchantId(mchidDongke).privateKeyFromPath(keyPathDongke).merchantSerialNumber("").apiV3Key("").build());
|
|
|
+ }
|
|
|
+ private Config getConfigQinggu() {
|
|
|
+ return Objects.nonNull(configQinggu) ? configQinggu : (configQinggu = new RSAAutoCertificateConfig.Builder()
|
|
|
+ .merchantId(mchidQinggu).privateKeyFromPath(keyPathQinggu)
|
|
|
+ .merchantSerialNumber("29ADADF7298C9CB7FB38EC837E8F3C4A0C07EFEF")
|
|
|
+ .apiV3Key("POIUYTREWQAS1q2w3e4r5t6y7u8i9o0p").build());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Native支付 栋科
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public String pcDongke(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.pc(this.getConfigDongke(), appid, mchidDongke, paynum, money, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Native支付 青谷
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public String pcQinggu(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.pc(this.getConfigQinggu(), appid, mchidQinggu, paynum, money, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。
|
|
|
+ * Native支付适用于PC网站、实体店单品或订单、媒体广告支付等场景
|
|
|
+ * @return 返回用于生成二维码的url
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ private String pc(Config config, String appid, String mchid, String paynum, int money, String body) throws Exception {
|
|
|
+ com.wechat.pay.java.service.payments.nativepay.NativePayService service = new com.wechat.pay.java.service.payments.nativepay.NativePayService.Builder().config(config).build();
|
|
|
+ com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest request = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
|
|
|
+ com.wechat.pay.java.service.payments.nativepay.model.Amount amount = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
|
|
|
+ amount.setTotal(money); // 订单总金额,单位为分
|
|
|
+ request.setAmount(amount);
|
|
|
+ request.setAppid(appid);
|
|
|
+ request.setMchid(mchid);
|
|
|
+ request.setDescription(body);
|
|
|
+ request.setOutTradeNo(paynum);
|
|
|
+ request.setNotifyUrl(domain+"/wxpay/notify");
|
|
|
+ try {
|
|
|
+ logger.debug("微信Native支付下单请求参数: {}", JsonUtil.toJson(request));
|
|
|
+ com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse response = service.prepay(request);
|
|
|
+ logger.debug("微信Native支付下单返回结果: {}", JsonUtil.toJson(response));
|
|
|
+ return response.getCodeUrl();
|
|
|
+ } catch (Exception exception) {
|
|
|
+ logger.error("微信Native支付下单请求异常", exception);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * App支付 栋科
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ApiPayWxAppResponseVo appDongke(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.app(this.getConfigDongke(), appid, mchidDongke, paynum, money, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * App支付 青谷
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ApiPayWxAppResponseVo appQinggu(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.app(this.getConfigQinggu(), appid, mchidQinggu, paynum, money, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * App支付是指商户通过在移动端应用App中集成开放SDK调起微信支付模块来完成支付。目前微信支付支持手机系统有:IOS(苹果)、Android(安卓)和WP(Windows Phone)。
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private ApiPayWxAppResponseVo app(Config config, String appid, String mchid, String paynum, int money, String body) {
|
|
|
+ com.wechat.pay.java.service.payments.app.AppServiceExtension service = new com.wechat.pay.java.service.payments.app.AppServiceExtension.Builder().config(config).build();
|
|
|
+ com.wechat.pay.java.service.payments.app.model.PrepayRequest request = new com.wechat.pay.java.service.payments.app.model.PrepayRequest();
|
|
|
+ com.wechat.pay.java.service.payments.app.model.Amount amount = new com.wechat.pay.java.service.payments.app.model.Amount();
|
|
|
+ amount.setTotal(money); // 订单总金额,单位为分
|
|
|
+ request.setAmount(amount);
|
|
|
+ request.setAppid(appid);
|
|
|
+ request.setMchid(mchid);
|
|
|
+ request.setDescription(body);
|
|
|
+ request.setOutTradeNo(paynum);
|
|
|
+ request.setNotifyUrl(domain+"/wxpay/notify");
|
|
|
+ try {
|
|
|
+ logger.debug("微信APP支付下单请求参数: {}", JsonUtil.toJson(request));
|
|
|
+ com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
|
|
|
+ logger.debug("微信APP支付下单返回结果: {}", JsonUtil.toJson(response));
|
|
|
+ ApiPayWxAppResponseVo vo = BeanUtil.transformBean(response, ApiPayWxAppResponseVo.class);
|
|
|
+ vo.setMchid(mchid);
|
|
|
+ return vo;
|
|
|
+ } catch (Exception exception) {
|
|
|
+ logger.error("微信APP支付下单请求异常", exception);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * JSAPI支付 栋科
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ApiPayWxJsApiResponseVo jsapiDongke(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.jsapi(this.getConfigDongke(), appid, mchidDongke, paynum, money, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * JSAPI支付 青谷
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public ApiPayWxJsApiResponseVo jsapiQinggu(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.jsapi(this.getConfigQinggu(), appid, mchidQinggu, paynum, money, body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * JSAPI支付是指商户通过调用微信支付提供的JSAPI接口,在支付场景中调起微信支付模块完成收款。
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private ApiPayWxJsApiResponseVo jsapi(Config config, String appid, String mchid, String paynum, int money, String body) {
|
|
|
+ com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension service = new com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension.Builder().config(config).build();
|
|
|
+ com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
|
|
|
+ com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
|
|
|
+ amount.setTotal(money); // 订单总金额,单位为分
|
|
|
+ request.setAmount(amount);
|
|
|
+ request.setAppid(appid);
|
|
|
+ request.setMchid(mchid);
|
|
|
+ request.setDescription(body);
|
|
|
+ request.setOutTradeNo(paynum);
|
|
|
+ request.setNotifyUrl(domain+"/wxpay/notify");
|
|
|
+ try {
|
|
|
+ logger.debug("微信JSAPI支付下单请求参数: {}", JsonUtil.toJson(request));
|
|
|
+ com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
|
|
|
+ logger.debug("微信JSAPI支付下单返回结果: {}", JsonUtil.toJson(response));
|
|
|
+ ApiPayWxJsApiResponseVo vo = BeanUtil.transformBean(response, ApiPayWxJsApiResponseVo.class);
|
|
|
+ vo.setMchid(mchid);
|
|
|
+ return vo;
|
|
|
+ } catch (Exception exception) {
|
|
|
+ logger.error("微信JSAPI支付下单请求异常", exception);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单查询 栋科
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public boolean queryDongke(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.query(this.getConfigDongke(), mchidDongke, paynum);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订单查询 青谷
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public boolean queryQinggu(String appid, String paynum, int money, String body) throws Exception {
|
|
|
+ return this.query(this.getConfigQinggu(), mchidQinggu, paynum);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public boolean query(Config config, String mchid, String paynum) throws Exception {
|
|
|
+ com.wechat.pay.java.service.payments.nativepay.NativePayService service = new com.wechat.pay.java.service.payments.nativepay.NativePayService.Builder().config(config).build();
|
|
|
+ com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest request = new com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest();
|
|
|
+ request.setMchid(mchid);
|
|
|
+ request.setOutTradeNo(paynum);
|
|
|
+ try {
|
|
|
+ logger.debug("微信订单查询api请求参数: {}", JsonUtil.toJson(request));
|
|
|
+ com.wechat.pay.java.service.payments.model.Transaction transaction = service.queryOrderByOutTradeNo(request);
|
|
|
+ logger.debug("微信订单查询api返回结果: {}", JsonUtil.toJson(transaction));
|
|
|
+ return transaction.getTradeState() == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.SUCCESS;
|
|
|
+ } catch (Exception exception) {
|
|
|
+ logger.error("微信订单查询api请求异常", exception);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|