◆ 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
◆ 用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付
◆ 将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付
注意点:
提交方式:采用POST方法提交
API密钥(前面中用到的key):交易过程生成签名的密钥,仅保留在商户系统和微信支付后台,不会在网络中传播。商户妥善保管该Key,切勿在网络中传输,不能在其他客户端中存储,保证key不会被泄漏。商户可根据邮件提示登录微信商户平台进行设置。也可按以下路径设置:微信商户平台(pay.weixin.qq.com)–>账户中心–>账户设置–>API安全–>密钥设置
1、在JSAPI支付文档的统一下单里看下必须传入的参数
// 公众账号id
private String appid;
// 商户号
private String mch_id;
// 商品描述
private String body;
// 随机字符串(32位以内)
private String nonce_str;
// 签名(统一下单的所有参数进行签名)
private String sign;
// 商户订单号
private String out_trade_no;
// 标价金额(单位为分)
private int total_fee;
// 终端IP
private String spbill_create_ip;
// 通知地址
private String notify_url;
// 交易类型
private String trade_type;
// 用户标识(每个用户的openid不一样)
private String openid;
2、获取到以上参数后按照以下xml格式发送给文档提供的接口
<xml>
<appid>wx2421b1c4370ec43b</appid>
<attach>支付测试</attach>
<body>JSAPI支付测试</body>
<mch_id>10000100</mch_id>
<detail><![CDATA[{ "goods_detail":[ { "goods_id":"iphone6s_16G", "wxpay_goods_id":"1001", "goods_name":"iPhone6s 16G", "quantity":1, "price":528800, "goods_category":"123456", "body":"苹果手机" }, { "goods_id":"iphone6s_32G", "wxpay_goods_id":"1002", "goods_name":"iPhone6s 32G", "quantity":1, "price":608800, "goods_category":"123789", "body":"苹果手机" } ] }]]></detail>
<nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
<notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url>
<openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
<out_trade_no>1415659990</out_trade_no>
<spbill_create_ip>14.23.150.211</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>
3、返回结果中获取prepay_id,然后进行准备h5调起支付,查看h5调起支付文档,需要参数如下
4、将前面五个参数进行前面后,将六个参数发送到h5页面按照以下格式填入信息,注意成功支付后处理,最好通过文档API到商户后台查询时候已支付完成,然后将结果返回给用户
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":"1395712654", //时间戳,自1970年以来的秒数
"nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5", //微信签名方式:
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
}
});
}
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();
}
5、到微信支付开发文档的开发步骤里,按照要求到商户后台(登录微信支付商户平台(pay.weixin.qq.com)–>产品中心–>开发配置)和公众号后台网页授权配置域名,
6、具体代码如下
Pay
public class Pay {
// 公众账号id
private String appid;
// 商户号
private String mch_id;
// 商品描述
private String body;
// 随机字符串
private String nonce_str;
// 签名
private String sign;
// 商户订单号
private String out_trade_no;
// 标价金额(单位为分)
private int total_fee;
// 终端IP
private String spbill_create_ip;
// 通知地址
private String notify_url;
// 交易类型
private String trade_type;
// 用户标识
private String openid;
}
主程序
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.zz.config.Parameter;
import com.zz.entity.Pay;
import com.zz.util.HttpsUtil;
import com.zz.util.PayUtil;
import com.zz.util.QRCodeUtil;
import com.zz.util.Sign;
import com.zz.util.XStreamUtil;
import com.zz.util.XmlUtil;
@RestController
@RequestMapping("pay")
public class PayController {
/**
* JSAPI支付
* @return
*/
@RequestMapping("jsapiPay")
public static Map<String,Object> getJsapiPay(){
// openid和金额需要数据库获取
String openid="从用户信息中获取";
int total_fee=2;
String nonce_str=PayUtil.getRandomString(20);
String out_trade_no=PayUtil.getCurrentTime()+PayUtil.getRandomString(5);
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", Parameter.appID);
parameters.put("mch_id", Parameter.mch_id);
parameters.put("nonce_str",nonce_str);
parameters.put("body", Parameter.body);
parameters.put("out_trade_no",out_trade_no);
parameters.put("total_fee", total_fee);
parameters.put("spbill_create_ip", Parameter.spbill_create_ip);
parameters.put("notify_url", Parameter.notify_url);
parameters.put("trade_type", Parameter.trade_type);
parameters.put("openid", openid);
//统一下单签名
String prePaySign=Sign.sign(parameters);
Pay pay = new Pay();
pay.setAppid(Parameter.appID);
pay.setMch_id(Parameter.mch_id);
pay.setNonce_str(nonce_str);
pay.setBody(Parameter.body);
pay.setOut_trade_no(out_trade_no);
pay.setTotal_fee(total_fee);
pay.setSpbill_create_ip(Parameter.spbill_create_ip);
pay.setNotify_url(Parameter.notify_url);
pay.setTrade_type(Parameter.trade_type);
pay.setOpenid(openid);
pay.setSign(prePaySign);
//生成xml格式
XStreamUtil.xstream.alias("xml", Pay.class);
String xml = XStreamUtil.xstream.toXML(pay).replaceAll("__", "_");
System.out.println(xml);
String prepay_id=null;
try {
String resXml=HttpsUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", xml);
prepay_id=XmlUtil.parseXml(resXml, "prepay_id");
} catch (Exception e) {
e.printStackTrace();
}
//微信内h5调起支付
String timeStamp= PayUtil.getTimeStamp();
String Package="prepay_id="+prepay_id;
SortedMap<Object,Object> h5parameters = new TreeMap<Object,Object>();
h5parameters.put("appId", Parameter.appID);
h5parameters.put("timeStamp",timeStamp);
h5parameters.put("nonceStr", nonce_str);
h5parameters.put("package",Package);
h5parameters.put("signType", "MD5");
String paySign=Sign.sign(h5parameters);
Map<String,Object> map = new HashMap<String,Object>();
map.put("appId", Parameter.appID);
map.put("timeStamp", timeStamp);
map.put("nonceStr", nonce_str);
map.put("package", Package);
map.put("signType", "MD5");
map.put("paySign", paySign);
return map;
}
/**
* 扫码/JSAPI支付回调
*
* @param request
* @return
* @throws NumberFormatException
* @throws Exception
*/
@RequestMapping("dealwith")
public String dealwith(HttpServletRequest request) throws NumberFormatException, Exception {
//获取回调信息
InputStream inputStream=null;
inputStream=request.getInputStream();
StringBuffer sb=new StringBuffer();
BufferedReader in=new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
String s;
while(null!=(s=in.readLine())){
sb.append(s);
}
in.close();
inputStream.close();
String resXml=sb.toString();
System.out.println("------------:"+resXml);
// 解析xml成map
Map<String,String> map = new HashMap<>();
map = XmlUtil.parseAllXml(resXml);
//设置 TreeMap
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
packageParams.putAll(map);
// 判断签名是否正确
Boolean isSign=Sign.isSign(packageParams);
if(isSign){
// ------------------------------
// 处理业务开始
// ------------------------------
if ("SUCCESS".equals(XmlUtil.parseXml(resXml, "result_code"))) {
System.out.println("支付成功");
//顾客具体信息,地址存入数据库,提供发货,通知用户下单成功
//向工作人员发送支付成功消息等(消息回复,模板消息)
////////// 执行自己的业务逻辑////////////////
System.out.println("验签成功");
String orderId = (String) packageParams.get("out_trade_no");
String transactionId = (String) packageParams.get("transaction_id");
if (orderId != null) {
// ReturnBody body = orderService.pay(orderId, transactionId, "微信支付");
}
// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
resXml = "" + " "
+ " " + " ";
} else {
System.out.println("支付失败,错误信息:" + packageParams.get("err_code"));
resXml = "" + " "
+ " " + " ";
}
// ------------------------------
// 处理业务完毕
// ------------------------------
return resXml;
} else {
System.out.println("通知签名验证失败");
}
return "" + " "
+ " "+"";
}
}
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="js/pay.js"></script>
</head>
<body>
</body>
</html>
js`
$(document).ready(function(){
$.getJSON("pay/prePay/",function(json){
console.log(json);
console.log(json.appId);
var appId=json.appId;
var timeStamp=json.timeStamp;
var nonceStr=json.nonceStr;
var package1=json.package;
var signType=json.signType;
var paySign=json.paySign;
pay();
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":appId, //公众号名称,由商户传入
"timeStamp":timeStamp, //时间戳,自1970年以来的秒数
"nonceStr":nonceStr, //随机串
"package":package1,
"signType":"MD5", //微信签名方式:
"paySign":paySign //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
//这里填写支付之后的页面跳转(一般要根据API查询接口到商户后台查询结果,然后在该页面显示)
window.location.href="test.html";
} else{
question = confirm("支付失败,是否重新支付");
if(question){
pay();
}
}
});
}
function pay(){
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();
}
}
})
})
支付链接:
http://域名/pay.html