微信 支付宝支付 友盟登录分享 统计
概述
详细
一、项目结构与前言
首先看下整体框架
如果我们项目中已经导入了友盟的SDK,那么我们就不必在导入微信 支付宝官方的SDK。
在使用友盟SDK时我们会遇到各种各样的问题,报错,例如:#import <UMSocialCore/UMSocialCore.h> not found #import <AlipaySDK/AlipaySDK.h> not found这一类报错的话,一般都是我们的地址不对,只需要在TARGETS-Build Settings - Header Search Paths里面修改找不到的类的地址就好。
在我们对接微信支付的时候解析XMl文件时报错ARC 文件提前 释放时 我们需要在Buils Phases - Compile Sources 里面的集体的某个控制器或者类的后面添加-fno-objc-arc字段。
支付宝支付存在APP支付和网页支付,微信支付只有App支付,
进行支付功能的集成 我们需要在项目中配置它的一些参数。
我们分享的View可以添加到任何位置,并不局限与下方。
分享的话有微信好友 朋友圈 QQ 空间 微博的分享,为了防止苹果审核被拒,友盟已经为我们做好了显示我们手机安装的可分享的第三方。
#pragma mark - 判断平台是否安装 - (BOOL)gz_UMSocialIsInstall:(UMSocialPlatformType)platformType { return [GZUMSocialData isInstall:platformType]; }
友盟分享也为我们提供了多种分享模式,纯文本 ,带图片文 ,纯图片 ,一般的分享是这种,title、content、缩略图、URL , 文本 + 图片【暂时只对新浪分享有效】 ,音乐 ,视频 ,gif 动图等等,完全可以满足我们的需求。
支付方面的问题绝大多数出现在回调函数这块,我们只要按照每个平台的官方文档进行书写,一般不会出什么大的问题。
二、准备工作
1、集成微信支付首先需要注册(https://open.weixin.qq.com )注册完成后我们选择移动应用,创建移动应用,信息自己填写, 最后我们需要申请支付功能,这个是需要交money的(300/年)成功后我们需要有一个商户帐号与之对接,最后就是协议签署,这样微信支付大功告成。
2、支付宝支付需要用户进蚂蚁金服官网注册帐号,来获取支付功能,同样它和微信一样每年300元的费用。
三、程序设计与实现
首先我们介绍我微信支付,微信公众平台有多种支付方式,我们选择的是App支付,集成微信支付按照微信文档进行下载SDK,
适用于商户在移动端APP中集成微信支付功能。
商户APP调用微信提供的SDK调用微信支付模块,商户APP会跳转到微信中完成支付,支付完后跳回到商户APP内,最后展示支付结果。
步骤1:用户进入商户APP,选择商品下单、确认购买,进入支付环节。商户服务后台生成支付订单,签名后将数据传输到APP端。以微信提供的DEMO为例。
步骤2:用户点击后发起支付操作,进入到微信界面,调起微信支付,出现确认支付界面。
步骤3:用户确认收款方和金额,点击立即支付后出现输入密码界面,可选择零钱或银行卡支付。
现在的微信支付SDK应该是在Xcode6的基础上,
1、项目设置APPID
商户在微信开放平台申请开发APP应用后,微信开放平台会生成APP的唯一标识APPID。在Xcode中打开项目,设置项目属性中的URL Schemes为您的APPID。
我们需要在info-URL Types 中填写商户自己的AppID
要想能i进行支付,我们还需要微信注册我们的APPID
1 2 3 4 5 6 7 8 9 10 11 12 | //微信支付 [WXApi registerApp:GZWX_APP_KEY]; 3、调起支付 商户服务器生成支付订单,先调用【统一下单API】生成预付单,获取到prepay_id后将参数再次签名传输给APP发起支付。以下是调起微信支付的关键代码: PayReq *request = [[[PayReq alloc] init] autorelease]; request.partnerId = @ "10000100" ; request.prepayId= @ "1101000000140415649af9fc314aa427" ; request.package = @ "Sign=WXPay" ; request.nonceStr= @ "a462b76e7436e98e0ed6e13c64b4fd1c" ; request.timeStamp= @ "1397527777" ; request.sign= @ "582282D72DD2B03AD892830965F428CB16E7A256" ; [WXApi sendReq:request]; |
我们需要注意的是,微信支付它的单位是以分来计算的,所以我们集成时,注意下这块!
1 2 3 4 5 6 | - ( NSMutableDictionary *)sendPay_OrderName:(NSString *)ProductName PayPrice:(NSString *)PriductPrice;{ //订单标题,展示给用户 NSString *order_name = ProductName; //订单金额,单位(分) // NSString *order_price = PriductPrice ; NSString *order_price = [NSString stringWithFormat:@ "%d" ,[PriductPrice intValue]]; //1分钱测试 |
对于这块,因为ARC的缘故我们需要在Build Phases - Compile Sources中添加 -fno-objc-arc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 调起微信支付 -( void )ByWeiXinBuy{ [self weXinAplyPayOrderName:@ "刚子支付Demo" PayPrice:@ "1" ]; } #pragma mark--微信支付 -( void )weXinAplyPayOrderName:(NSString *)OrderName PayPrice:(NSString *)PayPrice{ if (![WXApi isWXAppInstalled]) { [self.view gz_showAlertView:@ "温馨提示" message:@ "未检测到客户端,请安装" ]; } else { //创建支付签名对象 payRequsestHandler *req = [payRequsestHandler alloc]; //初始化支付签名对象 [req init:APP_ID mch_id:MCH_ID]; //设置密钥 [req setKey:PARTNER_ID]; //获取到实际调起微信支付的参数后,在app端调起支付 NSMutableDictionary *dict = [req sendPay_OrderName:OrderName PayPrice:PayPrice]; if (dict == nil){ //错误提示 NSString *debug = [req getDebugifo]; [self.view gz_showAlertView:@ "提示信息" message:debug]; } else { [self sendRepweixin:dict]; //提交支付 } } } -( void )sendRepweixin:(NSDictionary *)dict{ NSMutableString *stamp = [dict objectForKey:@ "timestamp" ]; //调起微信支付 PayReq* req = [[PayReq alloc] init]; req.openID = [dict objectForKey:@ "appid" ]; req.partnerId = [dict objectForKey:@ "partnerid" ]; req.prepayId = [dict objectForKey:@ "prepayid" ]; req.nonceStr = [dict objectForKey:@ "noncestr" ]; req.timeStamp = stamp.intValue; req.package = [dict objectForKey:@ "package" ]; req.sign = [dict objectForKey:@ "sign" ]; [WXApi sendReq:req]; } |
2、支付宝支付
首先在蚂蚁金服创建帐号申请分享 支付功能 (300RMB)
集成支付宝支付,将在官网下载的SDK导入到项目中
在Build Phases选项卡的Link Binary With Libraries中,增加以下依赖:
其中,需要注意的是:
-
如果是Xcode 7.0之后的版本,需要添加libc++.tbd、libz.tbd;
-
如果是Xcode 7.0之前的版本,需要添加libc++.dylib、libz.dylib
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | -( void )buyproduct{ //四美坊app商户ID 用户ID 私钥 NSString *pid = @ "2088421263479877" ; NSString *appID = @ "2016092201949956" ; NSString *privateKey = @ "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALhNuoy6DrIF27wxQXT1JarZIhCleLbGZIKi/xLGb0KMP6m9xP17GJ0asqhDqIPQOos2vmwmeA8ast2gQQWzbtaKMyqsrxQgrlTvYomwo3579JwOS29wgpjAWn2YQ9t3YGlECpFtoX3KtyJ7JPhtTcfJqPpHiNFjujmPCU83s9qJAgMBAAECgYAw4y1gttm/Dx7CRK6AP6bGMuJ+V+Y1VVrD7EiMymYo2NrqQ5RFSKm2wqYxTAEfNdTRqKvKNEoUd5iKgT++K2JywugECubbv/2hSzUqsr1VhQ/buzIwSTTPFJHrG2WSL+c8hqgsxk3Fn79vKarRnPdYj7r+7xZ43uwfxx/mzaXnoQJBANtyF6P8vjJLazCwrX+bg7CS447c/38Nsai6CTOr4GyvEzd+sIUkFahTGzk83qBdU4ksMGfGrv7Bwvk5X2c4AcMCQQDXAQ9067qOtGsWXiDgNqDe2+CgNotXwhBOKGlbv3t9xYi89K2u9hqIz3yUWBbbxOaolCJvpFREJV4mmtXQiEHDAkEAr1tijMZg7ivaQhRM8FXDTAx1DyqGeG7m8t+GjuXf9rmIb6YrRJlrPRD8Bicf96HcKRdIrwTTvfvz49f25rKYpQJBAK+OvRlCdlWZ+isMdxm9YYQ30+XeQ89Htdqr4sO4ydQ73Fg2Di/j4my9x0K13wxabeFO/ANfEjOGs6cgHOCmsdMCQQCNyYE6MloO1xaHkFIRuzMjUJB94Wkaip/DzZE5a/vIsm6mk6JcaPDCGAm2yf2xd6f/1y0WViaSLv6jLcdwZCZ8" ; //pid和appID获取失败,提示 if ([pid length] == 0 || [appID length] == 0 || [privateKey length] == 0) { [self.view gz_showAlertView:@ "提示" message:@ "缺少pid或者appID或者私钥。" ]; return ; } /* *生成订单信息及签名 */ Order* order = [Order new ]; //将商品信息赋予AlixPayOrder的成员变liang // NOTE: app_id设置 order.app_id = appID; order.notify_url = @ "http://www.88meichou.com/api/alipay/alipay.php" ; order.biz_content.seller_id = pid ; // NOTE: 支付接口名称 order.method = @ "alipay.trade.app.pay" ; // NOTE: 参数编码格式 order.charset = @ "utf-8" ; // NOTE: 当前时间点 NSDateFormatter* formatter = [NSDateFormatter new ]; [formatter setDateFormat:@ "yyyy-MM-dd HH:mm:ss" ]; order.timestamp = [formatter stringFromDate:[NSDate date]]; // NOTE: 支付版本 order.version = @ "1.0" ; // NOTE: sign_type设置 order.sign_type = @ "RSA" ; // NOTE: 商品数据 order.biz_content = [BizContent new ]; order.biz_content.body = @ "刚子支付Demo" ; order.biz_content.subject = [NSString stringWithFormat:@ "购买%@美豆" ,@ "1" ]; order.biz_content.out_trade_no = order_sn ; // order.biz_content.out_trade_no = [self generateTradeNO]; //订单ID(由商家自行制定) order.biz_content.timeout_express = @ "30m" ; //超时时间设置 // order.biz_content.total_amount = [NSString stringWithFormat:@"%.2f",0.01]; order.biz_content.total_amount = [NSString stringWithFormat:@ "%@" , @ "0.1" ]; //商品价格 //将商品信息拼接成字符串 NSString *orderInfo = [order orderInfoEncoded:NO]; NSString *orderInfoEncoded = [order orderInfoEncoded:YES]; // NSLog(@"orderSpec = %@",orderInfo); // NOTE: 获取私钥并将商户信息签名,外部商户的加签过程请务必放在服务端,防止公私钥数据泄露; // 需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode id<DataSigner> signer = CreateRSADataSigner(privateKey); NSString *signedString = [signer signString:orderInfo]; // NOTE: 如果加签成功,则继续执行支付 if (signedString != nil) { //应用注册scheme,在AliSDKDemo-Info.plist定义URL types NSString *appScheme = @ "ap2016092201949956" ; // NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式 NSString *orderString = [NSString stringWithFormat:@ "%@&sign=%@" , orderInfoEncoded, signedString]; // NSLog(@"~~~~~~~~~~~!!~~~~~~~~~~%@",orderString);签名 // NOTE: 调用支付结果开始支付 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) { // NSLog(@"reslut = %@",resultDic); NSString * str = resultDic[@ "memo" ]; // NSLog(@"~~~~~!!~~%@",str); NSString *result = resultDic[@ "resultStatus" ]; if ([result isEqualToString:@ "9000" ]) { #pragma 回掉函数 } }]; } } |
回调的话我们在最后给出 ,因为他们可以写在一个方法中
3、友盟分享 统计
注册友盟帐号,
1 2 3 4 5 | UMConfigInstance.appKey = GZUmengAppkey ; UMConfigInstance.channelId = @ "App Store" ; [MobClick startWithConfigure:UMConfigInstance];开启统计 |
1 2 3 4 5 6 | NSString *appVersion = [NSString stringWithFormat:@ "2、获取APP的版本号:%@" , [[[NSBundle mainBundle] infoDictionary] objectForKey:@ "CFBundleVersion" ]]; [MobClick setAppVersion:appVersion]; //对统计数据进行加密 [MobClick setEncryptEnabled:YES]; 分享的话 我做了一个分类,这样显得AppDelegate里面不是那么的乱。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | #pragma mark - ***** 友盟分享 - ( void )addShareOpt { GZShareManage *manager = [GZShareManage shareManage]; [manager gz_setupShareConfig]; #import <Foundation/Foundation.h> #import <UMSocialCore/UMSocialCore.h> #import <MessageUI/MessageUI.h> @protocol GZShareManageDelegate <NSObject> /*! 返回用户信息 */ - ( void )getUserData:(NSDictionary *)backUserData; @end typedef NS_ENUM(NSUInteger, GZUM_SHARE_TYPE) { /*! 纯文本 */ GZUM_SHARE_TYPE_TEXT = 1, /*! 纯图片:本地图片 */ GZUM_SHARE_TYPE_IMAGE, /*! 纯图片:网络图片 URL */ GZUM_SHARE_TYPE_IMAGE_URL, /*! 网页:一般的分享是这种,title、content、缩略图、URL */ GZUM_SHARE_TYPE_WEB_LINK, /*! 文本 + 图片 【暂时只对新浪分享有效】 */ GZUM_SHARE_TYPE_TEXT_IMAGE, /*! 音乐 */ GZUM_SHARE_TYPE_MUSIC_LINK, /*! 视频 */ GZUM_SHARE_TYPE_VIDEO_LINK, /*! gif 动图【注:目前只有微信支持动图分享,其他平台均不支持】*/ GZUM_SHARE_TYPE_GIF, /*! 文件【注:目前只有微信支持动图分享,其他平台均不支持】 */ GZUM_SHARE_TYPE_FILE }; /*! 登录后返回的数据回调 */ typedef void (^GZUMLoginCallback)(UMSocialUserInfoResponse *response); @interface GZShareManage : NSObject /*! 登录后返回的数据回调 */ @property (nonatomic, copy) GZUMLoginCallback loginCallback; /*! 分享标题 */ @property (nonatomic, strong) NSString *shareTitle; /*! 分享摘要 */ @property (nonatomic, strong) NSString *shareText; /*! 分享大图【本地 imageName】】 */ @property (nonatomic, strong) NSString *shareBigImage; /*! 分享 URL 图片 */ @property (nonatomic, strong) NSString *shareImageUrl; /*! 分享网页 */ @property (nonatomic, strong) NSString *shareWebpageUrl; /*! 分享音乐 URL【必传】 */ @property (nonatomic, strong) NSString *shareMusicUrl; /*! 分享音乐 DataUrl */ @property (nonatomic, strong) NSString *shareMusicDataUrl; /*! 分享视频 URL */ @property (nonatomic, strong) NSString *shareVideoUrl; /*! 分享 gif 动图路径 */ @property (nonatomic, strong) NSString *shareGifFilePath; /*! 分享文件路径 */ @property (nonatomic, strong) NSString *shareFileFilePath; /*! 分享文件后缀类型 */ @property (nonatomic, strong) NSString *shareFileFileExtension; /*! 授权回调 */ @property (nonatomic, strong) void (^authOpFinish)(); @property (nonatomic, strong) id<GZShareManageDelegate> delegate; /*! 图片数组 */ @property (nonatomic, strong) NSArray *shareImageArray; /*! 分享的名字数组(要和图片名字一一对应哦!) */ @property (nonatomic, strong) NSArray *shareNameArray; //// 友盟分享SDK的各种key设置【pod下来后只需调用下即可】 //@property (nonatomic, strong) NSString *GZShareUmengAppkey; //@property (nonatomic, strong) NSString *GZShareSinaAppKey; //@property (nonatomic, strong) NSString *GZShareWX_APP_KEY; //@property (nonatomic, strong) NSString *GZShareWX_APP_SECRET; //@property (nonatomic, strong) NSString *GZSharekQQKey; //@property (nonatomic, strong) NSString *GZSharekQQAppID; + (GZShareManage *)shareManage; /*! * 友盟分享设置 */ - ( void )gz_setupShareConfig; /*! * 判断平台是否安装 * * @param platformType 平台类型 @see UMSocialPlatformType * * @return YES 代表安装,NO 代表未安装 * @note 在判断QQ空间的App的时候,QQApi判断会出问题 */ - ( BOOL )gz_UMSocialIsInstall:(UMSocialPlatformType)platformType; #pragma mark - 友盟分享 version 2.1 /*! 微信分享 */ #pragma mark 微信分享 version 2.1 - ( void )gz_wechatShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark 微信朋友圈分享 version 2.1 - ( void )gz_wechatTimeLineShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark 新浪微博分享 version 2.1 - ( void )gz_sinaShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark qq分享 version 2.1 - ( void )gz_qqShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark Qzone分享 version 2.1 - ( void )gz_qZoneShareWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark - 友盟分享 /*! * 刚子友盟分享列表 version 2.1 * * @param shareType 分享类型,具体看枚举 * @param viewController viewController */ - ( void )gz_shareListWithShareType:(GZUM_SHARE_TYPE)shareType viewController:(UIViewController *)viewController; #pragma mark - 友盟登录 #pragma mark 微信登录 version 2.1 - ( void )gz_wechatLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:( BOOL )isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark QQ登录 version 2.1 - ( void )gz_qqLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:( BOOL )isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark QQZone登录 version 2.1 - ( void )gz_qZoneLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:( BOOL )isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark 微博登录 version 2.1 - ( void )gz_sinaLoginWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:( BOOL )isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark - 友盟登录列表 version 2.1 /*! * 友盟登录列表 version 2.1 * * @param viewController viewController description * @param isGetAuthWithUserInfo YES:授权并获取用户信息(获取uid、access token及用户名等) NO:只需获取第三方平台token和uid,不获取用户名等用户信息,可以调用以下接口 * @param loginCallback 登录后返回的数据回调 */ - ( void )gz_loginListWithViewController:(UIViewController *)viewController isGetAuthWithUserInfo:( BOOL )isGetAuthWithUserInfo loginCallback:(GZUMLoginCallback)loginCallback; #pragma mark - 清除授权 - ( void )gz_cancelAuthWithPlatformType:(UMSocialPlatformType)platformType; @end } |
以下为微信支付宝支付成功回调 友盟分享回调!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | // NOTE: 9.0以后使用新API接口 - ( BOOL )application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options { if ([url.host isEqualToString:@ "safepay" ]) { // 支付跳转支付宝钱包进行支付,处理支付结果 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { // NSLog(@"result = %@",resultDic); [[NSNotificationCenter defaultCenter]postNotificationName:@ "alipayResult" object:[resultDic objectForKey:@ "resultStatus" ]]; }]; return YES ; } else if ([url.host isEqualToString:@ "pay" ]) { return [WXApi handleOpenURL:url delegate:self]; } else { return [[UMSocialManager defaultManager] handleOpenURL:url]; } } /** 这里处理新浪微博SSO授权之后跳转回来,和微信分享完成之后跳转回来 */ - ( BOOL )application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { if ([url.host isEqualToString:@ "safepay" ]) { // 支付跳转支付宝钱包进行支付,处理支付结果 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { // NSLog(@"result = %@",resultDic); [[NSNotificationCenter defaultCenter]postNotificationName:@ "alipayResult" object:[resultDic objectForKey:@ "resultStatus" ]]; }]; return YES ; } else if ([url.host isEqualToString:@ "pay" ]) { return [WXApi handleOpenURL:url delegate:self]; } else { return [[UMSocialManager defaultManager] handleOpenURL:url]; } } - ( BOOL )application:(UIApplication *)application handleOpenURL:(NSURL *)url { if ([url.host isEqualToString:@ "safepay" ]) { // 支付跳转支付宝钱包进行支付,处理支付结果 [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { [[NSNotificationCenter defaultCenter]postNotificationName:@ "alipayResult" object:[resultDic objectForKey:@ "resultStatus" ]]; }]; return YES ; } else if ([url.host isEqualToString:@ "pay" ]) { return [WXApi handleOpenURL:url delegate:self]; } else { return [[UMSocialManager defaultManager] handleOpenURL:url]; } } //微信支付结果 - ( void ) onResp:(BaseResp*)resp { [[NSNotificationCenter defaultCenter] postNotificationName:@ "weixinPay" object:resp]; |
四、运行效果
效果图如下:
由于项目过大不能整体上传的平台 ,所以一些包文件请移步百度网盘进行下载,地址上面有!
注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?