支付那些小事

App内购与支付流程详解

       现在不管是电商还是一些社区类的App都接入了支付的功能,有的是走的苹果的支付【内购不是Apple Pay】,有的则是支付宝、微信和银联卡,不管是买卖商品还是打赏点赞,这些都是涉及到资金的流动。当然目前据《华尔街日报》,微信和其他公司的高管表示,苹果已经要求几家国内社交网络应用禁用它们的“打赏”功能,以遵守AppStore的规则。即使是这样还可以在打打赏的位置放置一些收款二维码来替代。当然如果真的放二维码了那就跟自己的应用没关系了,所以这一块也不用担心了。那么先说一下应用的内购吧,应用的内购流程(内购的流程具体可参见:http://www.cnblogs.com/liuluoxing/p/6553109.html)其实并不复杂,主要是一些点需要注意:设置卡号选择币种的时候人民币的标识是CNY,接着设置Tax的时候一般在天朝的话直接选择

 

图1.0

这些是税务信息一般来说U.S Tax Forms: 美国税务、Australia Tax Forms:澳大利亚税务、Canada Tax Forms: 加拿大税务 选择美国税务就可以。签完协议和税务信息,还要记得填写用户的职能即设置沙盒里面的测试账号,这样使用这个账号才能进行测试内购。这些是为内购做的准备,当进行集成的时候推荐一个轮子(RMStore这个开源库),过程中遇到一些问题就是付款过程中的未知错误处理是最多的无法连接到iTunes store,不过查阅一些资料的话可以发现,其实每种状态都有对应的枚举值如下:

enum {  
    SKErrorUnknown,  
    SKErrorClientInvalid,               // client is not allowed to issue the request, etc.  
    SKErrorPaymentCancelled,            // user cancelled the request, etc.  
    SKErrorPaymentInvalid,              // purchase identifier was invalid, etc.  
    SKErrorPaymentNotAllowed,           // this device is not allowed to make the payment  
    SKErrorStoreProductNotAvailable,    // Product is not available in the current storefront  
};  

可以根据这几个状态作相应的细节处理,提示用户即可。

       接着是支付宝和微信了,先说支付宝吧,在客户端的处理上支付宝的处理相对于微信来说更多一下,被吐槽的地方也更多一些,首先是支付宝的官方集成文档特别特别的难找,要找很久才能找对地方。这个是直达连接

     

 

图2.0
        涉及到的相关流程即:首先应用端选择支付宝付款,这里分为两种情况,一种是使用公司自己的服务器生成签名,订单号和订单的相关参数值,第二种是应用在客户端自己生成签名和订单信息.因为订单信息中包含签名和秘钥,会造成信息传递的不安全,所以还是建议将生成订单的步骤放在自己的服务器端(最好是服务器给返回的数据是已经拼接好的参数串例如:
{
  "code": 0,
  "message": "SUCCESS",
  "data": [
    {
      "data": "partner=2088121050949991&seller_id=774267424@qq.com&subject=充值测试&notify_url=http://1xx.xx.xx.xx:8081/v2/notify&payment_type=1&_input_charset=utf-8&it_b_pay=30m&sign=xxxxxxxxxxxx&sign_type=RSA"
    }
  ]
}
)这样客户端就可以直接拿着相应的data里面的返回订单信息去调起支付宝的api,设置好appScheme,直接用调用支付宝的支付接口即可:
  [self sendValueToAliPayWithOrderString:signedString FromScheme:appScheme];

相关的代码为:

- (void)sendValueToAliPayWithOrderString:(NSString *)orderString FromScheme:(NSString *)appScheme
{
    
    //    提供给商户快捷订单支付功能。  支付并返回回调结果
    [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
        
     
        if ([[resultDic objectForKey:@"resultStatus"]isEqualToString:@"9000"]) {
           // 支付成功的处理,跳转相关界面
        }else  if ([[resultDic objectForKey:@"resultStatus"]isEqualToString:@"4001"]) {
            UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"请您重新选择支付金额" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
            [av show];
            
        } else  if ([[resultDic objectForKey:@"resultStatus"]isEqualToString:@"4006"]) {
            
            UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"订单支付失败" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
            [av show];
            
            // 支付失败跳转的界面

        } else if ([[resultDic objectForKey:@"resultStatus"]isEqualToString:@"4003"]) {
        
            UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"您的账户目前不能正常支付" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
            [av show];
            // 支付失败跳转的界面

        } else if ([[resultDic objectForKey:@"resultStatus"]isEqualToString:@"6001"]) {
            
            UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"您已取消充值" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
            [av show];
            
            
        }else {
            
            UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"未支付成功" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
            [av show];
            // 支付失败的跳转
            
        }
    }];
}

除此之外还要在AppDelegate里面做相应的设置,这一块如果做了微信的支付回调的方法也是一致的,等下面说微信支付的时候一块贴上代码。如果签名什么的都在后台服务器做的话,那么在应用中的代码也就这么多。还有几个需要注意的点,就是为了支付成功回调做的准备:

应用注册的时候schme 在Info.plist定义URL types URL schme
将商品信息拼接成字符串
进行签名并将签名成功后的字符串格式化订单字符串
调用支付宝SDK发送数据
// 还包括相关错误码
9000 订单支付成功
8000 正在处理中
4000 订单支付失败
6001 用户中途取消
6002 网络连接出错
 

可以画个图展示一下:

图3.0

 以上就是支付宝支付所需要注意的点了。下面来说说微信,就像之前说到的,微信支付要比起支付宝支付来讲客户端处理的内容相对的较少一些,其主要的处理都是在服务端,首先可以看一下这个流程,一看就是比较复杂,不过这些都不用客户端来处理
 

图4.0

简化一下呢,就是是4个步骤,一个就是请求生成的订单数据,另一个就是调起微信支付德的api处理支付的结果;接着就是处理支付的回调结果,最后异步处理,通知服务器支付成功。画个图展示一下具体的步骤吧

图5.0

这些事理论上的表述,涉及到应用中的代码处理可以分为,先从服务器请求相应的数据,服务器返回的数据格式应该为:

{
  "code": 0,
  "message": "SUCCESS",
  "data": [
    {
      "app_id": "wx6a33db7xxxxx",
      "nonce_str": "IVY8yB5q7v6jpSgiVgxxxxxxxx",
      "extend_field": "Sign=WXPay",
      "partner_id": "1333317801",
      "prepay_id": "wx2017022414465218c0066b3d04xxxxxx",
      "timestamp": "1487918812",
      "sign": "D5001641D1F43C5DBA6F14xxxxxxxx"
    }
  ]
}

 在后台服务器请求完必要的参数后,此时就应该调起微信支付:具体代码如下:

  if([WXApi isWXAppInstalled]) // 判断 用户是否安装微信
    {
        PayReq *request = [[PayReq alloc] init] ;
        request.partnerId = _myModel.partner_id;
        request.prepayId= _myModel.prepay_id;
        request.package = _myModel.extend_field;
        request.nonceStr= _myModel.nonce_str;
        request.timeStamp= _myModel.timestamp;
        request.sign= _myModel.sign;
        
        [WXApi sendReq:request];
    }else {
        
        UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"提示" message:@"未安装微信客户端,请选择其他支付方式" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
        [av show];     
   }

再在其回调的方法内设置相应的跳转即可如下:

-(void)dealWXpayResult:(NSNotification*)notification{
    NSString*result=notification.object;
    if([result isEqualToString:@"1"]){
        // 支付成功的操作

    }else{
        
        //支付失败的操作
        UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"您已取消支付" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
        [av show]; 
    } 
}
 以上是在当前界面下的处理的回调逻辑,除此之外还要在AppDelegate里面设置相关的代理方法具体的设置内容如下所示:
首先是支付宝的:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
    if ([url.host isEqualToString:@"safepay"]) {
        // 设备已安装支付宝客户端情况下,处理支付宝客户端返回的 url
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            // 用SBJSON 或者 JSONKit 将回调信息(字典)转成字符串
            SBJSON *sbJson = [[SBJSON alloc] init];
            NSString *resultDicToString = [sbJson stringWithObject:resultDic error:nil];
            [self paymentResult:resultDicToString];
        }];
    }
    if ([url.host isEqualToString:@"platformapi"]){//支付宝钱包快登授权返回 authCode
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
    
        }];
    }
    return YES;
}
// 支付宝回调的新方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
    if ([url.host isEqualToString:@"safepay"]) {
        //   设备已安装支付宝客户端情况下,处理支付宝客户端返回的 url
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            //    用SBJSON 或者 JSONKit 将回调信息(字典)转成字符串
            SBJSON *sbJson = [[SBJSON alloc] init];
            NSString *resultDicToString = [sbJson stringWithObject:resultDic error:nil];
            [self paymentResult:resultDicToString];
            if ([[resultDic objectForKey:@"resultStatus"]isEqualToString:@"9000"]) {
                //    NSLog(@"当前页面下的支付成功");
                [[NSNotificationCenter defaultCenter]postNotificationName:@"chongzhiFinishAction" object:nil];
                
            }else {
                
                //    NSLog(@"当前页面下的未支付");
                UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"您已取消支付" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
                [av show];
                
            }
        }];
    }else{
        
        return  [WXApi handleOpenURL:url delegate:self];
    }
    if ([url.host isEqualToString:@"platformapi"]){//支付宝钱包快登授权返回 authCode
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {

            if ([[resultDic objectForKey:@"resultStatus"]isEqualToString:@"9000"]) {
                //                NSLog(@"当前页面下的支付成功");
                UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"您已支付成功" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
                [av show];
            }else {
                //                NSLog(@"当前页面下的未支付");
                UIAlertView *av = [[UIAlertView alloc] initWithTitle:nil message:@"您已取消支付" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
                [av show];
                
            }
            
        }];
    }else
    {
        return  [WXApi handleOpenURL:url delegate:self];
    }
    
    return  YES;
    
    
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    if ([url.host isEqualToString:@"safepay"]) {
        //    设备已安装支付宝客户端情况下,处理支付宝客户端返回的 url
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            // 用SBJSON 或者 JSONKit 将回调信息(字典)转成字符串
            SBJSON *sbJson = [[SBJSON alloc] init];
            NSString *resultDicToString = [sbJson stringWithObject:resultDic error:nil];
            [self paymentResult:resultDicToString];
        }];
    }else{
        return  [WXApi handleOpenURL:url delegate:self];
    }
    if ([url.host isEqualToString:@"platformapi"]){//支付宝钱包快登授权返回 authCode
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
       
        }];
    }else{
        //          return  [WXApi handleOpenURL:url delegate:self];
    }
    return YES;
}
//#pragma mark - 对独立客户端回调结果验证
- (void)paymentResult:(NSString *)resultDicToString
{
    //结果处理
    AlixPayResult *result = [[AlixPayResult alloc] initWithString:resultDicToString];
    if (result)
    {
        if (result.statusCode == 9000)
        {
            // 验证签名成功,交易结果无篡改
            // NSLog(@"支付成功!");
            
        }
        
        else
        {
            // 支付失败
            // NSLog(@"%d%@", result.statusCode, result.statusMessage);
        }
    }
    else
    {
        // 支付失败
        // NSLog(@"支付失败!");
    }
    
}

接着是微信的:

#pragma mark - 微信支付回调
-(void) onResp:(BaseResp*)resp
{
    NSString *strMsg = [NSString stringWithFormat:@"errcode:%d", resp.errCode];
    NSString *strTitle;
    
    if([resp isKindOfClass:[SendMessageToWXResp class]])
    {
        strTitle = [NSString stringWithFormat:@"发送媒体消息结果"];
    }
    if([resp isKindOfClass:[PayResp class]]){
        //支付返回结果,实际支付结果需要去微信服务器端查询
        strTitle = [NSString stringWithFormat:@"支付结果"];
        
        switch (resp.errCode) {
            case WXSuccess:
                strMsg = @"恭喜您支付:成功!";
                
                [[NSNotificationCenter defaultCenter] postNotificationName:@"WXpayresult" object:@"1"];
                break;
                
            default:
                strMsg = [NSString stringWithFormat:@"您已取消支付"];
                
                [[NSNotificationCenter defaultCenter] postNotificationName:@"WXpayresult" object:@"2"];
                
                break;
        }
    }
    
    
}

其实可以看出这两种方式的支付都有重合的地方,需要注意添加判断一下。

    对了,最后再说一点吧,如果你app同时使用了友盟分享(含微信分享)和微信支付 要注意两者的register步骤。要先调用友盟,然后调用微信。避免不必要的错误。

 
 

 

转载于:https://www.cnblogs.com/windsSunShine/p/6879928.html

<think>我们正在讨论支付功能的测试方法。根据引用内容,支付功能测试需要综合运用多种测试方法,并覆盖多个维度。以下是我的回答框架: 1. **测试方法综合运用**:引用[1][3]提到要结合边界值、等价类划分、错误推测、因果图等方法设计测试用例。 2. **测试维度**:引用[3]详细列举了金额、流程、设备、支付接口、容错性、账务处理等维度。 3. **财务安全性**:引用[3]强调“财务无小事”,测试必须严谨。 我将按以下结构组织答案: - 一、核心测试方法(黑盒方法组合运用) - 二、多维度测试覆盖(用表格整理6大维度) - 三、安全与异常测试重点 - 四、自动化测试建议 - 五、支付测试流程图 最后生成3个相关问题。 </think>### 支付功能测试方法详解 #### 一、核心测试方法综合运用[^1][^3] 1. **边界值分析** - 金额边界:测试最小值(如¥0.01)、最大值(如信用卡单笔限额)、超限值(如¥100万) - 字符边界:输入框测试空值、超长文本($L>50$字符)、特殊字符(如`!@#$%`) 2. **等价类划分** | 有效等价类 | 无效等价类 | |------------------|-------------------| | 整数金额(¥100) | 负数金额(¥-10) | | 两位小数(¥9.90)| 三位小数(¥5.555)| | 标准货币(CNY) | 非法货币(AAA) | 3. **错误推测法** - 网络中断时支付重试机制 - 余额不足时处理逻辑($账户余额 < 订单金额$) - 并发支付冲突处理(如双11高并发场景) 4. **因果图分析** ```mermaid graph LR 支付方式选择 -->|选择银行卡| 银行验证 支付方式选择 -->|选择微信| 扫码跳转 银行验证 --> 短信验证码 短信验证码错误 --> 支付失败 ``` #### 二、多维度测试覆盖[^3] | 测试维度 | 测试要点 | 典型案例 | |----------------|-----------------------------------|-----------------------------| | **金额维度** | 正常/最小/最大金额支付 | 1分钱支付验证 | | **流程维度** | 支付中断续付、多订单合并支付 | 支付中切换APP后恢复 | | **设备维度** | PC/手机/平板/POS机适配 | 不同分辨率下的UI兼容性 | | **接口维度** | 银行卡/支付宝/微信/银联接口 | 模拟微信回调超时 | | **容错维度** | 支付失败补单、差错账处理 | 重复支付退款验证 | | **账务维度** | 成功/失败订单对账 | 日终资金流水平衡校验 | #### 三、安全与异常测试重点 1. **安全防护验证** - 支付密码错误次数限制(如$错误次数 \geq 5$则锁定) - 敏感信息加密(卡号展示为`**** **** **** 1234`) - 防SQL注入测试:支付接口传入`' OR 1=1--` 2. **异常场景覆盖** ```python # 伪代码:异常流程测试 def test_payment_exception(): try: initiate_payment() simulate_network_failure() # 模拟网络中断 retry_payment() # 验证重试机制 assert payment_status == "成功" except PaymentException as e: handle_refund() # 验证异常处理流程 ``` 3. **资金安全验证** - 订单金额篡改检测(前端¥100传参时改为¥0.01) - 幂等性测试:重复支付请求仅扣款一次 - 对账差异检测(支付成功但商户未到账) #### 四、自动化测试实施 1. **接口自动化** - 使用Postman验证支付接口: ```json { "order_no": "20240521001", "amount": 99.99, "channel": "alipay" } ``` - 响应断言:`pm.test("Status 200", () => pm.response.to.have.status(200));` 2. **端到端自动化** ```gherkin # BDD场景示例 Scenario: 微信支付全流程 Given 用户选择¥198商品 When 点击微信支付 Then 跳转微信APP And 支付成功返回订单页 ``` > 关键原则:支付测试需遵循**金额零容忍**准则,任何资金异常必须立即阻断发布流程[^3]。建议采用沙箱环境模拟真实支付,避免生产环境资金风险。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值