IOS客户端接入微信支付_IOS

实际上,从代码的角度,调起支付APP就是把一些关键的参数通过一定方式打包成为一个订单,然后发送到支付平台的服务器。所以,只要搞清楚了参数设置,搞清楚了每个支付平台的SDK里面一些关键API的使用,基本上就可以很简单的支持支付。

今天记录一下客户端里面,如何支持微信支付。首先。我们要仔细阅读一下微信SDK的开发文档,了解一下整个支付的大概流程。

然后根据提示,把相应的SDK下载下来,所谓的SDK,也就是一个链接库和两个头文件,很简单。

下载完毕,需要把SDK导入到工程里面,并且配置一下工程。因为开发者文档已经有详细描述,这里就不再复述。

从文档看到,调起微信支付其实最核心的是一下这么一段

<code class="hljs" vbscript="">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];</code>

这里的范例是一段hardcode,真正使用的时候,参数都需要自行传入。

为了搞清楚如何使用API,我们可以下载Sample代码。不过,这个sample代码应该是微信的实习生写的,而且应该是一个对于C++比较熟悉,对于ObjectC比较陌生的实习生。。。代码风格可以看出很多东西哈。。所以这个sample读起来总觉得有点奇怪。当然,写出这个demo也是需要不错的水平,因为这个sample不仅仅是一些API的调用,还包括了一些算法的实现,MD5之类的。
看懂了sample之后,一般可以自己重构一下,成为自己APP里面的一个Manager类。

我是在2015 5 23下载的微信Sampel代码,里面包括有:

ApiXml.h

ApiXml.m

WXUtil.h

WXUtil.m

payRequestHandler.h

payRequestHandler.m

如果比较看重命名规范的OC程序猿,就会觉得这个payRequestHandler类非常别扭,不符合camel命名规则,而且handler这个词更偏向于c++风格。我就以这个类为原型,重构了一下,并改装成一个传参的方法,供自己的APP调用。APP里面卖商品,一般就是商品名字,价格两个关键参数。所以这个重构的方法也只是提供这两个参数的接口。
ApiXml.h && ApiXml.m && WXUtil.h && WXUtil.m不变

<code class="hljs" objectivec="">//
// WechatPayManager.h
//
// Created by HuangCharlie on 5/24/15.
//
//
#import <foundation foundation.h="">
#import WXUtil.h
#import ApiXml.h
#import WXApi.h
// 账号帐户资料
// 更改商户把相关参数后可测试
#define APP_ID     @wx@@@@@@@@@@@@@@@@    //APPID
#define APP_SECRET   @             //appsecret,看起来好像没用
//商户号,填写商户对应参数
#define MCH_ID     @@@@@@@@@@@
//商户API密钥,填写相应参数
#define PARTNER_ID   @12345678901234567890123456789012
//支付结果回调页面
#define NOTIFY_URL   @http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php
//获取服务器端支付数据地址(商户自定义)(在小吉这里,签名算法直接放在APP端,故不需要自定义)
#define SP_URL     @http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php
@interface WechatPayManager : NSObject
{
}
//预支付网关url地址
@property (nonatomic,strong) NSString* payUrl;
//debug信息
@property (nonatomic,strong) NSMutableString *debugInfo;
@property (nonatomic,assign) NSInteger lastErrCode;//返回的错误码
//商户关键信息
@property (nonatomic,strong) NSString *appId,*mchId,*spKey;
//初始化函数
-(id)initWithAppID:(NSString*)appID
       mchID:(NSString*)mchID
       spKey:(NSString*)key;
//获取当前的debug信息
-(NSString *) getDebugInfo;
//获取预支付订单信息(核心是一个prepayID)
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name
                     price:(NSString*)price
                    device:(NSString*)device;
@end
</foundation></code>
<code class="hljs" objectivec="">//
// WechatPayManager.m
//
// Created by HuangCharlie on 5/24/15.
//
//
#import WechatPayManager.h
@implementation WechatPayManager
//初始化函数
-(id)initWithAppID:(NSString*)appID mchID:(NSString*)mchID spKey:(NSString*)key
{
  self = [super init];
  if(self)
  {
    //初始化私有参数,主要是一些和商户有关的参数
    self.payUrl  = @https://api.mch.weixin.qq.com/pay/unifiedorder;
    if (self.debugInfo == nil){
      self.debugInfo = [NSMutableString string];
    }
    [self.debugInfo setString:@];
    self.appId = appID;//微信分配给商户的appID
    self.mchId = mchID;//
    self.spKey = key;//商户的密钥
  }
  return self;
}
//获取debug信息
-(NSString*) getDebugInfo
{
  NSString *res = [NSString stringWithString:self.debugInfo];
  [self.debugInfo setString:@];
  return res;
}
//创建package签名
-(NSString*) createMd5Sign:(NSMutableDictionary*)dict
{
  NSMutableString *contentString =[NSMutableString string];
  NSArray *keys = [dict allKeys];
  //按字母顺序排序
  NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [obj1 compare:obj2 options:NSNumericSearch];
  }];
  //拼接字符串
  for (NSString *categoryId in sortedArray) {
    if (  ![[dict objectForKey:categoryId] isEqualToString:@]
      && ![categoryId isEqualToString:@sign]
      && ![categoryId isEqualToString:@key]
      )
    {
      [contentString appendFormat:@%@=%@&, categoryId, [dict objectForKey:categoryId]];
    }
  }
  //添加key字段
  [contentString appendFormat:@key=%@, self.spKey];
  //得到MD5 sign签名
  NSString *md5Sign =[WXUtil md5:contentString];
  //输出Debug Info
  [self.debugInfo appendFormat:@MD5签名字符串:
%@
,contentString];
  return md5Sign;
}
//获取package带参数的签名包
-(NSString *)genPackage:(NSMutableDictionary*)packageParams
{
  NSString *sign;
  NSMutableString *reqPars=[NSMutableString string];
  //生成签名
  sign    = [self createMd5Sign:packageParams];
  //生成xml的package
  NSArray *keys = [packageParams allKeys];
  [reqPars appendString:@<xml>
];
  for (NSString *categoryId in keys) {
    [reqPars appendFormat:@<%@>%@<!--%@-->
, categoryId, [packageParams objectForKey:categoryId],categoryId];
  }
  [reqPars appendFormat:@<sign>%@</sign>
</xml>, sign];
  return [NSString stringWithString:reqPars];
}
//提交预支付
-(NSString *)sendPrepay:(NSMutableDictionary *)prePayParams
{
  NSString *prepayid = nil;
  //获取提交支付
  NSString *send   = [self genPackage:prePayParams];
  //输出Debug Info
  [self.debugInfo appendFormat:@API链接:%@
, self.payUrl];
  [self.debugInfo appendFormat:@发送的xml:%@
, send];
  //发送请求post xml数据
  NSData *res = [WXUtil httpSend:self.payUrl method:@POST data:send];
  //输出Debug Info
  [self.debugInfo appendFormat:@服务器返回:
%@
,[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
  XMLHelper *xml = [[XMLHelper alloc] autorelease];
  //开始解析
  [xml startParse:res];
  NSMutableDictionary *resParams = [xml getDict];
  //判断返回
  NSString *return_code  = [resParams objectForKey:@return_code];
  NSString *result_code  = [resParams objectForKey:@result_code];
  if ( [return_code isEqualToString:@SUCCESS] )
  {
    //生成返回数据的签名
    NSString *sign   = [self createMd5Sign:resParams ];
    NSString *send_sign =[resParams objectForKey:@sign] ;
    //验证签名正确性
    if( [sign isEqualToString:send_sign]){
      if( [result_code isEqualToString:@SUCCESS]) {
        //验证业务处理状态
        prepayid  = [resParams objectForKey:@prepay_id];
        return_code = 0;
        [self.debugInfo appendFormat:@获取预支付交易标示成功!
];
      }
    }else{
      self.lastErrCode = 1;
      [self.debugInfo appendFormat:@gen_sign=%@
  _sign=%@
,sign,send_sign];
      [self.debugInfo appendFormat:@服务器返回签名验证错误!!!
];
    }
  }else{
    self.lastErrCode = 2;
    [self.debugInfo appendFormat:@接口返回错误!!!
];
  }
  return prepayid;
}
- (NSMutableDictionary*)getPrepayWithOrderName:(NSString*)name
                     price:(NSString*)price
                    device:(NSString*)device
{
  //订单标题,展示给用户
  NSString* orderName = name;
  //订单金额,单位(分)
  NSString* orderPrice = price;//以分为单位的整数
  //支付设备号或门店号
  NSString* orderDevice = device;
  //支付类型,固定为APP
  NSString* orderType = @APP;
  //发器支付的机器ip,暂时没有发现其作用
  NSString* orderIP = @196.168.1.1;
  //随机数串
  srand( (unsigned)time(0) );
  NSString *noncestr = [NSString stringWithFormat:@%d, rand()];
  NSString *orderNO  = [NSString stringWithFormat:@%ld,time(0)];
  //================================
  //预付单参数订单设置
  //================================
  NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
  [packageParams setObject: self.appId forKey:@appid];    //开放平台appid
  [packageParams setObject: self.mchId forKey:@mch_id];   //商户号
  [packageParams setObject: orderDevice forKey:@device_info]; //支付设备号或门店号
  [packageParams setObject: noncestr   forKey:@nonce_str];  //随机串
  [packageParams setObject: orderType  forKey:@trade_type]; //支付类型,固定为APP
  [packageParams setObject: orderName  forKey:@body];    //订单描述,展示给用户
  [packageParams setObject: NOTIFY_URL forKey:@notify_url]; //支付结果异步通知
  [packageParams setObject: orderNO   forKey:@out_trade_no];//商户订单号
  [packageParams setObject: orderIP   forKey:@spbill_create_ip];//发器支付的机器ip
  [packageParams setObject: orderPrice  forKey:@total_fee];    //订单金额,单位为分
  //获取prepayId(预支付交易会话标识)
  NSString *prePayid;
  prePayid = [self sendPrepay:packageParams];
  if(prePayid == nil)
  {
    [self.debugInfo appendFormat:@获取prepayid失败!
];
    return nil;
  }
  //获取到prepayid后进行第二次签名
  NSString  *package, *time_stamp, *nonce_str;
  //设置支付参数
  time_t now;
  time(&now);
  time_stamp = [NSString stringWithFormat:@%ld, now];
  nonce_str = [WXUtil md5:time_stamp];
  //重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况
  //package    = [NSString stringWithFormat:@Sign=%@,package];
  package     = @Sign=WXPay;
  //第二次签名参数列表
  NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
  [signParams setObject: self.appId forKey:@appid];
  [signParams setObject: self.mchId forKey:@partnerid];
  [signParams setObject: nonce_str  forKey:@noncestr];
  [signParams setObject: package   forKey:@package];
  [signParams setObject: time_stamp  forKey:@timestamp];
  [signParams setObject: prePayid   forKey:@prepayid];
  //生成签名
  NSString *sign = [self createMd5Sign:signParams];
  //添加签名
  [signParams setObject: sign     forKey:@sign];
  [self.debugInfo appendFormat:@第二步签名成功,sign=%@
,sign];
  //返回参数列表
  return signParams;
}
@end</code>

然后,在需要调用微信支付的Controller里面,新建一个方法。在合适的地方调用。这个方法里面利用WechatPayManager这个类进行了初始化和参数封装,然后把上述的核心代码(PayReq那一段)

<code class="hljs" objectivec="">- (void)wxPayWithOrderName:(NSString*)name price:(NSString*)price
{
  //创建支付签名对象 && 初始化支付签名对象
  WechatPayManager* wxpayManager = [[[WechatPayManager alloc]initWithAppID:APP_ID mchID:MCH_ID spKey:PARTNER_ID] autorelease];

  //获取到实际调起微信支付的参数后,在app端调起支付
  //生成预支付订单,实际上就是把关键参数进行第一次加密。
  NSString* device = [[UserManager defaultManager]userId];
  NSMutableDictionary *dict = [wxpayManager getPrepayWithOrderName:name
                                price:price
                             device:device];
  if(dict == nil){
    //错误提示
    NSString *debug = [wxpayManager getDebugInfo];
    return;
  }

  NSMutableString *stamp = [dict objectForKey:@timestamp];

  //调起微信支付
  PayReq* req       = [[[PayReq alloc] init]autorelease];
  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];

//    BOOL flag = [WXApi sendReq:req];
  BOOL flag = [WXApi safeSendReq:req];
}</code>

再者,支付完成了需要调用一个delegate,这个delegate方便个性化显示支付结果。一般直接把这两个delegate放在AppDelegate就好了。因为有一些其他内容也是需要在AppDelegate里面实现,省的分开找不到。

<code class="hljs" objectivec="">-(void) onResp:(BaseResp*)resp
{
  //启动微信支付的response
  NSString *strMsg = [NSString stringWithFormat:@errcode:%d, resp.errCode];
  if([resp isKindOfClass:[PayResp class]]){
    //支付返回结果,实际支付结果需要去微信服务器端查询
    switch (resp.errCode) {
      case 0:
        strMsg = @支付结果:成功!;
        break;
      case -1:
        strMsg = @支付结果:失败!;
        break;
      case -2:
        strMsg = @用户已经退出支付!;
        break;
      default:
        strMsg = [NSString stringWithFormat:@支付结果:失败!retcode = %d, retstr = %@, resp.errCode,resp.errStr];
        break;
    }
  }
}</code>

注意事项:

1)如果APP里面已经使用了ShareSDK,就有一些地方要注意。不要再重复导入微信的SDK,因为shareSDK里面的extend已经包括了微信的SDK。

2)微信本身是鼓励客户APP把签名算法放到服务器上面,这样信息就不容易被破解。但是如果客户APP本身没有服务器端,或者认为不需要放到服务器端,也可以直接把签名(加密)的部分直接放在APP端。Sample代码的注释有点乱,多次提到服务器云云,但是其实可以不这么做。

3)微信的price单位是分。注意下即可。

4)暂时想不到,以后想到了再记录。。

以上是本文给大家叙述的IOS客户端接入微信支付的全部内容,希望大家喜欢。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索ios接入微信支付
ios微信客户端
客户端接入微信支付、微信支付 ios 接入、ios调用支付宝客户端、ios 判断支付宝客户端、ios 支付宝客户端架构,以便于您获取更多的相关知识。

时间: 2024-09-14 12:52:17

IOS客户端接入微信支付_IOS的相关文章

嘀嘀打车接入微信支付更受欢迎

打车软件使打车变得便捷.可控,而手机支付和打车软件的结合,则让体验更上一层楼.嘀嘀打车接入微信支付,产生的订单量和支付次数已经体现出这种方式的受欢迎程度. 前几天刚刚接入微信的嘀嘀打车,公布了和微信合作以来取得的最新成绩:1 月 4 日接入微信当天,在只支持 iOS 版的情况下,微信内叫车已经达到 2 万单,微信支付超过 6000 单:从 1 月 10 日 0 点开始,至 1 月 12 日下午 6 点,每天通过微信支付的打车订单量分别是 2.7 万单.3.6 万单.3.8 万单,通过微信支付的总

android 应用接入微信支付sdk

问题描述 android 应用接入微信支付sdk android 应用接入微信支付sdk 求思路.......... 解决方案 1.进入微信开放平台网站(https://open.weixin.qq.com/)2.到"资源下载"->Android资源下载,下载demo程序3.demo里面有接入实例,看着demo就能接入了,没多少代码4.还需要看着接入文档,开放平台有详细的接入文档 解决方案二: 在管理中心为移动应用申请微信支付成功后,请下载微信APP支付Android开发文档及资

王府井百货今日正式接入微信支付 付款过程只需10秒

王府井百货今日正式接入微信支付据悉,王府井百货已经正式接入微信支付.从3月8日起,用户只需用微信扫描收银台屏幕上的二维码或者打印出来的二维码小票,就可以通过微信支付完成付款.值得注意的是,此前上市公司天虹商场 .友阿股份 .红旗连锁 .中央商场 .王府井等相继与腾讯达成O2O合作.微信支付相关负责人向记者解释,只要是完成认证的服务号都可以申请接口,这也将加速百货商家包括营销.消费.支付.及客户维护在内的整个O2O闭环的打造, 预计会有更多合作商户接入支付功能.据了解,此次王府井初步完成微信支付接

去哪儿旅行宣布接入微信支付

[TechWeb报道]近日消息,知名中文旅游平台移动客户端"去哪儿旅行"宣布接入微信支付,用户只要手机中装有微信,就可通过微信支付的方式购买机票.记者从去哪儿获悉,该公司正式宣布接入微信支付.去哪儿认为,此次与微信支付的战略合作,是去哪儿在移动旅游市场的重要拓展.去哪儿选择在春节前发布支持微信支付,这样更多假期回家和旅游的用户又多了一种让出行顺利的方式.这种全程闭环式的支付方式,也更能有效提高购票安全性.

不再傲娇,渣打银行首次接入微信支付

今日,渣打银行(中国)有限公司(以下简称"渣打中国")正式宣布接入微信支付.渣打中国的信用卡客户可绑定微信支付功能,实现娱乐.购物.网上缴费.在线教育等全方位的便捷生活服务. 据了解,在一月前,渣打银行就已与微信结缘.其为工业企业美卓公司完成了手机钱包收款.据美卓(中国)投资有限公司司库经理王晨表示,该方案提供了更便捷的付款方式,简化公司财务的账户管理工作. 而两者结盟,与中国移动支付的盛行分不开.渣打中国个人金融部董事总经理朱亚明表示,中国移动支付发展迅猛,并在不断影响全球金融消费的

王府井百货已经全面接入微信支付

经过一段时间的内测,现在王府井百货已经全面接入微信支付.从3月8日起,用户逛王府井就不用再带钱包了,在结账的时候可以直接选择用微信扫描收银台屏幕上的二维码,或者是打印出来的二维码小票,进行微信支付. 首批接入微信支付的门店包括王府井百货大楼.长安商场.东安商场.双安商场.大兴王府井百货和赛特百货六家.据了解,后续王府井在全国各地的门店都将全面接入微信支付,并且从现在的收银台扫描二维码付款,升级成顾客在货品柜台就能直接付款. 传统的O2O玩法,一般来说是通过发布优惠活动在线上汇聚流量,而后把所有流

高朋新融资或超3000万美元 团购接入微信支付

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 腾讯科技讯(乐天)7月24日消息,高朋网今日宣布,即将获得来自Groupon.腾讯联合参与的新一轮融资.高朋网暂未公开透露本轮融资具体金额,不过腾讯科技从消息人士获悉,本轮融资金额或将超过3000万美元. 目前新高朋网的主要机构股东,仍然为腾讯.Groupon.君联资本.本轮新融资也是团购领域整体面临巨大洗牌之后,唯一的一轮新融资. 高朋网C

移动支付争夺战加剧 中信接入微信支付

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 10月30日消息,亿邦动力网最新获悉,日前,微信支付全面接入中信银行信用卡支付,用户将信用卡信息与微信进行绑定后,即可通过微信进行手机支付. 亿邦动力网了解到,中信银行近期上线的"微信银行",不仅是与客户点对点即时沟通的工具,更是服务大众的互联网金融平台,是继网上银行.电话银行.手机银行之后推出的又一便捷金融服务渠道. 用

微信支付大举进军O2O,王府井百货全面接入微信支付

摘要: 经过一段时间的内测,现在王府井百货已经全面接入微信支付.从3月8日起,用户逛王府井就不用再带钱包了,在结账的时候可以直接选择用微信扫描收银台屏幕上的二维码,或者是打 经过一段时间的内测,现在王府井百货已经全面接入微信支付.从3月8日起,用户逛王府井就不用再带钱包了,在结账的时候可以直接选择用微信扫描收银台屏幕上的二维码,或者是打印出来的二维码小票,进行微信支付. 首批接入微信支付的门店包括王府井百货大楼.长安商场.东安商场.双安商场.大兴王府井百货和赛特百货六家.据了解,后续王府井在全国