java微信公众号JSAPI支付以及所遇到的坑
上周做了个支付宝微信扫码支付,今天总结一下。微信相比支付宝要麻烦许多
由于涉及到代理商,没办法,让我写个详细的申请流程,懵逼啊。
先梳理下流程,对应的文档
要实现微信支付需要四个参数(需要企业认证,就不说了)
- 商户平台
- 商户号ID,也就是商户号。
- KEY,也就是API秘钥。
- 公众平台
- AppID
- AppSecret
梳理完之后,开始操作吧
第一步:参数准备和环境配置
上面的四大参数只有商户key相对比较麻烦
商户平台
公众平台
四大参数准备齐以及环境配置好开始第二步了。
第二步:开发流程
必须的参数有
- appid APPID (已有)
- mch_id 商户ID (已有)
- nonce_str 随机字符串
- sign 签名
- body 所支付的名称
- out_trade_no 咱们自己所提供的订单号,需要唯一
- total_fee 支付金额
- spbill_create_ip IP地址
- notify_url 回调地址
- trade_type 支付类型
- openid 支付人的微信公众号对应的唯一标识
官方就是官方,看着就是费劲,大白话听着多爽
陈海洋:
- 需要codeid,文档地址 https://qydev.weixin.qq.com/wiki/index.php?title=OAuth%E9%AA%8C%E8%AF%81%E6%8E%A5%E5%8F%A3 。
- 根据codeid来获取openid
- 根据openid来获取prepare_id
- 进行下单操作。js调起微信支付
操作1,用户授权获取code
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
注意点 redirect_url需要经过encodeURI编码。
可以使用 js内置的函数encodeURIComponent('http://www.baidu.com')来进行编码操作
我第一反应在想,为什么需要进行url编码,因为这个redirect_uri是作为参数来传递的。
之后就会重定向到你设置的url上面,并且携带code参数,我的后台是这么接收的
ok,code获取完毕
操作2,get请求接口对返回的string进行json解析获取到openid
操作3,post请求发送xml数据返回xml数据,通过官方下载的工具类实现xml转map获取预支付id
操作4,封装jsapi需要的
在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。
ok,到此结束,微信支付成功调起。
需要注意的地方。
微信回调到时候会携带xml数据,这个时候并不能用参数接收,而应该是使用流来接收。
贴出完整代码,记录下
后台java代码
/**
*
*/
package com.wxpay.config; import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate; import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.alipay.config.AlipayConfig;
import com.jeecms.cms.entity.main.CmsSite;
import com.jeecms.cms.ext.aworder.entiry.CmsAWOrder;
import com.jeecms.cms.ext.aworder.service.CmsAWOrderService;
import com.jeecms.cms.ext.crm.entity.CmsCrm;
import com.jeecms.cms.ext.crm.service.CmsCrmMng;
import com.jeecms.cms.web.CmsUtils;
import com.jeecms.cms.web.FrontUtils;
import com.wxpay.util.WXPayUtil; /**
* @author chy
*
* 2019年1月15日-下午7:35:06
*/
@Controller
@RequestMapping("wxpay")
public class WxPayController {// 公众号id
final static String APPID = "***ed9716263ff78b6";
// 公众号秘钥
final static String SECRET = "***2226ea83d7ef6eb799bd8b631ace0";
// 商户号
final static String MATCH_ID = "***0674102"; //商户号(财务)
// 商户key
final static String PATERNER_KEY = "***W3E4R5T6Y7U8I9O0P1Q2W3E4R5T6Y";//商户key(财务) // 微信通知的URL
final static String W_NOTIFY_URL = "www.xinghengedu.com/notifyUrl.htm";
// 支付宝return的URL
final static String A_RETURN_URL = "www.xinghengedu.com/res/success.html";
// 支付宝通知的URL
final static String A_NOTIFY_URL = "www.xinghengedu.com/anotifyUrl.htm"; // 获取openID的URL(微信)
final static String GETOPENID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
// 获取预付款ID的URL(微信)
final static String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; final static String DESC = "星恒订单描述"; final static String ZFB = "支付宝";
final static String WX = "微信"; @Autowired
private CmsAWOrderService orderService; @Autowired
private CmsCrmMng cmsCrmService; /**
* 微信
* @author chy
* 2019年1月17日-下午2:14:31
* @param code 微信必须的code码,需要用code码换取openid,之后需要openid来换取prepay_id。
* @param totalFee 商品价格
* @param username 代理商用户名
* @return
* @throws Exception
*/
@RequestMapping("order.htm")
public String order(HttpServletRequest request,String code,String totalFee,String cmsId ,ModelMap retMap) throws Exception{
System.out.println("***WxPayController.order()");
//先校验金额,由于是double类型,校验相对复杂,涉及到小数点。
String[] split = StringUtils.split(cmsId,",");
Double verify = 0d;
for (String string : split) {
CmsCrm crm = cmsCrmService.findById(Integer.parseInt(string));
verify += crm.getYifu();
}
// 判断需要都转化为分来进行判断
if((int)(verify*100) != (int)(Double.parseDouble(totalFee)*100)){
retMap.addAttribute("chymsg", "金额错误");
return "/res/wxpay/codeDemo.html";
}
String orderNo = getOrderNo("W");// 生成订单id
String getOpenIdparam= "appid="+APPID+"&secret="+SECRET+"&code="+code+"&grant_type=authorization_code";
String getOpenIdUrl = GETOPENID_URL+"?"+getOpenIdparam;
System.out.println("***getOpenId:"+getOpenIdUrl);
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
try {
String resString = rest.getForObject(new URI(getOpenIdUrl), String.class);
JSONObject opidJsonObject = JSONObject.parseObject(resString);
System.out.println("***opidJsonObject:"+opidJsonObject);
String openid = opidJsonObject.get("openid").toString();//获取到了openid
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put("appid", APPID); //公众账号ID
paramMap.put("mch_id", MATCH_ID); //商户号
paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串
paramMap.put("body", DESC); //商品描述
paramMap.put("out_trade_no", orderNo); //商户订单号
paramMap.put("total_fee", (int)(Double.parseDouble(totalFee)*100) +""); //标价金额
paramMap.put("spbill_create_ip", getIpAddress(request));//终端IP
paramMap.put("notify_url", W_NOTIFY_URL); //通知地址
paramMap.put("trade_type", "JSAPI"); //交易类型
paramMap.put("openid", openid);
String sign = WXPayUtil.generateSignature(paramMap, PATERNER_KEY);
paramMap.put("sign", sign);
String mapToXml = WXPayUtil.mapToXml(paramMap);
String postForObject = rest.postForObject(new URI(UNIFIEDORDER_URL), mapToXml, String.class);
System.out.println("***postForObject:"+postForObject);
String prepayId = "";//预支付id
if (postForObject.indexOf("SUCCESS") != -1) {
Map<String, String> map = WXPayUtil.xmlToMap(postForObject);
prepayId = (String) map.get("prepay_id");
}
Map<String, String> payMap = new HashMap<String, String>();
payMap.put("appId", APPID);
payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");
payMap.put("nonceStr", WXPayUtil.generateNonceStr());
payMap.put("signType", "MD5");
payMap.put("package", "prepay_id=" + prepayId);
String paySign = WXPayUtil.generateSignature(payMap, PATERNER_KEY);
payMap.put("paySign", paySign);
payMap.put("pack", "prepay_id=" + prepayId);
retMap.addAttribute("data", payMap); //进行微信生成订单操作
// 对中间表插入数据,如果传入多个crmid,那就是多对一。否则就是一对一,多对多目前没有这种情况。
for (String string : split) {
CmsCrm crm = cmsCrmService.findById(Integer.parseInt(string));
orderService.insertCmsIdAndOrderId(crm.getId(),orderNo);
System.out.println("中间表数据插入完毕。");
}
// 对订单表插入数据
CmsAWOrder order = new CmsAWOrder();
order.setOrderNo(orderNo);
order.setRelateId(cmsId);
order.setPrice(Double.parseDouble(totalFee));
order.setTotal(Double.parseDouble(totalFee)); // 由于传过来的是分,需要转化为元
order.setStatus(1);
order.setProduct(DESC);
order.setCreateTime(new Date());
order.setSource(WX);
orderService.save(order);
System.out.println("***微信创建订单成功");
} catch (Exception e) {
retMap.put("code", "500");
retMap.put("msg", e.getStackTrace());
e.printStackTrace();
}
return "/res/wxpay/codeDemo.html";
} /**
* 支付宝,测试可以使用支付宝做测试,毕竟比较简单。
* @author chy
* 2019年1月17日-下午2:14:15
* @param totalFee 商品价格
* @param username 代理商用户名
* @return
* @throws AlipayApiException
*/
@RequestMapping("aorder.htm")
public String order(HttpServletRequest request,HttpServletResponse httpResponse,Model model,String totalFee,String cmsId) throws AlipayApiException{
CmsSite site = CmsUtils.getSite(request);
System.out.println("---WxPayController.order()");
String[] split = StringUtils.split(cmsId,",");
Double verify = 0d;
for (String string : split) {
CmsCrm crm = cmsCrmService.findById(Integer.parseInt(string));
verify += crm.getYifu();
}
// 判断需要都转化为分来进行判断
if((int)(verify*100) != (int)(Double.parseDouble(totalFee)*100)){
model.addAttribute("chymsg", "金额错误");
return FrontUtils.getTplPath(request, site.getSolutionPath(), "common", "tpl.alipayapi");
} System.out.println("***zfbtotalFee:"+totalFee);
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id,AlipayConfig.merchant_private_key, "json", "UTF-8", AlipayConfig.alipay_public_key,AlipayConfig.sign_type);
AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request
alipayRequest.setReturnUrl(A_RETURN_URL);
alipayRequest.setNotifyUrl(A_NOTIFY_URL);
String out_trade_no = getOrderNo("A");
alipayRequest.setBizContent("{" +
"\"out_trade_no\":\""+out_trade_no+"\"," +
"\"total_amount\":"+totalFee+"," +
"\"product_code\":\"QUICK_WAP_WAY\","+
"\"hb_fq_num\":\"3\","+
"\"hb_fq_seller_percent\":\"0\","+
"\"subject\":\""+DESC+"\"" +
"}");
AlipayTradeWapPayResponse response = alipayClient.pageExecute(alipayRequest);
model.addAttribute("results", response.getBody());
System.out.println("results"+response.getBody());
//进行支付宝生成订单操作
// 对中间表插入数据,如果传入多个crmid,那就是多对一。否则就是一对一,多对多目前没有这种情况。
for (String string : split) {
CmsCrm crm = cmsCrmService.findById(Integer.parseInt(string));
orderService.insertCmsIdAndOrderId(crm.getId(),out_trade_no);
System.out.println("中间表数据插入完毕。");
}
// 对订单表插入数据
CmsAWOrder order = new CmsAWOrder();
order.setOrderNo(out_trade_no);
order.setRelateId(cmsId);
order.setPrice(Double.parseDouble(totalFee));
order.setTotal(Double.parseDouble(totalFee)); // 由于传过来的是分,需要转化为元
order.setStatus(1);
order.setProduct(DESC);
order.setCreateTime(new Date());
order.setSource(ZFB);
orderService.save(order);
System.out.println("***支付宝创建订单成功");
return FrontUtils.getTplPath(request, site.getSolutionPath(), "common", "tpl.alipayapi");
} // 业务操作
public void operation(String oderNo,String zfType){
CmsAWOrder order = orderService.findByProperty("orderNo", oderNo);
// 由于会重复通知(自己没有处理好),所以直接判断订单状态如果修改的话不进行操作。
if(!new Integer(2).equals(order.getStatus())){
order.setStatus(2);//设置为支付成功
order.setPayTime(new Date());
List<Integer> cmsId = orderService.findMiddleByOrderId(oderNo);
System.out.println(cmsId);
for (Integer string : cmsId) {
CmsCrm cmsCrm = cmsCrmService.findById(string);
System.out.println("ali_cmsId:"+string);
System.out.println("cmsCrm:"+cmsCrm);
if("尾款".equals(cmsCrm.getPayMessage()) || cmsCrm.getYingfu().equals(cmsCrm.getYifu())){
cmsCrm.setPaystatus("全部到帐");
if(isNumber(cmsCrm.getAddress())){
CmsCrm cmsCrm2 = cmsCrmService.findById(Integer.parseInt(cmsCrm.getAddress()));
cmsCrm2.setPaystatus("全部到帐");
cmsCrm2.setCwjingbanren("自动对账_"+zfType);
cmsCrm2.setDuizhangtime(new Date());
cmsCrmService.save(cmsCrm2);
}
// }else if(cmsCrm.getYingfu().equals(cmsCrm.getYifu())){
// cmsCrm.setPaystatus("全部到帐");
}else{
cmsCrm.setPaystatus("预付款已到帐");
}
cmsCrm.setCwjingbanren("自动对账_"+zfType);
cmsCrm.setDuizhangtime(new Date());
cmsCrmService.save(cmsCrm);//开课
cmsCrmService.kaike(cmsCrm);//保存
}
orderService.update(order);
System.out.println(zfType+"支付通知结束");
}
} /**
* 微信异步回调通知
* @param request
* @param response
* @return
*/
@ResponseBody
@RequestMapping("notifyUrl.htm")
public Map<String, Object> notifyUrl(HttpServletRequest request,HttpServletResponse response){
System.out.println("**WxPayController.notifyUrl()");
Map<String, Object> retMap = new HashMap<String, Object>();
retMap.put("code", 200);
InputStream is = null;
try {
is = request.getInputStream();//获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
String xml = WXPayUtil.inputStream2String(is, "UTF-8");
System.out.println("***xml:"+xml);
Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//将微信发的xml转map
System.out.println("***notifyMap:"+notifyMap);
if(notifyMap.get("return_code").equals("SUCCESS")){
if(notifyMap.get("result_code").equals("SUCCESS")){
String ordersSn = notifyMap.get("out_trade_no");//商户订单号
String amountpaid = notifyMap.get("total_fee");//实际支付的订单金额:单位 分
BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);//将分转换成元-实际支付金额:元
System.out.println("***notifyUrl.htm data:"+ordersSn+"---"+amountPay); // 进行业务逻辑操作
operation(ordersSn, WX);
}
}
//告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return retMap;
} @ResponseBody
@RequestMapping("anotifyUrl.htm")
public Map<String, Object> anotifyUrl(HttpServletRequest request){
System.out.println("***WxPayController.anotifyUrl()");
Map<String, Object> retMap = new HashMap<String, Object>();
retMap.put("code", 200);
//进行验证操作
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
System.out.println("***requestParams:"+requestParams);
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
System.out.println("___________name:"+name);
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++)
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
params.put(name, valueStr);
}
String trade_status = request.getParameter("trade_status");
boolean signVerified;
try {
signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
if(signVerified){//验证成功
System.out.println("***支付宝验证成功");
if (trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")) {
System.out.println("***判断成功"); // 进行业务逻辑操作
String out_trade_no = request.getParameter("out_trade_no");
operation(out_trade_no, ZFB);
}
} else {
System.out.println("***验证错误");
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return retMap;
} // 获取订单id 规则:当前日期_uuid(17位,总共32位) 支付宝64位。
public static String getOrderNo(String type){
return DateFormatUtils.format(new Date(), "yyyyMMddHHmmss")+"_"+type+"_"+WXPayUtil.generateNonceStr().substring(0, 15);
} // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址
public final static String getIpAddress(HttpServletRequest request) throws IOException {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} else if (ip.length() > 15) {
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = (String) ips[index];
if (!("unknown".equalsIgnoreCase(strIp))) {
ip = strIp;
break;
}
}
}
return ip;
} public boolean isNumber(String string){
String str = String.valueOf(string);
String regex = "^[1-9]\\d*$";
return str.matches(regex);
} }
前端html代码(两个页面,集成了支付宝支付,微信怕因为code失效问题,解决方式重新添加了一个html)
cmsDemo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>支付</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
body{background-color:#efeff4;}
.main{padding:15px;height:100vh;}
.mobile-box{padding:30px;background-color:#fff;}
.mobile-top h2{font-size:18px;color:#000;}
.mobile-content h3 img{margin-right:5px;}
.mobile-content h3{font-size:14px;color:#b2b2b2;}
.input-num{border-bottom: 1px solid #dcdcdc;margin-bottom: 5vh;padding-top: 5vh;}
.input-num .tit{font-size:16px;color:#999;}
.input-num .pay{position:relative;line-height: 50px;margin:10px 0;}
.input-num .pay input{padding-left: 30px;line-height: 50px;border:none;outline:none;}
.input-num .pay span.jinbi{font-weight:bold;color:#000;font-size:24px;position: absolute;left: 0;top: 0;}
.pay-click a.nopay{cursor: pointer;background-color: #a3dea3;color: #fff;width: 100%;display: block;border-radius: 5px;line-height: 50px;font-size: 20px;}
.pay-click a.pay{background-color:#1aac19;}
input[type=number] {-moz-appearance:textfield;}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {-webkit-appearance: none; margin: 0;}
@media(min-width:720px){
.mobile-box{width:720px;margin:0 auto;}
}
</style>
</head>
<body>
<div class="main">
<div class="mobile-box">
<div class="mobile-top ">
<div class="back">
<i class="fa fa-angle-left fa-2x"></i>
</div> <h2 class="top-center color21">北京星恒教育科技有限公司</h2> <div class="back"></div>
</div>
<div class="mobile-content">
<h3 class="color21 font">
<img src="http://img1.52mamahome.com/hotel/homes.png" class="mr10" alt="">北京星恒教育科技有限公司</h3>
<div class="input-num">
<div class="tit">金额</div>
<div class="pay">
<span class="jinbi">¥</span>
<input type="number" class="w-100" id="totalFee" readonly="readonly">
</div>
</div>
<p class="text-center pay pay-click" id="goPay" onclick="pay()"><a class="nopay pay">支付</a></p>
</div>
</div>
</div>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js"></script>
<script> $("#totalFee").val(GetQueryString("totalFee")); // 获取url参数
function GetQueryString(name){
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null;
} if (navigator.userAgent.indexOf("AlipayClient") > 0) {
//window.location.href="http://www.xinghengedu.com/res/wxpay/demo.html";
} else if (navigator.userAgent.indexOf("MicroMessenger") > 0) {
// window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxced9716263ff78b6&redirect_uri=http%3a%2f%2fwww.xinghengedu.com%2fres%2fwxpay%2fdemo.html&response_type=code&scope=snsapi_base#wechat_redirect";
}else{
alert("请使用微信或者支付宝支付");
} function pay() {
var rootUrl = "http://www.xinghengedu.com";
var param = "?totalFee="+GetQueryString("totalFee")+"&cmsId="+GetQueryString("cmsId");
if (navigator.userAgent.indexOf("AlipayClient") > 0) {
var aUrl = "/wxpay/aorder.htm";
//window.location.href="http://www.xinghengedu.com/wxpay/aorder.htm?totalFee="+totalFee;
window.location.href = rootUrl + aUrl + param;
} else if (navigator.userAgent.indexOf("MicroMessenger") > 0) {
//var redirect_url = "http%3a%2f%2fwww.xinghengedu.com%2fres%2fwxpay%2fcodeDemo.html%3ftotalFee%3d"+totalFee;
//var wUrl = "/res/wxpay/codeDemo.html";
var wUrl = "/wxpay/order.htm";
var redirect_url = rootUrl + wUrl + param;
//alert(redirect_url);
var wxUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxced9716263ff78b6&redirect_uri="+encodeURIComponent(redirect_url)+"&response_type=code&scope=snsapi_base#wechat_redirect";
//alert("微信:"+wxUrl);
window.location.href=wxUrl;
}
} </script>
</body>
</html>
codeDemo.html
<#if chymsg??>
alert('${chymsg}');
<#else>
function onBridgeReady(){
try{
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":"${data.appId}", //公众号名称,由商户传入
"timeStamp":"${data.timeStamp}", //时间戳,自1970年以来的秒数
"nonceStr":"${data.nonceStr}", //随机串
"package":"${data.pack}",
"signType":"MD5", //微信签名方式:
"paySign":"${data.paySign}" //微信签名
},
function(res){
//alert(JSON.stringify(res));
if(res.err_msg == "get_brand_wcpay_request:ok" ){
window.location.href = "http://www.xinghengedu.com/res/wxpay/success.html";
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
}
}); }catch(e){
alert(e);
}
}
</#if> if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}
ok,finish.
java微信公众号JSAPI支付以及所遇到的坑的更多相关文章
- 微信公众号JSAPI支付
微信公众号JSAPI支付 一:配置参数 申请成功后,获取接口文件, 将所有文件放入项目根目录weixin下,在WxPay.ub.config.php中填入配置账户信息; 二:设置授权 开发者中心-&g ...
- 微信公众号JSAPI支付-多公众号向同一商户号支付的问题解决
一.背景 项目提供公众号商城集成,在公众号里进行商品的购买,并与多家公众号合作增加渠道流量. . 二.实现 有关微信公众号.商户号的开通与支付绑定不细说 从背景里可知,我们需要实现多个公众号购买向同一 ...
- PHP应用如何对接微信公众号JSAPI支付
微信支付的产品有很多,1. JSAPI支付 2. APP支付 3. Native支付 4.付款码支付 5. H5支付. 其中基于微信公众号开发的应用选择“JSAPI支付“产品,其他APP支付需 ...
- 网站如何接入微信公众号JSAPI支付PHP版
1.首先,我们要有一个微信公众号(分类类型有订阅号,服务号,企业号)我们的微信公众号一定是个服务号只有它才有微信支付接口.. 并且这个微信公众号一定要进行微信认证才能申请微信支付接口. 2.申请JSA ...
- 【weixi】微信支付---微信公众号JSAPI支付
一.JSAPI支付 JSAPI支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付.应用场景有: ◆ 用户在微信公众账号内进入商家公众号,打 ...
- 在Thinkphp中微信公众号JsApi支付
由于网站使用的微信Native扫码支付,现在公众号需要接入功能,怎么办呢,看这官方文档,参考着demo进行写吧.直接进入正题 进入公众号(服务号)设置--->功能设置--->网页授权域名配 ...
- PHP微信公众号JSAPI网页支付(下)
上一篇PHP微信公众号JSAPI网页支付(上)中讲到了公众号平台的相关设置以及支付的大致流程. 这一篇重点讲支付后,异步接受回调通知,以及处理后同步通知微信服务器. 首先梳理下整个jsapi支付的流程 ...
- PHP微信公众号JSAPI网页支付(上)
一.使用场景以及说明 使用场景:商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程. 说明:1.用户打开图文消息或者扫描二维码,在微信内置浏览器打开网 ...
- Java微信公众号安全模式消息解密
这篇文章主要为大家详细介绍了Java微信公众号安全模式消息解密,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.微信公众平台下载解密工具,导入项目中,根据demo解密消息 public stat ...
随机推荐
- zabbix agent安装(三)
转载于https://mp.weixin.qq.com/s/33ab-JLoRfMkeI4aZDciJQ 前一篇文章介绍了zabbix server安装,这篇文章主要讲解zabbix agent安装以 ...
- JavaScript中的两种全局对象
这里总结的东西特别适合先学习c/c++, Java这类标准语言再学JS的童鞋们看,因为JS在程序执行之前就会初始化一个全局对象,这个全局对象到底是什么是跟JS程序运行环境有关的. 根据JavaScri ...
- CentOS7安装新版git
#安装Git yum install -y epel-release rpm -ivh https://centos7.iuscommunity.org/ius-release.rpm yum lis ...
- HTML5 文件API
filelist 表示文件对象的列表. <form name="upload"> <input type="file" name=" ...
- 函数和常用模块【day04】:内置函数分类总结(十一)
重点掌握 字符串格式化format() 字符串格式化百分号 判断 转换 数据类型 帮助信息 map和filter()函数 局部变量全局变量 计算内置函数 常用内置函数(其他) 后续会讲 不常用
- sublime代码对齐
来源于:Sublime 自动缩进怎么设置? - 郭缔的回答 - 知乎 https://www.zhihu.com/question/22987174/answer/90874465 { "k ...
- VS2010 设置main函数输入参数
main函数的argc.argv参数. 英文版:菜单Project -> Properties -> Configuration Properties -> Debugging在Co ...
- Java入门系列(六)方法
方法返回多个值 使用集合类 /** * 方法1:使用集合类 (Map以外的集合类也可以随意使用) * 目标:返回一个数组的最大值和最小值 */ public Map<String, Intege ...
- MySql数据库表的查询操作
http://www.cnblogs.com/whgk/p/6149009.html 优化:http://www.ihref.com/read-16422.html MYSQL常用的几种连接查询方法
- Docker学习笔记三 Dockerfile 指令 定制镜像
本文地址:https://www.cnblogs.com/veinyin/p/10412079.html 镜像是分层存储的,每一层都是独立存在的,修改当前层并不会修改其依赖的上一层,删除某一层也只是 ...