为了实现一码多付
生成一个通用二维码 通过支付宝或者微信都可以支付
1 使用支付宝扫码支付
支付宝提供了 扫码枪,用户扫商户动态生成的码 这样会根据用户不同或者金额不同需要动态的码,这样显然是不可以的
所以要实现商户生成一个静态码,并且商户能获取订单信息,后台通知只有实现一码多付 JSAPI
支付宝官方文档:https://openclub.alipay.com/read.php?tid=5458&fid=56
总结下来文档无非就是一下几点:
1 申请一个账号(我申请的是一个沙箱环境的),需要生产环境的自行去申请即可,简单
2 一码多付使用到支付宝的【alipay.trade.create-统一收单交易创建接口】需要签约当面付接口才能有这个接口的权限
3 使用【用户信息授权接口】只需要在appid添加功能即可不需要签约。 步骤二 需要用到 buyer_id 用户支付宝账号
这样就是一个正常流程了
第二步创建统一收单订单,buyer_id 不能为空,所以这就依赖第三步的用户信息授权获取用户的id
需要用户授权获取用户id https://docs.open.alipay.com/289/105656
参数名 | 是否必须 | 长度 | 描述 |
---|---|---|---|
app_id | 是 | 16 | 开发者应用的app_id; 相同支付宝账号下,不同的app_id获取的token切忌混用。 |
scope | 是 | 不定,取决于请求授权时scope个数 | 接口权限值,目前只支持auth_user(获取用户信息、网站支付宝登录)、auth_base(用户信息授权)、auth_ecard(商户会员卡)、auth_invoice_info(支付宝闪电开票)、auth_puc_charge(生活缴费)五个值;多个scope时用”,”分隔,如scope为”auth_user,auth_ecard”时,此时获取到的access_token,既可以用来获取用户信息,又可以给用户发送会员卡。 |
redirect_uri | 是 | 100 | 授权回调地址,是经过URLENCODE转义 的url链接(url必须以http或者https开头); 在请求之前,开发者需要先到开发者中心对应应用内,配置授权回调地址。 redirect_uri与应用配置的授权回调地址域名部分必须一致。 |
state | 否 | 100 | 商户自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户。 为防止CSRF攻击,建议开发者请求授权时传入state参数,该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联。 |
scope: auth_user 能获取用户的所有信息,auth_base(这个也叫静默授权:对用户来讲是没有感知的,不会弹出授权页面,但是这个只能获到用户的用户ID,无法获取用户的其他信息,这个也正是我们需要的)
https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=2018062060405677&scope=auth_base&redirect_uri=你的授权回调地址(后面可以拼接参数:http://www.baidu.com?业务参数=xxxx)
这样获取到了用户的authCode: 支付宝就会回调配置的授权回调地址
例如: 授权回调地址?业务参数=xxx&auchCode=XXXXX
下一步:auth_code换取access_token与user_id
AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request);
LogHelper.debug(logger, "用户ID userId={0}", oauthTokenResponse.getUserId());
resoponse=oauthTokenResponse.getBody();
requestData.put("buyer_id", oauthTokenResponse.getUserId());
到这里基本上完成三分之一了
下一步创建订单:这个没啥特别的直接上代码
this.initPaymentConfig(orderInfoModel.getProjectId().toString(), PaymentChannelEnum.ALIPAY);
Map<String, String> param = this.getRequestParam(orderInfoModel, null);
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
request.setNotifyUrl(this.notifyUrl);
request.setBizContent("{" +
"\"out_trade_no\":\"" +orderInfoModel.getOrderId()+"\","+
"\"total_amount\":\"" +param.get("amount")+"\","+
"\"subject\":\""+param.get("subject")+"\"," +
"\"buyer_id\":\""+param.get("buyer_id")+"\"," +
"\"timeout_express\":\"30m\"" +
" }");
AlipayTradeCreateResponse response = alipayClient.execute(request);
if(response.isSuccess()){
return response.getTradeNo();
}
返回订单的订单号 TradeNo: 在H5页面 通过订单号唤起收银台
一共会涉及到两个页面: 第一个页面用户扫码 (中转页面:用户获取用户的code)
1 页面
window.location.href=https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=2018062060405677&scope=auth_base&redirect_uri=你的授权回调地址(后面可以拼接参数:http://www.baidu.com?业务参数=xxxx)
支付宝会将auth_code 传递到 设置的授权回调地址,然后输入金额的页面,最后再js页面拉起收银台输入金额支付
2 页面
<!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>
</head>
<body>
<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 text-center">付款</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="">您正在向 ${(projectName)!}付款</h3>
<div class="input-num">
<input type="number" class="w-100" id="amount" placeholder="请输入要支付的金额">
<span class="color21 text-center">元</span>
</div>
<p class="text-center pay pay-click" id="goPay" onclick="pay()">支付</p>
</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>
function pay() {
var amount = $("#amount").val();
var exp = /^(([1-9]\d*)|\d)(\.[1-9]{1,2})?$/;
if(!exp.test(amount)){
alert('金额格式不正确');
return;
}
var projectId=$("#projectId").val();
var code=$("#code").val();
//获得渠道
var paymentType;
if (navigator.userAgent.indexOf("AlipayClient") > 0) {
paymentType="ALIPAY";
} else if (navigator.userAgent.indexOf("MicroMessenger") > 0) {
paymentType="WEIXIN";
}else{
alert("请使用微信或者支付宝支付");
return;
}
var orderUrl=amount="+amount+"&code="+code+"&projectId="+projectId+"&source="+paymentType;
$.ajax({
url: orderUrl,
type: "GET",
dataType: "json",
cache: false,
success: function (data) {
if(paymentType=='ALIPAY'){
//支付宝支付
alipayIsAlready();
AlipayJSBridge.call("tradePay", {
tradeNO: data.result
}, function (result) {
if ("9000" == result.resultCode) {
window.location.href=rootUrl+"success?amount="+amount;
}else{
window.location.href=rootUrl+"failed";
}
});
}else if(paymentType=='WEIXIN'){
//微信支付
wxIsAlready(JSON.parse(data.result));
}
},
error: function (data) {
window.location.href=rootUrl+"failed";
}
});
}
function alipayIsAlready(callback) {
// 如果jsbridge已经注入则直接调用
if (window.AlipayJSBridge) {
callback && callback();
} else {
// 如果没有注入则监听注入的事件
document.addEventListener('AlipayJSBridgeReady', callback, false);
}
}
/**
* @Description: 微信初始化参数
* @return
*/
function wxIsAlready(responseData) {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', weixinPay(responseData), false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', weixinPay(responseData));
document.attachEvent('onWeixinJSBridgeReady', weixinPay(responseData));
}
}else{
weixinPay(responseData);
}
}
function weixinPay(responseData) {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":responseData.appId, //公众号名称,由商户传入
"timeStamp":responseData.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr":responseData.nonceStr, //随机串
"package":responseData.package, //prepay_id = ?
"signType":'MD5', //微信签名方式:
"paySign":responseData.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
window.location.href=rootUrl+"success?amount="+amount;
} else {
window.location.href=rootUrl+"failed";
}
}
);
}
</script>
</body>
</html>
上面是调用支付宝和微信收银台的js 代码
https://docs.open.alipay.com/common/105591
支付宝静默授权: https://www.jianshu.com/p/665e398a66e4
参考文档:https://blog.csdn.net/a718515028/article/details/80684228
微信静默授权:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
参考文档:https://blog.csdn.net/qq_29863725/article/details/78620198
https://blog.csdn.net/qq_32404273/article/details/78126829