支付方式说明

注意:本页所有支付方式的说明,前提条件是需在adapay 控台开通响应的支付权限,并能成功在商户的服务端使用adapay的SDK 下单返回对应支付渠道的支付信息。

支付宝 APP 支付

支付宝APP 支付可通过多种方式实现。

  • 通过支付宝扫码实现

  • 通过支付宝小程序支付

  • 通过支付宝生活号支付

1,通过扫码的方式

服务端下单时,支付渠道pay_channel 为 alipay

此种方式的主要原理是:通过拉起支付宝APP 然后调用支付宝内said为10000007的扫码功能来发起支付。

前端拿到服务端返回的payment信息后,可通过以下方式调起支付宝,发起支付

1,解析payment 对象,取出其中的pay_info,在 APP 内 通过打开第三方APP的方式打开如下URL

示例:

alipays://platformapi/startapp?saId=10000007&qrcode=https://qr.alipay.com/bax02911brluc2xieoph6001

注意:系统会弹出是否允许打开支付宝,点击允许,跳转支付宝进行支付,此种方式没有考虑用户没有装支付宝的情况。

2,如需考虑未安装支付宝的情况,APP端可使用 webview,加载从Adapay下单返回的链接(例:https://qr.alipay.com/bax02911brluc2xieoph6001

此种方式,如未安装支付宝客户端,会跳转到支付宝下载页面,引导用户安装下载。

以上部分是在APP为原生开发的前提下,RN的方式参考以下示例,Union App开发的可参考以上实现思路来实现。

React Native方式

linkurl = 'alipays://platformapi/startapp?saId=10000007&qrcode='+ {URL}
Linking.openURL(linkurl);

2,通过小程序拉起支付

注意:服务端下单时,支付渠道pay_channel 为 alipay_lite

商户可以使用代理商的小程序来下单发起支付

此种方式的主要原理是:通过拉起支付宝APP,然后跳转到对应支付宝小程序中,在小程序内处理业务逻辑,下单,然后调用支付宝js API 发起支付。

步骤一: APP端打开第三方APP的方式打开如下URL

alipays://platformapi/startapp?appId=app_id&page=page_path"

其中appid 为在支付宝侧申请的小程序appid

page_path 为跳转过去的小程序页面路径

步骤二:获取 buyer_id,即付款用户的支付宝 user_id

详情参考支付宝官方文档:用户授权

1,小程序客户端内获取 authorization_code 示例:

my.getAuthCode({
    scopes: ['auth_user'],
    // 主动授权:auth_user,静默授权:auth_base。或者其它scope。如需同时获取用户多项授权,可在 scopes 中传入多个 scope 值。
    success: (res) => {

        if (res.authCode) {
        // 认证成功
        // 调用自己的服务端接口,让服务端进行后端的授权认证,并且利用session,需要解决跨域问题
        my.request({
            url: 'https://isv.com/auth', // 该url是您自己的服务地址,实现的功能是服务端拿到authcode去开放平台进行token验证
            data: {
            authcode: res.authCode,
            },
            success: () => {
            // 授权成功并且服务器端登录成功
            },
            fail: () => {
            // 根据自己的业务场景来进行错误处理
            },
        });
        }
    },
});

2,商户服务端获取 access_token、user_id

服务器端调用 alipay.system.oauth.token(换取授权访问令牌) 接口换取授权访问令牌,开发者可通过获取到的 auth_code 换取 access_token(授权令牌) 和 user_id (用户支付宝 ID)。

auth_code 作为换取 access_token 的票据,每次用户授权完成,回调地址中的 auth_code 将不一样,auth_cod 只能使用一次,一天未被使用自动过期。

AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode("4b203fe6c11548bcabd8da5bb087a83b");
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
if(response.isSuccess()){
    System.out.println("调用成功");
} else {
    System.out.println("调用失败");
}

步骤三:小程序内调用商户端接口,获取支付信息,支付信息中应包含tradeNO

该接口由商户自行根据业务内容实现。

步骤四:唤起收银台支付

在小程序端使用 tradeNO,调用 my.tradePay 接口唤起支付宝收银台,引导用户完成支付。详情参见支付宝官方说明:小程序唤起收银台

my.tradePay({
    tradeNO: '2017111521001104105336677922',
    success: function(res) {
      my.alert({
       content: JSON.stringify(res),
     });
    },
    fail: function(res) {
    my.alert({
      content: JSON.stringify(res),
      });
   },
});

3, 通过生活号拉起支付

首先要有个支付宝生活号

注意:服务端下单时,支付渠道pay_channel 为 alipay_pub

此种方式的主要原理是:通过拉起支付宝APP,然后跳转到对应支付宝扫码功能,打开生活号H5页面,在H5 内处理业务逻辑,下单,然后调用支付宝js API 发起支付。

步骤一: APP端打开第三方APP的方式打开如下URL

alipays://platformapi/startapp?saId=10000007&qrcode=https://pay.pubxxxx.com/prams=params

其中 qrcode= 后的URL 为生活号页面地址,可在URL 上附带支付相关业务参数。

步骤二:获取生活号授权用户信息

详情参考支付宝官方说明文档:获取生活号授权用户信息

  • URL拼接

  • 获取auth_code

  • 使用auth_code换取接口access_token及用户userId

步骤三:H5页面内调用服务端接口,下单传入user_id 以及pay_channel = alipay_pub,返回支付信息tradeNo 交易号

步骤四:唤起收银台支付

在页面内使用 tradeNO,调用 my.tradePay 接口唤起支付宝收银台,引导用户完成支付。详情参见支付宝官方说明:支付宝交易号唤起支付

<h1>点击以下按钮唤起收银台支付</h1>
<a href="javascript:void(0)" class="btn tradenoPay">支付宝交易号唤起支付</a>
<script>
    function ready(callback) {
        // 如果jsbridge已经注入则直接调用
        if (window.AlipayJSBridge) {
            callback && callback();
        } else {
            // 如果没有注入则监听注入的事件
            document.addEventListener('AlipayJSBridgeReady', callback, false);
        }
    }
    ready(function(){
        document.querySelector('.tradeno').addEventListener('click', function() {
            AlipayJSBridge.call("tradePay", {
                tradeNO: "201802282100100427058809844"
            }, function(result) {
                alert(JSON.stringify(result));
            });
        });
    });
</script>

支付宝网页支付

通过扫码支付实现

商户服务端下单时选择pay_channel = alipay_wap,使用返回的支付信息pay_info发起支付

  • 在H5页面内重定向到下面的URL

alipays://platformapi/startapp?saId=10000007&qrcode=URL

其中URL为后台下单返回的payinfo中的链接

示例: .. code:: javascript

window.location.href=’alipays://platformapi/startapp?saId=10000007&qrcode=https://qr.alipay.com/bax02911brluc2xieoph6001’

上面的方式是不考虑支付宝未安装的情况。如果考虑支付宝未安装的情况,可直接重定向到pay_info中的链接

示例: .. code:: javascript

window.location.href=https://qr.alipay.com/bax02911brluc2xieoph6001

支付宝生活号支付

支付宝生活号支付步骤分以下几步:

步骤一:获取生活号授权用户信息

详情参考支付宝官方说明文档:获取生活号授权用户信息

  • URL拼接

  • 获取auth_code

  • 使用auth_code换取接口access_token及用户userId

步骤二:H5页面内调用服务端接口,下单传入user_id 以及pay_channel = alipay_pub,并返回支付信息tradeNo 交易号

步骤三:唤起收银台支付

在页面内使用 tradeNO,调用 my.tradePay 接口唤起支付宝收银台,引导用户完成支付。详情参见支付宝官方说明:支付宝交易号唤起支付

<h1>点击以下按钮唤起收银台支付</h1>
<a href="javascript:void(0)" class="btn tradenoPay">支付宝交易号唤起支付</a>
<script>
    function ready(callback) {
        // 如果jsbridge已经注入则直接调用
        if (window.AlipayJSBridge) {
            callback && callback();
        } else {
            // 如果没有注入则监听注入的事件
            document.addEventListener('AlipayJSBridgeReady', callback, false);
        }
    }
    ready(function(){
        document.querySelector('.tradeno').addEventListener('click', function() {
            AlipayJSBridge.call("tradePay", {
                tradeNO: "201802282100100427058809844"
            }, function(result) {
                alert(JSON.stringify(result));
            });
        });
    });
</script>

支付宝小程序支付

支付宝小程序支付步骤分以下几步:

步骤一:获取 buyer_id,即付款用户的支付宝 user_id

详情参考支付宝官方文档:用户授权

1,小程序客户端内获取 authorization_code 示例:

my.getAuthCode({
    scopes: ['auth_user'],
    // 主动授权:auth_user,静默授权:auth_base。或者其它scope。如需同时获取用户多项授权,可在 scopes 中传入多个 scope 值。
    success: (res) => {

        if (res.authCode) {
        // 认证成功
        // 调用自己的服务端接口,让服务端进行后端的授权认证,并且利用session,需要解决跨域问题
        my.request({
            url: 'https://isv.com/auth', // 该url是您自己的服务地址,实现的功能是服务端拿到authcode去开放平台进行token验证
            data: {
            authcode: res.authCode,
            },
            success: () => {
            // 授权成功并且服务器端登录成功
            },
            fail: () => {
            // 根据自己的业务场景来进行错误处理
            },
        });
        }
    },
});

2,商户服务端获取 access_token、user_id

服务器端调用 alipay.system.oauth.token(换取授权访问令牌) 接口换取授权访问令牌,开发者可通过获取到的 auth_code 换取 access_token(授权令牌) 和 user_id (用户支付宝 ID)。

auth_code 作为换取 access_token 的票据,每次用户授权完成,回调地址中的 auth_code 将不一样,auth_cod 只能使用一次,一天未被使用自动过期。

AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode("4b203fe6c11548bcabd8da5bb087a83b");
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
if(response.isSuccess()){
    System.out.println("调用成功");
} else {
    System.out.println("调用失败");
}

步骤二:调用商户端服务端接口,获取payment接口中,pay_channel=alipay_lite,支付信息中应包含tradeNO

步骤三:唤起收银台支付

在小程序端使用 tradeNO,调用 my.tradePay 接口唤起支付宝收银台,引导用户完成支付。详情参见支付宝官方说明:小程序唤起收银台

my.tradePay({
    tradeNO: '2017111521001104105336677922',
    success: function(res) {
      my.alert({
       content: JSON.stringify(res),
     });
    },
    fail: function(res) {
    my.alert({
      content: JSON.stringify(res),
      });
   },
});

微信 APP 支付

由于微信不支持间联的 APP支付,但可以通过APP跳转微信小程序,小程序处理支付逻辑来实现。

APP 跳转小程序可参考微信官方文档:APP跳转微信小程序

前提条件

  • 在微信开放平台上有账号而且有通过的移动应用。

  • 在微信公众平台有账号而且有小程序,开发阶段可以使用体验版本,最终上线,小程序需上线审核通过。

  • 在微信开放平台把对应的移动应用和小程序建立关联。

主要步骤:

1,APP跳转微信小程序

下载微信SDK 并参考 微信官方说明 接入SDK

示例代码:iOS 为例,安卓参考官方说明

//微信建议应用启动时调用
[WXApi registerApp:@"wx_app_id"];//wx_app_id 为移动应用的appid
...
...
...
//跳转小程序部分
WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
launchMiniProgramReq.userName = @"gh_4fxxxxxx";  //待拉起的小程序原始Id
launchMiniProgramReq.path = @"pages/index/index?query='test'";    ////拉起小程序页面的可带参路径,不填默认拉起小程序首页,对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar"。
launchMiniProgramReq.miniProgramType = WXMiniProgramTypePreview; //拉起小程序的类型
[WXApi sendReq:launchMiniProgramReq];
...
...
...

2,通过授权获取用户open_id

wx.login({
    success (res) {
        if (res.code) {
            //发起网络请求
            wx.request({
                url: 'https://test.com/onLogin',
                data: {
                code: res.code
                }
            })
        } else {
            console.log('登录失败!' + res.errMsg)
        }
    }
})
  • 2,商户服务端使用第一步获取的code 换取 open_id ,后台调用接口 获取openID

GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

3,下单请求支付信息

通过上面的App打开的path是’path/index’, 所以需要把App的onLaunch事件定义在page/index.js上

_images/weixinlite.png

这里的options.scene是1069,这个场景id表示从app打开。

options.query.key1和options.query.key2就是app打开小程序传递的参数。

通过接口调用服务端下单接口,传入open_id 获取支付payment信息。

4,小程序端发起支付

使用返回的payment 信息中的pay_info 调用wx.requestPayment(OBJECT)发起微信支付

wx.requestPayment(
{
'timeStamp': '',
'nonceStr': '',
'package': '',
'signType': 'MD5',
'paySign': '',
'success':function(res){},
'fail':function(res){},
'complete':function(res){}
})

4,小程序返回APP

支付成功以后,附带支付结果跳转回APP。

返回APP说明

<button open-type="launchApp" app-parameter="wechat" binderror="launchAppError">打开APP</button>
Page({
    launchAppError (e) {
        console.log(e.detail.errMsg)
    }
})

注意 APP端需要设置正确URL scheme才能从微信正确回调。

商户可以使用代理商的小程序

微信小程序支付

1,通过授权获取用户open_id

wx.login({
    success (res) {
        if (res.code) {
            //发起网络请求
            wx.request({
                url: 'https://test.com/onLogin',
                data: {
                code: res.code
                }
            })
        } else {
            console.log('登录失败!' + res.errMsg)
        }
    }
})
  • 2,商户服务端使用第一步获取的code 换取 open_id ,后台调用接口 获取openID

GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

2,商户服务端使用 open_id 下单

商户服务端通过使用adapay SDK 下单请求payment 对象,其中pay_channel为 wx_lite

3,小程序端发起支付

小程序端使用返回的payment 对象中的pay_info 发起支付

调用wx.requestPayment(OBJECT)发起微信支付

wx.requestPayment(
{
'timeStamp': '',
'nonceStr': '',
'package': '',
'signType': 'MD5',
'paySign': '',
'success':function(res){},
'fail':function(res){},
'complete':function(res){}
})

微信公众号支付

微信公众号开发可参考 公众号官方指引

主要有以下几个步骤:

  • 通过授权获取用户open_id

  • 下单获取payment 支付信息

  • 发起支付

1, 通过授权,获取openID

授权说明见微信官方链接:网页授权

  • 微信公众号后台配置授权域名,将微信校验文件放到服务器根目录下

  • 用户静默授权获取code,前端页面在微信内打开授权地址,成功后并重定向到自己项目目标地址

只为获取openID的话静默授权就可以,无需用户同意。

let url=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${urlNow}&response_type=code&scope=${scope}&state=STATE&connect_redirect=1#wechat_redirect`;
window.location.replace(url);
  • 使用获取到的code,在服务端调用微信接口获取 access_token和openID

获取code后,请求以下链接获取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

示例代码如下:

url = 'https://api.weixin.qq.com/sns/oauth2/access_token'
params = {
    'appid': app_id,
    'secret': 'wx_secret',
    'code': wx_code,
    'grant_type': 'authorization_code',
}
resp = requests.get(url, params, timeout=15)
result_dict = json.loads(resp.text)
openid=result_dict.get('openid')

2, 下单请求支付信息

商户服务端通过adapay SDK 下单

支付方式选公众号支付pay_channel=wx_pub,下单参数填入openID

返回支付信息payment,将payment中payinfo 信息返回给前端页面

3,发起支付

前端页面直接调用JSAPI 使用 payment 中 pay_info 内容发起支付

示例代码如下:

WeixinJSBridge.invoke('getBrandWCPayRequest', {
        "appId": "wx2421b1c4370ec43b",
        "timeStamp": "1395712654",
        "nonceStr": "e61463f8efa94090b1f366cccfbbb444",
        "package": "prepay_id=up_wx21201855730335ac86f8c43d1889123400",
        "signType": "RSA",
        "paySign": "oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd7vaRvkYD7rthRAZ\/X+QBhcCYL21N7cHCTUxbQ+EAt6Uy+lwSN22f5YZvI45MLko8Pfso0jm46v5hqcVwrk6uddkGuT+Cdvu4WBqDzaDjnNa5UK3GfE1Wfl2gHxIIY5lLdUgWFts17D4WuolLLkiFZV+JSHMvH7eaLdT9N5GBovBwu5yYKUR7skR8Fu+LozcSqQixnlEZUfyE55feLOQTUYzLmR9pNtPbPsu6WVhbNHMS3Ss2+AehHvz+n64GDmXxbX++IOBvm2olHu3PsOUGRwhudhVf7UcGcunXt8cqNjKNqZLhLw4jq\/xDg==" //微信签名
    },
    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();
}