IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 微信支付(小程序微信支付) -> 正文阅读

[移动开发]微信支付(小程序微信支付)

微信开放平台(分享)

微信支付 - 中国领先的第三方支付平台 | 微信支付提供安全快捷的支付方式

微信公众平台(公众号,订阅号)

1.注册小程序

2.注册微信支付账号(由于需要营业执照等信息,暂无法注册)

一,模块架构

分为两部分 1.小程序(公众号) 2.微信支付(中)

?

?二,关键概念

1.首先注册成为商户

2.小程序APPID 登录小程序-开发-开发管理-开发设置

3.商家的商户ID,就是注册的用户名

4.商家的API私钥,就是下面设置的秘钥?

?三,接入准备

微信支付-开发者文档

?

?四,签约产品

即购买什么支付方法,二维码,还是JSAPI等

产品中心 - 微信支付商户平台

五,设置回调地址

支付完成之后,程序服务端接收微信支付成功的回调信息,之后进行其他业务逻辑处理,比如更新订单状态

?

?六,绑定微信支付与小程序

七,签名

类似token,调用接口传参。注意签名并不需要apiV3密钥,构建客户端需要。

微信支付-普通下单开发者文档

微信支付-开发者文档

八,构建客户端

GitHub - wechatpay-apiv3/wechatpay-apache-httpclient: 微信支付 APIv3 Apache HttpClient装饰器(decorator)

?重要概念:

/**
 * merchantId商户号。
 * merchantSerialNumber商户API证书的证书序列号。
 * merchantPrivateKey商户API私钥,如何加载商户API私钥请看常见问题。
 * wechatpayCertificates微信支付平台证书。你也可以使用后面章节提到的“自动更新证书功能”,而不需要关心平台证书的来龙去脉。
 * apiV3Key是String格式的API v3密钥 参考: https://kf.qq.com/faq/180830E36vyQ180830AZFZvu.html
 * <p>
 * 参考文档 开发指引:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_2.shtml
 */

客户端:

@Slf4j
public class WechatPayHttpClientUtil {

    /**
     * merchantId商户号。
     * merchantSerialNumber商户API证书的证书序列号。
     * merchantPrivateKey商户API私钥,如何加载商户API私钥请看常见问题。
     * wechatpayCertificates微信支付平台证书。你也可以使用后面章节提到的“自动更新证书功能”,而不需要关心平台证书的来龙去脉。
     * apiV3Key是String格式的API v3密钥 参考: https://kf.qq.com/faq/180830E36vyQ180830AZFZvu.html
     * <p>
     * 参考文档 开发指引:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_2.shtml
     */
    @Value("${wxpay.merchantId:merchantId}")
    private String merchantId;

    @Value("${wxpay.merchantSerialNumber:merchantSerialNumber}")
    private String merchantSerialNumber;

    @Value("${wxpay.merchantPrivateKey:merchantPrivateKey}")
    private String merchantPrivateKey;

    @Value("${wxpay.apiV3Key:apiV3Key}")
    private String apiV3Key;

    public HttpClient createHttpClient() {
	try {
	    // 加载商户私钥(privateKey:私钥字符串)
	    PrivateKey privateKey = PemUtil
			    .loadPrivateKey(new ByteArrayInputStream(merchantPrivateKey.getBytes("utf-8")));

	    // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
	    //https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient 自动更新证书功能
	    AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
			    new WechatPay2Credentials(merchantId,
					    new PrivateKeySigner(merchantSerialNumber, privateKey)),
			    apiV3Key.getBytes("utf-8"));

	    return WechatPayHttpClientBuilder.create().withMerchant(merchantId, merchantSerialNumber, privateKey)
			    .withValidator(new WechatPay2Validator(verifier)).build();
	} catch (Exception e) {
	    log.error("createHttpClient exception ", e);

	}
	return null;
    }

    public String httpPost(String url, String param, Map<String, Object> headers) throws IOException {
	BufferedReader bufferedReader = null;
	try {
	    HttpPost httpPost = new HttpPost(url);
	    httpPost.setHeader("Content-Type", "application/json;charset=utf-8");
	    httpPost.addHeader("Accept", "application/json");
	    if (headers != null) {
		headers.keySet().forEach(key -> {
		    httpPost.setHeader(key, headers.get(key).toString());
		});
	    }
	    if (StringUtils.isNotBlank(param)) {
		HttpEntity httpEntity = new StringEntity(param, "utf-8");
		httpPost.setEntity(httpEntity);
	    }
	    HttpResponse httpResponse = createHttpClient().execute(httpPost);
	    if (httpResponse.getStatusLine().getStatusCode() != 200) {
		log.error("httpPost failed: url: {}, httpResponse: {}", url, JSON.toJSONString(httpResponse));
	    }
	    String output;
	    bufferedReader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "utf-8"));
	    StringBuilder stringBuilder = new StringBuilder();
	    while ((output = bufferedReader.readLine()) != null) {
		stringBuilder.append(output);
	    }
	    return stringBuilder.toString();
	} catch (IOException e) {
	    e.printStackTrace();
	    throw e;
	} finally {
	    if (bufferedReader != null)
		bufferedReader.close();
	}
    }

    public String httpPost2(String url, String body) {
	//	HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
	HttpPost httpPost = new HttpPost(url);
	httpPost.addHeader("Accept", "application/json");
	httpPost.addHeader("Content-type", "application/json; charset=utf-8");

	ByteArrayOutputStream bos = new ByteArrayOutputStream();
	ObjectMapper objectMapper = new ObjectMapper();
	ObjectNode rootNode = objectMapper.createObjectNode();
	rootNode.put("mchid", "1900009191").put("appid", "wxd678efh567hg6787").put("description", "Image形象店-深圳腾大-QQ公仔")
			.put("notify_url", "https://www.weixin.qq.com/wxpay/pay.php")
			.put("out_trade_no", "1217752501201407033233368018");
	rootNode.putObject("amount").put("total", 1);
	rootNode.putObject("payer").put("openid", "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o");

	String bodyAsString = null;
	try {
	    objectMapper.writeValue(bos, rootNode);
	    //	    httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
	    httpPost.setEntity(new StringEntity(body, "UTF-8"));
	    HttpResponse response = createHttpClient().execute(httpPost);
	    bodyAsString = EntityUtils.toString(response.getEntity());
	} catch (IOException e) {
	    e.printStackTrace();
	}
	return bodyAsString;
    }

}

签名:

public class TokenUtil {

    /**
     * merchantId商户号。
     * merchantSerialNumber商户API证书的证书序列号。
     * merchantPrivateKey商户API私钥,如何加载商户API私钥请看常见问题。
     * wechatpayCertificates微信支付平台证书。你也可以使用后面章节提到的“自动更新证书功能”,而不需要关心平台证书的来龙去脉。
     * apiV3Key是String格式的API v3密钥 参考: https://kf.qq.com/faq/180830E36vyQ180830AZFZvu.html
     * <p>
     * 参考文档 开发指引:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_2.shtml
     */
    @Value("${wxpay.merchantId:merchantId}")
    private String merchantId;

    @Value("${wxpay.merchantSerialNumber:merchantSerialNumber}")
    private String merchantSerialNumber;

    @Value("${wxpay.merchantPrivateKey:merchantPrivateKey}")
    private String merchantPrivateKey;

    @Value("${wxpay.apiV3Key:apiV3Key}")
    private String apiV3Key;

    /**
     * 签名生成
     * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml
     *
     * @param method
     * @param url
     * @param body
     * @return
     */
    String getToken(String method, HttpUrl url, String body) {
	String nonceStr = "your nonce string";
	long timestamp = System.currentTimeMillis() / 1000;
	String message = buildMessage(method, url, timestamp, nonceStr, body);
	String signature = null;
	try {
	    signature = sign(message.getBytes("utf-8"));
	} catch (Exception e) {
	    e.printStackTrace();
	}

	return "mchid=\"" + merchantId + "\"," + "nonce_str=\"" + nonceStr + "\"," + "timestamp=\"" + timestamp + "\"," + "serial_no=\"" + merchantSerialNumber + "\"," + "signature=\"" + signature + "\"";
    }

    private String sign(byte[] message) throws SignatureException {
	Signature sign = null;
	try {
	    // 加载商户私钥(privateKey:私钥字符串)
	    PrivateKey privateKey = PemUtil
			    .loadPrivateKey(new ByteArrayInputStream(merchantPrivateKey.getBytes("utf-8")));

	    sign = Signature.getInstance("SHA256withRSA");
	    sign.initSign(privateKey);
	    sign.update(message);
	    return Base64.getEncoder().encodeToString(sign.sign());
	} catch (Exception e) {
	    e.printStackTrace();
	}
	return "";
    }

    private String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
	String canonicalUrl = url.encodedPath();
	if (url.encodedQuery() != null) {
	    canonicalUrl += "?" + url.encodedQuery();
	}
	return method + "\n" + canonicalUrl + "\n" + timestamp + "\n" + nonceStr + "\n" + body + "\n";
    }

    /**
     * 获取私钥。
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {
	String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
	try {
	    String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
			    .replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");

	    KeyFactory kf = KeyFactory.getInstance("RSA");
	    return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
	} catch (NoSuchAlgorithmException e) {
	    throw new RuntimeException("当前Java环境不支持RSA", e);
	} catch (InvalidKeySpecException e) {
	    throw new RuntimeException("无效的密钥格式");
	}
    }
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:17:43  更:2021-09-18 10:19:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:38:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码