官方文档的描述
小程序非同一主体下的商家进行收款
普通小程序由于没有授权回调地址,无法完成第三方授权。需要完成以上需求,目前有三种方案:
-
商户账号在 商家平台 > 产品中心 > 产品详情页面 点击 立即开通,填写并提交相关信息。详情可查看 开通产品。开通完成后请在产品详情页点击 管理小程序 APPID,关联绑定服务商拉支付的小程序应用 A。
-
服务商只有一个小程序平台,商家收款都在这个小程序中支付的场景。服务商开发一个小程序应用 A 并上线,然后再创建一个第三方应用 B(可以是非小程序第三方应用),创建第三应用 B 后添加 JSAPI 支付产品和获取用户信息的功能,然后生成第三方授权链接让商家登录账号后授权给第三方应用 B。授权完成后通过第三方应用 B 的 APPID 和商家授权的 app_auth_token 在服务端调用 alipay.trade.create(统一收单交易创建接口),并在入参 op_app_id 中传入小程序经营主体 APPID(指在服务商小程序中,拉起收银台支付时,对应的小程序应用的 APPID,此场景应填入小程序应用 A),创建交易获取 tradeNO 参数,将 tradeNO 参数通过 my.request 接口传到小程序应用 A 中,用 my.tradePay 接口唤起支付,即可实现收款到商家账号中。 注意:上述开发过程中可能会遇到获取 user_id 授权问题,为方便接口调用,服务商需要再将自己的小程序应用 A 授权给自己的第三方应用 B,授权成功后也会获得代表小程序 A 的 app_auth_token。小程序应用 A 中用户授权产生的 auth_code 需要通过第三方应用 B 在 alipay.system.oauth.token(换取授权访问令牌) 接口换 auth_token,此接口调用的时候需要加上代表小程序 A 的 app_auth_token 调用才可以成功获取到 user_id,详情请查看 获取会员基础信息、三方应用授权。
-
每个商家都有自己的小程序进行收款,可上服务市场给商家订购的场景。通过创建小程序第三方应用,在第三方应用中创建小程序模板,然后再帮助商家创建小程序和签约 JSAPI 支付进行授权。完成授权后,给商家小程序上传小程序版本,商家可在自己的小程序中进行收款。详细请参考 三方业务。
一、简单概括一下:需要完成的配置
准备两个账号,开放平台和商家平台不是同一个账号
- 开放平台创建小程序A,第三方应用B
- JSAPI支付产品开通并且绑定小程序A的APPID
- 商家授权token给第三方应用B
前期工作已经完成,小程序和第三方应用的密钥需要保存
二、换取授权访问令牌接口(获取UserID)
需要完成两个接口的调用, alipay.trade.create(统一收单交易创建接口), alipay.system.oauth.token(换取授权访问令牌)
本次代码中获取的是userID(2088开头的商户号),openID(加密后的商户号,做过微信开发的应该了解)自行配置
- 首先在小程序IDE(支付宝官方的开发工具)去获取code,发送到服务端接口,使用code换取userID
kotlin
//获取userid
my.getAuthCode({
scopes: 'auth_base',
success: res => {
const authCode = res.authCode;
console.log(authCode)
// 在服务端获取用户信息
my.request({
url: this.data.base_url + '/aliPayUserId',
method: "GET",
data: {
code: authCode
},
success(res) {
// 获取需要的用户信息
if (!res.data.data) return
//存储在缓存中
my.setStorageSync({
key: 'userId',
data: {
userId: res.data.data
},
})
}
})
},
fail: err => {
console.log('my.getAuthCode 调用失败', err)
}
});
- 服务端调用编写alipay.system.oauth.token接口
此处的APPID、PublicKey、PrivateKey均使用小程序A
ini
@GetMapping("/aliPayUserId")
public ApiRes getAliPayUserId(String code) throws AlipayApiException, JsonProcessingException {
//初始化AlipayClient
AlipayClient alipayClient = aliPayClientService.getAlipayClient(aliPayPublicKey, aliPayPrivateKey, aliPayAppId);
// 构造请求参数以调用接口
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
//填写请求参数
request.setCode(code);
// 设置授权方式
request.setGrantType("authorization_code");
//获取响应
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
System.out.println(response.getBody());
String body = response.getBody();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(body);
String user_id = rootNode.get("alipay_system_oauth_token_response").get("user_id").asText();
return ApiRes.ok(user_id);
}
使用第三方应用A配置存在弊端:
1、直接使用第三方应用B 报错示例 isv.unmatched-app-id(调用接口的应用标识(app_id)与令牌授权的应用不相符)
2、需要将小程序应用A授权给第三方应用B,获取app_auth_token
代码中需要添加 request.putOtherTextParam("app_auth_token",app_auth_token)
此时会发现开放平台中版本管理已禁用
解决方案:
1、直接使用小程序的应用配置即可
2、详情见提交审核小程序 - 支付宝文档中心
三、统一收单交易创建接口实现(获取tradeNO)
- 小程序IDE端编写
less
onPayClick() {
if(this.data.amount.length>=5){
return my.alert({
title:'金额超出限制!'
})
}
let res = my.getStorageSync({ key: 'userId' });
console.log(res.data)
//调用下单接口
my.request({
url: this.data.base_url + '/payOrders',
method: 'POST',
data: {
appId: this.data.appid,
amount: this.data.amount,
mchOrderNo: this.data.mchOrderNo,
wayCode: 'ALI_JSAPI',
authCode: 'authCode',
buyerUserId: my.getStorageSync({ key: 'userId' }).data.userId
}
}).then(res => {
let payData = JSON.parse(res.data.data.payData)
//调起收银台
if (res.data) {
my.tradePay({
tradeNO: payData.alipayTradeNo,
success: res => {
my.alert({
title: '支付中...',
content: this.data.amount + '元'
})
//轮询订单状态 请求服务端 此处暂未编写
},
fail: error => {
console.error('调用 my.tradePay 失败: ', JSON.stringify(error));
}
})
}
})
},
- 服务端代码
此接口不方便贴出,请参照官方示例自行编写
AlipayTradeCreateRequest对象 添加此段代码 request.putOtherTextParam("app_auth_token",商家授权的token)
根据token来确定是哪个商家来进行收款
java
package com.java.sdk.demo;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.alipay.api.domain.AlipayTradeCreateModel;
import com.alipay.api.request.AlipayTradeCreateRequest;
import com.alipay.api.domain.ExtendParams;
import com.alipay.api.FileItem;
import java.util.Base64;
import java.util.ArrayList;
import java.util.List;
public class AlipayTradeCreate {
public static void main(String[] args) throws AlipayApiException {
// 初始化SDK
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
// 构造请求参数以调用接口
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
// 设置商户订单号
model.setOutTradeNo("20150320010101001");
// 设置产品码
model.setProductCode("JSAPI_PAY");
// 设置小程序支付中
model.setOpAppId("2014072300007148");
// 设置订单总金额
model.setTotalAmount("88.88");
// 设置业务扩展参数
ExtendParams extendParams = new ExtendParams();
extendParams.setTradeComponentOrderId("2023060801502300000008810000005657");
model.setExtendParams(extendParams);
// 设置可打折金额
model.setDiscountableAmount("80.00");
// 设置订单标题
model.setSubject("Iphone6 16G");
// 设置订单附加信息
model.setBody("Iphone6 16G");
// uid参数未来计划废弃,存量商户可继续使用,新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
// model.setBuyerId("2088102146225135");
// 设置买家支付宝用户唯一标识
model.setBuyerOpenId("074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5");
// 设置商户门店编号
model.setStoreId("NJ_001");
request.setBizModel(model);
// 第三方代调用模式下请设置app_auth_token
// request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
AlipayTradeCreateResponse response = alipayClient.execute(request);
System.out.println(response.getBody());
if (response.isSuccess()) {
System.out.println("调用成功");
} else {
System.out.println("调用失败");
// sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
// String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
// System.out.println(diagnosisUrl);
}
}
private static AlipayConfig getAlipayConfig() {
String privateKey = "<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->";
String alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->";
AlipayConfig alipayConfig = new AlipayConfig();
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
alipayConfig.setAppId("<-- 请填写您的AppId,例如:2019091767145019 -->");
alipayConfig.setPrivateKey(privateKey);
alipayConfig.setFormat("json");
alipayConfig.setAlipayPublicKey(alipayPublicKey);
alipayConfig.setCharset("UTF-8");
alipayConfig.setSignType("RSA2");
return alipayConfig;
}
}
后续不明白的可以在开放平台寻求支付宝官方帮助,官方人员很热心 解疑答惑,在此感谢他们的帮助!