日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JSAPI微信公众号apiV3文档支付

發布時間:2023/12/9 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JSAPI微信公众号apiV3文档支付 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一.所需參數及maven依賴
  • 二.前端vue部分
  • 三.后端java部分


一.所需參數及maven依賴

官方文檔
1.公眾號id appid
2.商戶號 mchid
3.APIv3秘鑰 secret
4.商戶api私鑰 apiclient_key.pem
5.證書序列號

maven依賴

<!-- 微信支付V3版sdk --> <dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-apache-httpclient</artifactId><version>0.2.1</version> </dependency>

二.前端vue部分

// 確認支付 onSubmit() {// 手機端校驗if (!navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {this.$dialog.alert({ message: '請在手機端微信關注公眾號"躍遷賦能中心"進行購買' })return}// TODO 購買商品參數拼接、非空校驗let that = thisthis.$api.request({url: '/wxpay/pay',method: 'post',params: params}).then(response => {// 拉起微信支付參數賦值that.payMap = response.dataif (typeof WeixinJSBridge === 'undefined') {if (document.addEventListener) {document.addEventListener('WeixinJSBridgeReady', this.onBridgeReady, false)} else if (document.attachEvent) {document.attachEvent('WeixinJSBridgeReady', this.onBridgeReady)document.attachEvent('onWeixinJSBridgeReady', this.onBridgeReady)}} else {this.onBridgeReady()}}) }, // 拉起微信支付 onBridgeReady() {let payMap = this.payMaplet that = thisWeixinJSBridge.invoke('getBrandWCPayRequest', {'appId': payMap.appId, // 公眾號名稱,由商戶傳入'timeStamp': payMap.timeStamp, // 時間戳,自1970年以來的秒數'nonceStr': payMap.nonceStr, // 隨機串'package': payMap.package,'signType': payMap.signType, // 微信簽名方式:'paySign': payMap.paySign // 微信簽名},function(res) {if (res.err_msg == 'get_brand_wcpay_request:ok') {// 付款成功處理that.$router.replace({ path: '/' })}}) },

三.后端java部分

3.1 獲取前端拉起微信支付參數
Controller

@ApiOperation("微信公眾號支付") @PostMapping("/pay") public AjaxResult pay(HttpServletRequest request, @RequestParam(required = false) String miniIdStr,@RequestParam Double payAmount, @RequestParam String couponIdStr,@RequestParam(required = false) Long courseId) {Long personId = tokenService.getPersonId(request);// TODO 購買課程參數校驗try {JSONObject result = officeOrderService.wxPay(personId, miniIdStr, payAmount, couponIdStr, courseId);Integer status = result.getInteger("status");if (status != null && status == 0) {// 支付失敗不反回前端拉起微信支付參數return AjaxResult.error("支付失敗,請稍后再試");}return AjaxResult.success(result);} catch (Exception e) {log.error("微信支付下單接口失敗,personId:{},miniIdStr:{},payAmount:{},couponIdStr:{},courseId:{}", personId,miniIdStr, payAmount, couponIdStr, courseId, e);return AjaxResult.error("支付失敗,請稍后再試");} }

Service

@Override public JSONObject wxPay(Long personId, String miniIdStr, Double payAmount, String couponIdStr, Long courseId) {// 根據personId獲取公眾號openIdString openId = wxLoginMapper.selectOpenIdByPersonId(personId);// 生成商品訂單號String orderNumber = UUID.randomUUID().toString().replace("-", "");// TODO 查詢購買課程信息// 返回前端數據集合JSONObject payMap = new JSONObject();// TODO 校驗優惠券與購買課程是否相符(不符返回支付失敗)// TODO 查詢優惠券信息BigDecimal totalVal = BigDecimal.ZERO;// TODO 計算訂單金額 填充生成本地訂單數據(存入本地數據庫的訂單)Double total = totalVal.doubleValue();// 校驗訂單金額if (!total.equals(payAmount)) {log.error("訂單金額不符,personId:{},miniIdStr:{},payAmount:{},couponIdStr:{},total:{}", personId, miniIdStr,payAmount, couponIdStr, total);payMap.put("status", 0);return payMap;}// 支付金額大于0時調用微信支付if (total > 0) {// 拼接統一下單參數JSONObject params = new JSONObject();params.put("appid", WxConstants.OFFICIAL_APPID);params.put("mchid", WxConstants.PAY_MCH_ID);params.put("description", "課程購買");params.put("notify_url", "http://yq.zdxueqian.com/office/wxpay/payNotify");params.put("out_trade_no", orderNumber);// 商品金額JSONObject amount = new JSONObject();amount.put("total", totalVal.multiply(new BigDecimal(100)).intValue());log.info("訂單金額:" + amount.get("total"));params.put("amount", amount);// 支付者JSONObject payer = new JSONObject();payer.put("openid", openId);params.put("payer", payer);// 發送微信預支付訂單請求String prepayId = WxPayUtils.sendPay(params);if (StringUtils.isBlank(prepayId)) {// 生成預支付訂單id失敗(發送微信下單請求)log.error("生成預支付訂單id失敗,params:{}", params);payMap.put("status", 0);return payMap;}// 填充返回前端數據 注:返回前端的timeStamp與nonceStr字段必須與生成簽名的一致 否則前端驗簽失敗payMap.put("appId", WxConstants.OFFICIAL_APPID);long timestamp = System.currentTimeMillis() / 1000;payMap.put("timeStamp", timestamp + "");String nonceStr = WxPayUtils.generateNonceStr();payMap.put("nonceStr", nonceStr);payMap.put("package", "prepay_id=" + prepayId);payMap.put("signType", "RSA");// 生成請求簽名String paySign = WxPayUtils.getPaySign(nonceStr, timestamp, payMap.getString("package"));payMap.put("paySign", paySign);} else {// 訂單金額為0時返回status為1(按支付成功處理)payMap.put("status", 1);}// TODO 添加本地數據庫訂單信息return payMap; }

WxPayUtils工具類

package com.yueqian.common.utils.wxpay;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.cert.X509Certificate; import java.util.Base64; import java.util.Random;import javax.servlet.http.HttpServletRequest;import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; import org.springframework.core.io.ClassPathResource;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; import com.yueqian.common.constant.WxConstants;import lombok.extern.slf4j.Slf4j;/*** 微信支付工具類* * @author suihao* @create 2020-10-22 16:51*/ @Slf4j public class WxPayUtils {/*** 發送微信預支付訂單請求* * @param params* @return* @throws IOException*/public static String sendPay(JSONObject params) {try {// 讀取證書私鑰PrivateKey privateKey = PemUtil.loadPrivateKey(new ClassPathResource("apiclient_key.pem").getInputStream());// 不需要傳入微信支付證書,將會自動更新AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(new WechatPay2Credentials(WxConstants.PAY_MCH_ID,new PrivateKeySigner(WxConstants.PAY_SERIAL_NO, privateKey)),WxConstants.PAY_SECRET_V3.getBytes(StandardCharsets.UTF_8.name()));// 創建http請求HttpClient client = WechatPayHttpClientBuilder.create().withMerchant(WxConstants.PAY_MCH_ID, WxConstants.PAY_SERIAL_NO, privateKey).withValidator(new WechatPay2Validator(verifier)).build();// 配置http請求參數HttpPost post = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");post.setHeader("Content-Type", "application/json");post.setHeader("Accept", "application/json");post.setEntity(new StringEntity(params.toJSONString(), "utf-8"));// 獲取請求結果HttpResponse response = client.execute(post);// System.out.println("響應碼:" + response.getStatusLine());// System.out.println("響應body體:" + EntityUtils.toString(response.getEntity()));JSONObject jo = JSON.parseObject(EntityUtils.toString(response.getEntity()));// 預支付訂單生成失敗(微信端訂單)if (response.getStatusLine().getStatusCode() != 200) {log.error("發送微信預支付訂單請求失敗:" + jo.getString("message") + ",params:{}", params);return null;}// 獲取預支付訂單idreturn jo.getString("prepay_id");} catch (IOException e) {log.error("發送微信預支付訂單請求失敗,params:{}", params, e);return null;}}/*** 獲取調起微信支付簽名* * @param nonceStr* @param timestamp* @param prepayId* @return*/public static String getPaySign(String nonceStr, long timestamp, String prepayId) {String message = WxConstants.OFFICIAL_APPID + "\n" + timestamp + "\n" + nonceStr + "\n" + prepayId + "\n";String signature = null;try {signature = sign(message.getBytes(StandardCharsets.UTF_8.name()), "apiclient_key.pem");} catch (UnsupportedEncodingException e) {log.error("生成微信支付簽名失敗,message:{}", message, e);}return signature;}/*** 讀取請求體中數據* * @param request* @return*/public static String readData(HttpServletRequest request) {BufferedReader br = null;try {StringBuilder result = new StringBuilder();String line;for (br = request.getReader(); (line = br.readLine()) != null; result.append(line)) {if (result.length() > 0) {result.append("\n");}}line = result.toString();return line;} catch (IOException e) {throw new RuntimeException(e);} finally {if (br != null) {try {br.close();} catch (IOException e) {log.error("關閉字符輸入流失敗", e);}}}}/*** 微信支付回調簽名驗證并對加密請求參數解密** @param serialNo* @param result* @param signatureStr* @param nonce* @param timestamp* @param paySecretV3* @return*/public static String verifyNotify(String serialNo, String result, String signatureStr, String nonce,String timestamp, String paySecretV3) throws Exception {// 讀取證書私鑰PrivateKey privateKey = PemUtil.loadPrivateKey(new ClassPathResource("apiclient_key.pem").getInputStream());// 獲取平臺證書AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(new WechatPay2Credentials(WxConstants.PAY_MCH_ID,new PrivateKeySigner(WxConstants.PAY_SERIAL_NO, privateKey)),WxConstants.PAY_SECRET_V3.getBytes(StandardCharsets.UTF_8.name()));X509Certificate certificate = verifier.getValidCertificate();// 證書序列號String serialNumber = certificate.getSerialNumber().toString(16).toUpperCase();// 證書驗證if (serialNumber.equals(serialNo)) {// 構造驗簽名串String buildSignMessage = timestamp + "\n" + nonce + "\n" + result + "\n";// 獲取平臺公鑰PublicKey publicKey = certificate.getPublicKey();Signature signature = Signature.getInstance("SHA256WithRSA");signature.initVerify(publicKey);signature.update(buildSignMessage.getBytes(StandardCharsets.UTF_8));boolean verifySignature =signature.verify(Base64.getDecoder().decode(signatureStr.getBytes(StandardCharsets.UTF_8)));if (verifySignature) {JSONObject resultObject = JSON.parseObject(result);JSONObject resource = resultObject.getJSONObject("resource");String cipherText = resource.getString("ciphertext");String nonceStr = resource.getString("nonce");String associatedData = resource.getString("associated_data");AesUtil aesUtil = new AesUtil(paySecretV3.getBytes(StandardCharsets.UTF_8));return aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),nonceStr.getBytes(StandardCharsets.UTF_8), cipherText);}}return null;}/** 對字節數據進行私鑰簽名(加密) */private static String sign(byte[] message, String serialPath) {try {// 簽名方式(固定SHA256withRSA)Signature sign = Signature.getInstance("SHA256withRSA");// 使用私鑰進行初始化簽名(私鑰需要從私鑰文件【證書】中讀取)InputStream inputStream = new ClassPathResource(serialPath).getInputStream();sign.initSign(PemUtil.loadPrivateKey(inputStream));// 簽名更新sign.update(message);// 對簽名結果進行Base64編碼return Base64.getEncoder().encodeToString(sign.sign());} catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException | IOException e) {log.error("微信支付進行私鑰簽名失敗,message:{}", message, e);}return null;}/*** 獲取隨機字符串 Nonce Str* 隨機字符從symbols獲取* SecureRandom真隨機數* * @return String 隨機字符串*/public static String generateNonceStr() {String symbols = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";Random random = new SecureRandom();char[] nonceChars = new char[32];for (int index = 0; index < nonceChars.length; ++index) {nonceChars[index] = symbols.charAt(random.nextInt(symbols.length()));}return new String(nonceChars);}}

3.2 用戶支付成功回調

@ApiOperation("微信公眾號支付回調") @RequestMapping("/payNotify") public void payNotify(HttpServletRequest request, HttpServletResponse response) {JSONObject resObj = new JSONObject();String plainText = null;try {// 獲取回調請求頭String timestamp = request.getHeader("Wechatpay-Timestamp");String nonce = request.getHeader("Wechatpay-Nonce");String serialNo = request.getHeader("Wechatpay-Serial");String signature = request.getHeader("Wechatpay-Signature");// 獲取回調支付密文String result = WxPayUtils.readData(request);// 驗證簽名并對請求參數解密plainText =WxPayUtils.verifyNotify(serialNo, result, signature, nonce, timestamp, WxConstants.PAY_SECRET_V3);if (StringUtils.isNotBlank(plainText)) {JSONObject payResult = JSON.parseObject(plainText);// TODO 用戶支付成功業務處理(更改本地訂單支付狀態、添加購買記錄、刪除購物車內對應商品)// 注: 業務處理應先查本地數據庫訂單支付狀態 未處理時再進行后面業務處理 微信支付可能會多次調用回調接口response.setStatus(200);resObj.put("code", "SUCCESS");resObj.put("message", "SUCCESS");} else {log.warn("簽名校驗失敗");response.setStatus(500);resObj.put("code", "ERROR");resObj.put("message", "簽名錯誤");}// 響應請求結果response.setHeader("Content-type", "application/json");response.getOutputStream().write(resObj.toJSONString().getBytes(StandardCharsets.UTF_8));response.flushBuffer();} catch (Exception e) {log.error("微信支付回調接口處理失敗,plainText:{}", plainText, e);} }

第一次寫博文,去掉了業務處理部分,盡量使其簡化,寫的不好多見諒。

總結

以上是生活随笔為你收集整理的JSAPI微信公众号apiV3文档支付的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。