如何玩转微信支付宝提现功能开发功能的原理和开发

iOS(120)
需要下面第三方支持
备注:JSONKit框架是基于MRC的,如果工程开发环境是ARC的话,请在编译时设定 编译参数 -fno-objc-arc
1、首先到微信开放平台上,申请app及与T进行签约、认证
https://open./&
&* &微信开放平台申请得到的 appid, 需要同时添加在info.plist文件中URL schema,用于完成时,回调到app
#define WXAppId @&wxd930ea5d5a258f4f&
#define WXAppSecret @&db426aa0dcac7b&
以上两个参数用于获取access_token
access_token是APP的全局唯一票据,APP调用各接口时都需使用access_token。正常情况下access_token有效期为7200秒,重复获取将导致上次获取的access_token失效。
APP可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在开放平台后台获得。注意调用接口时需使用https协议。
接口调用请求说明
https://api./cgi-
bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
正常情况下,微信会返回下述JSON数据包给开发者:
{&access_token&:&ACCESS_TOKEN&,&expires_in&:7200}
参数说明:
appkey 、partnerId、partnerKey、paySignKey
appkey:appkey就是Paysignkey,申请支付通过之后由下发。
partnerId:财付通商户身份的标识。审核通过后,在财付通发送的邮件中查看。
partnerKey:财付通商户权限密钥Key。审核通过后,在财付通发送的邮件中查看。
paySignKey:除了支付请求需要用到paySignKey,公众平台接口API的权限获取所需密钥Key,在使用所有公众平台API时,都需要先用它去换取access_token,然后再进行调用。审核通过后,在微信发送的邮件中查看。
2、代码实现
@interface SkyAppDelegate : UIResponder &UIApplicationDelegate, WXApiDelegate& //在appDelegate方法中实现WXApiDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
& & // 向微信终端注册appID
& & [WXApi registerApp:WXAppId withDescription:@&weixin demo&];
&/*! @brief WXApi的成员函数,在微信终端程序中注册第三方应用。
&* 需要在每次启动第三方应用程序时调用。第一次调用后,会在微信的可用应用列表中出现。
&* @param appid 微信开发者ID
&* @param appdesc 应用附加信息,长度不超过1024字节
&* @return 成功返回YES,失败返回NO。
& & return YES;
//用于完成支付后的程序回调,
- (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
& & NSLog(@&%@&,url);//跳转到URL schema中配置的地址
& & return [WXApi handleOpenURL:url delegate:self];
//收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
- (void)onResp:(BaseResp *)resp
& & if ([resp isKindOfClass:[PayResp class]])
& & & & PayResp *response = (PayResp *)
& & & & NSString *strTitle = [NSString stringWithFormat:@&支付结果&];
& & & & NSString *strMsg = [NSString stringWithFormat:@&errcode:%d&, response.errCode];
& & & & UIAlertView *alert = [[UIAlertView alloc] initWithTitle:strTitle
& & & & & & & & & & & & & & & & & & & & & & & & & & & & message:strMsg
& & & & & & & & & & & & & & & & & & & & & & & & & & & &delegate:self
& & & & & & & & & & & & & & & & & & & & & & & cancelButtonTitle:@&OK&
& & & & & & & & & & & & & & & & & & & & & & & otherButtonTitles:nil, nil];
& & & & [alert show];
& & & & switch (response.errCode) {
& & & & & & case WXSuccess: {
& & & & & & & & NSNotification *notification = [NSNotification notificationWithName:ORDER_PAY_NOTIFICATION object:@&success&];
& & & & & & & & [[NSNotificationCenter defaultCenter] postNotification:notification];
& & & & & & & &
& & & & & & }
& & & & & & & &&
& & & & & & default: {
& & & & & & & & NSNotification *notification = [NSNotification notificationWithName:ORDER_PAY_NOTIFICATION object:@&fail&];
& & & & & & & & [[NSNotificationCenter defaultCenter] postNotification:notification];
& & & & & & & &
& & & & & & }
为了保证发送请求的方便,自己封装了两个工具类
typedef void (^BKHttpCallback)(BOOL isSuccessed, NSDictionary *result);
&* &GET方法请求数据
&* &@param url & & 请求的URL
&* &@param params &请求参数
&* &@param (BOOL isSuccessed, Result *result))callback &回调方法
+ (void)doGetWithUrl:(NSString *)url path:(NSString *)path params:(NSDictionary *)params callback:(BKHttpCallback)
&* &请求WebService数据
&* &@param baseUrl &请求的基础URL
&* &@param params & 请求参数
&* &@param (BOOL isSuccessed, Result *result))callback &回调方法
+ (void)doPostWithUrl:(NSString *)url path:(NSString *)path params:(NSDictionary *)params callback:(BKHttpCallback)
&* &Get方法请求图片
&* &@param url & & &图片URL
&* &@param (BOOL isSuccessed, Result *result))callback &回调方法
+ (void)getImageWithUrl:(NSString *)url callback:(BKHttpCallback)
+ (void)doGetWithUrl:(NSString *)url path:(NSString *)path params:(NSDictionary *)params callback:(BKHttpCallback) callback
& & AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:url]];
& & [httpClient getPath:path
& & & & & & &parameters:params
& & & & & & & & success:^(AFHTTPRequestOperation *operation, id responseObject){
& & & & & & & & & &&
& & & & & & & & & & NSString *responseJson = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
& & & & & & & & & & if (responseJson)
& & & & & & & & & & {
& & & & & & & & & & & & NSDictionary *result = [responseJson objectFromJSONString];
& & & & & & & & & & & & callback(YES, result);
& & & & & & & & & & }
& & & & & & & & & & else
& & & & & & & & & & {
& & & & & & & & & & & & callback(NO, nil);
& & & & & & & & & & }
& & & & & & & & }
& & & & & & & & failure:^(AFHTTPRequestOperation *operation, NSError *error){
& & & & & & & & & & callback(NO, nil);
& & & & & & & & }];
+ (void)doPostWithUrl:(NSString *)url path:(NSString *)path params:(NSDictionary *)params callback:(BKHttpCallback)callback
& & AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:url]];
& & httpClient.parameterEncoding = AFJSONParameterE
& & [httpClient postPath:path
& & & & & & & parameters:params
& & & & & & & & &success:^(AFHTTPRequestOperation *operation, id responseObject){
& & & & & & & & & &&
& & & & & & & & & & &NSString *responseJson = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
& & & & & & & & & & &if (responseJson)
& & & & & & & & & & &{
& & & & & & & & & & & & &NSDictionary *result = [responseJson objectFromJSONString];
& & & & & & & & & & & & &callback(YES, result);
& & & & & & & & & & &}
& & & & & & & & & & &else
& & & & & & & & & & &{
& & & & & & & & & & & & &callback(NO, nil);
& & & & & & & & & & &}
& & & & & & & & &}
& & & & & & & & &failure:^(AFHTTPRequestOperation *operation, NSError *error){
& & & & & & & & & & callback(NO, nil);
& & & & & & & & }];
+ (void)getImageWithUrl:(NSString *)url callback:(BKHttpCallback)callback
& & NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
& & AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:request];
& & [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
& & & & UIImage *image = responseO
& & & & NSDictionary *result = @{@&image&:image};
& & & & callback(YES, result);
& & } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
& & & & callback(NO, nil);
& & [requestOperation start];
2、MD5加密
+ (NSString *)md5:(NSString *)
+ (NSString *)sha1:(NSString *)
+ (NSString *)getIPAddress:(BOOL)preferIPv4;
+ (NSDictionary *)getIPA
#define IOS_CELLULAR & &@&pdp_ip0&
#define IOS_WIFI & & & &@&en0&
#define IP_ADDR_IPv4 & &@&ipv4&
#define IP_ADDR_IPv6 & &@&ipv6&
@implementation CommonUtil
+ (NSString *)md5:(NSString *)input
& & const char *cStr = [input UTF8String];
& & unsigned char digest[16];
& & CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
& & NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
& & for(int i = 0; i & CC_MD5_DIGEST_LENGTH; i++)
& & & & [output appendFormat:@&%02x&, digest[i]];
& & return &
+ (NSString *)sha1:(NSString *)input
& & const char *ptr = [input UTF8String];
& & int i =0;
& & int len = strlen(ptr);
& & Byte byteArray[len];
& & while (i!=len)
& & & & unsigned eachChar = *(ptr + i);
& & & & unsigned low8Bits = eachChar & 0xFF;
& & & & byteArray[i] = low8B
& & & & i++;
& & unsigned char digest[CC_SHA1_DIGEST_LENGTH];
& & CC_SHA1(byteArray, len, digest);
& & NSMutableString *hex = [NSMutableString string];
& & for (int i=0; i&20; i++)
& & & & [hex appendFormat:@&%02x&, digest[i]];
& & NSString *immutableHex = [NSString stringWithString:hex];
& & return immutableH
+ (NSString *)getIPAddress:(BOOL)preferIPv4
& & NSArray *searchArray = preferIPv4 ?
& & @[ IOS_WIFI @&/& IP_ADDR_IPv4, IOS_WIFI @&/& IP_ADDR_IPv6, IOS_CELLULAR @&/& IP_ADDR_IPv4, IOS_CELLULAR @&/& IP_ADDR_IPv6 ] :
& & @[ IOS_WIFI @&/& IP_ADDR_IPv6, IOS_WIFI @&/& IP_ADDR_IPv4, IOS_CELLULAR @&/& IP_ADDR_IPv6, IOS_CELLULAR @&/& IP_ADDR_IPv4 ] ;
& & NSDictionary *addresses = [self getIPAddresses];
& & //NSLog(@&addresses: %@&, addresses);
& & __block NSString *
& & [searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
& & & & &address = addresses[key];
& & & & &if(address) *stop = YES;
& & return address ? address : @&0.0.0.0&;
+ (NSDictionary *)getIPAddresses
& & NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
& & // retrieve the current interfaces - returns 0 on success
& & struct ifaddrs *
& & if(!getifaddrs(&interfaces)) {
& & & & // Loop through linked list of interfaces
& & & & struct ifaddrs *
& & & & for(interface= interface=interface-&ifa_next) {
& & & & & & if(!(interface-&ifa_flags & IFF_UP) || (interface-&ifa_flags & IFF_LOOPBACK)) {
& & & & & & & & // deeply nested code harder to read
& & & & & & }
& & & & & & const struct sockaddr_in *addr = (const struct sockaddr_in*)interface-&ifa_
& & & & & & if(addr && (addr-&sin_family==AF_INET || addr-&sin_family==AF_INET6)) {
& & & & & & & & NSString *name = [NSString stringWithUTF8String:interface-&ifa_name];
& & & & & & & & char addrBuf[INET6_ADDRSTRLEN];
& & & & & & & & if(inet_ntop(addr-&sin_family, &addr-&sin_addr, addrBuf, sizeof(addrBuf))) {
& & & & & & & & & & NSString *key = [NSString stringWithFormat:@&%@/%@&, name, addr-&sin_family == AF_INET ? IP_ADDR_IPv4 : IP_ADDR_IPv6];
& & & & & & & & & & addresses[key] = [NSString stringWithUTF8String:addrBuf];
& & & & & & & & }
& & & & & & }
& & & & // Free memory
& & & & freeifaddrs(interfaces);
& & // The dictionary keys have the form &interface& &/& &ipv4 or ipv6&
& & return [addresses count] ? addresses :
主体代码:
#define BASE_URL @&https://api.&
@interfaceSkyViewController ()
@property (nonatomic, copy) NSString *timeS
@property (nonatomic, copy) NSString *nonceS
@property (nonatomic, copy) NSString *traceId;
@implementation SkyViewController
- (void)viewDidLoad
& & [super viewDidLoad];
& & [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getOrderPayResult:) name:ORDER_PAY_NOTIFICATION object:nil];//监听一个通知
- (void)dealloc
& & [[NSNotificationCenter defaultCenter]removeObserver:self];//移除通知
- (void)didReceiveMemoryWarning
& & [super didReceiveMemoryWarning];
& & // Dispose of any resources that can be recreated.
- (IBAction)pay:(id)sender
& & [self getAccessToken];//获取access_token
#pragma mark - 主体流程
// 获取token
- (void)getAccessToken
& & NSString *tokenUrl = @&cgi-bin/token&;
& & NSDictionary *param = @{@&grant_type&:@&client_credential&, @&appid&:WXAppId, @&secret&:WXAppSecret};
& & [HttpUtil doGetWithUrl:BASE_URL
& & & & & & & & & & & path:tokenUrl
& & & & & & & & & & params:param
& & & & & & & & & callback:^(BOOL isSuccessed, NSDictionary *result){
& & & & & & & & & & &&
& & & & & & & & & & & NSString *accessToken = result[AccessTokenKey];
& & & & & & & & & & & [self getPrepayId:accessToken];
& & & & & & & & & }];
// 生成预支付订单
- (void)getPrepayId:(NSString *)accessToken
& & NSString *prepayIdUrl = [NSString stringWithFormat:@&pay/genprepay?access_token=%@&, accessToken];
& & // 拼接详细的订单数据
& & NSDictionary *postDict = [self getProductArgs];
& & [HttpUtil doPostWithUrl:BASE_URL
& & & & & & & & & & & &path:prepayIdUrl
& & & & & & & & & & &params:postDict
& & & & & & & & & &callback:^(BOOL isSuccessed, NSDictionary *result){
& & & & & & & & & & & &
& & & & & & & & & & & &NSString *prePayId = result[PrePayIdKey];
& & & & & & & & & & & &
& & & & & & & & & & & &// 获取预支付订单id,调用微信支付sdk
& & & & & & & & & & & &if (prePayId)
& & & & & & & & & & & &{
& & & & & & & & & & & & & &NSLog(@&--- PrePayId: %@&, prePayId);
& & & & & & & & & & & & & &
& & & & & & & & & & & & & &// 调起微信支付
& & & & & & & & & & & & & &PayReq *request & = [[PayReq alloc] init];
& & & & & & & & & & & & & &request.partnerId = WXPartnerId;
& & & & & & & & & & & & & &request.prepayId &= prePayId;
& & & & & & & & & & & & & &request.package & = @&Sign=WXPay&;
& & & & & & & & & & & & & &request.nonceStr &= self.nonceS
& & & & & & & & & & & & & &request.timeStamp = [self.timeStamp intValue];
& & & & & & & & & & & & & &
& & & & & & & & & & & & & &// 构造参数列表
& & & & & & & & & & & & & &NSMutableDictionary *params = [NSMutableDictionary dictionary];
& & & & & & & & & & & & & &[params setObject:WXAppId forKey:@&appid&];
& & & & & & & & & & & & & &[params setObject:WXAppKey forKey:@&appkey&];
& & & & & & & & & & & & & &[params setObject:request.nonceStr forKey:@&noncestr&];
& & & & & & & & & & & & & &[params setObject:request.package forKey:@&package&];
& & & & & & & & & & & & & &[params setObject:request.partnerId forKey:@&partnerid&];
& & & & & & & & & & & & & &[params setObject:request.prepayId forKey:@&prepayid&];
& & & & & & & & & & & & & &[params setObject:self.timeStamp forKey:@&timestamp&];
& & & & & & & & & & & & & &request.sign = [self genSign:params];
& & & & & & & & & & & & & &
& & & & & & & & & & & & & &// 在支付之前,如果应用没有注册到微信,应该先调用 [WXApi registerApp:appId] 将应用注册到微信
& & & & & & & & & & & & & &[WXApi safeSendReq:request];//发送一个安全请求
& & & & & & & & & & & &}
& & & & & & & & & &}];
#pragma mark - 生成各种参数
// 获取时间戳
- (NSString *)genTimeStamp
& & return [NSString stringWithFormat:@&%.0f&, [[NSDate date] timeIntervalSince1970]];
&* &获取32位内的随机串, 防重发
&* &注意:商户内部的订单号,32个字符内、可包含字母,确保在商户系统唯一
- (NSString *)genNonceStr
& & return [CommonUtil md5:[NSString stringWithFormat:@&%d&, arc4random() % 10000]];
&* &获取商家对用户的唯一标识
&* &traceId 由开发者自定义,可用于订单的查询与跟踪,建议根据支付用户信息生成此id
&* &建议 traceid 字段包含用户信息及订单信息,方便后续对订单状态的查询和跟踪
- (NSString *)genTraceId
& & return [NSString stringWithFormat:@&crestxu_%@&, [self genTimeStamp]];
- (NSString *)genOutTradNo
& & return [CommonUtil md5:[NSString stringWithFormat:@&%d&, arc4random() % 10000]];
// 订单详情
- (NSString *)genPackage
& & // 构造订单参数列表
& & NSMutableDictionary *params = [NSMutableDictionary dictionary];
& & [params setObject:@&WX& forKey:@&bank_type&];
& & [params setObject:@&千足金箍棒& forKey:@&body&];
& & [params setObject:@&1& forKey:@&fee_type&];
& & [params setObject:@&UTF-8& forKey:@&input_charset&];
& & [params setObject:@&& forKey:@&notify_url&];
& & [params setObject:[self genOutTradNo] forKey:@&out_trade_no&];
& & [params setObject:WXPartnerId forKey:@&partner&];
& & [params setObject:[CommonUtil getIPAddress:YES] forKey:@&spbill_create_ip&];
& & [params setObject:@&1& forKey:@&total_fee&]; & &// 1 == ?0.01
& & NSArray *keys = [params allKeys];
& & NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
& & & & return [obj1 compare:obj2 options:NSNumericSearch];
& & // 生成 packageSign
& & NSMutableString *package = [NSMutableString string];
& & for (NSString *key in sortedKeys) {
& & & & [package appendString:key];
& & & & [package appendString:@&=&];
& & & & [package appendString:[params objectForKey:key]];
& & & & [package appendString:@&&&];
& & [package appendString:@&key=&];
& & [package appendString:WXPartnerKey]; // 注意:不能hardcode在客户端,建议genPackage这个过程都由服务器端完成
& & // 进行md5摘要前,params内容为原始内容,未经过url encode处理
& & NSString *packageSign = [[CommonUtil md5:[package copy]] uppercaseString];
& & package =
& & // 生成 packageParamsString
& & NSString *value =
& & package = [NSMutableString string];
& & for (NSString *key in sortedKeys)
& & & & [package appendString:key];
& & & & [package appendString:@&=&];
& & & & value = [params objectForKey:key];
& & & & // 对所有键值对中的 value 进行 urlencode 转码
& & & & value = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)value, nil, (CFStringRef)@&!*'&=();:@+$,/?%#[]&, kCFStringEncodingUTF8));
& & & & [package appendString:value];
& & & & [package appendString:@&&&];
& & NSString *packageParamsString = [package substringWithRange:NSMakeRange(0, package.length - 1)];
& & NSString *result = [NSString stringWithFormat:@&%@&sign=%@&, packageParamsString, packageSign];
& & NSLog(@&--- Package: %@&, result);
- (NSString *)genSign:(NSDictionary *)signParams
& & // 排序
& & NSArray *keys = [signParams allKeys];
& & NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
& & & & return [obj1 compare:obj2 options:NSNumericSearch];
& & // 生成
& & NSMutableString *sign = [NSMutableString string];
& & for (NSString *key in sortedKeys) {
& & & & [sign appendString:key];
& & & & [sign appendString:@&=&];
& & & & [sign appendString:[signParams objectForKey:key]];
& & & & [sign appendString:@&&&];
& & NSString *signString = [[sign copy] substringWithRange:NSMakeRange(0, sign.length - 1)];
& & NSString *result = [CommonUtil sha1:signString];
& & NSLog(@&--- Gen sign: %@&, result);
// 构造订单参数列表
- (NSDictionary *)getProductArgs
& & self.timeStamp = [self genTimeStamp]; & // 获取时间戳
& & self.nonceStr = [self genNonceStr]; & & // 获取32位内的随机串, 防重发
& & self.traceId = [self genTraceId]; & & & // 获取商家对用户的唯一标识
& & NSMutableDictionary *params = [NSMutableDictionary dictionary];
& & [params setObject:WXAppId forKey:@&appid&];
& & [params setObject:WXAppKey forKey:@&appkey&];
& & [params setObject:self.timeStamp forKey:@&noncestr&];
& & [params setObject:self.timeStamp forKey:@&timestamp&];
& & [params setObject:self.traceId forKey:@&traceid&];
& & [params setObject:[self genPackage] forKey:@&package&];
& & [params setObject:[self genSign:params] forKey:@&app_signature&];
& & [params setObject:@&sha1& forKey:@&sign_method&];
#pragma mark - 支付结果
- (void)getOrderPayResult:(NSNotification *)notification
& & if ([notification.object isEqualToString:@&success&])
& & & & NSLog(@&success: 支付成功&);
& & & & NSLog(@&fail: 支付失败&);
这只是一个简单的使用,里面没有用到数据模型,在使用过程中,里面的有些参数要转成数据模型。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:55192次
积分:1644
积分:1644
排名:第18588名
原创:96篇
转载:44篇
(4)(2)(11)(13)(14)(3)(8)(44)(14)(31)iOS微信支付步骤以及出现的问题总结(二) - 简书 - 推酷
iOS微信支付步骤以及出现的问题总结(二) - 简书
前提是已经创建完应用了在微信的官网上。根据上一篇的微信获得支付能力的步骤,这一篇主要制作微信支付的demo。上一篇网址
往往回忆就是痛苦的因为记不住曾经的经历,还是喜欢简单粗暴。
1.微信支付的demo与SDK。
2.下载完之后,里面有好多的没用的文件,包括登录,分享,等等。(看到这里好恶心,为啥不单独做一个demo呢,哎,还能不能愉快的玩耍了)。
如下 的文件夹目录的内容:
3.创建一个wxDemo工程。
4.查看微信的官方文档。
5.因为现在 的工程是iOS9 ,所以需要配置网址与白名单。
配置网址与白名单
6.改变bitcode设置为NO。
改变bitcode为NO
7.添加URL Types,如下。
添加URL Schemes
8.添加微信SDK到wxDemo里面。
9.添加框架,用来安装应用。
。需要添加以下库:
SystemConfiguration.framework,
libz.dylib,
libsqlite3.0.dylib,
libc++.dylib
添加依赖库
10.在Appdelegate.m里面添加如下代码:
//注册微信支付
[WXApi & & & registerApp:@&wxXXXXXXXXXX&]; 此时运行编译,快捷键commd+b 运行程序会出现以下错误,以下是错误的信息:
Undefined symbols for architecture x86_64:
&_OBJC_CLASS_$_CTTelephonyNetworkInfo&, referenced from:
objc-class-ref in libWeChatSDK.a(MTAHelper.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
错误的图片:
错误信息的展示
11.修改错误操作,由于缺少一个依赖库:添加一个CoreTelephony.frame 依赖库,就可以解决了。
添加依赖库
12.根据微信里面的demo,添加需要的代码。以下是文件目录的一些解释:里面主要的方法就是支付的网络请求以及调用微信客户端的代码。
13.添加一个按钮的方法,实现支付。
说明:支付目前来说有两种实现方式,一种是本地的app直接实现跳转进行支付;另一种方式是通过后台服务器进行网络请求。下面的这一种是通过服务器进行支付的跳转。
- (void)WXPay {
NSString*urlString=@&http://wxpay./pub_v2/app/app_pay.php?plat=ios&;
//解析服务端返回json数据
//加载一个NSURL对象
NSURLRequest*request = [NSURLRequestrequestWithURL:[NSURLURLWithString:urlString]];
//将请求的url数据放到NSData对象中
NSData*response = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:nilerror:nil];
if(response !=nil) {
NSMutableDictionary*dict =NULL;
//IOS5自带解析类NSJSONSerialization从response中解析出数据放到字典中
dict = [NSJSONSerializationJSONObjectWithData:responseoptions:NSJSONReadingMutableLeaveserror:&error];
NSLog(@&********url:%@&,urlString);
if(dict !=nil){
NSMutableString*retcode = [dictobjectForKey:@&retcode&];
if(retcode.intValue==0){
NSMutableString*stamp= [dictobjectForKey:@&timestamp&];
//调起微信支付 &
//注意:此处的key一定要与demo中的key的字符一致,一个也不能少,一个也不能错。
PayReq* req= [[PayReqalloc]init];
req.partnerId= [dictobjectForKey:@&partnerid&];
req.prepayId= [dictobjectForKey:@&prepayid&];
req.nonceStr= [dictobjectForKey:@&noncestr&];
req.timeStamp= stamp.intV
req.package= [dictobjectForKey:@&package&];
req.sign= [dictobjectForKey:@&sign&];
[WXApisendReq:req];
//日志输出
NSLog(@&appid=%@\npartid=%@\nprepayid=%@\nnoncestr=%@\ntimestamp=%ld\npackage=%@\nsign=%@&,[dictobjectForKey:@&appid&],req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign);
NSLog(@&%@&,[dictobjectForKey:@&retmsg&]);
NSLog(@&服务器返回错误,未获取json对象&);
NSLog(@&服务器返回错误&);
14.在完成此处之后,点击支付按钮会出现下面的问题:
在跳转到支付界面之后,仅仅会出现一个“确定”的白色按钮。如下图:
支付出现问题
通过查找信息,是由于配置的参数问题。因此我们不用服务器端进行网络请求直接用自己生成这些参数,然后就可以实现支付功能了。
15.下面是获取参数的解释。
参数解释:
partnerId:& 商家向财付通申请的商家id(就是自己的id,也就是在你申请开发者资质认证之后,有一个商户平台,这个平台对应的id,就是你自己的id。好像还没有说明白。)
获取方式:
打开链接,直接将微信发送给你的邮件里面的内容登陆商户平台,就找到了partnerid了。
prepayId:& 预支付订单(需要向微信服务器提交申请后返回的一个支付交易ID)
获取方式:
这个一般情况下是服务器端已经申请好的,客户端直接调用。
a、微信的服务端返回的参数的说明:
。(看着很乱,可是呢,还是太乱)
b、还要生成一个签名,这个官方文档也是写了。
(虽然看着很简单,但是还是搞不定,坑太多,哎,没办法就是这么坑,多看几遍就好了)
根据微信的接口,返回的xml的数据参数。将数据解析之后,就能获得prepayid。
nonceStr: 随机串,防重发(随机字符串,不长于32位)
获取方式:
注意:#pragma mark-& 需要引入依赖库libcommonCrypto.tbd并且引入头文件#import &CommonCrypto/CommonGigest.h&
const &char*str = [input & UTF8String];
unsigned & char & result[CC_MD5_DIGEST_LENGTH];
CC_MD5(str,strlen(str),result);
NSMutableString* &ret = [NSMutableString &stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for(int i = 0 ;i &CC_MD5_DIGEST_LENGTH;i++) {
[ret appendFormat:@&%02X&,result[i]];
NSLog(@&%@&,[ret& uppercaseString]);
注意:就是一个随机数。noncestr就是在第一次生成签名的时候的那个随机数,不要再次生成。
timeStamp:时间戳,防重发(标准北京时间,时区为东八区,自日 0点0分0秒以来的秒数)
获取方式:
NSString* timeString = [NSString & & &stringWithFormat:@&%.0f&[[NSDate date]timeIntervalSince1970]];
@property(nonatomic,assign)UInt32 &timeS
所以在提交的时候需要转换成对应的格式,UInt32 格式。
sign: 商家根据微信开放平台文档对数据做的签名,
这里的签名不同于你第一次申请的prepayid的签名,这里的签名的参数是appid,prepayid,partnerid,timestamp,noncestr,package & 这几个排序后再拼接的key最后生成一个sign。
上面这些只是介绍了这些参数如何获取,在下面一篇文章中,开始仔细介绍,最后一步的支付流程,也就是配置参数、服务器相关的一些配置。
参考资源:
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 支付功能开发 的文章

 

随机推荐