项目中使用了微信的统一支付以及扫码支付,记录下学习记录

目录

项目中使用了微信的统一支付以及扫码支付,记录下学习记录

1、配置wechat4j.properties 文件

2.编写支付工具类

3.统一支付

3.扫码支付

4、工具类方法

5.Controller层调用

6.前台页面处理

7.总结


1、配置wechat4j.properties 文件

话不多说,直接上配置文件代码

#url
wechat.url=
#token
wechat.token=wechatserver
#encodingaeskey
wechat.encodingaeskey=
wechat4j.config=/wechat4j-test.properties
#wechat appid
wechat.appid=xxxxxx
#wechat app secret
wechat.appsecret=xxxxxwechat.mch.id=xxxx
#wechat mch api secret key, must be 32 length
wechat.mch.key=xxxx

配置文件里面主要使用的参数是wechat.mch.id 和wechat.mch.key 分别需要配置商户的id和key,配置好这个后可以进行下一步了。

2.编写支付工具类

在实际开发中,我是将统一支付、撤单、扫码支付等相关接口写到一个支付工具类中,方便多处地方调用。参考微信的官方文档,将其中需要传递的参数封装成一个实体类,方便具体controller中设定参数,具体参数如下:

private String config = "/wechat4j.properties";private String body;private String detail;private String attach;private String outTradeNo;private String userOpenId;private String notifyUrl;private String authCode;get..set 省略

3.统一支付

首先写下我自己实际使用中使用的类名称导入列表,方便用户使用中可以参考下,具体类使用的是哪个包下面的

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdom2.JDOMException;
import org.springframework.stereotype.Service;
import org.sword.wechat4j.common.Config;
import org.sword.wechat4j.pay.PayManager;
import org.sword.wechat4j.pay.protocol.unifiedorder.UnifiedorderRequest;
import org.sword.wechat4j.pay.protocol.unifiedorder.UnifiedorderResponse;
import org.sword.wechat4j.util.RandomStringGenerator;import com.jfinal.kit.StrKit;
import com.sdhr.shu.bean.extend.BizException;
import com.sdhr.shu.common.Constants;import net.sf.json.JSONObject;

也不会写什么具体解释了,直接贴代码吧,这个方法主要是统一支付的函数,其中可能用到了一些其他的工具类方法,下面尽量全部写进来。

/*** 支付入口* * @param recordId* @param payMoney  支付金额* @param request* @param notifyUrl 回调url*/public Map<String, String> ToPayment(Double payMoney, HttpServletRequest request) throws Exception {// Integer min =// Integer.valueOf(ReadPropertiesUtils.getInstance().getProperty("order_pay_wechat_expiretime"));Integer min = 30;Date start = new Date();Calendar date = Calendar.getInstance();date.setTime(start);date.set(Calendar.MINUTE, date.get(Calendar.MINUTE) + min);Date end = date.getTime();// 支付开始时间String timeStart = DateUtil.formatDateTime(start, DateFormatter.SDF_YMDHMS4);// 支付结束时间String timeExpire = DateUtil.formatDateTime(end, DateFormatter.SDF_YMDHMS4);// 统一下单UnifiedorderRequest unifiedorderRequest = new UnifiedorderRequest(config);unifiedorderRequest.setNonce_str(RandomStringGenerator.generate());// 随机字符串unifiedorderRequest.setBody(body);// 商品描述unifiedorderRequest.setDetail(detail);// 商品详情unifiedorderRequest.setAttach(attach); // 随便写,会原样带回unifiedorderRequest.setOut_trade_no(outTradeNo); // 我们自己的交易订单号unifiedorderRequest.setTotal_fee((int) (payMoney * 100)); // 钱,单位是分unifiedorderRequest.setSpbill_create_ip(Utils.getIpAddr(request));// ip地址unifiedorderRequest.setTime_start(timeStart);unifiedorderRequest.setTime_expire(timeExpire);SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");unifiedorderRequest.setTime_start(sdf.format(new Date()));unifiedorderRequest.setTrade_type("JSAPI");// 交易类型// 获取支付用户的openIdunifiedorderRequest.setOpenid(userOpenId);unifiedorderRequest.setNotify_url(notifyUrl);// 通知地址UnifiedorderResponse unifiedorderResponse = PayManager.unifiedorder(unifiedorderRequest, config);String prepayId = unifiedorderResponse.getPrepay_id();if (prepayId == null) {throw new BizException("E110", Message.getMessage("E110"));}String jsParam = null;if (prepayId != null && prepayId.length() > 10) {// 生成微信支付参数,此处拼接为完整的JSON格式,符合支付调起传入格式jsParam = createPackageValue(Config.instance(config).getAppid(), Config.instance(config).getMchKey(),prepayId);// 此处可以添加订单的处理逻辑logger.info("生成的微信调起JS参数为:" + jsParam);logger.debug("-----ToPayment---------outTradeNo:" + outTradeNo + ",totalMoney:" + payMoney);}Map<String, String> map = new HashMap<String, String>();map.put("prepayId", prepayId);map.put("jsParam", jsParam);map.put("outTradeNo", outTradeNo);return map;}

3.扫码支付

扫码支付对比统一支付相对参数会简单点,具体代码如下:

public Map<String, String> scanQRCodePay(String payMoney, HttpServletRequest request)throws JDOMException, IOException {Integer min = 30;Date start = new Date();Calendar date = Calendar.getInstance();date.setTime(start);date.set(Calendar.MINUTE, date.get(Calendar.MINUTE) + min);Date end = date.getTime();// 支付开始时间String timeStart = DateUtil.formatDateTime(start, DateFormatter.SDF_YMDHMS4);// 支付结束时间String timeExpire = DateUtil.formatDateTime(end, DateFormatter.SDF_YMDHMS4);SortedMap<String, String> params = new TreeMap<String, String>();params.put("appid", Config.instance().getAppid());params.put("mch_id", Config.instance().getMchId());params.put("nonce_str", RandomStringGenerator.generate());params.put("body", body);params.put("attach", attach);params.put("out_trade_no", outTradeNo);params.put("total_fee", payMoney);params.put("spbill_create_ip", Utils.getIpAddr(request));params.put("auth_code", authCode);params.put("time_start", timeStart);params.put("time_expire", timeExpire);SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");params.put("time_start", sdf.format(new Date()));long curren = System.currentTimeMillis();curren += 15 * 60 * 1000;Date dateExpire = new Date(curren);SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");params.put("time_expire", dateFormat.format(dateExpire));String sign = createSign(params, Config.instance(config).getMchKey());params.put("sign", sign);String httpRequest = httpRequest(Constants.MICROPAYURI, "POST", toXml(params));Map<String, String> xmlMap = XMLUtil.doXMLParse(httpRequest);return xmlMap;}

4、工具类方法

package com.sdhr.shu.util;import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import java.io.ByteArrayInputStream;
public class XMLUtil {/*** 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。* @param strxml* @return* @throws JDOMException* @throws IOException*/public static Map doXMLParse(String strxml) throws JDOMException, IOException {strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");if(null == strxml || "".equals(strxml)) {return null;}Map m = new HashMap();InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));SAXBuilder builder = new SAXBuilder();Document doc = builder.build(in);Element root = doc.getRootElement();List list = root.getChildren();Iterator it = list.iterator();while(it.hasNext()) {Element e = (Element) it.next();String k = e.getName();String v = "";List children = e.getChildren();if(children.isEmpty()) {v = e.getTextNormalize();} else {v = XMLUtil.getChildrenText(children);}m.put(k, v);}//关闭流in.close();return m;}/*** 获取子结点的xml* @param children* @return String*/public static String getChildrenText(List children) {StringBuffer sb = new StringBuffer();if(!children.isEmpty()) {Iterator it = children.iterator();while(it.hasNext()) {Element e = (Element) it.next();String name = e.getName();String value = e.getTextNormalize();List list = e.getChildren();sb.append("<" + name + ">");if(!list.isEmpty()) {sb.append(XMLUtil.getChildrenText(list));}sb.append(value);sb.append("</" + name + ">");}}return sb.toString();}/*** 获取xml编码字符集* @param strxml* @return* @throws IOException* @throws JDOMException*/public static String getXMLEncoding(String strxml) throws JDOMException, IOException {InputStream in = HttpClientUtil.String2Inputstream(strxml);SAXBuilder builder = new SAXBuilder();Document doc = builder.build(in);in.close();return (String)doc.getProperty("encoding");}/*** 支付成功,返回微信那服务器* @param return_code* @param return_msg* @return*/public static String setXML(String return_code, String return_msg) {return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";}public static String createXML(Map<String,Object> map){Set<Entry<String,Object>> set=map.entrySet();set.iterator();return null;}}
/*** 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。*/private static String createSign(SortedMap<String, String> packageParams, String AppKey) {StringBuffer sb = new StringBuffer();Set es = packageParams.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + AppKey);String sign = Md5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();return sign;}/*** 方法名:byteToHex</br>* 详述:字符串加密辅助方法 </br>* 开发人员:souvc </br>* 创建时间:2016-1-5 </br>* * @param hash* @return 说明返回值含义* @throws 说明发生此异常的条件*/private static String byteToHex(final byte[] hash) {Formatter formatter = new Formatter();for (byte b : hash) {formatter.format("%02x", b);}String result = formatter.toString();formatter.close();return result;}/*** 方法名:httpRequest</br>* 详述:发送http请求</br>* 开发人员:souvc </br>* 创建时间:2016-1-5 </br>* * @param requestUrl* @param requestMethod* @param outputStr* @return 说明返回值含义* @throws 说明发生此异常的条件*/public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {JSONObject jsonObject = null;StringBuffer buffer = new StringBuffer();try {TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();httpUrlConn.setSSLSocketFactory(ssf);httpUrlConn.setDoOutput(true);httpUrlConn.setDoInput(true);httpUrlConn.setUseCaches(false);httpUrlConn.setRequestMethod(requestMethod);if ("GET".equalsIgnoreCase(requestMethod))httpUrlConn.connect();if (null != outputStr) {OutputStream outputStream = httpUrlConn.getOutputStream();outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}InputStream inputStream = httpUrlConn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;httpUrlConn.disconnect();// jsonObject = JSONObject.fromObject(buffer.toString());} catch (ConnectException ce) {ce.printStackTrace();} catch (Exception e) {e.printStackTrace();}return buffer.toString();}/*** 微信下单map to xml* * @param params 参数* @return {String}*/public static String toXml(Map<String, String> params) {StringBuilder xml = new StringBuilder();xml.append("<xml>");for (Entry<String, String> entry : params.entrySet()) {String key = entry.getKey();String value = entry.getValue();// 略过空值if (StrKit.isBlank(value))continue;xml.append("<").append(key).append(">");xml.append(entry.getValue());xml.append("</").append(key).append(">");}xml.append("</xml>");return xml.toString();}

5.Controller层调用

实际controller层使用的时候,我使用的方法是使用@Autowried 方法注入了一个微信支付相关bean,直接根据相关需要传递的参数设置好后,调用统一支付接口,或者扫码支付接口。下面举简单例子吧。

需要注意的是,微信是区分为预支付和实际支付两种,预支付就是我们将我们本地产生的金额、第三方订单号、交易详细等相关信息封装好请求微信支付接口,需要设定好回调url,在实际支付的接口中根据返回值做相关本地业务逻辑处理。

 @Autowiredprivate WechatPayUtil wc;/**
*预支付
**/
public OutputBean prePay(HttpServletRequest request){。。。 具体业务逻辑处理,返回订单号等信息。。。wc.setBody("收费");wc.setDetail("xxx收费");wc.setNotifyUrl("回调url");wc.setUserOpenId("用户openid");wc.setOutTradeNo("订单号");wc.setAttach("附加数据");map = wc.ToPayment(“金额”, request);//request 必须是请求url
}public String realPay(HttpServletRequest request, HttpServletResponse response){logger.info("--- 微信支付回调 ---");InputStream inStream = request.getInputStream();ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}outSteam.close();inStream.close();String result = new String(outSteam.toByteArray(), "utf-8");Map<String, String> map = null;map = XMLUtil.doXMLParse(result); //解析微信回调参数if (map.get("return_code").equals("SUCCESS")) {if (map.get("result_code").equals("SUCCESS")) {//支付成功,相关处理,具体可以参考微信支付开发文档}}
}

扫码支付与统一下单比较类似,具体实现方法已经贴出来了,这里不做展示,需要注意的是需要对支付订单结果返回值判断做详细点,因为可能出现问题是,5次内微信是小额免密支付的,但5次后需要输入密码,而且因为网路传输问题,对订单的返回都是有影响的,需要间隔5秒左右(官方推荐)再次查询订单状况,根据实际返回情况做页面显示和具体业务逻辑处理。在这里我贴下我自己的判断逻辑,希望大佬指教。

if(!Utils.isNullOrEmpty(returnCode) && "SUCCESS".equals(returnCode)){String resultCode = map.get("result_code");String sign = map.get("sign");if(!Utils.isNullOrEmpty(resultCode) && "SUCCESS".equals(resultCode)){logger.info("-- 收款成功 ---");wxScanPayOutPutBean.setErrorCode("SUCCESS");wxScanPayOutPutBean.setErrorMsg("付款成功");flag = true;}else {// 通信成功,但支付失败if("USERPAYING".equals(errorCode) || "BANKERROR".equals(errorCode) || "SYSTEMERROR".equals(errorCode) ){//间隔5秒查询订单,直至支付超时// 查询订单String tradeState = "";for(int times = 0;times<=6;times++){Thread.sleep(5000);OrderqueryRequest orderqueryRequest = new OrderqueryRequest();orderqueryRequest.setAppid(map.get("appid"));orderqueryRequest.setMch_id(map.get("mch_id"));orderqueryRequest.setOut_trade_no(preBillUuid);orderqueryRequest.setNonce_str(RandomStringGenerator.generate());orderqueryRequest.setSign(map.get("sign"));OrderqueryResponse orderqueryResponse = PayManager.orderquery(orderqueryRequest);System.out.println(orderqueryResponse);if(!Utils.isNullOrEmpty(orderqueryResponse.getResult_code()) && "SUCCESS".equals(orderqueryResponse.getResult_code())){if("SUCCESS".equals(orderqueryResponse.getTrade_state())){wxScanPayOutPutBean.setErrorMsg("付款成功");flag = true;break;}else {wxScanPayOutPutBean.setErrorCode(orderqueryResponse.getTrade_state());wxScanPayOutPutBean.setErrorMsg(orderqueryResponse.getTrade_state_desc());}}}if(Utils.isNullOrEmpty(tradeState) || !"SUCCESS".equals(tradeState)){//撤销订单Map<String, String> reverseOrder = wc.reverseOrder(preBillUuid);if(null != reverseOrder){if(!Utils.isNullOrEmpty(reverseOrder.get("return_code")) && "SUCCESS".equals(reverseOrder.get("return_code"))){flag = false;if(!Utils.isNullOrEmpty(reverseOrder.get("result_code")) && "SUCCESS".equals(reverseOrder.get("result_code"))){wxScanPayOutPutBean.setResult(2);//支付失败,请重新支付wxScanPayOutPutBean.setErrorCode("FAIL");wxScanPayOutPutBean.setErrorMsg("收款失败,订单已被撤销,请重试");}else if("REVERSE_EXPIRE".equals(reverseOrder.get("result_code"))){wxScanPayOutPutBean.setResult(2);//支付失败,请重新支付wxScanPayOutPutBean.setErrorCode("FAIL");wxScanPayOutPutBean.setErrorMsg("收款失败,订单已过期无法撤销");}else {wxScanPayOutPutBean.setResult(5);wxScanPayOutPutBean.setErrorCode(errorCode);wxScanPayOutPutBean.setErrorMsg("系统错误");}}}else {wxScanPayOutPutBean.setResult(2);//支付失败,请重新支付wxScanPayOutPutBean.setErrorCode("FAIL");wxScanPayOutPutBean.setErrorMsg("收款失败,请重试");}System.err.println(reverseOrder);}}else if ("ORDERPAID".equals(errorCode) ) {// 通知前台已经订单已经支付,或已关闭,不能继续扫码wxScanPayOutPutBean.setResult(3);wxScanPayOutPutBean.setErrorCode(errorCode);wxScanPayOutPutBean.setErrorMsg(err_code_des);}else if ("AUTHCODEEXPIRE".equals(errorCode) || "NOTENOUGH".equals(errorCode) || "NOTSUPORTCARD".equals(errorCode) || "ORDERREVERSED".equals(errorCode) || "BUYER_MISMATCH".equals(errorCode) || "AUTH_CODE_INVALID".equals(errorCode) || "ORDERCLOSED".equals(errorCode) ) {// 重新扫码,通知前台错误结果wxScanPayOutPutBean.setResult(4);wxScanPayOutPutBean.setErrorCode(errorCode);wxScanPayOutPutBean.setErrorMsg(err_code_des);}else {// 通知前台系统错误,不能扫码wxScanPayOutPutBean.setResult(5);wxScanPayOutPutBean.setErrorCode(errorCode);wxScanPayOutPutBean.setErrorMsg("系统错误");}}

6.前台页面处理

首先需要引入微信js

 <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js" ></script>

在首先调用预支付接口产生费用后,将相关参数封装为json格式字符串传递到微信支付接口

                 var prepayId = thatData['prepayId'];var jsParam = thatData['jsParam'];var outTradeNo = thatData['outTradeNo'];toPay(jsParam);function toPay(jsParam){var obj = JSON.parse(jsParam);WeixinJSBridge.invoke('getBrandWCPayRequest',obj,function(res){//   loading();WeixinJSBridge.log(res.err_msg);if(res.err_msg == "get_brand_wcpay_request:ok"){window.location.href = "xxxxx";//去支付成功页面}else if(res.err_msg == "get_brand_wcpay_request:cancel"){window.location.href = "支付取消处理"}else{$.toast("支付失败", "forbidden", function() {window.location.href = "支付失败处理"});}}); }

扫码支付配置如下,需要先配置js  wx.config相关参数,js必须要提前引入

<script src='https://res.wx.qq.com/open/js/jweixin-1.0.0.js'></script><script>/*    $(function(){$.ajax({     type: "Post",     //方法所在页面和方法名      url: "/shu-wechat-client/park/charge/getWxConfig",   data:{}, dataType: "json",     success: function(data) { */wx.config({debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: "${sessionScope.appId}", // 必填,公众号的唯一标识timestamp: "${sessionScope.timestamp}", // 必填,生成签名的时间戳nonceStr:  "${sessionScope.nonceStr}", // 必填,生成签名的随机串signature: "${sessionScope.signature}",// 必填,签名,见附录1jsApiList: ['checkJsApi','scanQRCode'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});/*   },     error: function(err) {Lalert("请求出错");}     });  }) */</script> 

实际扫码收款操作

wx.ready(function() {wx.checkJsApi({  jsApiList : ['scanQRCode'],  success : function(res) {  }  });  });//var result ;$("#scanQrcode").click(function(){$("#payimg").attr("src","/shu-wechat-client/img/parkpay/nopay.png");$(".pay-state-word").text("支付中");wx.scanQRCode({  needResult : 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,  scanType : [ "qrCode", "barCode" ], // 可以指定扫二维码还是一维码,默认二者都有  success : function(res) {  var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果  loading("支付中...");scanToPayFuction(result); //调用后台实际扫码接口,并根据返回值做处理}  });  });

7.总结

之上就是我自己做微信统一支付以及扫码支付的一个做法吧,在这里记录下,以后遇到也能够有解决的回溯,也希望能够帮助到一些需要这些知识的人,可能写的不太好,或者有些方法不是很完善,希望大佬指点下,谢谢。

第三篇、记录微信统一支付、扫码支付开发相关推荐

  1. 微信PC端扫码支付 java 模式二的扫码支付

    前言 这次分享的是java对接微信的支付接口,实现电脑端扫码支付后,跳转支付成功页面的例子.之所以分享是微信的Api太坑了.留下的文档也少,对接过程中容易出现各种各样的问题,在实现这扫码支付功能的时候 ...

  2. Java之微信支付(扫码支付模式二)案例实战

    摘要:最近的一个项目中涉及到了支付业务,其中用到了微信支付和支付宝支付,在做的过程中也遇到些问题,所以现在总结梳理一下,分享给有需要的人,也为自己以后回顾留个思路. 一:微信支付接入准备工作: 首先, ...

  3. 微信支付:小程序支付/扫码支付

    0.yml文件配置 1.微信支付controller import io.swagger.annotations.Api; import io.swagger.annotations.ApiOpera ...

  4. html+css+js实现微信和支付宝扫码支付前端

    本章教程,主要利用html+css+js技术实现微信和支付宝扫码支付前端页面. 目录 一.效果图预览 (1)支付宝扫码支付 (2)微信扫码支付 二.项目部分源码文件 (1)目录结构 (2)alipay ...

  5. Java PC端微信、支付宝扫码支付(二)

    Java PC端微信.支付宝扫码支付(二) 前几天写了微信支付,附上链接 https://blog.csdn.net/qq_43494610/article/details/90411391 ,今天抽 ...

  6. VB.net开发微信、支付宝扫码支付源码

    扫码消费机介绍:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-21914722028.2.2b826baawDkx32&id=170 ...

  7. VFP开发微信、支付宝扫码支付

    &&扫码消费机介绍:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-21914722028.4.2b826baa9cTxs0& ...

  8. 【开发技巧】-- 一篇女朋友也能看懂的Spring整合第三方支付(微信支付-扫码支付实现篇)

    1.1 为什么要在项目中使用微信支付? 众所周知,支付宝与财付通(微信支付)是如今第三方支付的两大领头企业,同是微信是一个拥有大量用户群体的一个软件,在项目中整合微信支付在一定程度上可以方便用户购物支 ...

  9. ThinkPHP 整合微信支付 扫码支付 模式二 图文教程

    这篇文章主要介绍扫码支付场景二. 目前有两种模式,模式一比模式二稍微复杂点,至于模式一与模式二的具体内容,流程,微信开发文档都有详细介绍,这里就不多说废话,接下来赶紧上教程! Table of Con ...

  10. 微信支付—— 扫码支付

    个人认为扫码支付比Jsapi支付从开发和使用上要顺心的多.扫码支付不用担心是PC端还是移动浏览器还是微信客户端访问的问题,生成一个二维码,扫描支付即可. 一些配置和代码SDK以及SDK存在的错误可以参 ...

最新文章

  1. 从入门到放弃的javaScrip——队列
  2. 30亿美金投入!一文读懂英伟达性能凶残的Tesla V100牛在哪?
  3. php 函数静态变量,php 函数中静态变量使用的问题实例分析
  4. Python requests 笔记(一)
  5. 被清华免试录取的围棋天才,横扫60位围棋大师的最强AI,竟然都输给了高中生!?...
  6. android 禁止屏幕放大缩小,禁止APP内Webview页面跟随系统缩放字号
  7. Page和AbilitySlice
  8. opencv-Mat数据类型及位数总结
  9. 华为员工实力炫富,工作六年有房有豪车,存款六十万
  10. “SCSA-S学习导图+”系列:文件解析
  11. 在超市使用室内地图的5个好处
  12. 小程序apkg还原_Macbook不为人知实用小技巧,学到就赚到!
  13. 创客思维在高等教育中的启迪作用
  14. 服务器断电mysql文件丢失_服务器断电了怎么恢复数据?
  15. 上海第二家K11项目动工;v2food获近3.5亿元B+轮融资;华彬快消品贵州功能饮料生产基地投产...
  16. PTA Sheldon的小本本
  17. 调用QQ音乐接口,实现自制MV播放器
  18. 利用两期土地利用数据构造混淆矩阵(土地利用面积转移矩阵)
  19. 有一个强大又好看的,赛过Typora,阿里开发的语雀编辑器
  20. 时间序列预测--ARIMA、LSTM

热门文章

  1. Python使用property函数为类创建管理方法属性
  2. c语言共阴极数码管数字6,7段数码管共阴极共阳极的0-9(字形码)
  3. vpwm的控制变频_变频器常用的几种控制方式
  4. 2 Linux环境基础开发工具
  5. ASP.Net一键自动化更新代码、编译、合并dll、压缩js、css、混淆dll、zip打包、发布到测试环境的bat批处理...
  6. 总结几个比较常用的数学公式(新手入门)
  7. TCAD软件(Sentaurus、Silvaco、Medici、Tsuprem4)安装总结
  8. Sieve of Eratosthenes algorithm
  9. 40G QSFP+光模块汇总
  10. 私藏的实用工具/学习网站