共计 19507 个字符,预计需要花费 49 分钟才能阅读完成。
前言:
本文基于 PC 网站须要,所开发的微信 Native 网页领取,技术栈,后端蕴含 JAVA、SpringBoot、Maven、Mybatis、Mysql,前端蕴含 HTML5、JS、JQUERY、AJAX 等
开发前筹备:
1、申请 APPID
申请形式:
第一种:微信小程序,请返回小程序平台申请
第二种:微信公众号,请返回公众平台申请
第三种:如果商户已领有以上两种的其一,则能够返回开放平台申请
2、申请 mchId
步骤:
1、首先返回商户号申请平台申请
2、其次申请胜利后,微信官网会向申请时所填写的分割邮箱下发告诉邮件,内容蕴含申请胜利的 mchid 及其登录账号密码,亦能够,登录商户平台,在【账户核心】的商户信息哪里也能够看到
3、最初,请妥善保留 2 的信息
留神:一个 mchid 只能对应一个结算币种,若须要应用多个币种收款,须要申请对应数量的 mchid。
3、绑定 APPID 及 mchid
步骤:
1、登录微信商户平台,点击【产品核心】,在左侧点击【AppID 账号治理】,而后再点击【我关联的 AppID 账号】,呈现列表,而后点击【+ 关联 AppID】,而后输出商户号,提交就实现第一步了。
2、登录微信公众平台(公众号,只有服务号才有微信领取,订阅号没有,望留神!),点击左侧“广告与服务 -> 微信领取 -> 商户号治理 -> 待关联商户号”,而后在列表中找到确认信息,点击确认,即可实现绑定。
留神:只有服务号才有微信领取,订阅号没有,望留神!
提供流程图:
1、
2、
3、
4、去商户平台配置 APIV3 密钥
步骤:
1、登录微信商户平台,进入【账户核心 > API 平安】目录,设置 APIV3 密钥。
2、在弹出窗口中点击“已沟通”。
3、输出 API 密钥,内容为 32 位字符,包含数字及大小写字母。点击获取短信验证码。
(MD5 加密收费获取 32 位字符)
4、输出短信验证码,点击“确认”即设置胜利。
5、实现
5、下载并配置商户证书
步骤:
1、【商户平台】商户可登录微信商户平台,在【账户核心】->【API 平安】->【申请证书】
2、【商户平台】在弹出窗口中点击“确定”。
3、【商户平台】在弹出窗口内点击“下载证书工具”按钮下载证书工具。
4、【证书工具】装置证书工具并关上,抉择证书须要存储的门路后点击“申请证书”。
5、【证书工具】在证书工具中,将复制的商户信息粘贴并点击“下一步”。
6、获取申请串
【证书工具】中操作
【商户平台】中操作
【商户平台】中操作
7、【证书工具】复制证书串
8、【证书工具】粘贴证书串
9、【证书工具】生成证书胜利
10、在【证书工具】-“生成证书”环节,已实现申请证书流程,点击“查看证书文件夹”,查看已生成的证书文件。
11、实现
留神:在后面带【商户平台】,意思是在商户平台中的操作,后面带【证书工具】,意思是在证书工具中操作,望勿弄混!
6、获取证书中的商户序列号,领取须要用到
步骤:
1、【商户平台】商户可登录微信商户平台,在【账户核心】->【API 平安】->【治理证书】
2、关上的窗口,展现证书列表,第一列就是证书序列号,将其保留,以待前面用到。
正式开发步骤:
提要:步骤分的很细,很费神,但能够更直辩的了解!
1、Maven 引入领取依赖包
<!-- 微信领取依赖包 -->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
2、Maven 引入领取签名、应答签名的验证封装依赖包
<!-- 微信领取签名、应答签名的验证封装包 -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.7</version>
</dependency>
3、Maven 引入生成二维码的依赖包
<!-- 引入生成二维码的依赖 -->
<!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
4、创立微信领取工具类 WeChatPayUtils.java
提要:本工具类:蕴含下单办法、查单办法,以及可能会用到的转换以及获取办法等
/**
* 微信领取工具类
* @date 2022/6/16
* @author gxw
*/
public class WeChatPayUtils {
/* 公众号 / 小程序信息 */
//appId
private static final String APP_ID = PropertiesValues.getPropertiesValue("wx.pay.app_id", "application.properties");
//secret
private static final String APP_SECRET = "";
/* 商户信息 */
// 商户号 mch_id
private static final String MCH_ID = PropertiesValues.getPropertiesValue("wx.pay.mch_id", "application.properties");
// 商户私钥 mch_key
private static final String MCH_KEY = "下载证书的 ***key.pem 文件内容";
// 商户证书序列号
private static final String MCH_SERIAL_NO = PropertiesValues.getPropertiesValue("wx.pay.mch_serial_no", "application.properties");
//API3 私钥
private static final String MCH_API_V3_KEY = PropertiesValues.getPropertiesValue("wx.pay.api_key", "application.properties");
/* 领取信息 */
//native 对立下单 API
public static final String NATIVE_PAY_API = PropertiesValues.getPropertiesValue("wx.pay.native.url", "application.properties");
//native 商户订单号查单 API
public static final String NATIVE_PAY_OUT_TRADE_NO_QUERY_ORDER_API = PropertiesValues.getPropertiesValue("wx.pay.out_trade_no.query_order", "application.properties");
//native 微信零碎订单号查单 API
public static final String NATIVE_PAY_TRANSACTIONS_ID_QUERY_ORDER_API = PropertiesValues.getPropertiesValue("wx.pay.transactions_id.query_order", "application.properties");
// 货币类型
public static final String CURRENCY_CNY = "CNY";
// 领取类型
public static final String TRADE_TYPE = "NATIVE";
// 异步回调地址
public static final String NOTIFY_URL = PropertiesValues.getPropertiesValue("wx.pay.notify_url", "application.properties");
/**
* NATIVE 获取 CloseableHttpClient
*/
private static CloseableHttpClient initHttpClient(){
PrivateKey merchantPrivateKey = null;
try {
merchantPrivateKey = PemUtil
.loadPrivateKey(new ByteArrayInputStream(MCH_KEY.getBytes("utf-8")));
// //* 加载证书管理器实例 *//*
// // 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3 密钥)// AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(// new WechatPay2Credentials(MCH_ID, new PrivateKeySigner(MCH_SERIAL_NO, merchantPrivateKey)),MCH_API_V3_KEY.getBytes("utf-8"));
// // 获取单例实例
CertificatesManager certificatesManager = CertificatesManager.getInstance();
// // 向证书管理器减少商户信息,并开启自动更新
certificatesManager.putMerchant(
MCH_ID,
new WechatPay2Credentials(MCH_ID, new PrivateKeySigner(MCH_SERIAL_NO, merchantPrivateKey)),
MCH_API_V3_KEY.getBytes("utf-8")
);
// 从证书管理器取得验签器
Verifier verifier = certificatesManager.getVerifier(MCH_ID);
CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(MCH_ID, MCH_SERIAL_NO, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier)).build();
return httpClient;
} catch (Exception e){e.printStackTrace();
}
return null;
}
/**
* NATIVE 对立下单
* @param money
* @param body
* @return
*/
public static Map<String, String> native_payment_order(String money, String body, String outTradeNo) {
try {CloseableHttpClient httpClient = initHttpClient();
HttpPost httpPost = new HttpPost(NATIVE_PAY_API);
// 申请 body 参数
String reqdata = "{"
//+ "\"time_expire\":\"2018-06-08T10:34:56+08:00\","
+ "\"amount\": {"
+ "\"total\":" + Integer.parseInt(String.valueOf(Float.parseFloat(money) * 100).split("\\.")[0]) + ","
+ "\"currency\":\"" + CURRENCY_CNY + "\""
+ "},"
+ "\"mchid\":\"" + MCH_ID + "\","+"\"description\":\""+ body +"\","
+ "\"notify_url\":\"" + NOTIFY_URL + "\","+"\"out_trade_no\":\""+ outTradeNo +"\","
+ "\"goods_tag\":\" 课程购买 \","
+ "\"appid\":\"" + APP_ID + "\""
+ "}";
StringEntity entity = new StringEntity(reqdata, "utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
// 实现签名并执行申请
CloseableHttpResponse response = null;
Map<String, String> resultMap = new HashMap<>();
try {response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { // 解决胜利
String codeUrl = EntityUtils.toString(response.getEntity());
codeUrl = codeUrl.substring(codeUrl.indexOf("w"), codeUrl.indexOf("}") - 1);
String path = QRCodeGenerator.generateQRCodeImage(codeUrl);
resultMap.put("code", "200");
resultMap.put("data", path);
System.out.println("生成胜利,门路为:" + path);
System.out.println("success,return body =" + codeUrl);
return resultMap;
} else if (statusCode == 204) { // 解决胜利,无返回 Body
System.out.println("success");
resultMap.put("code", "204");
resultMap.put("msg", "解决胜利,但无返回 Body");
return resultMap;
} else {System.out.println("failed,resp code =" + statusCode + ",return body =" + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} catch (Exception e) {e.printStackTrace();
} finally {response.close();
}
} catch (Exception e) {e.printStackTrace();
}
return null;
}
/**
* NATIVE 查问订单
* @param outTradeNo 商户订单号
* @return
*/
public static Map<String, String> native_query_order(String outTradeNo) {
CloseableHttpResponse response = null;
try {
String url = NATIVE_PAY_OUT_TRADE_NO_QUERY_ORDER_API + outTradeNo;
// 申请 URL
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.setParameter("mchid", MCH_ID);
// 实现签名并执行申请
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader("Accept", "application/json");
response = initHttpClient().execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
Map<String, String> resultMap = new HashMap<>();
if (statusCode == 200) {String resData = EntityUtils.toString(response.getEntity());
Map<String, Object> data = JSON.parseObject(resData, HashMap.class);
String tradeState = String.valueOf(data.get("trade_state"));
if("SUCCESS".equals(tradeState)){resultMap.put("msg", "领取胜利");
}else if("NOTPAY".equals(tradeState)){resultMap.put("msg", "订单尚未领取");
}else if("CLOSED".equals(tradeState)){resultMap.put("msg", "此订单已敞开,请从新下单");
}else if("USERPAYING".equals(tradeState)){resultMap.put("msg", "正在领取中,请尽快领取实现哦");
}else if("PAYERROR".equals(tradeState)){resultMap.put("msg", "领取失败,请从新下单");
}
resultMap.put("code", "200");
resultMap.put("tradeState", tradeState);
// resultMap.put("openId", String.valueOf(JSON.parseObject(String.valueOf(data.get("payer")), HashMap.class).get("openid")));
// resultMap.put("transactionId", String.valueOf(data.get("transaction_id")));
return resultMap;
} else if (statusCode == 204) {System.out.println("success");resultMap.put("code", "204");
resultMap.put("msg", "解决胜利,但无返回 Body");
return resultMap;
} else {System.out.println("failed,resp code =" + statusCode+ ",return body =" + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} catch (URISyntaxException e) {e.printStackTrace();
} catch (ClientProtocolException e) {e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
} finally {
try {response.close();
} catch (IOException e) {e.printStackTrace();
}
}
return null;
}
/**
* APIV3 密钥版,NATIVE 领取回调参数解密
* @param map
* @return
*/
public static Map<String, Object> paramDecodeForAPIV3(Map<String, Object> map){
// 应用微信 SDK 提供的 AesUtil 工具类和 APIV3 密钥进行签名验证
AesUtil aesUtil = new AesUtil(MCH_API_V3_KEY.getBytes(StandardCharsets.UTF_8));
JSONObject paramsObj = new JSONObject(map);
JSONObject rJ = paramsObj.getJSONObject("resource");
Map<String, String> paramMap = (Map) rJ;
try {
// 如果 APIV3 密钥和微信返回的 resource 中的信息不统一,是拿不到微信返回的领取信息
String decryptToString = aesUtil.decryptToString(paramMap.get("associated_data").getBytes(StandardCharsets.UTF_8),
paramMap.get("nonce").getBytes(StandardCharsets.UTF_8),
paramMap.get("ciphertext"));
// 验证胜利后将获取的领取信息转为 Map
Map<String, Object> resultMap = WeChatPayUtils.strToMap(decryptToString);
return resultMap;
} catch (GeneralSecurityException e) {e.printStackTrace();
}
return null;
}
/**
* 交易起始工夫
*/
public static String getTimeStart(){SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
return sdf.format(new Date());
}
/**
* 交易完结工夫(订单生效工夫)* @return
*/
public static String getTimeExpire(){SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
Calendar now = Calendar.getInstance();
now.add(Calendar.MINUTE, 30);
return sdf.format(now.getTimeInMillis());
}
/**
* 获取 32 位随机字符串
* @return
*/
public static String getRandomStr() {return UUID.randomUUID().toString().replace("-", "");
}
/**
* 生成订单号
* @return
*/
public static String generateOrderNo() {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
return sdf.format(new Date()) + makeRandom(15);
}
/**
* 生成随机数 纯数字
*
* @return
*/
public static String makeRandom(int len) {return RandomUtils.generateRandomString(len);
}
/**
* 将 Map 转换为 XML 格局的字符串
*
* @param data Map 类型数据
* @return XML 格局的字符串
* @throws Exception
*/
public static String mapToXml(Map<String, String> data) throws Exception {org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key: data.keySet()) {String value = data.get(key);
if (value == null) {value = "";}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(com.gxw.util.StringUtils.toUTF8(value)));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
try {writer.close();
}
catch (Exception ex) { }
return output;
}
/**
* Xml 字符串转换为 Map
*
* @param xmlStr
* @return
*/
public static Map<String, String> xmlStrToMap(String xmlStr) {Map<String, String> map = new HashMap<String, String>();
Document doc;
try {doc = DocumentHelper.parseText(xmlStr);
Element root = doc.getRootElement();
List children = root.elements();
if (children != null && children.size() > 0) {for (int i = 0; i < children.size(); i++) {Element child = (Element) children.get(i);
map.put(child.getName(), child.getTextTrim());
}
}
} catch (DocumentException e) {e.printStackTrace();
}
return map;
}
/**
* 办法用处: 对所有传入参数依照字段名的 ASCII 码从小到大排序(字典序),并且生成 url 参数串 <br>
* 实现步骤: <br>
*
* @param paraMap 要排序的 Map 对象
* @param urlEncode 是否须要 URLENCODE
* @param keyToLower 是否须要将 Key 转换为全小写
* true:key 转化成小写,false: 不转化
* @return
*/
public static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower) {
String buff = "";
Map<String, String> tmpMap = paraMap;
try {List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet());
// 对所有传入参数依照字段名的 ASCII 码从小到大排序(字典序)Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {return (o1.getKey()).toString().compareTo(o2.getKey());
}
});
// 结构 URL 键值对的格局
StringBuilder buf = new StringBuilder();
for (Map.Entry<String, String> item : infoIds) {if (StringUtils.isNotBlank(item.getKey())) {String key = item.getKey();
String val = item.getValue();
if (urlEncode) {val = URLEncoder.encode(val, "utf-8");
}
if (keyToLower) {buf.append(key.toLowerCase() + "=" + val);
} else {buf.append(key + "=" + val);
}
buf.append("&");
}
}
buff = buf.toString();
if (buff.isEmpty() == false) {buff = buff.substring(0, buff.length() - 1);
}
} catch (Exception e) {return null;}
return buff;
}
/**
* 字符串转换为 Map 汇合
* @param str
* @return
*/
public static Map<String, Object> strToMap(String str){Map<String, Object> map = JSON.parseObject(str, HashedMap.class);
return map;
}
}
5、Controller 领取下单接口
/**
* native 领取下单
* @param request
* @param lcGoodsOrder
* @return
*/
@RequestMapping("/nativePaymentOrder")
@NoVerify
public synchronized Map<String, String> nativePaymentOrder(
HttpServletRequest request,
@RequestBody LcGoodsOrder lcGoodsOrder){logger.info("【微信 Native 领取 - 领取下单】************ 开始解决 *************");
// 商户订单号
String outTradeNo = ALiPayUtils.generateOrderNum();
Map<String, String> data = WeChatPayUtils.native_payment_order(lcGoodsOrder.getTotalAmount(), lcGoodsOrder.getSubject(), outTradeNo);
if("200".equals(data.get("code"))){logger.info("【微信 Native 领取 - 领取下单】下单胜利,下单用户:{}, 下单手机号:{}", lcGoodsOrder.getPayUserName(), lcGoodsOrder.getPayUserPhone());
/* 订单记录数据库中 */
lcGoodsOrder.setOutTradeNo(outTradeNo);
lcGoodsOrder.setPayType("1");// 微信 Native 领取类型
lcGoodsOrderService.wxInsert(lcGoodsOrder);
/* 解决返回前端须要数据 */
data.put("outTradeNo", outTradeNo);
data.put("payUserName", lcGoodsOrder.getPayUserName());
data.put("payUserPhone", lcGoodsOrder.getPayUserPhone());
data.put("totalAmount", lcGoodsOrder.getTotalAmount());
return data;
}
logger.info("【微信 Native 领取 - 领取下单】下单失败,下单用户:{}, 下单手机号:{}", lcGoodsOrder.getPayUserName(), lcGoodsOrder.getPayUserPhone());
logger.info("【微信 Native 领取 - 领取下单】************ 完结解决 *************");
return null;
}
6、Controller 领取回调接口
/**
* native 异步回调解决办法
* @param request
* @return
*/
@PostMapping("/nativeNotifyProcess")
@NoVerify
public synchronized String nativeNotifyProcess(
HttpServletRequest request,
HttpServletResponse response) throws Exception {logger.info("【微信 Native 领取 - 领取回调】************ 开始解决 *************");
Map<String, Object> map = new ObjectMapper().readValue(request.getInputStream(), Map.class);
logger.info("【微信 Native 领取 - 领取回调】返回后果:{}",map);
Map<String, Object> dataMap = WeChatPayUtils.paramDecodeForAPIV3(map);
// 判断是否⽀付胜利
if("SUCCESS".equals(dataMap.get("trade_state"))){logger.info("【微信 Native 领取 - 领取回调】判断领取胜利, 商户订单号:{}", dataMap.get("out_trade_no"));
// 领取胜利,业务解决
LcGoodsOrder lcGoodsOrder = new LcGoodsOrder();
// 商户订单号
lcGoodsOrder.setOutTradeNo(String.valueOf(dataMap.get("out_trade_no")));
// 付款用户 openId
lcGoodsOrder.setWxOpenId(String.valueOf(JSON.parseObject(String.valueOf(dataMap.get("payer")), HashMap.class).get("openid")));
// 领取胜利
lcGoodsOrder.setOrderStatus("2");
// 微信系统生成的订单号
lcGoodsOrder.setWxSysOrderNo(String.valueOf(dataMap.get("transaction_id")));
// 批改订单信息
lcGoodsOrderService.updateById(lcGoodsOrder);
// 给微信发送我已接管告诉的响应
// 创立给微信响应的对象
Map<String, String> returnMap = new HashMap<>();
returnMap.put("code", "SUCCESS");
returnMap.put("message", "胜利");
// 将返回微信的对象转换为 xml
String returnXml = WeChatPayUtils.mapToXml(returnMap);
logger.info("【微信 Native 领取 - 领取回调】微信 Native 领取胜利,并且给微信返回响应数据!, 商户订单号:{}", dataMap.get("out_trade_no"));
return returnXml;
}
// 领取失败
// 创立给微信响应的对象
Map<String, String> returnMap = new HashMap<>();
returnMap.put("code", "FALL");
returnMap.put("message", "");
// 将返回微信的对象转换为 xml
String returnXml = WeChatPayUtils.mapToXml(returnMap);
logger.info("【微信 Native 领取 - 领取回调】判断领取失败, 商户订单号:{}", dataMap.get("out_trade_no"));
logger.info("【微信 Native 领取 - 领取回调】************ 完结解决 *************");
return returnXml;
}
7、Controller 查问订单接口
/**
* native 领取查单,通过商户订单号查问订单状态
* @param lcGoodsOrder
* @return
*/
@RequestMapping("/nativeQueryOrder")
@NoVerify
public synchronized Map<String, String> nativeQueryOrder(@RequestBody LcGoodsOrder lcGoodsOrder){logger.info("【微信 Native 领取 - 商户订单号查单】************ 开始解决 *************,商户订单号:{}", lcGoodsOrder.getOutTradeNo());
Map<String, String> data = WeChatPayUtils.native_query_order(lcGoodsOrder.getOutTradeNo());
// 判断查单是否胜利
if("200".equals(data.get("code"))){logger.info("【微信 Native 领取 - 商户订单号查单】查单胜利,商户订单号:{}", lcGoodsOrder.getOutTradeNo());
// 判断查问订单是否领取胜利
if("SUCCESS".equals(data.get("tradeState"))){logger.info("【微信 Native 领取 - 商户订单号查单 - 领取胜利】查单后果领取胜利,商户订单号:{}", lcGoodsOrder.getOutTradeNo());
ResultMap resultMap = lcGoodsOrderService.selectByType("outTradeNo", lcGoodsOrder.getOutTradeNo());
// 判断数据库订单查问是否胜利
if("200".equals(resultMap.getCode())){logger.info("【微信 Native 领取 - 商户订单号查单 - 数据库数据验证】数据库订单数据查问胜利,商户订单号:{}", lcGoodsOrder.getOutTradeNo());
LcGoodsOrder lcGoodsOrder1 = (LcGoodsOrder) resultMap.getData();
// 如果数据库数据尚未批改订单为实现状态,则进行批改
if(lcGoodsOrder1.getOrderStatus().equals("1")){logger.info("【微信 Native 领取 - 商户订单号查单 - 数据库数据验证】数据库订单数据尚未确认订单实现,商户订单号:{}", lcGoodsOrder.getOutTradeNo());
// 付款用户 openId
lcGoodsOrder.setWxOpenId(data.get("openId"));
// 领取胜利
lcGoodsOrder.setOrderStatus("2");
// 微信系统生成的订单号
lcGoodsOrder.setWxSysOrderNo(data.get("transactionId"));
lcGoodsOrderService.updateById(lcGoodsOrder);
logger.info("【微信 Native 领取 - 商户订单号查单 - 数据库数据验证】数据库订单数据确认订单实现,商户订单号:{}", lcGoodsOrder.getOutTradeNo());
}
}
}
// data.remove("openId");
// data.remove("transactionId");
logger.info("【微信 Native 领取 - 商户订单号查单】************ 完结解决 *************,商户订单号:{}", lcGoodsOrder.getOutTradeNo());
return data;
}
return null;
}
8、PC 网站页面调用下单接口
/**
* 调用微信领取接口
* @param {Object} data
* @autors gxw
*/
function wechatPay(data){
var url = "http://127.0.0.1:8686/lcWeChataPay/nativePaymentOrder";
$.ajax({
url: url,
type: 'post',
data: JSON.stringify({
payUserName: data.payUserName,
payUserPhone: data.payUserPhone,
payMessage: data.payMessage,
goodsId: data.goodsId,
totalAmount: data.totalAmount,
subject: data.subject,
}),
contentType: "application/json",
dataType: 'json',
success: function(res){if(res != null){if(res.code == "200"){
window.location.href = "wx_pay.html?otn="+res.outTradeNo
+"&pun="+encodeURI(res.payUserName)
+"&pup="+res.payUserPhone
+"&codePath="+res.data
+"&m="+res.totalAmount
}else{alert("网络异样");
alert(res.msg);
}
}else{alert("网络异样,确认网络无问题,请刷新页面!");
}
},
fail: function(res){console.log("失败")
console.log(res);
}
})
}
9、领取实现,点击已领取,调用查单接口,判断是否领取胜利,胜利,则跳转到胜利页面
/**
* 查问订单,测验订单状态
* @autors gxw
*/
function checkPayStatus(){
var url = "http://127.0.0.1:8686/lcWeChataPay/nativeQueryOrder";
$.ajax({
url: url,
type: 'post',
data: JSON.stringify({outTradeNo: otn}),
contentType: "application/json",
dataType: 'json',
success: function(res){if(res != null){if(res.code == "200"){if(res.tradeState == "SUCCESS"){
window.location.href = "pay_success.html?otn="+otn
+"&pun="+encodeURI(pun)
+"&pup="+pup
+"&m="+m
}else{alert(res.msg);
return false;
}
}else{alert("网络异样");
alert(res.msg);
}
}else{alert("网络异样,确认网络无问题,请刷新页面!");
}
},
fail: function(res){console.log("失败")
console.log(res);
}
})
}
10、这样 PC 网站微信 NATIVE 网页领取,即可实现!
========================= 但这还没有完结 ====================
在这个章节第 4 条,微信领取工具类外面,有须要生成二维码的一段代码援用
但,这块生成二维码代码工具类尚未提供,所以上面的地址,就是你想的那样哟!
== https://segmentfault.com/a/11… ==
也能够点击二维码工具类代码这里哟
遇到问题:
1、the trustAnchors parameter must be non-empty
起因:
遇到 JDK8/jre/lib/security/cacerts 因证书过期或不存在导致
解决:
将 C 盘的 **\jre\lib\security(这个门路后面各有不同,但后缀几个文件目录都一样,也能够间接在 C 盘搜寻栏搜寻”cacerts”,也能够找到)下的 cacerts 替换掉 JDK8 下门路的 cacerts 即可。
2、java.security.InvalidKeyException: Illegal key size
起因:
为了数据代码在传输过程中的平安,很多时候咱们都会将要传输的数据进行加密,而后等对方拿到后再解密应用。咱们在应用 AES 加解密的时候,在遇到 128 位密钥加解密的时候,没有进行什么非凡解决;然而,在应用 256 位密钥加解密的时候,如果不进行非凡解决的话,往往会呈现这个异样 java.security.InvalidKeyException: Illegal key size。
解决:
去官网下载 JCE 无限度权限策略文件。
jdk5:http://www.oracle.com/technet…
jdk6:http://www.oracle.com/technet…
JDK7:http://www.oracle.com/technet…
JDK8:http://www.oracle.com/technet…
下载后解压,能够看到 local_policy.jar 和 US_export_policy.jar 以及 readme.txt
如果装置了 JRE,将两个 jar 文件放到 %JRE_HOME%\lib\security 目录下笼罩原来的文件。
如果装置了 JDK,还要将两个 jar 文件也放到 %JDK_HOME%\jre\lib\security 目录下笼罩原来文件。
==================== 分享 =====================
JDK8 JCE 无限度权限策略文件:
百度网盘链接:https://pan.baidu.com/s/11vPh…
提取码:tnc7