微信小程序支付V3版本接口实现

这篇具有很好参考价值的文章主要介绍了微信小程序支付V3版本接口实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.说明和前期准备(小程序的V3版本)

特别说明:遇到 java.security.InvalidKeyException: Illegal key size ******* getValidator的错误
参考添加链接描述
JDK7的下载地址
JDK8的下载地址:

下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件
如果安装了JDK,还要将两个jar文件也放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件。
微信小程序支付V3版本接口实现

1.场景:小程序项目需要对接微信小程序的支付接口,这里使用的是V3版本

官方文档链接:微信小程支付申请文档链接

1.1按照上面的文档申请支付

拿到相关的参数(小程序的Appid,小程序的appSecret ,商户秘钥 PrivateKey,商户号 Mchid,证书序列号MchSerialNo,V3秘钥))本人读取方式为从配置文件中读取

package com.wxapplet.model;

import java.io.IOException;
import java.util.Properties;

import org.springframework.beans.factory.annotation.Value;

import com.foc.alipay.config.AlipayServiceEnvConstants;
import com.foc.common.util.Constants;

public class WxV3payConfig {

	static {
		/**
		 * 静态代码块初始化类变量
		 */

		Properties proper = new Properties();
		try {
			proper.clear();
			proper.load(WxV3payConfig.class.getResourceAsStream("/paykey.properties"));
			appletAppid=proper.getProperty("appletAppid");
			appletMchid=proper.getProperty("appletMchid");
			appletPrivateKeyPath=proper.getProperty("appletPrivateKeyPath");
			appletMchSerialNo=proper.getProperty("appletMchSerialNo");
			appletSecret=proper.getProperty("appletSecret");
			appletApiV3Key=proper.getProperty("appletApiV3Key");
		
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static String appletAppid;// 由微信生成的应用ID
	public static String appletMchid;// 直连商户的商户号,由微信支付生成并下发。
	public static String appletPrivateKeyPath;// 小程序商户秘钥

	public static String appletMchSerialNo;// 商户证书序列号

	public static String appletSecret;// 小程序 appSecret

	public static String appletApiV3Key;// V3密钥

	@Value("${appletAppid}")
	public static void setAppletAppid(String appletAppid) {
		WxV3payConfig.appletAppid = appletAppid;
	}

	@Value("${appletMchid}")
	public static void setAppletMchid(String appletMchid) {
		WxV3payConfig.appletMchid = appletMchid;
	}

	@Value("${appletPrivateKeyPath}")
	public static void setAppletPrivateKey(String appletPrivateKeyPath) {
		WxV3payConfig.appletPrivateKeyPath = appletPrivateKeyPath;
	}

	@Value("${appletMchSerialNo}")
	public static void setAppletMchSerialNo(String appletMchSerialNo) {
		WxV3payConfig.appletMchSerialNo = appletMchSerialNo;
	}

	@Value("${appletSecret}")
	public static void setAppletSecret(String appletSecret) {
		WxV3payConfig.appletSecret = appletSecret;
	}

	@Value("${appletApiV3Key}")
	public static void setAppletApiV3Key(String appletApiV3Key) {
		WxV3payConfig.appletApiV3Key = appletApiV3Key;
	}
	
	
	

}

微信小程序支付V3版本接口实现
对应的paykey.properties文件

#v3
#ying yong id 
appletAppid=
#shang hu hao
appletMchid=

appletPrivateKeyPath=appletPrivateKey.pem

#zheng shu xu lie hao
appletMchSerialNo=
#appsectet
appletSecret=
#v3 mi yao
appletApiV3Key=

微信小程序支付V3版本接口实现

2.引入相关的maven包

2.1参考的微信官方文档

微信开发指引
微信java给出的示例
微信小程序支付V3版本接口实现

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

微信小程序支付V3版本接口实现

3.相关工具类

3.1发送http请求工具类
package com.wxapplet.util;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;

@Component
public class AppletHttpClient  {
	
   /**
	 * 将通知参数转化为字符串
	 * 
	 * @param request
	 * @return
	 */
	public static String readData(HttpServletRequest request) {
		BufferedReader br = null;
		try {
			StringBuilder result = new StringBuilder();
			br = request.getReader();
			for (String line; (line = br.readLine()) != null;) {
				if (result.length() > 0) {
					result.append("\n");
				}
				result.append(line);
			}
			return result.toString();
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 获取商户的私钥文件
	 * 
	 * @param filename
	 * @return
	 */
	public PrivateKey getPrivateKey(String filename) {
		InputStream insss = AppletHttpClient.class.getClassLoader().getResourceAsStream(filename);

		// InputStream insss = ClassLoader.getSystemResourceAsStream(filename);
		return PemUtil.loadPrivateKey(insss);
	}

	/**
	 * 获取http请求对象
	 * 
	 * @param verifier
	 * @return
	 */
	@Bean(name = "wxPayClient")
	public CloseableHttpClient getWxPayClient(AutoUpdateCertificatesVerifier verifier) {

		// 获取商户私钥
		PrivateKey privateKey = getPrivateKey(WxV3payConfig.appletPrivateKeyPath);

		WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
				.withMerchant(WxV3payConfig.appletMchid, WxV3payConfig.appletMchSerialNo, privateKey).withValidator(new WechatPay2Validator(verifier));
		// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient

		// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
		CloseableHttpClient httpClient = builder.build();

		return httpClient;
	}

	/**
	 * 获取HttpClient,无需进行应答签名验证,跳过验签的流程
	 */
	@Bean(name = "wxPayNoSignClient")
	public CloseableHttpClient getWxPayNoSignClient() {

		// 获取商户私钥
		PrivateKey privateKey = getPrivateKey(WxV3payConfig.appletPrivateKeyPath);

		// 用于构造HttpClient
		WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
				// 设置商户信息
				.withMerchant(WxV3payConfig.appletMchid, WxV3payConfig.appletMchSerialNo, privateKey)
				// 无需进行签名验证、通过withValidator((response) -> true)实现
				.withValidator((response) -> true);

		// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
		CloseableHttpClient httpClient = builder.build();

		return httpClient;
	}
	

	

	
	
	/**
	 * V3  SHA256withRSA 签名.
	 * @param appid 
	 * @param timeStamp
	 * @param nonceStr
	 * @param prepayId
	 * @param privateKey
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 * @throws SignatureException
	 * @throws FileNotFoundException 
	 */
	
	public String getSign1(String appid ,String timeStamp,String nonceStr ,String prepayId  , String  privateKeyPath) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, FileNotFoundException{
		try {
			String signatureStr = Stream.of(appid, timeStamp, nonceStr, prepayId)
		            .collect(Collectors.joining("\n", "", "\n"));
			Signature	sign = Signature.getInstance("SHA256withRSA");
			 InputStream insss = PayCommonUtil.class.getClassLoader().getResourceAsStream(privateKeyPath);
			PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(insss);
			sign.initSign(merchantPrivateKey);
			sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
			return Base64.getEncoder().encodeToString(sign.sign());
		} catch (Exception e) {
			e.printStackTrace();
		}
	    
		return null;
	}
	
	
	/**
	 * 获取签名验证器
	 * 
	 * @return
	 */
	@Bean
	public AutoUpdateCertificatesVerifier  getVerifier() {

		// 获取商户私钥
		PrivateKey privateKey = getPrivateKey(WxV3payConfig.appletPrivateKeyPath);

		// 私钥签名对象
		PrivateKeySigner privateKeySigner = new PrivateKeySigner(WxV3payConfig.appletMchSerialNo, privateKey);

		// 身份认证对象
		WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(WxV3payConfig.appletMchid, privateKeySigner);

		// 使用定时更新的签名验证器,不需要传入证书
		AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(wechatPay2Credentials,
				WxV3payConfig.appletApiV3Key.getBytes(StandardCharsets.UTF_8));

		return verifier;

	}
}

3.2进行下单操作

微信小程序支付V3版本接口实现
这里使用JSAPI下单,微信小程序JSAPI下单参考

     String appId =WxV3payConfig.appletAppid; // 
			 String mchId =WxV3payConfig.appletMchid; // 商户号
			 String privateKeyPath =WxV3payConfig.appletPrivateKeyPath;//  你的商户私钥路径

			 
			 String nonceStr = RandomUtil.randomString(32);//随机字符串
			 
			 

				// 构造订单信息
				JSONObject jsonObject = new JSONObject();
				jsonObject.put("appid",appId); // 小程序的应用appid
				jsonObject.put("mchid", mchId); // 直连商户的商户号,由微信支付生成并下发。
				String body = "订单消费";
				Project project = projectService.findOne(tempPersonalRecord.getProjectId());
				if (project != null && StringUtils.isNotBlank(project.getName())) {
					body = project.getName();
				}
				jsonObject.put("description", body); // 商品描述
				jsonObject.put("out_trade_no", outTradeNo); // 商户订单号
				logger.info("total_fee=" + Math.round(tempPersonalRecord.getMoney() * 100) + "");
				JSONObject amoutJson = new JSONObject();
				amoutJson.put("total", tempPersonalRecord.getMoney() * 100); // 总金额,订单总金额,单位为分
				amoutJson.put("currency", "CNY");// 货币类型CNY:人民币,境内商户号仅支持人民币。
				jsonObject.put("amount", amoutJson); // 订单金额信息
				jsonObject.put("notify_url", notifyUrl); // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
				
				JSONObject payUser = new JSONObject();
				payUser.put("openid", mfUser.getOpenId());
				jsonObject.put("payer", payUser); // 支付者用户在商户appid下的唯一标识。
				
				

				// 发送请求进行JSAPI下单
				 HttpPost httpPost = new  HttpPost(APPLET_JSAPI_URL); 
				 
				 StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
				  entity.setContentType("application/json");
			        httpPost.setEntity(entity);
			        httpPost.setHeader("Accept", "application/json");
			      //完成签名并执行请求
			        CloseableHttpResponse response = wxPayClient.execute(httpPost);
			        
			        String reString = EntityUtils.toString(response.getEntity());//响应体
			        int statusCode = response.getStatusLine().getStatusCode();//响应状态码
			        
			        if (statusCode==200) {//处理成功
			        	logger.info("微信小程序支付响应成功,返回的结果为="+reString);
						
					}else if (statusCode==204) {//处理成功无返回的boy
						logger.info("微信小程序支付响应成功");
					}else {
						logger.info("微信小程序响应失败,响应码为="+statusCode+",返回的结果为="+reString);
						return new ResultVO(ResultCode.ORDERERROR);
					}
			       


				SortedMap<String, String> params = new TreeMap<String, String>();
				String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);// 时间戳
				String preId = "prepay_id=" + JSON.parseObject(reString).getString("prepay_id");
				String paySign = appletHttpClient.getSign1(appId, timeStamp, nonceStr, preId,
						privateKeyPath);// 签名
				

				rr.put("appId", appId);// appid
				rr.put("timeStamp", timeStamp);// 时间戳
				rr.put("nonceStr", nonceStr);// 随机字符串
				rr.put("package", "prepay_id=" + JSON.parseObject(reString).getString("prepay_id"));// 订单详情扩展字符串
				rr.put("signType", "RSA");// 签名类型,默认为RSA,仅支持RSA
				rr.put("paySign", paySign);// 签名
				 rr.put("outTradeNo", tempPersonalRecord.getOutTradeNo());//订单编号
				return new ResultVO(ResultCode.SUCCESS, rr);
3.3获取返回的prepay_id稍后返回给前端

4.向前端传递调用wx.requestPayment(OBJECT)发起微信支付的参数

Api地址
特别说明:签名使用的是SHA256 with RSA签名,并对签名结果进行Base64编码得到签名值。

4.1生成签名的工具类
	
	/**
	 * V3  SHA256withRSA 签名.
	 * @param appid 
	 * @param timeStamp
	 * @param nonceStr
	 * @param prepayId
	 * @param privateKey
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 * @throws SignatureException
	 */
	public static String getSign(String appid ,String timeStamp,String nonceStr ,String prepayId  , String  privateKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException{
		try {
			String signatureStr = Stream.of(appid, timeStamp, nonceStr, prepayId)
		            .collect(Collectors.joining("\n", "", "\n"));
			Signature	sign = Signature.getInstance("SHA256withRSA");
			PrivateKey merchantPrivateKey = PemUtil
			        .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
			sign.initSign(merchantPrivateKey);
			sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
			return Base64.getEncoder().encodeToString(sign.sign());
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    
		return null;
	}
	

官方签名参考地址

4.2签名的生成
	String nonceStr = RandomUtil.randomString(32);// 随机字符串
	String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);// 时间戳
	String preId = "prepay_id=" + JSON.parseObject(reString).getString("prepay_id");
	
			String paySign = PayCommonUtil.getSign(weChatPub.getAppletAppid(), timeStamp, nonceStr, preId,
					weChatPub.getAppletPrivateKey());// 签名
			
			rr.put("appId", weChatPub.getAppletAppid());// appid
			rr.put("timeStamp", timeStamp);// 时间戳
			rr.put("nonceStr", nonceStr);// 随机字符串
			rr.put("package", "prepay_id=" + JSON.parseObject(reString).getString("prepay_id"));// 订单详情扩展字符串
			rr.put("signType", "RSA");// 签名类型,默认为RSA,仅支持RSA
			rr.put("paySign", paySign);// 签名
			return new ResultVO(ResultCode.SUCCESS, rr);
	
4.3使用对生成的签名使用官方工具验签

工具下载地址
微信小程序支付V3版本接口实现

5.支付成功后微信的回调

官方的验签和解密
微信小程序支付V3版本接口实现

// 构建request,传入必要参数
 NotificationRequest request = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)
        .withNonce(nonce)
        .withTimestamp(timestamp)
        .withSignature(signature)
        .withBody(body)
        .build();
NotificationHandler handler = new NotificationHandler(verifier, apiV3Key.getBytes(StandardCharsets.UTF_8));
// 验签和解析请求体
Notification notification = handler.parse(request);
// 从notification中获取解密报文
System.out.println(notification.getDecryptData());

相关示例代码(包含验签操作)自己实现的代码

logger.info("支付成功进入回调方法--" + DateUtil.formatDate(new Date()));
		Map<String, String> map1 = new HashMap<>();// 应答对象
		Gson gson = new Gson();
		Map<String, String> map = new HashMap<>();// 应答对象
		String outTradeNo = null;// 商户订单号
		String transactionId = null;// 微信支付订单号
		String timeEnd = null;//
		String openid = null;// 用户标识
		String tradeState = null;// 交易状态
	
			
			// 处理通知参数
			String body = appletHttpClient.readData(request);
			Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
			String requestId = (String) bodyMap.get("id");
				// 获取验签器
				// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
				PrivateKey privateKey =appletHttpClient.getPrivateKey(WxV3payConfig.appletPrivateKeyPath);
				AutoUpdateCertificatesVerifier verifier = appletHttpClient.getVerifier();
				WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(
						verifier, requestId, body);
				// 进行验签操作
				if (!wechatPay2ValidatorForRequest.validate(request)) {// 验签成功

					logger.error("支付通知验签失败");
					// 失败应答
					response.setStatus(500);
					map.put("code", "ERROR");
					map.put("message", "通知验签失败");
					return gson.toJson(map);

				}
				logger.info("支付通知验证成功");
				// 获取明文
				String plainText = wxAPIV3AesUtil.decryptFromResource(bodyMap, WxV3payConfig.appletApiV3Key);
				// 将明文转换成map
				Map<String, String> resultMap = JSON.parseObject(plainText, HashMap.class);
				outTradeNo = resultMap.get("out_trade_no");// 商户订单号
				transactionId = resultMap.get("transaction_id");// 微信支付订单号
				timeEnd = resultMap.get("time_end");//
				openid = resultMap.get("openid");// 用户标识
				tradeState = resultMap.get("trade_state");// 交易状态
			
5.1验签的工具类
package com.wxapplet.util;

import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;

import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.*;

public class WechatPay2ValidatorForRequest {
	 protected static final Logger log = LoggerFactory.getLogger(WechatPay2ValidatorForRequest.class);
	    /**
	     * 应答超时时间,单位为分钟
	     */
	    protected static final long RESPONSE_EXPIRED_MINUTES = 5;
	    protected final Verifier verifier;
	    protected final String requestId;
	    protected final String body;


	    public WechatPay2ValidatorForRequest(Verifier verifier, String requestId, String body) {
	        this.verifier = verifier;
	        this.requestId = requestId;
	        this.body = body;
	    }

	    protected static IllegalArgumentException parameterError(String message, Object... args) {
	        message = String.format(message, args);
	        return new IllegalArgumentException("parameter error: " + message);
	    }

	    protected static IllegalArgumentException verifyFail(String message, Object... args) {
	        message = String.format(message, args);
	        return new IllegalArgumentException("signature verify fail: " + message);
	    }

	    //·验签
	    public final boolean validate(HttpServletRequest request) throws IOException {
	        try {
	            //处理请求参数
	            validateParameters(request);

	            //构造验签名串
	            String message = buildMessage(request);

	            String serial = request.getHeader(WECHAT_PAY_SERIAL);
	            String signature = request.getHeader(WECHAT_PAY_SIGNATURE);

	            //验签
	            if (!verifier.verify(serial, message.getBytes(StandardCharsets.UTF_8), signature)) {
	                throw verifyFail("serial=[%s] message=[%s] sign=[%s], request-id=[%s]",
	                        serial, message, signature, requestId);
	            }
	        } catch (IllegalArgumentException e) {
	            log.warn(e.getMessage());
	            return false;
	        }

	        return true;
	    }

	    protected final void validateParameters(HttpServletRequest request) {

	        // NOTE: ensure HEADER_WECHAT_PAY_TIMESTAMP at last
	        String[] headers = {WECHAT_PAY_SERIAL, WECHAT_PAY_SIGNATURE, WECHAT_PAY_NONCE, WECHAT_PAY_TIMESTAMP};

	        String header = null;
	        for (String headerName : headers) {
	            header = request.getHeader(headerName);
	            if (header == null) {
	                throw parameterError("empty [%s], request-id=[%s]", headerName, requestId);
	            }
	        }

	        //判断请求是否过期
	        String timestampStr = header;
	        try {
	            Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestampStr));
	            // 拒绝过期请求
	            if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= RESPONSE_EXPIRED_MINUTES) {
	                throw parameterError("timestamp=[%s] expires, request-id=[%s]", timestampStr, requestId);
	            }
	        } catch (DateTimeException | NumberFormatException e) {
	            throw parameterError("invalid timestamp=[%s], request-id=[%s]", timestampStr, requestId);
	        }
	    }

	    protected final String buildMessage(HttpServletRequest request) throws IOException {
	        String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
	        String nonce = request.getHeader(WECHAT_PAY_NONCE);
	        return timestamp + "\n"
	                + nonce + "\n"
	                + body + "\n";
	    }

	    protected final String getResponseBody(CloseableHttpResponse response) throws IOException {
	        HttpEntity entity = response.getEntity();
	        return (entity != null && entity.isRepeatable()) ? EntityUtils.toString(entity) : "";
	    }

}

5.2 解密回调通知的数据相关工具类
@Component
public class WxAPIV3AesUtil {

	/**
	 * 对称解密
	 * 
	 * @param bodyMap
	 * @return
	 */
	public static String decryptFromResource(Map<String, Object> bodyMap, String apiV3Key)
			throws GeneralSecurityException {

		// 通知数据
		Map<String, String> resourceMap = (Map) bodyMap.get("resource");
		// 数据密文
		String ciphertext = resourceMap.get("ciphertext");
		// 随机串
		String nonce = resourceMap.get("nonce");
		// 附加数据
		String associatedData = resourceMap.get("associated_data");

		AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
		String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
				nonce.getBytes(StandardCharsets.UTF_8), ciphertext);

		return plainText;
	}


}

参考链接

官方微信V3排错指南
参考1
参考2文章来源地址https://www.toymoban.com/news/detail-483327.html

到了这里,关于微信小程序支付V3版本接口实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot整合IJPay实现微信支付-V3---微信小程序

    微信支付适用于许多场合,如小程序、网页支付、但微信支付相对于其他支付方式略显麻烦,我们使用IJpay框架进行整合 JPay 让支付触手可及, 封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。不依赖任何第三方 mvc 框架,仅仅作为工具使用简单

    2024年02月02日
    浏览(70)
  • Python对接微信小程序V3接口进行支付,并使用uwsgi+nginx+django进行https部署

    网上找了很多教程,但是很乱很杂,并且教程资源很少且说的详细。这里就记录一下分享给大家 共分为以下几个步骤: 目录 一、开始前准备信息 二、使用前端code获取用户的openid 三、对接小程序v3接口下单 四、小程序支付的回调 五、安装并启动uwsgi 六、安装并启动nginx 七、

    2024年02月12日
    浏览(44)
  • Java实现微信小程序V3支付 (完整demo)

    2024年02月07日
    浏览(40)
  • SpringBoot整合微信小程序支付V3(支付、退款)

    微信支付开发前,需要先获取商家信息,包括商户号、AppId、证书和密钥。 获取商户号 微信商户平台 申请成为商户 = 提交资料 = 签署协议 = 获取商户号 获取AppID 微信公众平台 注册服务号 = 服务号认证 = 获取APPID = 绑定商户号 申请商户证书 登录商户平台 = 选择 账户中心 = 安

    2024年02月08日
    浏览(44)
  • 小程序微信支付V3版本Java集成

    相较于之前的微信支付API,主要区别是: 遵循统一的REST的设计风格 使用JSON作为数据交互的格式,不再使用XML 使用基于非对称密钥的SHA256-RSA的数字签名算法,不再使用MD5或HMAC-SHA256 不再要求携带HTTPS客户端证书(仅需携带证书序列号) 使用AES-256-GCM,对回调中的关键信息进

    2024年02月11日
    浏览(62)
  • 【Java】微信小程序V3支付(后台)

    目录         相关官网文档         1.需要的参数         2.引入库         3.用到的工具类         4.支付下单实现         5.支付回调 接入前准备-小程序支付 | 微信支付商户平台文档中心 微信支付-JSAPI下单 获取平台证书列表-文档中心-微信支付商户平

    2024年02月12日
    浏览(49)
  • SpringBoot 整合微信小程序微信支付V3 jsapi (支付、退款)

    最近的一个微信小程序项目里有用到微信支付,网上找的资料都是特别乱,看起来特别懵,结合了好多文章的内容,终于做了出来,可能我的这个博文看起来也是特别乱,但是是可以直接C走简单改一改就可以用的。(支付成功回调,和退款回调因为昨天刚在阿里申请的域名还

    2024年04月25日
    浏览(50)
  • PHP实现对微信支付v3版本回调数据的解密

    PS:本文使用了微信官方给出的demo来实现对回调数据的解密,本文主要对微信官方给出的demo如何使用作出部分个人讲解,以及对解密前后数据的格式进行展示 PHP类:这是微信官方给出的demo

    2024年02月15日
    浏览(48)
  • 【微信小程序】Java实现微信支付(小程序支付JSAPI-V3)java-sdk工具包(包含支付出现的多次回调的问题解析,接口幂等性)

          对于一个没有写过支付的小白,打开微信支付官方文档时彻底懵逼 ,因为 微信支付文档太过详细, 导致我无从下手,所以写此文章,帮助第一次写支付的小伙伴梳理一下。 一、流程分为三个接口:(这是前言,先看一遍,保持印象,方便理解代码) 1、第一个接口:

    2024年01月16日
    浏览(77)
  • java微信小程序支付V2版本(亲测有效)

    MCHID(商户号) 就是商户注册之后,微信支付给你的唯一的数字 APPID(小程序的appid) SSLFILE(微信支付需要申请证书,这个字段就是把申请的证书下载之后,存放在你服务器的某个文件夹的路径) NOTIFYURL(支付成功之后,微信会给你这个url发送一条支付成功的消息) APIKEY(证书的秘钥

    2024年02月09日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包