美文网首页
iOS 拉取微信卡包里的电子发票,超详细

iOS 拉取微信卡包里的电子发票,超详细

作者: 你duck不必呀 | 来源:发表于2020-12-15 18:23 被阅读0次
配图.jpg

微信提供了外部App拉起发票列表的接口。与微信内拉起发票列表接口相似,外部App开发者在用户勾选并点击确认后,可以获得发票的标识数据。微信电子发票详细文档

1 需要一个微信开放平台账号;微信开放平台

2 在微信开放平台上创建一个应用并提交应用通过审核。
审核通过会得到AppID, AppSecret要用这两个凭证来获取access_token,access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。
详细文档

https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

3 接入微信SDK,通过cocoaPods倒入,或者直接拖到工程目录下都可以 微信SDK下载
3.1 导入到工程中

这里只做演示,就直接拖到工程,下载下来的SDK如下:

image.png
拖到工程以后,如果报错library not found for -需要到 Targets -> Build Phases -> Link Binary With Libraries 添加 libWeChatSDK.a,一般新建的工程拖进来会自动添加,老的项目就需要注意替换,如果还报错,可能是中途改了目录或者添加的路径不对,删掉重新拖进来试试?
image.png

3.2 SDK激活

需要当前应用在开放平台注册的appID, universalLink需要开发者在工程里配置。
universalLink是微信返回的你的app,并且带着发票信息的重要参数,没有就不能获取到发票信息
universalLink的配置参考这里

[WXApi registerApp:@"appID" universalLink:@"universalLink"];

拉起微信:

[WXApi sendReq:cardReq completion:^(BOOL success) {
        //do ...
    }]

WXChooseInvoiceReq是微信SDK提供的类型,封装了请求参数,对api_ticket,timeStamp,nonceStrtongg签名后,赋值给cardSign;
如下:

 -(void)popToWeChat{
    
    BOOL isWXApplnstalled = [WXApi isWXAppInstalled];
    if (!isWXApplnstalled) { // 用户没装微信,直接返回。
        return;
    }
    
    WXChooseInvoiceReq *cardReq = [[WXChooseInvoiceReq alloc]init];
    cardReq.appID = WX_APPID;
    cardReq.timeStamp = [[NSDate date] timeIntervalSince1970];
    NSString* timeStamp = [NSString stringWithFormat:@"%u",(unsigned int)cardReq.timeStamp];
    cardReq. nonceStr = @"sfim_invoice";
    //api_ticket 通过 access_token换取
    NSString *cardSign = [self genCardSignWithNonceStr: cardReq.nonceStr andTimeStr:timeStamp andApiTicket:api_ticket];
    cardReq.cardSign = cardSign;
    
    [WXApi sendReq:cardReq completion:^(BOOL success) {
        //do ...
    }];
    
}

签名中用到api_ticket,通过上面access_token 换取(获取access_token上面已经提到过)
api_ticket获取文档

请求URL:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=wx_card
请求方法:GET

签名过程,对需要签名的参数按照ASCII排序,最后拼成字符串并签名如下:

-(NSString *)genCardSignWithNonceStr:(NSString *)nonceStr andTimeStr:(NSString *)timeStamp andApiTicket:(NSString *)ticket{
    
    NSMutableDictionary *cardSignDic = [NSMutableDictionary dictionary];
    [cardSignDic setObject:nonceStr forKey:@"nonceStr"];
    [cardSignDic setObject:timeStamp forKey:@"timestamp"];
    [cardSignDic setObject:ticket forKey:@"api_ticket"];
    [cardSignDic setObject:@"INVOICE" forKey:@"cardType"];
    [cardSignDic setObject:WX_APPID forKey:@"appid"];
    NSMutableString *contentString = [NSMutableString string];
    NSArray *values = [cardSignDic allValues];
    //按字母顺序排序
    NSArray *sortedArray = [values sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    //拼接字符串
    for (NSString *value in sortedArray) {
        [contentString appendFormat:@"%@", value];
    }
    NSString *cardSign = [self sha1:contentString];
    
    return cardSign;
    
}

sha1签名算法:

- (NSString *)sha1:(NSString *)input {
    NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(data.bytes, (unsigned int)data.length, digest);
    NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
    for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++){
        [output appendFormat:@"%02x", digest[I]];
    }
    return output;
}

从微信获取到发票之后系统回掉:

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler

在这个方法里调用微信的handleOpenUniversalLink

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler{
    
    return [WXApi handleOpenUniversalLink:userActivity delegate:self];
}

微信代理:

微信的回掉,加密后的发票信息保存在resp 的cardAry数组中
- (void)onResp:(BaseResp *)resp{
    if ([resp isKindOfClass:[WXChooseInvoiceResp class]]) {
        [self getWxticketInfo:(WXChooseInvoiceResp *)resp];
    }
}

调用微信接口解密:参考电子发票文档

单条获取,批量获取;
示例:

请求:
{
    "card_id": "pjZ8Yt5crPbAouhFqFf6JFgZv4Lc",
    "encrypt_code": "fbdt/fWy1VitQwhbKtSjNeR3BJyfpeJXfZjjGsdCXiM="
}
返回:
{
    "errcode": 0,
    "errmsg": "ok",
    "card_id": "pjZ8Yt5crPbAouhFqFf6JFgZv4Lc",
    "begin_time": 1476068114,
    "end_time": 1476168114,
    "user_card_status": "EXPIRE",
    "openid": "obLatjnG4vRXJvSO8p914rSK8-Vo",
    "type": "广东省增值税普通发票",
    "payee": "测试-收款方",
    "detail": "测试-detail",
    "user_info": {
        "fee": 1100,
        "title": "XX公司",
        "billing_time": 1468322401,
        "billing_no": "hello",
        "billing_code": "world",
            "info": [
                {
                    "name": "绿巨人",
                    "num": 10,
                    "unit": "吨",
                    "price": 4
                }
        ],
        "accept": true,
        "fee_without_tax": 2345,
        "tax": 123,
        "pdf_url": "pdf_url",
        " reimburse_status": "INVOICE_REIMBURSE_INIT",
    }
}

总结:微信的文档说的很详细,但是会有些零散因此写这片文章记录下

相关文章

网友评论

      本文标题:iOS 拉取微信卡包里的电子发票,超详细

      本文链接:https://www.haomeiwen.com/subject/bogigktx.html