此前,已设计过多应用多平台支付模块的基础开篇。传送门
本篇,准备对接支付宝App支付基础模块,并基于此模块实现具体的业务功能逻辑。
实现思路
一、前期准备工作
1、参考网址
支付宝文档写的已经很详细了,就不多赘述了,传送门。
二、后端功能开发
1、定义yml配置文件
- 需求分析,思路梳理
通过阅读支付宝官方文档,梳理以下参数需要动态配置。开放平台APP Id、公钥、私钥、阿里公钥key。其中,由于公、私钥内容比较大,我准备采用文件路径配置方式存储,其他的则采用yml形式配置。
- 配置示例如下
1、yml配置示例
2、密钥文件配置示例
2、实现下单扩展
- 引用V3支付jar
<!-- 支付宝支付sdk -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.34.90.ALL</version>
</dependency>
- 代码实现如下
package com.flycoding.biz.order.factory.impl.ali;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.flycoding.biz.order.config.OrderDictConfig;
import com.flycoding.biz.order.config.extend.PaymentExtend;
import com.flycoding.biz.order.entity.OrderInfo;
import com.flycoding.biz.order.enums.PayWay;
import com.flycoding.biz.order.factory.impl.base.BasePaymentFactory;
import com.flycoding.biz.order.utils.PayUtils;
import com.flycoding.drivenlibrary.engine.config.constants.DrivenConstants;
import com.flycoding.drivenlibrary.enums.ResponseResult;
import com.flycoding.drivenlibrary.exception.ResponseException;
import com.flycoding.drivenlibrary.factory.OpenPlatformConfig;
import com.flycoding.utillibrary.java.ArrayUtils;
import com.flycoding.utillibrary.strings.StringUtils;
import java.util.List;
/**
* 支付宝app支付
*
* @author 赵屈犇
* @version 1.0
* @date 创建时间: 2022/12/7 20:46
* @Copyright(C): 2022 by 赵屈犇
*/
@PaymentExtend(OrderDictConfig.PayWay.ALI_APP_API)
public class AliAppPaymentFactory extends BasePaymentFactory<AlipayTradeAppPayResponse> {
@Override
public AlipayTradeAppPayResponse placeOrder(OrderInfo orderInfo, OpenPlatformConfig platform) throws Exception {
String appId = platform.getConfig(DrivenConstants.PlatformConstants.AliPayConstants.OPEN_APP_ID);
String publicKey = platform.getSecretConfig(DrivenConstants.PlatformConstants.AliPayConstants.APP_PUBLIC_KEY);
String privateKey = platform.getSecretConfig(DrivenConstants.PlatformConstants.AliPayConstants.APP_PRIVATE_KEY);
if (StringUtils.isEmptys(appId, privateKey, publicKey)) {
logger.error("aliPayAppId 或 ali-pay.app.public-key 或 ali-pay.app.private-key 未配置,请检查!");
throw new ResponseException(ResponseResult.NOT_CONFIG_ALI_PAY);
}
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", appId,
privateKey, "json", "UTF-8", publicKey,
"RSA2");
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl(PayUtils.getNotifyUrl(PayWay.ALI_APP_API));
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", orderInfo.getOrderNum());
bizContent.put("total_amount", orderInfo.getPayMoney());
bizContent.put("subject", orderInfo.getOrderName());
bizContent.put("product_code", "QUICK_MSECURITY_PAY");
//bizContent.put("time_expire", "2022-08-01 22:00:00");
//// 商品明细信息,按需传入
List<JSONObject> goodsDetail = ArrayUtils.newArrayList();
JSONObject goods = new JSONObject();
goods.put("goods_id", orderInfo.getOrderId());
goods.put("goods_name", orderInfo.getOrderName());
goods.put("quantity", 1);
goods.put("price", orderInfo.getPayMoney());
goodsDetail.add(goods);
bizContent.put("goods_detail", goodsDetail);
//// 扩展信息,按需传入
//JSONObject extendParams = new JSONObject();
//extendParams.put("sys_service_provider_id", "2088511833207846");
//bizContent.put("extend_params", extendParams);
request.setBizContent(bizContent.toString());
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (response.isSuccess()) {
return response;
}
throw new ResponseException(ResponseResult.PLACE_ORDER_FAILURE);
}
}
三、支付回调
- 实现回调代码
package com.flycoding.biz.order.api.notify.ali;
import com.alibaba.fastjson.TypeReference;
import com.alipay.api.internal.util.AlipaySignature;
import com.flycoding.biz.order.api.notify.base.BasePayNotifyExtend;
import com.flycoding.biz.order.config.OrderResponseConfig;
import com.flycoding.biz.order.entity.OrderInfo;
import com.flycoding.biz.order.entity.ali.AliPayNotifyBO;
import com.flycoding.drivenlibrary.engine.annotation.api.Api;
import com.flycoding.drivenlibrary.engine.config.constants.DrivenConstants;
import com.flycoding.drivenlibrary.enums.ResponseResult;
import com.flycoding.drivenlibrary.enums.dictionary.ContentType;
import com.flycoding.drivenlibrary.exception.ResponseException;
import com.flycoding.drivenlibrary.factory.OpenPlatformConfig;
import com.flycoding.utillibrary.strings.StringUtils;
import java.util.Map;
/**
* 支付宝App支付回调
*
* @author 赵屈犇
* @version 1.0
* @date 创建时间: 2022/12/9 20:23
* @Copyright(C): 2022 by 赵屈犇
*/
@Api(apiUrl = "notify", apiName = "支付宝回调", moduleUrl = "pay/aliApp", isVerifyToken = false, isVerifyLogin = false,
isEncryptedResult = false, isDecryptParams = false, isStartAuth = false,
responseCode = OrderResponseConfig.ALI_NOTIFY_RESPONSE, requestContentType = ContentType.NOT_VERIFY
)
public class AliAppPayNotifyExtend extends BasePayNotifyExtend<AliPayNotifyBO> {
@Override
protected boolean isPaySuccess(OrderInfo orderInfo, OpenPlatformConfig platform) throws Exception {
AliPayNotifyBO payNotifyBO = getRequestParams();
String publicKey = platform.getSecretConfig(DrivenConstants.PlatformConstants.AliPayConstants.APP_ALI_PUBLIC_KEY);
if (StringUtils.isEmpty(publicKey)) {
logger.error("未定义支付宝公钥,请联系开发者!");
throw new ResponseException(ResponseResult.NOT_CONFIG_ALI_PAY);
}
Map<String, String> params = getParams().toJavaObject(new TypeReference<Map<String, String>>() {});
return AlipaySignature.rsaCheckV1(params, publicKey, payNotifyBO.getCharset(), payNotifyBO.getSign_type());
}
}
三、Android功能开发
1、引入jar
// 支付宝支付SDK相关
api 'com.alipay.sdk:alipaysdk-android:+@aar'
2、实现调用函数
/**
* 调用SDK支付宝支付
*
* @param context
* @param payInfo
*/
public void payAlipay(final Context context, final String payInfo, final String extData) {
Runnable payRunnable = () -> {
// 构造PayTask 对象
PayTask alipay = new PayTask((Activity) context);
Map<String,String> result = alipay.payV2(payInfo,true);
result.put("extData", extData);
Message msg = new Message();
msg.what = PayConstants.SDK_PAY_FLAG;
msg.obj = result;
handler.sendMessage(msg);
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
}