项目接入微信支付的准备工作:

  1. 注册成为开发者,进行资质认证,这里是需要300元的审核费用的;
  2. 在微信商户平台创建应用,提交等待审核(大致需要5-7个工作日);
  3. 应用审核通过之后,进入应用,开通微信支付,提交审核(大致需要2-3个工作日);
  4. 审核通过之后,微信会给注册的邮箱发送商户号,用户和密码等信息。

接入App支付的业务流程主要如下图所示:

接下来,就描述一下接入项目的详细步骤:

  1. 基础信息配置文件:WeiChartConfig.java
  2. 调用API接口的工具类:WeiChartUtil.java
  3. 对外接口:WeiChartController.java

WeiChartConfig.java

此文件主要配置接入微信支付需要的基础信息,例如:商户号、AppId、密钥、异步通知地址等信息,以及微信支付Api地址等信息。

 import com.erenju.util.GlobleConfig;

 /**
* 微信支付基础信息配置
* 沙箱测试地址前边添加:sandboxnew 例如:https://api.mch.weixin.qq.com/sandboxnew/pay/orderquery
* @author rxn
* @date 2018/04/23
*
*/
public class WeiChartConfig { /**
* 预支付请求接口(统一下单)
*/
public static final String PrePayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
// public static final String PrePayUrl = "https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder"; /**
* 异步通知回调地址 ,外网可访问
*/
public static final String notify_url = GlobleConfig.getProperty("PayNotifyUrl")+"/wxpay/notify.json"; /**
* 查询订单地址
*/
public static final String OrderUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
// public static final String OrderUrl = "https://api.mch.weixin.qq.com/sandboxnew/pay/orderquery"; /**
* 关闭订单地址
*/
public static final String CloseOrderUrl = "https://api.mch.weixin.qq.com/pay/closeorder";
// public static final String CloseOrderUrl = "https://api.mch.weixin.qq.com/sandboxnew/pay/closeorder"; /**
* 申请退款地址
*/
public static final String RefundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
// public static final String RefundUrl = "https://api.mch.weixin.qq.com/sandboxnew/secapi/pay/refund"; /**
* 查询退款地址
*/
public static final String RefundQueryUrl = "https://api.mch.weixin.qq.com/pay/refundquery";
// public static final String RefundQueryUrl = "https://api.mch.weixin.qq.com/sandboxnew/pay/refundquery"; /**
* 商户AppId
*/
public static final String AppId = "wx****************"; /**
* 商户号,10位数字
*/
public static final String MchId = "**********"; /**
* 商户密钥 (32位),正式环境和沙箱环境的商户密钥是不同的
*/
public static final String AppSercret = "*****";//正式
/**
* Api Key(32位)
*/
public static final String ApiKey = "*****"; /**
* 商品描述
*/
public static final String body = "****"; /**
* 退款需要证书文件,证书文件的地址
*/
public static final String refund_file_path = "";
}

WeiChartUtil.java

将业务逻辑和调用Api接口的逻辑分开写了,这样业务逻辑没有那么复杂,还增加了代码的复用率。

主要涉及的API如下图所示:(详细的API,请参考微信支付开放平台https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1)

 package com.xhgx.web.pay.weiChart;

 import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element; import com.xhgx.util.HttpClientUtil;
import com.xhgx.util.StringUtil; import common.Logger; /**
* 微信支付调用API接口
* @author rxn
* @date 2018/04/23
*
*/
public class WeiChartUtil { public static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); public static Logger log = Logger.getLogger(WeiChartUtil.class); public static void main(String[] args) { Map map = new HashMap<>();
map.put("mch_id", WeiChartConfig.MchId);
map.put("nonce_str", getRandomString());
String sign = getSign(map);
map.put("sign", sign);
System.out.println(map.get("mch_id"));
System.out.println(map.get("nonce_str"));
System.out.println(sign); String string = HttpClientUtil.sendHttpPost("http://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey", map);
System.out.println(string);
} /**
* 请求获取预支付订单
* @param orderId 订单id
* @param totalFee 总金额(单位:分)
* @return
*/
public static Map<String, Object> getPrepayOrderInfo(String orderId,String totalFee){
Map<String, Object> m = new HashMap<String, Object>();
try {
for(int i=0;i<1;i++){
if(StringUtil.isEmpty(orderId)){
m.put("code", -1);
m.put("message", "订单号不能为空");
break;
}
if(Double.parseDouble(totalFee)<=0){
m.put("code", -1);
m.put("message", "订单金额有误");
break;
} Map<String,String> resultMap = getPreyId(orderId, totalFee, "义龙出行"); System.out.println("resultMap:"+resultMap); String return_code = resultMap.get("return_code");//返回状态码
String return_msg = resultMap.get("return_msg");//返回信息
//签名失败
/*if(!StringUtil.isEmpty(return_msg)){
m.put("code", -1);
m.put("message", return_msg);
break;
}*/ if("SUCCESS".equals(return_code)){
// String appid = resultMap.get("appid");//应用APPID
String mch_id = resultMap.get("mch_id");//商户号
// String device_info = resultMap.get("device_info");//设备号
String nonce_str = resultMap.get("nonce_str");//随机字符串
String sign = resultMap.get("sign");//签名
String result_code = resultMap.get("result_code");//业务结果 if("SUCCESS".equals(result_code)){
String trade_type = resultMap.get("trade_type");//交易类型:APP
String prepay_id = resultMap.get("prepay_id");//预支付交易会话标识,有效期为两个小时 //重新生成sign
Map<String,String> signMap = new HashMap<String,String>();
String timeStamp = getTenTimes();
// signMap.put("appid", appid);
signMap.put("appid", WeiChartConfig.AppId);
signMap.put("partnerid", mch_id);
signMap.put("prepayid", prepay_id);
signMap.put("package", "Sign=WXPay");
signMap.put("noncestr", nonce_str);
signMap.put("timestamp", timeStamp);//时间戳:10位 String newSign = getSign(signMap);
// System.out.println("String:"+newSign);
System.out.println(creatXml(signMap));
m.put("sign", newSign);
// m.put("sign", sign);
m.put("appid", WeiChartConfig.AppId);
m.put("mch_id", mch_id);
m.put("nonce_str", nonce_str);
m.put("trade_type", trade_type);
m.put("prepay_id", prepay_id);
m.put("package", "WXPay");
m.put("timestamp", timeStamp); m.put("code", 0);
m.put("message", "请求成功");
break;
}else{
String err_code = resultMap.get("err_code");//错误代码
String err_code_des = resultMap.get("err_code_des");//错误代码描述 m.put("code", -1);
m.put("err_code", err_code);
m.put("message", err_code_des);
break;
} }else{
m.put("code", -1);
m.put("message", "请求失败");
break;
} }
} catch (Exception e) {
e.printStackTrace();
m.put("code", -1);
m.put("message", "程序异常");
}
return m;
} /**
* 统一下单
* @param orderId 订单id
* @param totalFee 总金额(分)
* @param schoolLabel
* @return
*/
public static Map<String, String> getPreyId(String orderId,String totalFee,String schoolLabel){
Map<String,String> m = new HashMap<String,String>();
m.put("appid", WeiChartConfig.AppId);//应用id
m.put("body", "【"+schoolLabel+"】"+WeiChartConfig.body);//商品描述
m.put("mch_id", WeiChartConfig.MchId);//商户号
m.put("nonce_str", getRandomString());//随机字符串
m.put("notify_url", WeiChartConfig.notify_url);//通知地址
m.put("out_trade_no", orderId);//订单号
m.put("spbill_create_ip", getHostIp());//用户端实际ip
Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR_OF_DAY, 2);//有效时间
m.put("time_expire", sdf.format(cal.getTime()));//交易结束时间,非必填
Calendar cal1 = Calendar.getInstance();
m.put("time_start", sdf.format(cal1.getTime()));//交易起始时间,非必填
// m.put("total_fee", totalFee);//总金额
m.put("total_fee", 1+"");//总金额
m.put("trade_type", "APP");//交易类型
m.put("sign", getSign(m));//签名 String reqStr = creatXml(m);
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.PrePayUrl, reqStr); System.out.println("微信调起统一下单接口返回结果:"+retStr);
return getInfoByXml(retStr);
} /**
* 查询订单
* @param orderId
* @return
*/
public static Map<String, String> getOrder(String orderId){
Map<String, String> m = new HashMap<String,String>();
m.put("appid", WeiChartConfig.AppId);
m.put("mch_id", WeiChartConfig.MchId);
m.put("nonce_str", getRandomString());
m.put("out_trade_no", orderId);//商户订单号
m.put("sign", getSign(m)); String reqStr = creatXml(m);
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.OrderUrl, reqStr);
return getInfoByXml(retStr);
} /**
* 关闭订单
* @param orderId
* @return
*/
public static Map<String, String> closeOrder(String orderId){
Map<String, String> m = new HashMap<String,String>();
m.put("appid", WeiChartConfig.AppId);
m.put("mch_id", WeiChartConfig.MchId);
m.put("out_trade_no", orderId);//商户订单号
m.put("nonce_str", getRandomString());
m.put("sign", getSign(m)); String reqStr = creatXml(m);
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.CloseOrderUrl, reqStr);
return getInfoByXml(retStr);
} /**
* 退款
* @param orderId 订单号
* @param refundId 退款单号
* @param totalFee 订单金额(分)
* @param refundFee 退款金额(分)
* @return
*/
public static Map<String, String> refund(String orderId,String refundId,String totalFee,String refundFee){
Map<String, String> m = new HashMap<String,String>();
m.put("appid", WeiChartConfig.AppId);
m.put("mch_id", WeiChartConfig.MchId);
m.put("nonce_str", getRandomString());
m.put("out_trade_no", orderId);//商户订单号
m.put("out_refund_no", refundId);//退款单号
m.put("total_fee", totalFee);//订单金额
m.put("refund_fee", refundFee);//退款金额
m.put("sign", getSign(m)); String reqStr = creatXml(m);
String retStr = "";
try {
retStr = HttpClientUtil.postHttplientNeedSSL(WeiChartConfig.RefundUrl, reqStr, WeiChartConfig.refund_file_path, WeiChartConfig.MchId);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
return getInfoByXml(retStr);
}
/**
* 查询退款
* @param orderId
* @return
*/
public static Map<String, String> getOrderRefundQueryInfo(String orderId){
Map<String,String> m = new HashMap<String,String>();
m.put("appid", WeiChartConfig.AppId);
m.put("mch_id", WeiChartConfig.MchId);
m.put("nonce_str", getRandomString());
m.put("out_trade_no", orderId);//订单号
m.put("sign", getSign(m)); String reqStr = creatXml(m);
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.RefundQueryUrl, reqStr);
return getInfoByXml(retStr);
} /**
* 得到随机字符串
*
* @param length
* @return
*/
public static String getRandomString() {
int length = 32;
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; ++i) {
int number = random.nextInt(62);// [0,62)
sb.append(str.charAt(number));
}
return sb.toString();
} /**
* 得到本地机器的IP
*
* @return
*/
private static String getHostIp() {
String ip = "";
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return ip;
}
/**
* 生成为头为XML的xml字符串,例如:<xml><key>123</key></xml>
* @param reqMap
* @return
*/
public static String creatXml(Map<String, String> reqMap){
Set<String> set = reqMap.keySet();
StringBuffer b = new StringBuffer();
b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
b.append("<xml>");
for(String key : set){
b.append("<"+key+">").append(reqMap.get(key)).append("</"+key+">");
}
b.append("</xml>");
return b.toString();
} /**
* 生成签名
*
* @param map
* @return
*/
public static String getSign(Map<String, String> map) {
String[] keys = map.keySet().toArray(new String[0]);
Arrays.sort(keys);
StringBuffer reqStr = new StringBuffer();
for (String key : keys) {
String v = map.get(key);
if (v != null && !v.equals("")) {
reqStr.append(key).append("=").append(v).append("&");
}
}
reqStr.append("key").append("=").append(WeiChartConfig.ApiKey); return getMd5ByOrder(reqStr.toString()).toUpperCase();
} /**
* 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
* @return boolean
*/
public static boolean isTenpaySign(Map<String, String> map) { String sign = map.get("sign");//获取微信返回的sign,进行比较
map.remove("sign");//生成签名时,去除sign String[] keys = map.keySet().toArray(new String[0]);
Arrays.sort(keys);
StringBuffer reqStr = new StringBuffer();
for (String key : keys) {
String v = map.get(key);
if (v != null && !v.equals("")) {
reqStr.append(key).append("=").append(v).append("&");
}
}
reqStr.append("key").append("=").append(WeiChartConfig.ApiKey); //算出摘要
String mysign = getMd5ByOrder(reqStr.toString()).toLowerCase();
String tenpaySign = sign.toLowerCase(); // System.out.println(tenpaySign + " " + mysign);
return tenpaySign.equals(mysign);
} /**
* 解析xml
*
* @param xmlStr
* @return
*/
public static Map<String, String> getInfoByXml(String xmlStr) {
try {
Map<String, String> m = new HashMap<String, String>();
Document d = DocumentHelper.parseText(xmlStr);
Element root = d.getRootElement();
for (Iterator<?> i = root.elementIterator(); i.hasNext();) {
Element element = (Element) i.next();
String name = element.getName();
if (!element.isTextOnly()) {
// 不是字符串 跳过。确定了微信放回的xml只有根目录
continue;
} else {
m.put(name, element.getTextTrim());
}
}
Map<String,String> map = new HashMap<String,String>();
map.putAll(m);
// 对返回结果做校验.去除sign 字段再去加密
String retSign = m.get("sign");
m.remove("sign");
String rightSing = getSign(m);
if (rightSing.equals(retSign)) {
return map;
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
} /**
* 获取10位的时间戳
* @return
*/
public static String getTenTimes(){
String time = System.currentTimeMillis()+"";
return time.substring(0, time.length()-3);
}
/**
* 将文本转排序后,换成MD5加密后的字符串
* @param s
* @return
* @author Rxn
* @date 2018-05-08
*/
public static String getMd5ByOrder(String s){
MessageDigest md;
StringBuilder sStringBuilder = new StringBuilder();
try {
md = MessageDigest.getInstance("MD5");
md.reset();
try {
md.update(s.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
byte[] digest = md.digest();
sStringBuilder.setLength(0); for (int i = 0; i < digest.length; ++i) {
int b = digest[i] & 255;
if (b < 16) {
sStringBuilder.append('0');
} sStringBuilder.append(Integer.toHexString(b));
} return sStringBuilder.toString().toUpperCase(); } catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} return null;
}
}

WeiChartController.java

这里主要涉及一些业务处理,代码中我主要粘了对外的异步通知接口(主要作用是App支付成功后,会有一个支付成功的返回信息告知商户),其他需要的接口已经在WeiChartUtil.java中处理过了,直接调用即可。

 import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.xhgx.util.StringUtil;
import com.xhgx.web.SpringContextUtil;
import common.Logger; /**
*
* @author rxn
* @data 2018/05/03
*
*/
@Controller
public class WeiChartController{ public static Logger log = Logger.getLogger(WeiChartController.class); public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static SimpleDateFormat ymdhms = new SimpleDateFormat("yyyyMMddHHmmss"); /**
* 异步通知,回调方法
* @param request
* @param response
* @throws IOException
*/
@ResponseBody
@RequestMapping("/wxpay/notify.json")
public static void getNotifyInfo(HttpServletRequest request, HttpServletResponse response) throws IOException{
System.out.println("微信APP异步通知,回调方法");
//读取参数
InputStream inputStream ;
StringBuffer sb = new StringBuffer();
inputStream = request.getInputStream();
String s ;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((s = in.readLine()) != null){
sb.append(s);
}
in.close();
inputStream.close(); String reqStr = new String(sb);
//将xml解析成map
Map<String, String> reqMap = WeiChartUtil.getInfoByXml(reqStr); //过滤空
Map<String,String> paramMap = new HashMap<String,String>();
Iterator it = reqMap.keySet().iterator();
while (it.hasNext()) {
String name = (String) it.next();
String value = reqMap.get(name); String v = "";
if(value!=null){
v = value.trim();
}
paramMap.put(name, v);
} String resXml="";//响应数据
//创建一个对象,保存通知信息,可以根据业务需求自己定义
PayNotifyTbl payNotifyTbl = new PayNotifyTbl();
payNotifyTbl.setPay_type(1);//支付类型: 1微信 2支付宝
payNotifyTbl.setCreate_dt(new Date());
//验证签名
if(WeiChartUtil.isTenpaySign(paramMap)){
String return_code = paramMap.get("return_code");//返回状态码
String return_msg = paramMap.get("return_msg");//返回信息
String result_code = paramMap.get("result_code");
String err_code = paramMap.get("err_code");
String err_code_des = paramMap.get("err_code_des"); payNotifyTbl.setReturn_code(return_code);
payNotifyTbl.setReturn_msg(return_msg);
payNotifyTbl.setResult_code(result_code);
payNotifyTbl.setErr_code(err_code);
payNotifyTbl.setErr_code_des(err_code_des); if("SUCCESS".equals(return_code)&&"SUCCESS".equals(result_code)){
String appid = paramMap.get("appid");
String mch_id = paramMap.get("mch_id");
String openid = paramMap.get("openid");
String trade_type = paramMap.get("trade_type");
String total_fee = paramMap.get("total_fee");//单位:分
String transaction_id = paramMap.get("transaction_id");//微信支付订单号
String out_trade_no = paramMap.get("out_trade_no");//商户订单号
String time_end = paramMap.get("time_end");//支付完成时间 payNotifyTbl.setAppid(appid);
payNotifyTbl.setOpenid(openid);
payNotifyTbl.setOrder_id(out_trade_no);
payNotifyTbl.setTrade_type(trade_type);
payNotifyTbl.setTotal_fee(Double.parseDouble(total_fee)/100.00);
payNotifyTbl.setTransaction_id(transaction_id);
try {
payNotifyTbl.setTime_end(sdf.format(ymdhms.parse(time_end)));
} catch (ParseException e) {
e.printStackTrace();
} //业务处理,查询订单
OrderTbl order = orderTblService.get(Integer.parseInt(out_trade_no));
//安全起见,添加金额作比较
if(!WeiChartConfig.MchId.equals(mch_id) || order==null || Double.parseDouble(total_fee)/100!=getIntRound(order.getPrice().doubleValue()){
payNotifyTbl.setPay_result("参数错误");
log.info("支付失败,错误信息:" + "参数错误");
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[参数错误]]></return_msg>" + "</xml> ";
}else{
if(order.getOrder_status()==7){
//逻辑处理,支付完成,修改订单状态
order.setOrder_status(OrderStatus.STEP_08.getNodeId());//订单完成
order.setTotal_price(Double.parseDouble(total_fee)/100);//支付费用
order.setPay_way(1);//微信支付
order.setPay_time(new Date());//支付时间
order = ycOrderTblService.save(order); payNotifyTbl.setPay_result("支付成功");
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
}else{
payNotifyTbl.setPay_result("订单已经被处理");
log.info("订单已经被处理");
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} } }else{
payNotifyTbl.setPay_result(paramMap.get("return_msg"));
log.info("微信支付异步通知返回的错误信息:"+paramMap.get("return_msg"));
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
} }else{
payNotifyTbl.setPay_result("微信支付异步通知签名验证失败");
log.info("微信支付异步通知签名验证失败");
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[通知签名验证失败]]></return_msg>" + "</xml> ";
} if(payNotifyTblService==null){
payNotifyTblService= (PayNotifyTblService) SpringContextUtil.getBean(PayNotifyTblService.class);
} payNotifyTbl = payNotifyTblService.save(payNotifyTbl);
//返回微信支付系统告知成功接收
BufferedOutputStream out = new BufferedOutputStream(
response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
} }

在接入微信支付时,入了很多坑,特别注意:生成签名时传入参数的顺序,不同的顺序会导致生成的签名与微信返回的签名不一致。尤其注意调用统一下单接口后,重新生成签名的顺序,一定要按照appid,partnerid,prepayid,noncestr,timestamp,package的顺序,否则App会调起支付页面失败,报签名异常的错误。另外注意:异步通知地址一定是外网可以访问的,而且和微信平台上配置的异步通知地址一致。

微信支付之App支付的更多相关文章

  1. asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1

    2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...

  2. 微信支付(APP支付)-服务端开发(一)

    微信支付,首先需要注册一个商户平台公众账号,(网址:https://pay.weixin.qq.com/index.php/home/d_login) 目前微信支付的接入方式有四种方式:公众号支付,A ...

  3. 微信、支付宝App支付-JPay0.0.2发布

    JPay 对微信App支付.支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调 GitHub:https://github.com/Javen205/JPay OsChina:h ...

  4. asp.net core 微信APP支付(扫码支付,H5支付,公众号支付,app支付)之4

    微信app支付需要以下参数,类封装如下 public class WxPayModel { /// <summary> /// 应用ID /// </summary> publ ...

  5. uni-app - 支付(app支付、小程序支付、h5(微信端)支付)

    App支付.小程序支付.h5(微信端)支付 APP支付(内置) appPay.js /** * 5+App支付,仅支持支付宝以及微信支付 * * 支付宝Sdk集成,微信sdk未集成 * * @para ...

  6. 微信JSAPI 公众号支付 H5支付以及APP支付 WEBAPI接口开发测试

    统一下单入口 调用该方法入口: public void WxPayAPI() { //string PayPrice ="99.9"; ////订单号 //string Payor ...

  7. ThinkPHP 5 整合支付宝微信支付(支付宝H5,微信H5、APP支付、公众号支付)

    因项目没有PC站所以没有写电脑网站支付. Pay.php支付控制器 <?php // +----------------------------------------------------- ...

  8. php支付走过的坑(微信篇 包含h5支付和app支付 注册 秘钥 环境等等配置)

    支付这东西,说容易也容易,说难也难 代码这玩意还比较好说 但是 如果没有demo 直接去看官方文档 十有八九一脸懵逼 今天就整理一下 支付这块走过的坑 涉及 微信h5支付 支付宝h5支付 (api文档 ...

  9. asp.net core 微信公众号支付(扫码支付,H5支付,公众号支付,app支付)之3

    在微信公众号中访问手机网站,当需要调用支付时候无法使用H5支付,只有使用微信公众号支付,使用公众号支付用户必须关注该公众号同时该公众号必须开通公众号支付功能. 1.获取用户的OpenId ,参考之前写 ...

随机推荐

  1. netcore log4相关

    配置: 1:NuGet程序包 - 搜索log4net - 安装 2:配置代码 Startup文件 #region log4        public static ILoggerRepository ...

  2. numpy交换列

    x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(x) x = x[:, [1, 0, 2]] print(x) 输出 [[1 2 3] [4 ...

  3. Polynomial_0

    @[注]两个一元多项式按照指数由大到小的顺序输入! #include <stdio.h> #define MAXSIZE 50 struct PolyNode { int coeffici ...

  4. windows----------windows10如何固定局域网ip

    1. 2. 3. 4. 5.

  5. Oracle中hex和raw的相互转换

    可以参考以下语句: select hextoraw(rawtohex('你好')) from dual select utl_raw.cast_to_varchar2(hextoraw('E4BDA0 ...

  6. URLs ...

    各浏览器对ES6的支持 https://blog.csdn.net/lpw_cn/article/details/84789183 http://kangax.github.io/compat-tab ...

  7. 切换用户后,/etc/profile的配置不起效

    遇到的问题 在配置linux的时候,发现一个问题:su root切换到root用户后,/etc/profile 中配置的PATH不起效果. 问题分析和疑问 是不是~/.profile,~/.bashr ...

  8. linux下列出所有连接到你的Server的IP地址

    linux下列出所有连接到你的Server的IP地址 最近要做一个检查所有连接到主机的IP的脚本,google到一篇老外写的文章 <List all IP addresses connected ...

  9. PHP 异常处理 throw new exception

    当异常被抛出时,其后的代码不会继续执行,PHP 会尝试查找匹配的 "catch" 代码块. 如果异常没有被捕获,而且又没用使用 set_exception_handler() 作相 ...

  10. CCF CSP 201809-2 买菜

    题目链接:http://118.190.20.162/view.page?gpid=T78 问题描述 小H和小W来到了一条街上,两人分开买菜,他们买菜的过程可以描述为,去店里买一些菜然后去旁边的一个广 ...