您的位置:首页 > 其它

支付宝当面付(条码支付)功能开发

2017-09-08 16:27 519 查看

1、什么是当面付

当面付产品介绍
商户可通过以下任一方式在线下完成交易收款:商家通过扫描线下买家支付宝钱包中的条码、二维码等方式将买家的交易资金直接打入卖家支付宝账户,资金实时到账;

线下买家通过使用支付宝钱包扫描商家的二维码等方式完成支付,提升商家收银效率,资金实时到账;

线下买家使用支付宝钱包中的当面付功能,通过声波支付的方式向商家完成付款,资金实时到账。

简单地说,即我们日常中使用的 条码支付、扫码支付、声波支付。
本篇的开发流程,将以条码支付为功能开发展开说明,条码支付即用户展示付款条码,商家设定金额后采用扫码枪(或输入用户条码值)扫描用户条码,直接进行扣款,所有操作由商家完成,用户仅需提供条码。

2、条码支付业务说明



使用步骤很简单:用户登录支付宝钱包,在首页点击“付款”,进入付款码界面
收银员在商家收银系统操作生成订单
用户出示其“付款码”,收银员用扫码设备扫描用户手机上的条码(或手动输入条码值)后,商家收银系统提交支付
付款后支付宝后台会返回支付结果给商家,同时将支付情况通知到用户



3、如何接入条码支付

官方接入文档说明:当面付快速接入

3.1 创建应用和配置

3.1.1 创建应用

登陆支付宝开放平台,找到 “ 开发者中心 - 应用 - 创建应用 ”:

创建应用后,选择支付应用,因为是自己开发自己用,所以选择自用型应用,名称自定义:

3.1.2 填写资料和提交审核


功能选项中需要签约开通“当面付”,提交一些审核资料什么的,此处不展开。 这部分的说明在官方有详细文档《开放平台应用创建指南》,此处仅对 “开发配置” 作重点说明:

3.1.2.1 应用网关 和 授权回调地址

应用网关,用于接收支付宝异步通知(比如用户付款成功了的通知会发送到该地址,口碑开店的门店信息修改也会触发通知)

授权回调地址,即第三方授权或用户信息授权后回调地址

这两项是非必需填写项,根据实际情况来是否配置。

3.1.2.2 应用密钥RSA2

密钥的生成在官方有文档说明《如何生成密钥》:下载Windows版RSA密钥生成器(Mac版点这里
根据官方文档说明进行密钥生成,此处不再详细展开

注意:其中密钥长度为1024的即为RSA(SHA1),长度为2048的即为RSA2(SHA256)

3.1.2.3 提交审核

各项设置完成后,提交审核,审核预计在一个工作日完成,审核完成后,应用状态会显示为“已上线”。

(注意:应用命名不能出现如支付字样,于是之前我的应用因为名字“猛追湾一卡通条码支付”被驳回审核了,手动微笑)

3.2 条码支付开发

先看下官方提供的接口调用流程:


显然,如上所示,涉及三个接口:支付 alipay.trade.pay
查询 alipay.trade/query
撤销 alipay.trade.cancel

接口调用涉及一大堆参数,支付宝倒是也很贴心,直接帮我们做好了相关的SDK(服务端SDK),可以直接调用API,而且对于一些公共参与已经帮我们封装好了,调用时只需要传入业务参数即可。
下载好SDK之后,里面的readme也写的很明白,集成支付宝接口需要引入的文件是:alipay-sdk-java*.jar

commons-logging-1.1.1.jar

在《服务端SDK》中有调用示例如下:
//实例化客户端

AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");

//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.open.public.template.message.industry.modify

AlipayOpenPublicTemplateMessageIndustryModifyRequest request = new AlipayOpenPublicTemplateMessageIndustryModifyRequest();

//SDK已经封装掉了公共参数,这里只需要传入业务参数

//此次只是参数展示,未进行字符串转义,实际情况下请转义

request.setBizContent("  {" +

"    \"primary_industry_name\":\"IT科技/IT软件与服务\"," +

"    \"primary_industry_code\":\"10001/20102\"," +

"    \"secondary_industry_code\":\"10001/20102\"," +

"    \"secondary_industry_name\":\"IT科技/IT软件与服务\"" +

" }");

AlipayOpenPublicTemplateMessageIndustryModifyResponse response = alipayClient.execute(request);

//调用成功,则处理业务逻辑

if(response.isSuccess()){

//.....

}

[/code]
显然因为SDK封装得很友好,我们只需要传入配置参数,设置好业务内容参数,直接调起方法就可以了。下面是我个人的代码示例:
为了方便将来配置参数的修改,配置直接写到了配置文件中:
#应用id,要求应用上线,且其下功能签约状态为生效

appId=20110906...78327


#应用私钥(appId所属应用的应用私钥)RSA2加密方式

privateKey=MIIEvgI...oC6/I2xPqZnvhbntS5qi1NwYg2


#支付宝公钥

alipayPublicKey=MIIBI...wIDAQAB

[/code]
然后做一个类来进行封装开发者配置,用一个类来封装业务参数的JSON,再封装一个工具类以使用。
封装开发者配置的类:
import java.io.IOException;

import java.io.InputStream;

import java.util.Properties;


/**

* 支付宝API类

*/

public class AlipayAPI {

/** 应用ID*/

private static String appId;

/** 应用私钥*/

private static String privateKey;

/** 支付宝公钥*/

private static String alipayPublicKey;


/** 支付调用接口*/

private static final String url_pay = "https://openapi.alipay.com/gateway.do";


static {

InputStream is = AlipayAPI.class.getResourceAsStream("/alipay.properties");

Properties prop = new Properties();

try {

prop.load(is);

setAppId(prop.getProperty("appId"));

setPrivateKey(prop.getProperty("privateKey"));

setAlipayPublicKey(prop.getProperty("alipayPublicKey"));


} catch (IOException e) {

e.printStackTrace();

}

}


public static String getAppId() {

return appId;

}


public static void setAppId(String appId) {

AlipayAPI.appId = appId;

}


public static String getPrivateKey() {

return privateKey;

}


public static void setPrivateKey(String privateKey) {

AlipayAPI.privateKey = privateKey;

}


public static String getAlipayPublicKey() {

return alipayPublicKey;

}


public static void setAlipayPublicKey(String alipayPublicKey) {

AlipayAPI.alipayPublicKey = alipayPublicKey;

}


public static String getUrl_pay() {

return url_pay;

}


}

[/code]
封装业务请求参数的类(注意,此处示例仅有部分必要参数,更多参数详见官方文档的请求参数部分):
/**

* 统一收单交易支付的参数封装类

*/

public class PayParam {

/** 商户订单*/

private String out_trade_no;

/** 支付场景*/

private String scene;

/** 支付授权码,即用户的付款码*/

private String auth_code;

/** 订单标题*/

private String subject;

/** 订单金额*/

private double total_amount;


public PayParam(String out_trade_no, String subject, double total_amount, String auth_code) {

this.out_trade_no = out_trade_no;

this.subject = subject;

this.total_amount = total_amount;

this.auth_code = auth_code;
}


public String getOut_trade_no() {

return out_trade_no;

}


public void setOut_trade_no(String out_trade_no) {

this.out_trade_no = out_trade_no;

}


public String getScene() {

return scene;

}


public void setScene(String scene) {

this.scene = scene;

}


public String getAuth_code() {

return auth_code;

}


public void setAuth_code(String auth_code) {

this.auth_code = auth_code;

}


public String getSubject() {

return subject;

}


public void setSubject(String subject) {

this.subject = subject;

}


public double getTotal_amount() {

return total_amount;

}


public void setTotal_amount(double total_amount) {

this.total_amount = total_amount;

}

}

[/code]
支付工具类和测试代码:
import com.alibaba.fastjson.JSON;

import com.alipay.api.AlipayApiException;

import com.alipay.api.AlipayClient;

import com.alipay.api.DefaultAlipayClient;

import com.alipay.api.request.AlipayTradePayRequest;

import com.alipay.api.response.AlipayTradePayResponse;


import java.util.Date;


/**

* 支付宝的工具类

*/

public class AlipayUtil {

/** UTF8编码格式*/

private static final String CHARSET_UTF8 = "UTF-8";

/** 加密方式*/

private static final String SIGN_TYPE = "RSA2";

/** 数据格式*/

private static final String FORMAT = "JSON";

/** 支付场景,条码支付*/

private static final String SCENE_BARCODE = "bar_code";


/**

* 当面付(条码支付)

* @param content

* @return

  */

public static AlipayTradePayResponse barCodePay(PayParam content){

AlipayClient client = new DefaultAlipayClient(AlipayAPI.getUrl_pay(), AlipayAPI.getAppId(),

    AlipayAPI.getPrivateKey(), FORMAT, CHARSET_UTF8, AlipayAPI.getAlipayPublicKey(), SIGN_TYPE);


AlipayTradePayRequest request = new AlipayTradePayRequest();

content.setScene(SCENE_BARCODE);

String bizContent = JSON.toJSONString(content);

request.setBizContent(bizContent);


AlipayTradePayResponse response = null;

try {

response = client.execute(request);

} catch (AlipayApiException e) {

e.printStackTrace();

}

return response;

}


/**

* 支付完成后的业务处理

* @param response

  */

public static void afterBarCodePay(AlipayTradePayResponse response) {

if (response.isSuccess()) {

//处理业务逻辑

System.out.println("start handle business");

}

}


/**

* 获取商户订单

* @return

  */

public static String getTradeNo() {

return "PAY" + new Date().getTime();

}



//测试

public static void main(String[] args) {

String tradeNo = getTradeNo();

String subject = "测试用订单";

double totalAmount = 0.01;

String authCode = "274726044141298157";


PayParam param = new PayParam(tradeNo, subject, totalAmount, authCode);

AlipayTradePayResponse response = barCodePay(param);

System.out.println(response.getBody());

afterBarCodePay(response);

}


}

[/code]
因为SDK封装的缘故,所以整体过程很简单了,对于支付成功后的响应,以及其他支付查询、支付退款等功能就不再展开了。
但是自己在过程中还是有两个点觉得有点坑,再次提一下:创建AlipayClient对象的传参中,公钥是支付宝公钥,而不是应用公钥
服务端SDK的示例中请求调用的类是AlipayOpenPublicTemplateMessageIndustryModifyResponse,实际条码支付的请求类应该调用AlipayTradePayRequest

4、参考链接

支付宝扫码支付(当面付)开发流程

支付宝支付-刷卡支付(条码支付)

附件列表

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: