Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS小技能:封装银联接口协议(收银台的订单退款、查询机制)【下篇】

iOS小技能:封装银联接口协议(收银台的订单退款、查询机制)【下篇】

作者头像
公众号iOS逆向
发布于 2022-08-22 03:04:37
发布于 2022-08-22 03:04:37
84400
代码可运行
举报
文章被收录于专栏:iOS逆向与安全iOS逆向与安全
运行总次数:0
代码可运行

引言

  1. 上篇:业务功能、退款接口的协议规则、请求 https://kunnan.blog.csdn.net/article/details/115084885
  2. 下篇:返回结果处理、测试技巧、常见问题处理方案

I 返回结果处理

1、申请退款成功,立马创建处理中的本地数据 2、退款查询,根据查询状态修改订单状态

  • 数据按XML的格式实时返回

字段名

变量名

必填

类型

说明

版本号

version

String(8)

版本号,version默认值是2.0。

字符集

charset

String(8)

可选值 UTF-8 ,默认为 UTF-8。

签名方式

sign_type

String(8)

签名类型,取值:MD5默认:MD5

授权交易机构

sign_agentno

String(12)

授权交易的服务商机构代码,商户授权给服务商交易的情况下返回,签名使用服务商的密钥

连锁商户号

groupno

String(15)

连锁商户为其下门店发交易的情况返回,签名使用连锁商户的密钥

返回状态码

status

String(16)

0表示成功,非0表示失败此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断

返回信息

message

String(128)

返回信息,如非空,为错误原因签名失败参数格式校验错误

网关返回码

code

String(32)

网关返回码

以下字段在 status 为 0的时候有返回

业务结果

result_code

String(16)

0表示成功,非0表示失败注:此处返回0表示退款申请接收成功,实际的退款结果根据退款查询接口查询

商户号

mch_id

String(15)

商户号,由平台分配

设备号

device_info

String(32)

终端设备号

随机字符串

nonce_str

String(32)

随机字符串,不长于 32 位

错误代码

err_code

String(32)

具体错误码请看文档最后错误码列表

签名

sign

String(32)

MD5签名结果,详见“安全规范”

以下字段在 status 和 result_code 都为 0的时候有返回

平台订单号

transaction_id

String(32)

平台交易号

商户订单号

out_trade_no

String(32)

商户系统内部的订单号

商户退款单号

out_refund_no

String(32)

商户退款单号

平台退款单号

refund_id

String(32)

平台退款单号

退款渠道

refund_channel

String(16)

ORIGINAL—原路退款,默认

退款金额

refund_fee

Int

退款总金额,单位为分,可以做部分退款

现金券退款金额

coupon_refund_fee

Int

现金券退款金额 <= 退款金额, 退款金额-现金券退款金额为现金,单位为分

交易类型

trade_type

String(32)

pay.weixin.micropay——微信被扫支付pay.alipay.micropay——支付宝被扫支付pay.unionpay.micropay――银联被扫支付

1.1 状态判断逻辑

先判断协议字段返回,再判断业务返回,最后判断交易状态

1、返回状态码(status)参数:0表示调用成功;非0表示调用失败。此字段是通信标识,非交易标识,交易是否成功需要查看 result_code 来判断2、业务结果(result_code) : 0表示成功,非0表示失败注:此处返回0表示退款申请接收成功,实际的退款结果根据退款查询接口查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
协议级错误返回:
<xml>
<status>500</status>
<message><![CDATA[SYSERR]]></message>
</xml>
正确返回数据:
<xml>
<status>0</status>
<message><![CDATA[OK]]></message>
<result_code>0</result_code>

</xml>
业务级错误返回:
<xml>
<status>0</status>
<message><![CDATA[OK]]></message>
<result_code>1</result_code>
<err_code><![CDATA[AUTHCODE_EXPIRE]]></err_code>
<err_code_des><![CDATA[二维码已过期,请刷新再试]]></err_code_des>
</xml>

1.2 字段解析(XML解析)

https://blog.csdn.net/z929118967/article/details/74747249

  • 从Nsdata 转成CXMLDocument对象
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 NSString * strResponse = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
                CXMLDocument *xml= [[CXMLDocument alloc] initWithXMLString:strResponse options:0 error:nil];
                [weakSelf ProcessSucXML:xml];

  • 解析字段
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 1、字符串类型的解析:银行卡名字
    [Session Instance].strBankNameReset = [[xml nodesForXPath:@"//ROOT/BODY/BNKNM" error:nil].lastObject stringValue];
 // 2、integerValue类型的解析:订单金额
        [Sessionsss sss].ssss = [[xml nodesForXPath:@"//ROOT/BODY/OsssMT" error:nil].lastObject stringValue].integerValue;
//3、数组的解析
    NSArray *arr = [xml nodesForXPath:@"//ROOT/BODY/REC" error:nil];



//采用遍历CXMLElement方法
    for (CXMLElement *element in arr)
    {
        NSString *strNumber = @"";
        NSArray *aNumber = [element elementsForName:@"NO"];
        if (aNumber != 0) {
            strNumber = [aNumber.firstObject stringValue];
        }
    }

//————————————————
//版权声明:本文为CSDN博主「#公众号:iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/z929118967/article/details/74747249

II、解决商户平台交易流水的订单记录无法实时与银联同步的问题

目前平台和银联的订单对账间隔是1天,因此需要在app本地创建退款失败、退款中、退款成功的订单数据。

2.1 订单列表数据追加本地数据:数据去重和按照时间戳排序

  • 数据去重

iOS数据搜索技巧:1、 应用NSPredicate进行数据筛选:从数组搜索特定条件的元素2、利用正则表达式进行匹配查找数据3、使用系统特定API进行数据查找来避免循环遍历数组

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 数据去重:判断构造的数据,是否与接口返回的数据列表重复
 */
- (BOOL )iscontainsinarr:(NSArray*)arr;

- (BOOL )iscontainsinarr:(NSArray*)arr{
    
    
    

    NSPredicate* predicate = [NSPredicate predicateWithFormat:@"paymentNo == %@", self.paymentNo];
    
    
    

    NSArray *arFiltered = [  arr filteredArrayUsingPredicate:predicate];//以一定的条件(特定日期)过滤数组,即进行大数据搜索。
    
    
    if(arFiltered.count>0){
        
        return YES;
        

    }
    
    
    return NO;

}

  • 对象数组按照时间戳排序

iOS 排序指南:参数名ASCII码从小到大排序、数据按照日期进行分组、对象数组按照时间戳排序https://kunnan.blog.csdn.net/article/details/115242819

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

/**
        weakSelf.viewModel.listModels=   [QCT_Common sortedArrayUsingObjectKey:@"createTime" arr:weakSelf.viewModel.listModels];

 IOS中将对象数组按照时间戳排序
 */
- (NSMutableArray*)sortedArrayUsingObjectKey:(NSString*)key arr:(NSArray*)listModels{
    
    
    //1)取出日期分组
    
    NSString* valueForKeyPath = FMSTR(@"@distinctUnionOfObjects.%@",key);
    
    
    
    NSArray *arDistinct = [listModels valueForKeyPath:valueForKeyPath];
    
    
    //listModels是一些含有日期属性的对象集合
    //2)构建排序规则NSComparator
    NSComparator cmptr = ^(id obj1, id obj2){
        NSString *strData1 = obj1;
        NSString *strData2 = obj2;
        NSComparisonResult ret = [strData1 compare:strData2];
        return ret;
    };
//     3)按数字从小到大进行排序(将最新的数据显示在前面)
 
    NSArray  *arSorted = [arDistinct sortedArrayUsingComparator:cmptr];
    arSorted = arSorted.reverseObjectEnumerator.allObjects;//顺序取反
    NSMutableArray *newSorted_arr = [NSMutableArray array];
    
    //     4)按照日期进行分组
        for (NSString *strDateCreated in arSorted)
        {
     
            NSPredicate*   predicate = [NSPredicate predicateWithFormat:@"createTime == %@", strDateCreated];
            
            
     
            NSArray *arFiltered = [listModels filteredArrayUsingPredicate:predicate];//以一定的条件(特定日期)过滤maTemp数组,即进行大数据搜索。
            
            
            [newSorted_arr addObjectsFromArray:arFiltered];
            
            
            
     
        }
    
    return newSorted_arr;

//        ————————————————
//        版权声明:本文为CSDN博主「#公众号:iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//        原文链接:https://blog.csdn.net/z929118967/article/details/115242819

//    ————————————————
//    版权声明:本文为CSDN博主「#公众号:iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//    原文链接:https://blog.csdn.net/z929118967/article/details/113499172
    

}


  • 数据过滤: 获取最近7天的数据
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        // 数据过滤:  获取最近7天的数据
        NSMutableString *str = [[NSMutableString alloc]initWithString: [QCT_Common get4TodayTimeWithDateFormat:@"yyyy-MM-dd HH:mm:ss"]];
        
        
        NSMutableArray *tmp = [NSMutableArray array];

        for (QCTReceiptDetailModel *obj in tmparr) {
            
            

            NSInteger day  = [QCT_Common contrastTimeBackDayWithStartDate:obj.completeTime endDate:str DateFormat:@"yyyy-MM-dd HH:mm:ss"];//  endDate 大
            
            
            
            
            NSLog(@"day: %ld",(long)day);

            if (day > 6) {
                                
            }else{
                [tmp addObject:obj];

                
            }

            
            

            
        }
        
/**
     计算两个时间的间隔(天)
     
     @param start 开始时间
     @param end 结束时间
     @return 间隔时间
     */
    + (NSInteger)contrastTimeBackDayWithStartDate:(NSString *)start endDate:(NSString *)end DateFormat:(NSString*)Format
    {
        
        NSTimeInterval time = [self contrastTimeWithStartDate:start endDate:end dateFormatter:Format];
        
        
        
        NSInteger minute,second,hour,day;
        second=(NSInteger)time%1000;
        minute = (NSInteger)(time/60)%60;
        hour = (NSInteger)(time/3600)%24;
        day = (time/3600/24);
        return day;
    }

    /**
     计算两个时间的间隔(毫秒)
     
     @param start 开始时间
     @param end 结束时间
     @return 间隔时间
     */
    + (NSTimeInterval)contrastTimeWithStartDate:(NSString *)start endDate:(NSString *)end dateFormatter:(NSString*)Formatter
    {
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    //    [dateFormatter setDateFormat:@"yyyy-MM-dd"];
        
        [dateFormatter setDateFormat:Formatter];
        
        
        
        NSDate *startDate = [dateFormatter dateFromString:start];
        NSDate *endDate = [dateFormatter dateFromString:end];
        NSTimeInterval time = [endDate timeIntervalSinceDate:startDate];
        return time;
    }


2.2 退款状态查询处理

https://up.95516.com/open/openapi/doc?index_1=2&index_2=1&chapter_1=274&chapter_2=296

  • 退款状态

SUCCESS—退款成功 FAIL—退款失败 PROCESSING—退款处理中 NOTSURE—未确定, 需要商户原退款单号重新发起 CHANGE—转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者平台转账的方式进行退款。

  • 处理查询结果
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    
    [NetworkHelper4XML postWithURL:url params:params successBlock:^(CXMLDocument * _Nonnull xml) {
        //$n 表示记录的序号,取值为 0~($ refund_count -1),例如 refund_count 指示返回的退款记录有 2 条。第一条序号为“0”,第二条序号为“1”。

        
//        退款笔数refund_count Int 退款记录数
        NSString *refund_count = [[xml nodesForXPath:@"//xml/refund_count" error:nil].lastObject stringValue];
        
        
        
        refund_count = [NSNumber numberWithInteger:(refund_count.integerValue-1)].description;
        
        
        NSString* refund_status =  [[xml nodesForXPath:FMSTR(@"%@%@",@"//xml/refund_status_",refund_count) error:nil].lastObject stringValue];
        
        if([refund_status isEqualToString:@"SUCCESS"]){
                                    
            
//            refund_time_$n 退款时间 yyyyMMddHHmmss
            
            NSString* refund_time_ = [[xml nodesForXPath:FMSTR(@"%@%@",@"//xml/refund_time_",refund_count) error:nil].lastObject stringValue];
            
            //商户退款单号
            

            NSString* out_refund_no_ = [[xml nodesForXPath:FMSTR(@"%@%@",@"//xml/out_refund_no_",refund_count) error:nil].lastObject stringValue];

            
//            退款金额,单位为分,可以做部分退款
            NSString*   refund_fee_ =[[xml nodesForXPath:FMSTR(@"%@%@",@"//xml/refund_fee_",refund_count) error:nil].lastObject stringValue];
#pragma mark - ********退款成功界面: 退款编号、退款时间、退款人、退款金额、打印小票
            
            payinfomodel.orderNo = out_refund_no_;
            
            payinfomodel.paymentNo = out_refund_no_;
            
            
            payinfomodel.createTime  = [QCT_Common strdatedateFormat:@"yyyy-MM-dd HH:mm:ss" fromDateFormat:@"yyyyMMddHHmmss" objstr:refund_time_];// 格式化时间
            
            
            payinfomodel.completeTime = payinfomodel.createTime;
            
            model4list.completeTime =payinfomodel.createTime;
            model4list.createTime =payinfomodel.createTime;
            

            
            payinfomodel.paymentAmount = [NSNumber numberWithDouble: refund_fee_.doubleValue/100.00].description;
            
            payinfomodel.stateName = @"退款成功";
                        
            payinfomodel.state = [NSNumber numberWithInt:k_PAY_STATE_Enum4PAY_STATE_SUCCESS].description;
            model4list.state = payinfomodel.state;
            model4list.stateName =payinfomodel.stateName;
            
            [model4list  bg_updatetoDB];
            
        [[NSNotificationCenter defaultCenter] postNotificationName:QCTupdateInffo4ReceiptListNotification object: [NSNumber numberWithInteger:1] userInfo:@{QCTchangeViewNotificationuserInfo:NSClassFromString(@"QCTNewslist4ReceiptViewControllerNewViewController")}];// 只要门店需要筛选

            

            QCTRefundSUCCModel *model4SUCCModel = payinfomodel.RefundSUCCModel;


            QCTrefund_successfulViewController *vc = [QCTrefund_successfulViewController new];
            
            vc.viewModel.model = model4SUCCModel;
            
            
            [weakSelf.navigationController pushViewController:vc  animated:YES];
            
            NSLog(@"跳到成功页");
            
            
            
        }else if([refund_status isEqualToString:@"CHANGE"]){
            
            
            payinfomodel.stateName = @"其他错误";
            
                        
            payinfomodel.state = [NSNumber numberWithInt:k_PAY_STATE_Enum4PAY_STATE_PAYMENT_FAILURE].description;
            
            payinfomodel.remark = @"转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者平台转账的方式进行退款";
            
            
            model4list.state = payinfomodel.state;
            
            model4list.stateName =payinfomodel.stateName;
            

            [LBAlertController showAlertTitle:nil content:@"CHANGE:转入代发" cancelString:@"确定" cancleBlock:^{
                [self pop];
                
            } sureString:nil sureBlock:nil
                            currentController:[QCT_Common getCurrentVC]];

        
    }else if([refund_status isEqualToString:@"FAIL"]){//退款失败
        
        
        payinfomodel.stateName = @"退款失败";
        
                    
        payinfomodel.state = [NSNumber numberWithInt:k_PAY_STATE_Enum4PAY_STATE_PAYMENT_FAILURE].description;
        
        model4list.state = payinfomodel.state;
        model4list.stateName =payinfomodel.stateName;

        [LBAlertController showAlertTitle:nil content:@"退款失败" cancelString:@"确定" cancleBlock:^{
            [self pop];
            
        } sureString:nil sureBlock:nil
                        currentController:[QCT_Common getCurrentVC]];

        
    }else if([refund_status isEqualToString:@"PROCESSING"]){//退款处理中
        [self.view showHUDMessage:@"PROCESSING:退款处理中" ];
        
        
                    

                    NSString* out_refund_no_ = [[xml nodesForXPath:FMSTR(@"%@%@",@"//xml/out_refund_no_",refund_count) error:nil].lastObject stringValue];

                    
        //            退款金额,单位为分,可以做部分退款
                    NSString*   refund_fee_ =[[xml nodesForXPath:FMSTR(@"%@%@",@"//xml/refund_fee_",refund_count) error:nil].lastObject stringValue];
                    
        payinfomodel.paymentAmount = [NSNumber numberWithDouble: refund_fee_.doubleValue/100.00].description;

        //        NSLog(@"跳到退款中界面");
                
        payinfomodel.orderNo = out_refund_no_;
        
        payinfomodel.paymentNo = out_refund_no_;
        
        
        model4list.paymentAmount = payinfomodel.paymentAmount ;
        
        payinfomodel.createTime = weakSelf.viewModel.payinfomodel.createTime4out_refund_no;
        
//        [QCT_Common strdate4YYMMDDWithyyyyMMddHHmmssstr:refund_time_];// 格式化
        payinfomodel.completeTime = payinfomodel.createTime;
        
        model4list.completeTime =payinfomodel.createTime;
        model4list.createTime =payinfomodel.createTime;

                
                QCTRefundSUCCModel *model = payinfomodel.RefundSUCCModel;
                
            model.isFromFretless = YES;
                
                
                
                QCTrefund_ingViewController *vc =                     [QCTrefund_ingViewController new];

                
                vc.viewModel.model = model;
                
                
                [weakSelf.navigationController pushViewController:vc  animated:YES];
                
                


    
    }else if([refund_status isEqualToString:@"NOTSURE"]){//退款处理中
        // 新增备注信息: 转入代发,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者平台转账的方式进行退款
        payinfomodel.stateName = @"其他错误";
        
                    
        payinfomodel.state = [NSNumber numberWithInt:k_PAY_STATE_Enum4PAY_STATE_PAYMENT_FAILURE].description;
        
        
        
        
        model4list.state = payinfomodel.state;
        model4list.stateName =payinfomodel.stateName;
        
        payinfomodel.remark =@"未确定,请重新发起退款";        // 新增备注信息:未确定,请重新发起退款
    

        [LBAlertController showAlertTitle:nil content:@"NOTSURE:未确定,请重新发起退款" cancelString:@"确定" cancleBlock:^{
            [self pop];
            
        } sureString:nil sureBlock:nil
                        currentController:[QCT_Common getCurrentVC]];

        

    }
        
#pragma mark - ********  更新账单流水列表数据
        [model4list  bg_updatetoDB];
        
    [[NSNotificationCenter defaultCenter] postNotificationName:QCTupdateInffo4ReceiptListNotification object: [NSNumber numberWithInteger:1] userInfo:@{QCTchangeViewNotificationuserInfo:NSClassFromString(@"QCTNewslist4ReceiptViewControllerNewViewController")}];// 只要门店需要筛选

        
            
    } RspCDFailed:nil failure:nil isShowLoadingDataGif:YES];
    



IIII 测试技巧

3.1 产生订单数据

  • 由于商户平台侧的订单数据和银联的是一天同步一次,因此可以提前一天使用支付宝多交易产生订单,以便第二天测试退款。

当天的退款金额<=收款金额

  • iOS签名demo下载地址:从CSDN下载demo地址:https://download.csdn.net/download/u011018979/15483107

原理文章:https://blog.csdn.net/z929118967/article/details/108195721

  • 在线测试签名地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=20_1

3.2 修改返回报文

  • 去掉空格之后,再使用。否则会导致节点的值会包含空格
  • 正确的格式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<xml><appid><![CDATA[]]></appid> <charset><![CDATA[UTF-8]]></charset> <coupon_refund_fee_0><![CDATA[0]]></coupon_refund_fee_0> <mch_id><![CDATA[]]></mch_id> <mdiscount_0><![CDATA[0]]></mdiscount_0> <nonce_str><![CDATA[]]></nonce_str> <out_refund_no_0><![CDATA[]]></out_refund_no_0> <out_trade_no><![CDATA[]]></out_trade_no> <out_transaction_id><![CDATA[]]></out_transaction_id> <refund_channel_0><![CDATA[ORIGINAL]]></refund_channel_0> <refund_count><![CDATA[1]]></refund_count> <refund_fee_0><![CDATA[1]]></refund_fee_0> <refund_id_0><![CDATA[]]></refund_id_0> <refund_status_0><![CDATA[SUCCESS]]></refund_status_0> <refund_time_0><![CDATA[]]></refund_time_0> <result_code><![CDATA[0]]></result_code> <sign><![CDATA[]]></sign> <sign_agentno><![CDATA[]]></sign_agentno> <sign_type><![CDATA[MD5]]></sign_type> <status><![CDATA[0]]></status> <total_fee><![CDATA[1]]></total_fee> <trade_type><![CDATA[pay.alipay.micropay]]></trade_type> <transaction_id><![CDATA[]]></transaction_id> <version><![CDATA[2.0]]></version> 
</xml>

see also

openapi

java demo

https://github.com/zhangkn/web-pay-unionPay中国银联云闪付合作伙伴开放平台https://partner.95516.com/portal/document#pf29

iOS网络请求指南: 请求参数的拼接(签名)、返回参数解析(JSON/XML解析)

https://kunnan.blog.csdn.net/article/details/11517570

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iOS逆向 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS小技能:封装银联接口协议(收银台的订单退款、查询机制)【上篇】
背景:如果商家平台侧服务出现问题,商家需要一个备选方案进行正常的收退款;因此在POS机新增一个开关进行切换支付通道,智能机app直接与银联对接。并在本地维护产生的订单数据和维护订单状态。
公众号iOS逆向
2022/08/22
1K0
iOS小技能:封装银联接口协议(收银台的订单退款、查询机制)【上篇】
iOS小技能:参数名ASCII码从小到大排序、对象数组排序
利用KVC的 valueForKeyPath API、谓词的NSPredicate、数组的sortedArrayUsingComparator:API进行实现。
公众号iOS逆向
2022/08/22
1.9K0
iOS小技能:参数名ASCII码从小到大排序、对象数组排序
JAVA移动支付微信和支付宝后台代码
前言:之前接APP支付,微信遇到了一点点坑,为了方便以后copy,把之前写的代码粘贴出来。需要的同学可以参考一下,具体参数说明还请详细查看官方文档:
王念博客
2019/07/25
4.8K0
.NET Core 微信小程序退款——(统一退款)
继上一篇".NET Core 微信小程序支付——(统一下单)后",本文将实现统一退款功能,能支付就应该能退款嘛,一般涉及到钱的东西都会比较敏感,所以在设计退款流程时一定要严谨,不能出一点差错,否则你将会面临自己掏腰包的可能,下面我们来讲一讲退款的实现步骤。
hailang2zh
2020/06/19
1.5K0
.NET Core 微信小程序退款——(统一退款)
SpringBoot集成微信支付JSAPIV3保姆教程
最近为一个公众号h5商城接入了微信支付功能,查找资料过程中踩了很多坑,以此文章记录一下和大家分享
code2roc
2023/09/12
2K0
SpringBoot集成微信支付JSAPIV3保姆教程
C# 实现微信退款及对帐
在招聘报名系统里,考务费支付是其中一个环节,支付方式很多种,比如银联、微信、支付宝等等。本次我们以微信支付进行举例,在考生注册账号、编写简历、报名职位、被初审核通过等一系列基础的条件的具备下,可以进入支付考务费的环节(笔试费用),我们会为其生成一个支付二维码,考生支付后(无论成功与否),都会记录其支付结果状态。
初九之潜龙勿用
2024/06/20
1970
C# 实现微信退款及对帐
iOS小技能:金额格式处理 (货币符号本地化)
iOS 系统自带格式化NSFormatter的常用子类有:NSNumberFormatter(数字格式化)、NSDateFormatter(NSISO8601DateFormatter日期格式化)、NSPersonNameComponentsFormatter(名片格式化)、NSMeasurementFormatter(数量单位格式化)。
公众号iOS逆向
2022/08/22
2.5K0
iOS小技能:金额格式处理 (货币符号本地化)
【畅购商城】微信支付模块之微信支付二维码
https://kf.qq.com/product/weixinmp.html#hid=87
陶然同学
2023/02/24
1.9K0
【畅购商城】微信支付模块之微信支付二维码
电商系统设计之订单
用户交易将经历一段艰辛的历程,一般用户感觉不到,实际程序是经历了一段生死离别。具体付款流程如下:
前端教程
2018/08/16
2.9K0
电商系统设计之订单
微信公众号H5支付遇到的那些坑
官方文档说的很清楚,商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程。
小柒2012
2019/12/09
8970
【畅购商城】微信支付之支付回调和支付状态
步骤四:编写flow4,与flow3基本内容一致,提示信息为“支付成功,货物即将送出!”
陶然同学
2023/02/24
1K0
【畅购商城】微信支付之支付回调和支付状态
微信小程序支付Java工具类
引入微信支付开放平台的 API 依赖,以便能够使用 Java 调用相关 API 接口。
默存
2024/04/16
4280
微信小程序支付Java工具类
从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期
继前文章取消订单接口和查询订单接口此篇为申请退款流程,此篇文章过长我将分几个阶段的文章发布(项目源码都有,小程序和PC端)
杨不易呀
2023/08/07
3.9K22
从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期
微信支付之微信退款
无论刷卡支付、微信公众号支付、扫码支付、H5支付、APP支付等都有申请退款API并且接口一样,本篇文章就拿刷卡支付中的申请退款API文档举例
Javen
2018/08/21
9.6K0
java调用微信支付接口(调用微信支付)
前言百度搜了一下微信支付,都描述的不太好,于是乎打算自己写一个案例,希望以后拿来直接改造使用。 因为涉及二维码的前端显示,所以有前端的内容
全栈程序员站长
2022/07/28
6.7K0
java调用微信支付接口(调用微信支付)
微信刷卡支付API详解
最近因项目需要微信支付,通过扫码抢扫描微信付款码,调用微信刷卡支付API完成扣费,过程中遇到了遇到了一些问题,填了很多坑,所以把自己的经验分享给大家,本篇文章介绍如何使用刷卡支付API。 场景: 收银
南风
2018/07/02
1.7K0
PHP微信小程序支付工具类封装
微信小程序支付流程 小程序登录,获取openid 后端调用微信支付统一下单 得到预支付交易会话标识prepay_id 组装小程序支付所需的几个参数,并进行签名 支付成功,主动查询订单支付状态 接收微信
骤雨重山
2022/01/17
1K0
PHP微信小程序支付工具类封装
微信支付-Java-SpringMVC基础一些代码支持
官网文档和demo代码下载地址 https://mp.weixin.qq.com/htmledition/res/bussiness-faq/wx_app_pay.zip 1. 基础常量代码 package com.xiaoshuai.util; /** * 配置类 * @author 小帅帅 * @date 2016-7-5下午01:40:53 */ public class ConfigUtil { /** * 服务号相关信息 */ public final static S
小帅丶
2018/02/08
1.9K0
微信支付-Java-SpringMVC基础一些代码支持
【愚公系列】2022年10月 微信小程序-电商项目-小微商户支付后端功能实现(node版)
微信支付是腾讯集团旗下的第三方支付平台,致力于为用户和企业提供安全、便捷、专业的在线支付服务。以“微信支付,不止支付”为核心理念,为个人用户创造了多种便民服务和应用场景。微信支付为各类企业以及小微商户提供专业的收款能力,运营能力,资金结算解决方案,以及安全保障。用户可以使用微信支付来购物、吃饭、旅游、就医、交水电费等。企业、商品、门店、用户已经通过微信连在了一起,让智慧生活,变成了现实。
愚公搬代码
2022/10/31
6840
SpringCloud(七) - 微信支付
1、开发文档 微信开发文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 安全规范:https://pay.weixin.q
化羽羽
2022/11/16
3320
SpringCloud(七) - 微信支付
推荐阅读
相关推荐
iOS小技能:封装银联接口协议(收银台的订单退款、查询机制)【上篇】
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验