.NET版支付宝商户会员卡接入

  最近公司计划对接支付宝会员卡功能,而任务恰巧由领导安排给我这边,小弟之前也未做过支付宝接口,研究了三天,终于将支付宝会员卡API接口大体上调通了,现将其整理下,以供参考。

  蚂蚁金服开发平台-商户会员卡文档地址:https://docs.open.alipay.com/251

 

  支付宝会员卡接口我大体上分为四块:

1、会员卡模板管理:包括会员卡模板创建会员卡模板查询会员卡模板修改

2、会员卡开卡模块:会员卡开卡表单模板配置,获取会员卡领卡投放链接,查询用户提交的开卡表单数据信息,会员卡的增删改查(会员卡开卡接口会员卡查询接口,会员卡更新,会员卡删除)

3、会员卡消费记录同步

4、会员卡依赖的接口:图片资料上传接口用户信息授权接口

调用接口直接使用支付宝提供的SDK,下来来针对这四块分别说明。

 

会员卡模板管理

  这块儿需要注意的点是:卡模板的栏位信息中的自定义栏位的展现形式如果是openWeb,必须要填写more_info字段的信息,主要是url的信息需要填写。这儿打开二级页面的展现方式我这边没用到,就没写,有兴趣的同学可以自己尝试。支付宝文档还是比较全,凡是按照支付宝标准接口文档说明来开发,大问题应该没。注意这个接口安接口文档上来说,logo_id和background_id必填,并且其ID是图片资料上传接口返回的结果图片image_id,但我开始几次调用的时候都是随便传的值,也调用成功并且没看出来哪里受影响(貌似会员卡开卡后用户支付宝上显示的会员卡哪里是张灰色的图片),我也就不纠结这个了。直接上一段我调用修改卡模板的代码:

  因为我这里是写的示例,所有构建的实体对象的字段都是直接写死的。实际开发中一般都是从配置或其他来源的数据读取的值。

/// <summary>
        /// 卡模板修改
        /// 
        /// </summary>
        public void demoCardModify()
        {
            IAopClient client = new DefaultAopClient("https://openapi.alipay.com/gateway.do", APPID, APP_PRIVATE_KEY, "json", "1.0", "RSA2", ALIPAY_PUBLIC_KEY, CHARSET, false);
            AlipayMarketingCardTemplateModifyRequest request = new AlipayMarketingCardTemplateModifyRequest();
            CardTemplateModify entity = getModifyParams();
            TemplateFieldRuleDTO fieldDto = new TemplateFieldRuleDTO();
            fieldDto.field_name = "OpenDate";
            fieldDto.rule_name = "DATE_IN_FUTURE";
            fieldDto.rule_value = "10m";
            entity.field_rule_list.Add(fieldDto);

            request.BizContent = Newtonsoft.Json.JsonConvert.SerializeObject(entity); ;

            AlipayMarketingCardTemplateModifyResponse response = client.Execute(request);
            Console.WriteLine(response.Body);
            if (!string.IsNullOrEmpty(response.Body))
                WriteFileLog.WriteLog("修改会员卡模板返回信息:" + response.Body);
        }

        /// <summary>
        /// 构造修改的实体
        /// </summary>
        /// <returns></returns>
        public CardTemplateModify getModifyParams()
        {
            CardTemplateModify entity = new CardTemplateModify();
            entity.request_id = DateTime.Now.ToString("yyyyMMddHHmmss") + "000001";
            entity.write_off_type = "qrcode";
            entity.template_id = template_id;

            entity.template_style_info = new TemplateStyleInfoDTO();
            entity.template_style_info.card_show_name = "五岳天下秀";
            entity.template_style_info.logo_id = "VY3VJvlATW6TrUs_6Ik_gQAAACMAAAAA";
            entity.template_style_info.color = "rgb(55,112,179)";
            entity.template_style_info.background_id = "VY3VJvlATW6TrUs_6Ik_gQAAACMAAAAA";
            entity.template_style_info.bg_color = "rgb(55,112,179)";
            entity.template_style_info.front_text_list_enable = false;

            entity.column_info_list = new List<TemplateColumnInfoDTO>();
            TemplateColumnInfoDTO columnDto = new TemplateColumnInfoDTO();
            //columnDto.code = "BENEFIT_INFO";
            columnDto.code = "BENEFIT_INFO";
            columnDto.operate_type = "staticinfo";
            columnDto.title = "优惠大礼";
            columnDto.value = "优惠礼包大放送";
            entity.column_info_list.Add(columnDto);

            TemplateColumnInfoDTO columnDto1 = new TemplateColumnInfoDTO();
            columnDto1.code = "TELEPHONE";
            columnDto1.operate_type = "staticinfo";
            columnDto1.title = "客服热线";
            columnDto1.value = "4006-999-999";
            entity.column_info_list.Add(columnDto1);

            TemplateColumnInfoDTO columnDto2 = new TemplateColumnInfoDTO();
            columnDto2.code = "MEMO";
            columnDto2.operate_type = "staticinfo";
            columnDto2.title = "使用说明";
            columnDto2.value = "仅限支付宝支付";
            entity.column_info_list.Add(columnDto2);

            //TemplateColumnInfoDTO columnDto3 = new TemplateColumnInfoDTO();
            //columnDto3.code = "WAIBULINK";
            //columnDto3.operate_type = "openWeb"; //必须要填写more_info信息
            //columnDto3.title = "官网地址1";
            //columnDto3.value = "http://www.baidu.com";
            //columnDto3.more_info = new MoreInfoDTO();
            //columnDto3.more_info.url = "http://www.baidu.com";
            //columnDto3.more_info.title = "官网地址";
            ////columnDto3.more_info.Params = new Params();
            //columnDto3.more_info.Params = "{}";  //这里大小写

            //entity.column_info_list.Add(columnDto3);

            entity.field_rule_list = new List<TemplateFieldRuleDTO>();
            TemplateFieldRuleDTO fieldDto = new TemplateFieldRuleDTO();
            fieldDto.field_name = "Balance";
            fieldDto.rule_name = "CONST";
            fieldDto.rule_value = "500";
            entity.field_rule_list.Add(fieldDto);

            return entity;
            //序列化Json串
            //return Newtonsoft.Json.JsonConvert.SerializeObject(entity);
        }
View Code

 会员卡开卡模块

  我几乎一半的时间都是耗费在会员卡领卡投放链接和会员卡开卡模块上,主要是这块儿的流程弄了好久才想通:这里主要是两种情况,第一种:就是支付宝手机APP里面的【卡包—会员卡】这个菜单里面的会员卡,支付宝这个版块现状是不对外开发,如果需要向这个里面添加自己活公司的会员卡产品,需要一定的条件,这个我具体也不怎么清楚。第二种:就是调用领卡投放链接接口获取到一个URL链接地址,将其制作成二维码,用户通过手机支付宝扫描这个二维码进行领卡操作。我这边测试Demo主要是这种。我这边主要纠结的问题是首先获取了这个地址后,怎么才能使用的问题,这个通过详细阅读了开发文档后解决了,生成二维码然后扫描即可。第二个纠结的点是扫描跳转到了用户授权页面,用户点击确认领卡后会有个回调,因为我这是在开发测试阶段,并没有发布到外网,所以就没有什么回调地址。这个通过联系支付宝技术支持确认说必须要有回调地址,因为这个支付宝没有沙箱环境(就是支付宝的接口测试环境),我在想难道真的必须要在外网先布置一个回调么?中间也查阅过其他人开发的资料,说貌似不需要回调也可以调用,只不过开卡后没有回调动作。我后来是领卡链接地址中的回调参数随便传了一个互联网上能用的网址,比如百度首页。然后手机扫描—确认领卡—跳转到百度首页了。当时就激动一把,以为调通了,赶快手机支付宝卡包版块查看,瞅了半天也没找到,期间又理了下思路反复做了几次领卡操作,手机上就是没有显示卡(这里纠结了好久),因为我这里回调地址随便填的,又看不到支付宝回调的东东是什么。我就在想变通的方法,我将领卡的链接直接通过浏览器访问,跳转到支付宝的登陆页面,扫码登陆,然后跳转到了百度首页,只不过此时地址栏url类似https://www.baidu.com/?app_id=2020120100000001&source=alipay_wallet&scope=auth_ecard&auth_code=894ca7b6051d486e9d002846ae24AN51,通过这个auth_code拿到用户的支付宝Id和访问token,然后直接调用会员卡开卡接口,看用户返回的信息是什么错误信息,大致意思是授权令牌不正确什么的,在开发文档上没找到这个错误对应的说明,赶快联系了下支付宝技术支持,告知说是应用配置的回调地址和callback参数不一致,我核实了确认不一致,改过来在调用一下,返回开卡成功,此时去支付宝手机APP里查了下,会员卡成功在支付宝卡包版块展示。后续会员卡更新,会员卡查询都一步通过实现了,并且通过修改会员卡模板,在去查看刚刚领取的会员卡,看卡片的展示样式同步更新成功。贴一段构建开卡实体的代码:

 
/// <summary>
        /// 会员卡开卡-Test
        /// </summary>
        public void OpenCard()
        {
            IAopClient client = new DefaultAopClient("https://openapi.alipay.com/gateway.do", CardTemplateManage.APPID, CardTemplateManage.APP_PRIVATE_KEY, "json", "1.0", "RSA2", CardTemplateManage.ALIPAY_PUBLIC_KEY, CardTemplateManage.CHARSET, false);
            AlipayMarketingCardOpenRequest request = new AlipayMarketingCardOpenRequest();

            //client

            MemberOpenCard openCard=new MemberOpenCard();
            openCard.out_serial_no = DateTime.Now.ToString("yyyyMMddHHmmss") + "001"; //保证唯一
            WriteFileLog.WriteLog("会员卡开卡商户流水号:" + openCard.out_serial_no);//
            openCard.card_template_id = CardTemplateManage.template_id;

            openCard.card_user_info = new CardUserInfo();
            openCard.card_user_info.user_uni_id = "208850281750000"; 
            //openCard.card_user_info.user_uni_id = "12121UserID";
            openCard.card_user_info.user_uni_id_type = "UID";

            openCard.card_ext_info =new MerchantCard();
            openCard.card_ext_info.external_card_no = "1002017121100001";
            openCard.card_ext_info.open_date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            openCard.card_ext_info.valid_date = DateTime.Now.AddYears(10).ToString("yyyy-MM-dd HH:mm:ss");
            string auth_token = "composeB66e2a9aba0ac4ec3b2976cdb222dbX52"; //访问令牌
            if (string.IsNullOrEmpty(auth_token))
            {
                //这里要有个回调地址,接收支付宝的回调参数
                string auth_url = string.Format(
                    "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id={0}&scope={1}&redirect_uri={2}",
                    CardTemplateManage.APPID, "auth_user,auth_ecard", "https://www.baidu.com/");

                auth_token = System.Web.HttpContext.Current.Request.QueryString["auth_code"];
                string scope = System.Web.HttpContext.Current.Request.QueryString["auth_code"];
                string app_id = System.Web.HttpContext.Current.Request.QueryString["auth_code"];
            }
            request.BizContent = Newtonsoft.Json.JsonConvert.SerializeObject(openCard);
            if(string.IsNullOrEmpty(auth_token))
                return;
            AlipayMarketingCardOpenResponse response = client.Execute(request, auth_token);

            if (!string.IsNullOrEmpty(response.Body))
                WriteFileLog.WriteLog("会员卡开卡模板返回信息:" + response.Body);
            Console.WriteLine(response.Body);
        }
View Code

 

 未完待续。

posted @ 2017-12-15 12:04  奔四的大龄码农  阅读(1268)  评论(1编辑  收藏  举报