payRequsestHandler.mm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #import <Foundation/Foundation.h>
  2. #import "payRequsestHandler.h"
  3. /*
  4. 服务器请求操作处理
  5. */
  6. @implementation payRequsestHandler
  7. //初始化函数
  8. -(BOOL) init:(NSString *)app_id mch_id:(NSString *)mch_id;
  9. {
  10. //初始构造函数
  11. payUrl = @"https://api.mch.weixin.qq.com/pay/unifiedorder";
  12. if (debugInfo == nil){
  13. debugInfo = [NSMutableString string];
  14. }
  15. [debugInfo setString:@""];
  16. appid = app_id;
  17. mchid = mch_id;
  18. return YES;
  19. }
  20. //设置商户密钥
  21. -(void) setKey:(NSString *)key
  22. {
  23. spkey = [NSString stringWithString:key];
  24. }
  25. //获取debug信息
  26. -(NSString*) getDebugifo
  27. {
  28. NSString *res = [NSString stringWithString:debugInfo];
  29. [debugInfo setString:@""];
  30. return res;
  31. }
  32. //获取最后服务返回错误代码
  33. -(long) getLasterrCode
  34. {
  35. return last_errcode;
  36. }
  37. //创建package签名
  38. -(NSString*) createMd5Sign:(NSMutableDictionary*)dict
  39. {
  40. NSMutableString *contentString =[NSMutableString string];
  41. NSArray *keys = [dict allKeys];
  42. //按字母顺序排序
  43. NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
  44. return [obj1 compare:obj2 options:NSNumericSearch];
  45. }];
  46. //拼接字符串
  47. for (NSString *categoryId in sortedArray) {
  48. if ( ![[dict objectForKey:categoryId] isEqualToString:@""]
  49. && ![categoryId isEqualToString:@"sign"]
  50. && ![categoryId isEqualToString:@"key"]
  51. )
  52. {
  53. [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
  54. }
  55. }
  56. //添加key字段
  57. [contentString appendFormat:@"key=%@", spkey];
  58. //得到MD5 sign签名
  59. NSString *md5Sign =[WXUtil md5:contentString];
  60. //输出Debug Info
  61. [debugInfo appendFormat:@"MD5签名字符串:\n%@\n\n",contentString];
  62. return md5Sign;
  63. }
  64. //获取package带参数的签名包
  65. -(NSString *)genPackage:(NSMutableDictionary*)packageParams
  66. {
  67. NSString *sign;
  68. NSMutableString *reqPars=[NSMutableString string];
  69. //生成签名
  70. sign = [self createMd5Sign:packageParams];
  71. //生成xml的package
  72. NSArray *keys = [packageParams allKeys];
  73. [reqPars appendString:@"<xml>\n"];
  74. for (NSString *categoryId in keys) {
  75. [reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
  76. }
  77. [reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign];
  78. return [NSString stringWithString:reqPars];
  79. }
  80. //提交预支付
  81. -(NSString *)sendPrepay:(NSMutableDictionary *)prePayParams
  82. {
  83. NSString *prepayid = nil;
  84. //获取提交支付
  85. NSString *send = [self genPackage:prePayParams];
  86. //输出Debug Info
  87. [debugInfo appendFormat:@"API链接:%@\n", payUrl];
  88. [debugInfo appendFormat:@"发送的xml:%@\n", send];
  89. //发送请求post xml数据
  90. NSData *res = [WXUtil httpSend:payUrl method:@"POST" data:send];
  91. //输出Debug Info
  92. [debugInfo appendFormat:@"服务器返回:\n%@\n\n",[[NSString alloc] initWithData:res encoding:NSUTF8StringEncoding]];
  93. XMLHelper *xml = [[XMLHelper alloc] autorelease];
  94. //开始解析
  95. [xml startParse:res];
  96. NSMutableDictionary *resParams = [xml getDict];
  97. //判断返回
  98. NSString *return_code = [resParams objectForKey:@"return_code"];
  99. NSString *result_code = [resParams objectForKey:@"result_code"];
  100. if ( [return_code isEqualToString:@"SUCCESS"] )
  101. {
  102. //生成返回数据的签名
  103. NSString *sign = [self createMd5Sign:resParams ];
  104. NSString *send_sign =[resParams objectForKey:@"sign"] ;
  105. //验证签名正确性
  106. if( [sign isEqualToString:send_sign]){
  107. if( [result_code isEqualToString:@"SUCCESS"]) {
  108. //验证业务处理状态
  109. prepayid = [resParams objectForKey:@"prepay_id"];
  110. return_code = 0;
  111. [debugInfo appendFormat:@"获取预支付交易标示成功!\n"];
  112. }
  113. }else{
  114. last_errcode = 1;
  115. [debugInfo appendFormat:@"gen_sign=%@\n _sign=%@\n",sign,send_sign];
  116. [debugInfo appendFormat:@"服务器返回签名验证错误!!!\n"];
  117. }
  118. }else{
  119. last_errcode = 2;
  120. [debugInfo appendFormat:@"接口返回错误!!!\n"];
  121. }
  122. return prepayid;
  123. }
  124. //============================================================
  125. // V3V4支付流程模拟实现,只作帐号验证和演示
  126. // 注意:此demo只适合开发调试,参数配置和参数加密需要放到服务器端处理
  127. // 服务器端Demo请查看包的文件
  128. // 更新时间:2015年3月3日
  129. // 负责人:李启波(marcyli)
  130. //============================================================
  131. - ( NSMutableDictionary *)sendPay_demo
  132. {
  133. //订单标题,展示给用户
  134. NSString *order_name = @"V3支付测试";
  135. //订单金额,单位(分)
  136. NSString *order_price = @"1";//1分钱测试
  137. //================================
  138. //预付单参数订单设置
  139. //================================
  140. srand( (unsigned)time(0) );
  141. NSString *noncestr = [NSString stringWithFormat:@"%d", rand()];
  142. NSString *orderno = [NSString stringWithFormat:@"%ld",time(0)];
  143. NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
  144. [packageParams setObject: appid forKey:@"appid"]; //开放平台appid
  145. [packageParams setObject: mchid forKey:@"mch_id"]; //商户号
  146. [packageParams setObject: @"APP-001" forKey:@"device_info"]; //支付设备号或门店号
  147. [packageParams setObject: noncestr forKey:@"nonce_str"]; //随机串
  148. [packageParams setObject: @"APP" forKey:@"trade_type"]; //支付类型,固定为APP
  149. [packageParams setObject: order_name forKey:@"body"]; //订单描述,展示给用户
  150. [packageParams setObject: NOTIFY_URL forKey:@"notify_url"]; //支付结果异步通知
  151. [packageParams setObject: orderno forKey:@"out_trade_no"];//商户订单号
  152. [packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//发器支付的机器ip
  153. [packageParams setObject: order_price forKey:@"total_fee"]; //订单金额,单位为分
  154. //获取prepayId(预支付交易会话标识)
  155. NSString *prePayid;
  156. prePayid = [self sendPrepay:packageParams];
  157. if ( prePayid != nil) {
  158. //获取到prepayid后进行第二次签名
  159. NSString *package, *time_stamp, *nonce_str;
  160. //设置支付参数
  161. time_t now;
  162. time(&now);
  163. time_stamp = [NSString stringWithFormat:@"%ld", now];
  164. nonce_str = [WXUtil md5:time_stamp];
  165. //重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况
  166. //package = [NSString stringWithFormat:@"Sign=%@",package];
  167. package = @"Sign=WXPay";
  168. //第二次签名参数列表
  169. NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
  170. [signParams setObject: appid forKey:@"appid"];
  171. [signParams setObject: nonce_str forKey:@"noncestr"];
  172. [signParams setObject: package forKey:@"package"];
  173. [signParams setObject: mchid forKey:@"partnerid"];
  174. [signParams setObject: time_stamp forKey:@"timestamp"];
  175. [signParams setObject: prePayid forKey:@"prepayid"];
  176. //[signParams setObject: @"MD5" forKey:@"signType"];
  177. //生成签名
  178. NSString *sign = [self createMd5Sign:signParams];
  179. //添加签名
  180. [signParams setObject: sign forKey:@"sign"];
  181. [debugInfo appendFormat:@"第二步签名成功,sign=%@\n",sign];
  182. //返回参数列表
  183. return signParams;
  184. }else{
  185. [debugInfo appendFormat:@"获取prepayid失败!\n"];
  186. }
  187. return nil;
  188. }
  189. //============================================================
  190. // V3V4支付流程模拟实现,只作帐号验证和演示
  191. // 注意:此demo只适合开发调试,参数配置和参数加密需要放到服务器端处理
  192. // 服务器端Demo请查看包的文件
  193. // 更新时间:2015年3月3日
  194. // 负责人:李启波(marcyli)
  195. //============================================================
  196. - ( NSMutableDictionary *)sendPay:(NSString *)txtTitle money:(NSString *)money orderNo:(NSString *)orderNo notifyURL:(NSString *)notifyURL
  197. {
  198. //订单标题,展示给用户
  199. NSString *order_name = txtTitle;
  200. //订单金额,单位(分)
  201. NSString *order_price = money;//1分钱测试
  202. //================================
  203. //预付单参数订单设置
  204. //================================
  205. srand( (unsigned)time(0) );
  206. NSString *noncestr = [NSString stringWithFormat:@"%d", rand()];
  207. NSString *orderno = orderNo;//[NSString stringWithFormat:@"%ld",time(0)];
  208. NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
  209. [packageParams setObject: appid forKey:@"appid"]; //开放平台appid
  210. [packageParams setObject: mchid forKey:@"mch_id"]; //商户号
  211. [packageParams setObject: @"APP-001" forKey:@"device_info"]; //支付设备号或门店号
  212. [packageParams setObject: noncestr forKey:@"nonce_str"]; //随机串
  213. [packageParams setObject: @"APP" forKey:@"trade_type"]; //支付类型,固定为APP
  214. [packageParams setObject: order_name forKey:@"body"]; //订单描述,展示给用户
  215. [packageParams setObject: notifyURL forKey:@"notify_url"]; //支付结果异步通知
  216. [packageParams setObject: orderno forKey:@"out_trade_no"];//商户订单号
  217. [packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];//发器支付的机器ip
  218. [packageParams setObject: order_price forKey:@"total_fee"]; //订单金额,单位为分
  219. //获取prepayId(预支付交易会话标识)
  220. NSString *prePayid;
  221. prePayid = [self sendPrepay:packageParams];
  222. if (prePayid != nil) {
  223. //获取到prepayid后进行第二次签名
  224. NSString *package, *time_stamp, *nonce_str;
  225. //设置支付参数
  226. time_t now;
  227. time(&now);
  228. time_stamp = [NSString stringWithFormat:@"%ld", now];
  229. nonce_str = [WXUtil md5:time_stamp];
  230. //重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况
  231. //package = [NSString stringWithFormat:@"Sign=%@",package];
  232. package = @"Sign=WXPay";
  233. //第二次签名参数列表
  234. NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
  235. [signParams setObject: appid forKey:@"appid"];
  236. [signParams setObject: nonce_str forKey:@"noncestr"];
  237. [signParams setObject: package forKey:@"package"];
  238. [signParams setObject: mchid forKey:@"partnerid"];
  239. [signParams setObject: time_stamp forKey:@"timestamp"];
  240. [signParams setObject: prePayid forKey:@"prepayid"];
  241. //[signParams setObject: @"MD5" forKey:@"signType"];
  242. //生成签名
  243. NSString *sign = [self createMd5Sign:signParams];
  244. //添加签名
  245. [signParams setObject: sign forKey:@"sign"];
  246. [debugInfo appendFormat:@"第二步签名成功,sign=%@\n",sign];
  247. //返回参数列表
  248. return signParams;
  249. }else{
  250. [debugInfo appendFormat:@"获取prepayid失败!\n"];
  251. }
  252. return nil;
  253. }
  254. @end