springboot下实现微信合单支付

最近根据公司业务发展,需要开发合单支付。

官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter5_1_3.shtml

其实合单支付属于微信的基础支付,早就支持了,只是我们需要找DB开通权限,如果为开通权限,则会提示:

{"code":"NO_AUTH","message":"服务商商户号未开通该产品的受理权限"}

开通权限之后,一下就是代码。

首先我们用到的微信提供的sdk

		<dependency>
			<groupId>com.github.wechatpay-apiv3</groupId>
			<artifactId>wechatpay-apache-httpclient</artifactId>
			<version>0.4.7</version>
		</dependency>

CombineController.java

package com.4zdkGAB75K92isVeI2Tpay.module.wechat.combine.controller;


import javax.servlet.http.HttpServletRequest;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.4zdkGAB75K92isVeI2Tpay.module.wechat.combine.pojo.CombBeanForm;
import com.4zdkGAB75K92isVeI2Tpay.module.wechat.combine.service.CombineService;
import com.4zdkGAB75K92isVeI2Tpublics.response.GenericResponse;

/**
 * 合单支付
 * 
 * @author libaibai
 * @version 1.0 
 */
@RestController
@Validated
@RequestMapping("/comb")
public class CombineController {

	CombineService combineService;
	public CombineController(CombineService combineService) {
		super();
		this.combineService = combineService;
	}

	/**
	 * 支付
	 */
	@PostMapping("/getCombPayOrder")
	@ResponseBody
	public GenericResponse getCombPayOrder(@Validated @RequestBody CombBeanForm bean) {
		return combineService.getCombPayOrder(bean);
	}

	/**
	 * 微信回调
	 */
	@PostMapping("/payCallBack")
	public GenericResponse payCallback(HttpServletRequest request) {
		return combineService.payCallback(request);
	}


}

ComPayOrder.java

package com.pay.module.wechat.combine.payorder;

import com.pay.module.wechat.combine.pojo.NotifyResourceVo;
import com.pay.module.wechat.combine.protocol.Combine;
import com.pay.module.wechat.combine.protocol.CombineResponse;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 合单支付
 *
 * @author libaibai
 * @version 1.0 
 */
public interface CombPayOrder {

	/**
	 * 合单JSAPI下单
	 */
	CombineResponse getPayOrder(Combine combine) throws IOException;

	/**
	 * 回调通知 验签
	 * @return 解密对象
	 */
	NotifyResourceVo payNotify(HttpServletRequest request);
}

CombPayOrderImpl.java

package com.pay.module.wechat.combine.payorder.impl;

import com.alibaba.fastjson.JSONObject;
import com.pay.module.wechat.combine.payorder.CombPayOrder;
import com.pay.module.wechat.combine.pojo.NotifyResourceVo;
import com.pay.module.wechat.combine.pojo.PayNotifyVo;
import com.pay.module.wechat.combine.protocol.Combine;
import com.pay.module.wechat.combine.protocol.CombineResponse;
import com.publics.config.SysConfig;
import com.publics.response.ResponseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.icbc.api.internal.apache.http.ParseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 *
 * @author libaibai
 * @version 1.0
 */
@Service
public class CombPayOrderImpl implements CombPayOrder {

	private static final Logger log = LogManager.getLogger();
	
	@Resource
	CloseableHttpClient httpClient;

	@Override
	public CombineResponse getPayOrder(Combine combine) throws IOException {
		HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/combine-transactions/jsapi");
		httpPost.addHeader("Accept", "application/json");
		httpPost.addHeader("Content-type", "application/json; charset=utf-8");
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.writeValue(bos, combine);
//		System.out.println(JSONObject.toJSONString(combine));
		httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
		return execute(httpPost);
	}

	/**
	 * 发起http请求
	 */
	private CombineResponse execute(HttpUriRequest request) throws IOException {

		CloseableHttpResponse response = httpClient.execute(request);
		String bodyAsString = EntityUtils.toString(response.getEntity());

		JSONObject object = JSONObject.parseObject(bodyAsString);
		Map<String, Object> res = new HashMap<>(object);
		if (res.containsKey("prepay_id")) {
			CombineResponse combineResponse = new CombineResponse();
			combineResponse.setAppId(SysConfig.WX_APPID);
			combineResponse.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000L));
			combineResponse.setPackage("prepay_id=" + res.get("prepay_id"));
			combineResponse.setPaySign(sign(combineResponse));
			return combineResponse;
		} else {
			throw new ResponseException(res.get("message").toString());
		}
	}

	@Resource
	PrivateKey privateKey;

	/**
	 * 签名
	 */
	private String sign(CombineResponse combineResponse) {
		String sb = combineResponse.getAppId() + "\n" + combineResponse.getTimeStamp() + "\n" + combineResponse.getNonceStr() + "\n"
				+ combineResponse.getPackage() + "\n";
		try {
			// 签名方式(固定SHA256withRSA)
			Signature sign = Signature.getInstance("SHA256withRSA");
			// 使用私钥进行初始化签名(私钥需要从私钥文件【证书】中读取)
			sign.initSign(privateKey);
			// 签名更新
			sign.update(sb.getBytes());
			// 对签名结果进行Base64编码
			return Base64.getEncoder().encodeToString(sign.sign());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public NotifyResourceVo payNotify(HttpServletRequest request) {
		NotifyResourceVo notifyResourceVo = null;
		try {
			// 微信返回的请求体
			String body = getRequestBody(request);
			// 如果验证签名序列号通过
			if (verifiedSign(request, body)) {
				// 微信支付通知实体类
				PayNotifyVo payNotifyVO = JSONObject.parseObject(body, PayNotifyVo.class);
				// 如果支付成功
				if ("TRANSACTION.SUCCESS".equals(payNotifyVO.getEvent_type())) {
					// 通知资源数据
					PayNotifyVo.Resource resource = payNotifyVO.getResource();
					// 解密后资源数据
					String notifyResourceStr = decryptResponseBody(resource.getAssociated_data(), resource.getNonce(),
							resource.getCiphertext());
					// 通知资源数据对象
					notifyResourceVo = JSONObject.parseObject(notifyResourceStr, NotifyResourceVo.class);

				} else {
					log.info("微信返回支付错误摘要:" + payNotifyVO.getSummary());
				}
				// 通知微信正常接收到消息,否则微信会轮询该接口
			}
		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ResponseException("验签失败,请联系管理员");
		}
		return notifyResourceVo;
	}

	/**
	 * 获取请求文体
	 */
	private static String getRequestBody(HttpServletRequest request) throws IOException {
		ServletInputStream stream;
		BufferedReader reader = null;
		StringBuilder sb = new StringBuilder();
		try {
			stream = request.getInputStream();
			// 获取响应
			reader = new BufferedReader(new InputStreamReader(stream));
			String line;
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			throw new IOException("读取返回支付接口数据流出现异常!");
		} finally {
			if (reader != null) {
				reader.close();
			}
		}
		return sb.toString();
	}

	/**
	 * 用微信V3密钥解密响应体.
	 *
	 */
	private static String decryptResponseBody(String associatedData, String nonce, String ciphertext) {
		try {
			Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

			SecretKeySpec key = new SecretKeySpec(SysConfig.WX_AESKEY_APIV3.getBytes(StandardCharsets.UTF_8), "AES");
			GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes(StandardCharsets.UTF_8));

			cipher.init(Cipher.DECRYPT_MODE, key, spec);
			cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));

			byte[] bytes;
			try {
				bytes = cipher.doFinal(Base64Utils.decodeFromString(ciphertext));
			} catch (GeneralSecurityException e) {
				throw new IllegalArgumentException(e);
			}
			return new String(bytes, StandardCharsets.UTF_8);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			throw new IllegalStateException(e);
		} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
			throw new IllegalArgumentException(e);
		}
	}

	@Resource
	X509Certificate certificate;// 平台证书

	/**
	 * 验证微信签名
	 */
	private boolean verifiedSign(HttpServletRequest request, String body)
			throws ParseException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
//		//微信返回的证书序列号
//		String serialNo = request.getHeader("Wechatpay-Serial");
		// 微信返回的随机字符串
		String nonceStr = request.getHeader("Wechatpay-Nonce");
		// 微信返回的时间戳
		String timestamp = request.getHeader("Wechatpay-Timestamp");
		// 微信返回的签名
		String wechatSign = request.getHeader("Wechatpay-Signature");
		// 组装签名字符串
		String signStr = Stream.of(timestamp, nonceStr, body).collect(Collectors.joining("\n", "", "\n"));

		// SHA256withRSA签名
		Signature signature = Signature.getInstance("SHA256withRSA");
		signature.initVerify(certificate);
		signature.update(signStr.getBytes());
		// 返回验签结果
		return signature.verify(Base64Utils.decodeFromString(wechatSign));
	}

}

数据vo,combine.java

package com.dlys.pay.module.wechat.combine.protocol;

import java.io.Serializable;
import java.util.List;

/**
 * 合单对象
 * 
 * @author libaibai
 * @version 1.0 
 */
public class Combine implements Serializable {

	private static final long serialVersionUID = -8164174497243390489L;

	private String combine_appid; // 合单发起方的appid。
	private String combine_mchid; // 合单发起方商户号,服务商和电商模式下,传服务商商户号。
	private String combine_out_trade_no; // 合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。

	private List<CombineSub> sub_orders; // 子单信息
	private CombinePayerInfo combine_payer_info; // 支付者

	private String notify_url; // 通知地址

	public Combine(String combine_appid, String combine_mchid, String combine_out_trade_no, List<CombineSub> sub_orders, String openId,
			String notify_url) {
		super();
		this.combine_appid = combine_appid;
		this.combine_mchid = combine_mchid;
		this.combine_out_trade_no = combine_out_trade_no;
		this.sub_orders = sub_orders;
		this.combine_payer_info = new CombinePayerInfo(openId);
		this.notify_url = notify_url;
	}

	public String getCombine_appid() {
		return combine_appid;
	}

	public void setCombine_appid(String combine_appid) {
		this.combine_appid = combine_appid;
	}

	public String getCombine_mchid() {
		return combine_mchid;
	}

	public void setCombine_mchid(String combine_mchid) {
		this.combine_mchid = combine_mchid;
	}

	public String getCombine_out_trade_no() {
		return combine_out_trade_no;
	}

	public void setCombine_out_trade_no(String combine_out_trade_no) {
		this.combine_out_trade_no = combine_out_trade_no;
	}

	public List<CombineSub> getSub_orders() {
		return sub_orders;
	}

	public void setSub_orders(List<CombineSub> sub_orders) {
		this.sub_orders = sub_orders;
	}

	public CombinePayerInfo getCombine_payer_info() {
		return combine_payer_info;
	}

	public void setCombine_payer_info(CombinePayerInfo combine_payer_info) {
		this.combine_payer_info = combine_payer_info;
	}

	public String getNotify_url() {
		return notify_url;
	}

	public void setNotify_url(String notify_url) {
		this.notify_url = notify_url;
	}

	public static class CombinePayerInfo {

		private String openid;

		public CombinePayerInfo(String openid) {
			super();
			this.openid = openid;
		}

		public String getOpenid() {
			return openid;
		}

		public void setOpenid(String openid) {
			this.openid = openid;
		}
	}

}



package com.dlys.pay.module.wechat.combine.protocol;

import java.io.Serializable;

import com.dlys.util.UUIDUtil;

/**
 * 子单信息
 * 
 * @author libaibai
 * @version 1.0
 */
public class CombineSub implements Serializable {

	private static final long serialVersionUID = -5616814104328718154L;

	private String mchid; // 子单发起方商户号,必须与发起方appid有绑定关系。服务商和电商模式下,传服务商商户号。
	private String attach = UUIDUtil.getUUID16(); // 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。

	private CombineSubAmout amount; // 订单金额
	private String out_trade_no; //

	private String sub_mchid; // 二级商户商户号,由微信支付生成并下发。服务商子商户的商户号,被合单方。直连商户不用传二级商户号。
	private String description; // 商品简单描述。需传入应用市场上的APP名字-实际商品名称,例如:天天爱消除-游戏充值。

	public CombineSub(String mchid, int amount, String out_trade_no, String sub_mchid, String description) {
		super();
		this.mchid = mchid;
		this.amount = new CombineSubAmout(amount);
		this.out_trade_no = out_trade_no;
		this.sub_mchid = sub_mchid;
		this.description = description;
	}

	public String getMchid() {
		return mchid;
	}

	public void setMchid(String mchid) {
		this.mchid = mchid;
	}

	public String getAttach() {
		return attach;
	}

	public void setAttach(String attach) {
		this.attach = attach;
	}

	public CombineSubAmout getAmount() {
		return amount;
	}

	public void setAmount(CombineSubAmout amount) {
		this.amount = amount;
	}

	public String getOut_trade_no() {
		return out_trade_no;
	}

	public void setOut_trade_no(String out_trade_no) {
		this.out_trade_no = out_trade_no;
	}

	public String getSub_mchid() {
		return sub_mchid;
	}

	public void setSub_mchid(String sub_mchid) {
		this.sub_mchid = sub_mchid;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public static class CombineSubAmout {

		private int total_amount; // 子单金额,单位为分。
		private String currency = "CNY"; // 符合ISO 4217标准的三位字母代码,人民币:CNY。

		public CombineSubAmout(int total_amount) {
			this.total_amount = total_amount;
		}

		public int getTotal_amount() {
			return total_amount;
		}

		public void setTotal_amount(int total_amount) {
			this.total_amount = total_amount;
		}

		public String getCurrency() {
			return currency;
		}

		public void setCurrency(String currency) {
			this.currency = currency;
		}

	}
}


package com.dlys.pay.module.wechat.combine.protocol;

import com.alibaba.fastjson.annotation.JSONField;
import com.dlys.util.UUIDUtil;

import java.io.Serializable;

/**
 * 
 * @author libaibai
 * @version 1.0 
 */
public class CombineResponse implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private String appId; // 服务商申请的公众号或移动应用appid。\
	private String timeStamp; // 当前的时间,示例值:1414561699
	private String nonceStr = UUIDUtil.getUUID32(); // 随机字符串,不长于32位。

	@JSONField(name = "package")
	private String _package = "12"; // JSAPI下单接口返回的prepay_id参数值,提交格式如:prepay_id=***

	private String signType = "RSA"; // 签名类型,默认为RSA,仅支持RSA。
	private String paySign; // 签名

	public String getAppId() {
		return appId;
	}

	public void setAppId(String appId) {
		this.appId = appId;
	}

	public String getTimeStamp() {
		return timeStamp;
	}

	public void setTimeStamp(String timeStamp) {
		this.timeStamp = timeStamp;
	}

	public String getNonceStr() {
		return nonceStr;
	}

	public void setNonceStr(String nonceStr) {
		this.nonceStr = nonceStr;
	}
	public String getPackage() {
		return _package;
	}
	public void setPackage(String _package) {
		this._package = _package;
	}

	public String getSignType() {
		return signType;
	}

	public void setSignType(String signType) {
		this.signType = signType;
	}

	public String getPaySign() {
		return paySign;
	}

	public void setPaySign(String paySign) {
		this.paySign = paySign;
	}
}

以下是获取证书工具类,payUtils.java

package com.dlys.pay.module.wechat.combine.util;

import com.dlys.publics.config.SysConfig;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivateKey;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class PayUtils {
    X509Certificate apiClientCert() throws IOException {
        return getCertificate(apiClient_Cert);
    }
    @Bean
    public X509Certificate platformCert() throws IOException {
        return getCertificate(platform_Cert);
    }
    @Bean
    public PrivateKey getMerchantPrivateKey() throws IOException {
        InputStream fis = new ClassPathResource(apiClient_Key).getInputStream();
        return PemUtil.loadPrivateKey(fis);
    }
    @Bean
    public CloseableHttpClient getHttpClient() throws IOException {

        List<X509Certificate> wechatPayCertificates = new ArrayList<>();
        wechatPayCertificates.add(platformCert());
        // 商户API证书的证书序列号
        String merchantSerialNumber = apiClientCert().getSerialNumber().toString(16).toUpperCase();
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(merchantId, merchantSerialNumber, getMerchantPrivateKey())
                .withWechatPay(wechatPayCertificates);
        return builder.build();
    }

    /**
     * 获取证书。
     */
    static X509Certificate getCertificate(String path) throws IOException {
        InputStream fis = new ClassPathResource(path).getInputStream();
        try (BufferedInputStream bis = new BufferedInputStream(fis)) {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
            cert.checkValidity();
            return cert;
        } catch (Exception e) {
            if (e instanceof CertificateExpiredException) {
                throw new RuntimeException("证书已过期", e);
            } else if (e instanceof CertificateNotYetValidException) {
                throw new RuntimeException("证书尚未生效", e);
            } else {
                throw new RuntimeException("无效的证书文件", e);
            }
        }
    }
    // 商户号
    private final static String merchantId = SysConfig.WXPAY_MCHIDSP;
    // 商户API证书
    private final static String apiClient_Cert = "conf/cert/apiclient_cert.pem";
    // 平台证书
    private final static String platform_Cert = "conf/cert/rootca2.pem";
    // 商户API私匙
    private final static String apiClient_Key = "conf/cert/apiclient_key.pem";
//    // v3私钥
//    static String apiV3Key = SysConfig.WX_AESKEY_APIV3;
}

另外就是回调的代码片段

package com.dlys.pay.module.wechat.combine.pojo;

import java.util.List;

/**
 * 微信通知数据解密后对象
 */
public class NotifyResourceVo {

    /**
     * 合单商户appid
     */
    private String combine_appid;
    /**
     * 合单商户号
     */
    private String combine_mchid;
    /**
     * 合单商户订单号
     */
    private String combine_out_trade_no;
    /**
     * 场景信息
     */
    private SceneInfo scene_info;
    /**
     * 子单信息
     */
    private List<SubOrder> sub_orders;
    /**
     * 支付者
     */
    private CombinePayerInfo combine_payer_info;

    /**
     * 场景信息
     */
    public class SceneInfo{

        /**
         * 商户端设备号
         */
        private String device_id;

        public String getDevice_id() {
            return device_id;
        }

        public void setDevice_id(String device_id) {
            this.device_id = device_id;
        }
    }

    /**
     * 子单信息
     */
    public class SubOrder{
        /**
         * 子单商户号
         */
        private String mchid;
        /**
         * 交易类型
         */
        private String trade_type;
        /**
         * 交易状态
         */
        private String trade_state;
        /**
         * 付款银行
         */
        private String bank_type;
        /**
         * 附加信息
         */
        private String attach;
        /**
         * 支付完成时间
         */
        private String success_time;
        /**
         * 微信订单号
         */
        private String transaction_id;
        /**
         * 子单商户订单号
         */
        private String out_trade_no;
        /**
         * 二级商户号
         */
        private String sub_mchid;

        /**
         * 子商户应用ID
         */
        private String sub_appid;
        /**
         * 订单金额
         */
        private Amount amount;
        /**
         * 订单金额
         */
        public class Amount{
            /**
             * 标价金额
             */
            private Integer total_amount;
            /**
             * 标价币种
             */
            private String currency;
            /**
             * 现金支付金额
             */
            private Integer payer_amount;
            /**
             * 现金支付币种
             */
            private String payer_currency;

            public Integer getTotal_amount() {
                return total_amount;
            }

            public void setTotal_amount(Integer total_amount) {
                this.total_amount = total_amount;
            }

            public String getCurrency() {
                return currency;
            }

            public void setCurrency(String currency) {
                this.currency = currency;
            }

            public Integer getPayer_amount() {
                return payer_amount;
            }

            public void setPayer_amount(Integer payer_amount) {
                this.payer_amount = payer_amount;
            }

            public String getPayer_currency() {
                return payer_currency;
            }

            public void setPayer_currency(String payer_currency) {
                this.payer_currency = payer_currency;
            }
        }

        /**
         * 优惠功能
         */
        List<PromotionDetail> promotion_detail;

        /**
         * 优惠功能
         */
        public class PromotionDetail{
            /**
             * 券ID
             */
            private String coupon_id;
            /**
             * 优惠名称
             */
            private String name;
            /**
             * 优惠范围
             */
            private String scope;
            /**
             * 优惠类型
             */
            private String type;
            /**
             * 优惠券金额
             */
            private  Integer amount;
            /**
             * 活动id
             */
            private String stock_id;
            /**
             * 微信出资
             */
            private Integer wechatpay_contribute;
            /**
             * 商户出资
             */
            private Integer merchant_contribute;
            /**
             * 其他出资
             */
            private Integer other_contribute;
            /**
             * 优惠币种
             */
            private String currency;
            /**
             * 单品列表
             */
            List<GoodsDetail> goods_detail;
            /**
             * 单品列表
             */
            public class GoodsDetail{
                /**
                 * 商品编码
                 */
                private String goods_id;
                /**
                 * 商品数量
                 */
                private Integer quantity;
                /**
                 * 商品价格
                 */
                private Integer unit_price;
                /**
                 * 商品优惠金额
                 */
                private Integer discount_amount;
                /**
                 * 商品备注
                 */
                private String goods_remark;

                public String getGoods_id() {
                    return goods_id;
                }

                public void setGoods_id(String goods_id) {
                    this.goods_id = goods_id;
                }

                public Integer getQuantity() {
                    return quantity;
                }

                public void setQuantity(Integer quantity) {
                    this.quantity = quantity;
                }

                public Integer getUnit_price() {
                    return unit_price;
                }

                public void setUnit_price(Integer unit_price) {
                    this.unit_price = unit_price;
                }

                public Integer getDiscount_amount() {
                    return discount_amount;
                }

                public void setDiscount_amount(Integer discount_amount) {
                    this.discount_amount = discount_amount;
                }

                public String getGoods_remark() {
                    return goods_remark;
                }

                public void setGoods_remark(String goods_remark) {
                    this.goods_remark = goods_remark;
                }
            }

            public String getCoupon_id() {
                return coupon_id;
            }

            public void setCoupon_id(String coupon_id) {
                this.coupon_id = coupon_id;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            public String getScope() {
                return scope;
            }

            public void setScope(String scope) {
                this.scope = scope;
            }

            public String getType() {
                return type;
            }

            public void setType(String type) {
                this.type = type;
            }

            public Integer getAmount() {
                return amount;
            }

            public void setAmount(Integer amount) {
                this.amount = amount;
            }

            public String getStock_id() {
                return stock_id;
            }

            public void setStock_id(String stock_id) {
                this.stock_id = stock_id;
            }

            public Integer getWechatpay_contribute() {
                return wechatpay_contribute;
            }

            public void setWechatpay_contribute(Integer wechatpay_contribute) {
                this.wechatpay_contribute = wechatpay_contribute;
            }

            public Integer getMerchant_contribute() {
                return merchant_contribute;
            }

            public void setMerchant_contribute(Integer merchant_contribute) {
                this.merchant_contribute = merchant_contribute;
            }

            public Integer getOther_contribute() {
                return other_contribute;
            }

            public void setOther_contribute(Integer other_contribute) {
                this.other_contribute = other_contribute;
            }

            public String getCurrency() {
                return currency;
            }

            public void setCurrency(String currency) {
                this.currency = currency;
            }

            public List<GoodsDetail> getGoods_detail() {
                return goods_detail;
            }

            public void setGoods_detail(List<GoodsDetail> goods_detail) {
                this.goods_detail = goods_detail;
            }
        }

        public String getMchid() {
            return mchid;
        }

        public void setMchid(String mchid) {
            this.mchid = mchid;
        }

        public String getTrade_type() {
            return trade_type;
        }

        public void setTrade_type(String trade_type) {
            this.trade_type = trade_type;
        }

        public String getTrade_state() {
            return trade_state;
        }

        public void setTrade_state(String trade_state) {
            this.trade_state = trade_state;
        }

        public String getBank_type() {
            return bank_type;
        }

        public void setBank_type(String bank_type) {
            this.bank_type = bank_type;
        }

        public String getAttach() {
            return attach;
        }

        public void setAttach(String attach) {
            this.attach = attach;
        }

        public String getSuccess_time() {
            return success_time;
        }

        public void setSuccess_time(String success_time) {
            this.success_time = success_time;
        }

        public String getTransaction_id() {
            return transaction_id;
        }

        public void setTransaction_id(String transaction_id) {
            this.transaction_id = transaction_id;
        }

        public String getOut_trade_no() {
            return out_trade_no;
        }

        public void setOut_trade_no(String out_trade_no) {
            this.out_trade_no = out_trade_no;
        }

        public String getSub_appid() {
            return sub_appid;
        }

        public void setSub_appid(String sub_appid) {
            this.sub_appid = sub_appid;
        }

        public Amount getAmount() {
            return amount;
        }

        public void setAmount(Amount amount) {
            this.amount = amount;
        }

        public List<PromotionDetail> getPromotion_detail() {
            return promotion_detail;
        }

        public void setPromotion_detail(List<PromotionDetail> promotion_detail) {
            this.promotion_detail = promotion_detail;
        }

        public String getSub_mchid() {
            return sub_mchid;
        }

        public void setSub_mchid(String sub_mchid) {
            this.sub_mchid = sub_mchid;
        }
    }

    /**
     * 支付者
     */
    public class CombinePayerInfo{
        /**
         * 用户标识
         */
        private String openid;

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }
    }


    public String getCombine_appid() {
        return combine_appid;
    }

    public void setCombine_appid(String combine_appid) {
        this.combine_appid = combine_appid;
    }

    public String getCombine_mchid() {
        return combine_mchid;
    }

    public void setCombine_mchid(String combine_mchid) {
        this.combine_mchid = combine_mchid;
    }

    public String getCombine_out_trade_no() {
        return combine_out_trade_no;
    }

    public void setCombine_out_trade_no(String combine_out_trade_no) {
        this.combine_out_trade_no = combine_out_trade_no;
    }

    public SceneInfo getScene_info() {
        return scene_info;
    }

    public void setScene_info(SceneInfo scene_info) {
        this.scene_info = scene_info;
    }

    public List<SubOrder> getSub_orders() {
        return sub_orders;
    }

    public void setSub_orders(List<SubOrder> sub_orders) {
        this.sub_orders = sub_orders;
    }

    public CombinePayerInfo getCombine_payer_info() {
        return combine_payer_info;
    }

    public void setCombine_payer_info(CombinePayerInfo combine_payer_info) {
        this.combine_payer_info = combine_payer_info;
    }
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Spring Boot可以通过集成微信支付SDK来实现微信支付。具体步骤如下: 1. 在pom.xml文件中添加微信支付SDK的依赖: ``` <dependency> <groupId>com.github.wxpay</groupId> <artifactId>wxpay-sdk</artifactId> <version>3.0.9</version> </dependency> ``` 2. 在application.properties文件中配置微信支付相关参数: ``` # 微信支付相关配置 wxpay.appId=微信公众号或小程序的AppID wxpay.mchId=商户号 wxpay.key=商户密钥 wxpay.notifyUrl=支付结果通知地址 ``` 3. 创建一个统一下单API的Controller: ``` @RestController @RequestMapping("/wxpay") public class WxPayController { @Autowired private WxPayService wxPayService; @PostMapping("/unifiedOrder") public Map<String, String> unifiedOrder(@RequestBody WxPayUnifiedOrderRequest request) throws Exception { return wxPayService.unifiedOrder(request); } } ``` 4. 在WxPayService中实现统一下单API的逻辑: ``` @Service public class WxPayService { @Autowired private WxPayConfig wxPayConfig; public Map<String, String> unifiedOrder(WxPayUnifiedOrderRequest request) throws Exception { WXPay wxPay = new WXPay(wxPayConfig); Map<String, String> data = new HashMap<>(); data.put("body", request.getBody()); data.put("out_trade_no", request.getOutTradeNo()); data.put("total_fee", request.getTotalFee()); data.put("spbill_create_ip", request.getSpbillCreateIp()); data.put("notify_url", wxPayConfig.getNotifyUrl()); data.put("trade_type", "JSAPI"); data.put("openid", request.getOpenid()); Map<String, String> result = wxPay.unifiedOrder(data); return result; } } ``` 5. 调用统一下单API进行支付: ``` WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); request.setBody("测试商品"); request.setOutTradeNo("123456789"); request.setTotalFee("1"); request.setSpbillCreateIp("127.0.0.1"); request.setOpenid("用户的openid"); Map<String, String> result = wxPayService.unifiedOrder(request); ``` 以上就是使用Spring Boot实现微信支付的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木小百99

听说打赏的人都发财了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值