蜻蜓设备+支付宝会员的开发笔记
开发前准备
- 商户拥有蜻蜓设备;
- 商户需要开通支付宝商户会员卡功能;
- 商户准备好应用的AppId;
- 商户配置好授权回调地址;
- 商户下载支付宝签名工具配置应用的私钥、公钥;
准备好要用的参数
private static final String SERVER_URL="https://openapi.alipay.com/gateway.do";//支付宝网关地址
private static final String APPID="你的应用ID";
private static final String PRIVATE_KEY="你的私钥";
private static final String PUBLIC_KEY="你的支付宝公钥";
所有方法开头第一句都用到了里面的参数(多个商户改造成从数据库提取这些保存的参数)
一、上传会员卡模板需要的图片
//上传照片和视频
public static String getImageUploadId(){
AlipayClient alipayClient=new DefaultAlipayClient(SERVER_URL,APPID,PRIVATE_KEY,"JSON","utf-8",PUBLIC_KEY,"RSA2");
AlipayOfflineMaterialImageUploadRequest request=new AlipayOfflineMaterialImageUploadRequest();
request.setImageType("jpg");
request.setImageName("logo");
FileItem imageContent=new FileItem("C:\\Users\\Administrator\\Downloads\\67662e05fb1285966ecb999ca9239def.jpg");
request.setImageContent(imageContent);
try{
AlipayOfflineMaterialImageUploadResponse response = alipayClient.execute(request);
if (response.isSuccess()){
System.out.println("调用成功"+response.getImageId());
return response.getImageId();
}else {
System.out.println("调用失败");
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
保存好返回的图片ID后面会用到。
二、创建会员卡模板
public static String getTemplateCreateId(){
AlipayClient alipayClient=new DefaultAlipayClient(SERVER_URL,APPID,PRIVATE_KEY,"JSON","utf-8",PUBLIC_KEY,"RSA2");
AlipayMarketingCardTemplateCreateRequest request=new AlipayMarketingCardTemplateCreateRequest();
//公共请求参数
Map<String,Object> biz_content=new HashMap<>();
String requestId=System.currentTimeMillis()+ RandomUtil.randomNumbers(10);
String logo_id="zaEyRrsXTdasc9vZBwfcYgAAACMAAQED";//由第一步返回的图片Id设置
String background_id="zaEyRrsXTdasc9vZBwfcYgAAACMAAQED";//图片Id
System.out.println(requestId);
biz_content.put("request_id",requestId);//请求ID,由开发者生成并保证唯一性
biz_content.put("card_type","OUT_MEMBER_CARD");//卡类型为外部权益卡
biz_content.put("biz_no_suffix_len","14");//业务卡号尾缀
biz_content.put("write_off_type","qrcode");//扫用户卡中二维码显示额外传入的卡号
//规则是数组形式
List<Map<String,String>> field_rule_list=new ArrayList<>();
Map<String,String> field_rule_list_map=new HashMap<>();//规则列表
field_rule_list_map.put("field_name","OpenDate");
field_rule_list_map.put("rule_name","ASSIGN_FROM_REQUEST");//规则
field_rule_list_map.put("rule_value","OpenDate");
field_rule_list.add(field_rule_list_map);
biz_content.put("field_rule_list",field_rule_list);
//栏位信息是数组格式
List<Map<String,String>> column_info_list=new ArrayList<>();
Map<String,String> column_info_list_map=new HashMap<>();
column_info_list_map.put("code","BENEFIT_INFO");//支付宝分配各栏信息
column_info_list_map.put("title","会员专享");//栏目标题
column_info_list.add(column_info_list_map);
biz_content.put("column_info_list",column_info_list);
Map<String,String> template_style_info=new HashMap<>();
template_style_info.put("bg_color","rgb(55,112,179)");//背景颜色
template_style_info.put("background_id",background_id);//upload接口上传获取到的id 1020*643px 2m
template_style_info.put("logo_id",logo_id);//logo图片ID 500*500px 1m
template_style_info.put("card_show_name","水果篮子会员卡");//钱包端名称
biz_content.put("template_style_info",template_style_info);
String bizContent= JacksonUtil.toJson(biz_content);
System.out.println(bizContent);
request.setBizContent(bizContent);
try{
AlipayMarketingCardTemplateCreateResponse response=alipayClient.execute(request);
if (response.isSuccess()){
System.out.println("调用成功"+response.getTemplateId());
return response.getTemplateId();
}else {
System.out.println("调用失败");
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
用户可以自己定义会员卡模板长什么模样,这里只是举个例子,同样保存好返回的模板ID。
三、创建会员开卡表单模板
public static void cardFormTemplate(){
AlipayClient alipayClient=new DefaultAlipayClient(SERVER_URL,APPID,PRIVATE_KEY,"JSON","utf-8",PUBLIC_KEY,"RSA2");
AlipayMarketingCardFormtemplateSetRequest request=new AlipayMarketingCardFormtemplateSetRequest();
Map<String,Object> biz_content=new HashMap<>();
String template_id="这里是你创建的会员卡模板ID";
biz_content.put("template_id",template_id);//卡模板Id
Map<String,Object> fields=new HashMap<>();
Map<String,Object> common_fields=new HashMap<>();
List<String> commonFields=new ArrayList<>();
commonFields.add("OPEN_FORM_FIELD_NAME");//名称
commonFields.add("OPEN_FORM_FIELD_GENDER");//性别
common_fields.put("common_fields",commonFields);
Map<String,Object> optional_fields=new HashMap<>();
List<String> optionalFields=new ArrayList<>();
optionalFields.add("OPEN_FORM_FIELD_MOBILE");//手机号
optional_fields.put("common_fields",optionalFields);
fields.put("required",common_fields);
fields.put("optional",optional_fields);
biz_content.put("fields",fields);
String bizContent=JacksonUtil.toJson(biz_content);
System.out.println(bizContent);
request.setBizContent(bizContent);
try {
AlipayMarketingCardFormtemplateSetResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
} catch (Exception e) {
e.printStackTrace();
}
}
开卡表单是用户点击领卡投放链接后出现的要填写的表单信息,有的敏感字段需要向支付宝业务BD申请。
四、获取会员卡领卡投放链接
public static String cardActivateUrl(){
AlipayClient alipayClient=new DefaultAlipayClient(SERVER_URL,APPID,PRIVATE_KEY,"JSON","utf-8",PUBLIC_KEY,"RSA2");
AlipayMarketingCardActivateurlApplyRequest request=new AlipayMarketingCardActivateurlApplyRequest();
Map<String,String> biz_content=new HashMap<>();
//额外参数入参回传时使用
Map<String,String> outString=new HashMap<>();
outString.put("templateId","自定义参数方便业务逻辑处理吖");
outString.put("merchantId","自定义参数方便业务逻辑处理吖");
String out_string=JacksonUtil.toJson(outString);
biz_content.put("out_string",out_string);
biz_content.put("template_id","会员模板ID");
//回调地址与应用配置的授权回调地址一样
biz_content.put("callback","应用配置的授权回调地址");
String bizContent=JacksonUtil.toJson(biz_content);
request.setBizContent(bizContent);
try {
AlipayMarketingCardActivateurlApplyResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("调用成功"+response.getApplyCardUrl());
String url= URLDecoder.decode(response.getApplyCardUrl(),"utf-8");
log.info("解码后的url:{}",url);
return url;//返回的是开卡链接
} else {
System.out.println("调用失败");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
生成的投放链接保存后配置在推广方案里面
五、用户授权换取access_token和userId
public static Map<String, String> getAccessTokenAndUserId(String auth_code){
AlipayClient alipayClient=new DefaultAlipayClient(SERVER_URL,APPID,PRIVATE_KEY,"JSON","utf-8",PUBLIC_KEY,"RSA2");
AlipaySystemOauthTokenRequest request=new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode(auth_code);
try {
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
if(response.isSuccess()){
log.info("调用成功授权码:{},支付宝Id:{}",response.getAccessToken(),response.getUserId());
Map<String,String> infoMap=new HashMap<>();
infoMap.put("accessToken",response.getAccessToken());//返回来的数据不止这些我只拿其中两个
infoMap.put("userId",response.getUserId());
return infoMap;
} else {
log.info("调用失败");
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return null;
}
用户点击投放链接后填写信息并且授权会调用配置的回调地址此时用回调带回来的auth_code码换取access_token和userId
以便进行下一步的操作。
六、获取用户开卡表单填写的信息
public static String getMarketingCardForm(String accessToken,String requestId,String templateId){
AlipayClient alipayClient=new DefaultAlipayClient(SERVER_URL,APPID,PRIVATE_KEY,"JSON","utf-8",PUBLIC_KEY,"RSA2");
AlipayMarketingCardActivateformQueryRequest request=new AlipayMarketingCardActivateformQueryRequest();
Map<String,String> biz_content=new HashMap<>();
biz_content.put("biz_type","MEMBER_CARD");
biz_content.put("template_id",templateId);//会员卡模板ID
biz_content.put("request_id",requestId);//用户提交授权信息返回的请求Id
String bizContent= JacksonUtil.toJson(biz_content);
request.setBizContent(bizContent);
try {
AlipayMarketingCardActivateformQueryResponse response = alipayClient.execute(request,accessToken);
if(response.isSuccess()){
log.info("调用成功:{}",response.getInfos());
return response.getInfos();//可以用json转化
} else {
log.info("调用失败");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
带上之前获取的access_token调用此方法获取用户填写的信息后进行业务逻辑处理,查询本商户下是否有会员,如果有则
进行会员信息的补充,没有则新增会员。
七、会员卡开卡
public static String marketingCardOpen(String memberId,String templateId,String userId,String memberNum,String accessToken,String openCardTime){
AlipayClient alipayClient=new DefaultAlipayClient(SERVER_URL,APPID,PRIVATE_KEY,"JSON","utf-8",PUBLIC_KEY,"RSA2");
AlipayMarketingCardOpenRequest request = new AlipayMarketingCardOpenRequest();
Map<String,Object> biz_content=new HashMap<>();
biz_content.put("out_serial_no",memberId);//外部商户流水号保持唯一 == 会员Id
biz_content.put("card_template_id",templateId);//外部传入卡模板Id
Map<String,String> card_user_info=new HashMap<>();
card_user_info.put("user_uni_id",userId);//用户唯一标识userId
card_user_info.put("user_uni_id_type","UID");
biz_content.put("card_user_info",card_user_info);
Map<String,String> card_ext_info=new HashMap<>();
card_ext_info.put("external_card_no",memberNum);//外部会员卡号
card_ext_info.put("open_date",openCardTime);//开卡时传入的时间外部表字段
card_ext_info.put("valid_date","2099-02-20 21:20:46");//开卡时传入的有效期
biz_content.put("card_ext_info",card_ext_info);
String bizContent=JacksonUtil.toJson(biz_content);
request.setBizContent(bizContent);
try {
AlipayMarketingCardOpenResponse response = alipayClient.execute(request,accessToken);
if(response.isSuccess()){
log.info("调用成功:{}",response.getCardInfo().getBizCardNo());
return response.getCardInfo().getBizCardNo();
} else {
log.info("调用失败");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
最后调用开卡方法进行开卡,开卡成功后会在支付宝卡包里出现商户的会员卡。
最后贴上本菜鸟进入回调地址后的业务逻辑
回调接口时支付宝会带回来的参数是:auth_code、request_id、out_string。
public void marketingCard(String authCode,String requestId,String outString){
log.info("进入用户开卡模式----授权码:{},请求Id:{}",authCode,requestId);
//根据授权码换取accessToken
Map<String, String> accessTokenAndUserId = AlipayMemberUtil.getAccessTokenAndUserId(authCode);
String accessToken=accessTokenAndUserId.get("accessToken");
String userId=accessTokenAndUserId.get("userId");
//回传额外参数解析
Map<String,String> outStringMap= JacksonUtil.toStringMap(outString);
String templateId=outStringMap.get("templateId");
String merchantId=outStringMap.get("merchantId");
//调用会员卡表单信息查询
String infos=AlipayMemberUtil.getMarketingCardForm(accessToken,requestId,templateId);
log.info("返回的数据:{}",infos);
String gender="";
String mobile="";
String name="";
List<AliPayFormInfo> stringObjectMap = JacksonUtil.toList(infos, AliPayFormInfo.class);
for (AliPayFormInfo aliPayFormInfo:stringObjectMap){
if (!ParamUtil.isBlank(aliPayFormInfo.getOPEN_FORM_FIELD_GENDER())){
gender=aliPayFormInfo.getOPEN_FORM_FIELD_GENDER();
}
if (!ParamUtil.isBlank(aliPayFormInfo.getOPEN_FORM_FIELD_MOBILE())){
mobile=aliPayFormInfo.getOPEN_FORM_FIELD_MOBILE();
}
if (!ParamUtil.isBlank(aliPayFormInfo.getOPEN_FORM_FIELD_NAME())){
name=aliPayFormInfo.getOPEN_FORM_FIELD_NAME();
}
}
log.info("姓名:{},手机号:{},性别:{}",name,mobile,gender);
//获取到的手机号和商户ID查找商户下存在的会员
Member member=memberRepository.findByPhoneAndMerchantIdAndDelFlag(mobile,merchantId,1);
if (ParamUtil.isBlank(member)){
log.info("该商户未曾有过该会员进入新增");
member=new Member();
member=initMember(member);//初始化
member.setUserId(userId);
member.setMerchantId(merchantId);
if (gender.equals(Member.Sex.MEM.getDescription())){
member.setSex(Member.Sex.MEM.getCode());
}else{
member.setSex(Member.Sex.FEMALE.getCode());
}
member=memberService.save(member);
}else {
log.info("该用户是老会员进行信息补充");
member.setUserId(userId);
}
//调用会员卡开卡接口
String openCardTime=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(member.getCreateTime());
//支付宝保存留用号
String bizCardNo=AlipayMemberUtil.marketingCardOpen(member.getId(),templateId,userId,member.getMemberNum(),accessToken,openCardTime);
member.setBizCardNo(bizCardNo);
memberService.save(member);
log.info("支付宝开卡成功");
}